Skip to content

Commit

Permalink
Added CM_Get_DevNode_Registry_Property to Cfgmgr32 and Cfgmgr32Util (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
dbwiddis authored Apr 21, 2021
1 parent b56891b commit 7a33efb
Show file tree
Hide file tree
Showing 5 changed files with 288 additions and 27 deletions.
1 change: 1 addition & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ Features
* [#1336](https://github.com/java-native-access/jna/pull/1336): Add `HKEY_CURRENT_USER_LOCAL_SETTINGS` to `c.s.j.p.win32.WinReg` - [@Dani-Hub](https://github.com/Dani-Hub).
* [#1337](https://github.com/java-native-access/jna/pull/1337): Add `REG_NOTIFY_THREAD_AGNOSTIC` to `c.s.j.p.win32.WinNet` and update `REG_LEGAL_CHANGE_FILTER` - [@Dani-Hub](https://github.com/Dani-Hub).
* [#1338](https://github.com/java-native-access/jna/pull/1338): Add `RegNotifyChangeKeyValue` to `c.s.j.p.win32.Advapi32` - [@Dani-Hub](https://github.com/Dani-Hub).
* [#1340](https://github.com/java-native-access/jna/issues/1340): Added `CM_Get_DevNode_Registry_Property` to `c.s.j.p.win32.Cfgmgr32` and corresponding util in `c.s.j.p.win32.Cfgmgr32Util` - [@dbwiddis](https://github.com/dbwiddis).

Bug Fixes
---------
Expand Down
13 changes: 13 additions & 0 deletions contrib/platform/src/com/sun/jna/platform/win32/Advapi32Util.java
Original file line number Diff line number Diff line change
Expand Up @@ -961,6 +961,19 @@ public static String[] registryGetStringArray(HKEY hKey, String value) {
&& rc != W32Errors.ERROR_INSUFFICIENT_BUFFER) {
throw new Win32Exception(rc);
}
return regMultiSzBufferToStringArray(data);
}

/**
* Convert the null-delimited buffer of strings returned from registry values of
* type {@link WinNT.REG_MULTI_SZ} to an array of strings.
*
* @param data
* A buffer containing strings delimited by a null character, ending
* with two null characters.
* @return An array of strings corresponding to the strings in the buffer.
*/
static String[] regMultiSzBufferToStringArray(Memory data) {
ArrayList<String> result = new ArrayList<String>();
int offset = 0;
while (offset < data.size()) {
Expand Down
89 changes: 82 additions & 7 deletions contrib/platform/src/com/sun/jna/platform/win32/Cfgmgr32.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,50 @@
public interface Cfgmgr32 extends Library {
Cfgmgr32 INSTANCE = Native.load("Cfgmgr32", Cfgmgr32.class, W32APIOptions.DEFAULT_OPTIONS);

public final static int CR_SUCCESS = 0;
public final static int CR_BUFFER_SMALL = 0x0000001A;
int CR_SUCCESS = 0;
int CR_BUFFER_SMALL = 0x0000001A;
int CR_NO_SUCH_VALUE = 0x00000025;

public final static int CM_LOCATE_DEVNODE_NORMAL = 0;
public final static int CM_LOCATE_DEVNODE_PHANTOM = 1;
public final static int CM_LOCATE_DEVNODE_CANCELREMOVE = 2;
public final static int CM_LOCATE_DEVNODE_NOVALIDATION = 4;
public final static int CM_LOCATE_DEVNODE_BITS = 7;
int CM_LOCATE_DEVNODE_NORMAL = 0;
int CM_LOCATE_DEVNODE_PHANTOM = 1;
int CM_LOCATE_DEVNODE_CANCELREMOVE = 2;
int CM_LOCATE_DEVNODE_NOVALIDATION = 4;
int CM_LOCATE_DEVNODE_BITS = 7;

int CM_DRP_DEVICEDESC = 0x00000001; // DeviceDesc REG_SZ property (RW)
int CM_DRP_HARDWAREID = 0x00000002; // HardwareID REG_MULTI_SZ property (RW)
int CM_DRP_COMPATIBLEIDS = 0x00000003; // CompatibleIDs REG_MULTI_SZ property (RW)
int CM_DRP_SERVICE = 0x00000005; // Service REG_SZ property (RW)
int CM_DRP_CLASS = 0x00000008; // Class REG_SZ property (RW)
int CM_DRP_CLASSGUID = 0x00000009; // ClassGUID REG_SZ property (RW)
int CM_DRP_DRIVER = 0x0000000A; // Driver REG_SZ property (RW)
int CM_DRP_CONFIGFLAGS = 0x0000000B; // ConfigFlags REG_DWORD property (RW)
int CM_DRP_MFG = 0x0000000C; // Mfg REG_SZ property (RW)
int CM_DRP_FRIENDLYNAME = 0x0000000D; // FriendlyName REG_SZ property (RW)
int CM_DRP_LOCATION_INFORMATION = 0x0000000E; // LocationInformation REG_SZ property (RW)
int CM_DRP_PHYSICAL_DEVICE_OBJECT_NAME = 0x0000000F; // PhysicalDeviceObjectName REG_SZ property (R)
int CM_DRP_CAPABILITIES = 0x00000010; // Capabilities REG_DWORD property (R)
int CM_DRP_UI_NUMBER = 0x00000011; // UiNumber REG_DWORD property (R)
int CM_DRP_UPPERFILTERS = 0x00000012; // UpperFilters REG_MULTI_SZ property (RW)
int CM_DRP_LOWERFILTERS = 0x00000013; // LowerFilters REG_MULTI_SZ property (RW)
int CM_DRP_BUSTYPEGUID = 0x00000014; // Bus Type Guid, GUID, (R)
int CM_DRP_LEGACYBUSTYPE = 0x00000015; // Legacy bus type, INTERFACE_TYPE, (R)
int CM_DRP_BUSNUMBER = 0x00000016; // Bus Number, DWORD, (R)
int CM_DRP_ENUMERATOR_NAME = 0x00000017; // Enumerator Name REG_SZ property (R)
int CM_DRP_SECURITY = 0x00000018; // Security - Device override (RW)
int CM_DRP_SECURITY_SDS = 0x00000019; // Security - Device override (RW)
int CM_DRP_DEVTYPE = 0x0000001A; // Device Type - Device override (RW)
int CM_DRP_EXCLUSIVE = 0x0000001B; // Exclusivity - Device override (RW)
int CM_DRP_CHARACTERISTICS = 0x0000001C; // Characteristics - Device Override (RW)
int CM_DRP_ADDRESS = 0x0000001D; // Device Address (R)
int CM_DRP_UI_NUMBER_DESC_FORMAT = 0x0000001E; // UINumberDescFormat REG_SZ property (RW)
int CM_DRP_DEVICE_POWER_DATA = 0x0000001F; // CM_POWER_DATA REG_BINARY property (R)
int CM_DRP_REMOVAL_POLICY = 0x00000020; // CM_DEVICE_REMOVAL_POLICY REG_DWORD (R)
int CM_DRP_REMOVAL_POLICY_HW_DEFAULT = 0x00000021; // CM_DRP_REMOVAL_POLICY_HW_DEFAULT REG_DWORD (R)
int CM_DRP_REMOVAL_POLICY_OVERRIDE = 0x00000022; // CM_DRP_REMOVAL_POLICY_OVERRIDE REG_DWORD (RW)
int CM_DRP_INSTALL_STATE = 0x00000023; // CM_DRP_INSTALL_STATE REG_DWORD (R)
int CM_DRP_LOCATION_PATHS = 0x00000024; // CM_DRP_LOCATION_PATHS REG_MULTI_SZ (R)
int CM_DRP_BASE_CONTAINERID = 0x00000025; // Base ContainerID REG_SZ property (R)

/**
* The CM_Locate_DevNode function obtains a device instance handle to the
Expand Down Expand Up @@ -189,4 +225,43 @@ public interface Cfgmgr32 extends Library {
* CM_Get_Device_ID_Size</A>
*/
int CM_Get_Device_ID_Size(IntByReference pulLen, int dnDevInst, int ulFlags);

/**
* The CM_Get_DevNode_Registry_Property function retrieves a specified device
* property from the registry.
*
* @param dnDevInst
* A caller-supplied device instance handle that is bound to the
* local machine.
* @param ulProperty
* A {@code CM_DRP_}-prefixed constant value that identifies the
* device property to be obtained from the registry. These constants
* are defined in Cfgmgr32.h.
* @param pulRegDataType
* Optional, can be {@code null}. A pointer to a location that
* receives the registry data type, specified as a
* {@code REG_}-prefixed constant defined in Winnt.h.
* @param buffer
* Optional, can be {@code null}. A pointer to a caller-supplied
* buffer that receives the requested device property. If this value
* is {@code null}, the function supplies only the length of the
* requested data in the address pointed to by {@code pulLength}.
* @param pulLength
* A pointer to a {@code ULONG} variable into which the function
* stores the length, in bytes, of the requested device property.
* <p>
* If the Buffer parameter is set to {@code null}, the ULONG variable
* must be set to zero.
* <p>
* If the Buffer parameter is not set to {@code null}, the
* {@code ULONG} variable must be set to the length, in bytes, of the
* caller-supplied buffer.
* @param ulFlags
* Not used, must be zero.
* @return If the operation succeeds, the function returns {@code CR_SUCCESS}.
* Otherwise, it returns one of the {@code CR_}-prefixed error codes
* that are defined in Cfgmgr32.h.
*/
int CM_Get_DevNode_Registry_Property(int dnDevInst, int ulProperty, IntByReference pulRegDataType, Pointer buffer,
IntByReference pulLength, int ulFlags);
}
103 changes: 97 additions & 6 deletions contrib/platform/src/com/sun/jna/platform/win32/Cfgmgr32Util.java
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* Copyright (c) 2018 Daniel Widdis, All Rights Reserved
/* Copyright (c) 2018, 2021 Daniel Widdis, All Rights Reserved
*
* The contents of this file is dual-licensed under 2
* alternative Open Source/Free licenses: LGPL 2.1 or later and
Expand Down Expand Up @@ -26,11 +26,10 @@
import com.sun.jna.Memory;
import com.sun.jna.Native;
import com.sun.jna.ptr.IntByReference;
import com.sun.jna.win32.W32APITypeMapper;

/**
* Cfgmgr32 utility API.
*
* @author widdis[at]gmail[dot]com
*/
public abstract class Cfgmgr32Util {
@SuppressWarnings("serial")
Expand All @@ -47,13 +46,13 @@ public int getErrorCode() {
}

/**
* Utility method to call Cfgmgr32's CM_Get_Device_ID that allocates the
* Utility method to call Cfgmgr32's CM_Get_Device_ID_Size, allocates the
* required memory for the Buffer parameter based on the type mapping used,
* calls to CM_Get_Device_ID, and returns the received string.
*
* @param devInst
* Caller-supplied device instance handle that is bound to the
* local machine.
* Caller-supplied device instance handle that is bound to the local
* machine.
* @return The device instance ID string.
* @throws Cfgmgr32Exception
*/
Expand Down Expand Up @@ -96,4 +95,96 @@ public static String CM_Get_Device_ID(int devInst) throws Cfgmgr32Exception {
return buffer.getWideString(0);
}
}

/**
* Utility method to call Cfgmgr32's CM_Get_DevNode_Registry_Property that
* allocates the required memory for the Buffer parameter, and returns values of
* the appropriate type.
*
* @param devInst
* Caller-supplied device instance handle that is bound to the local
* machine.
* @param ulProperty
* A {@code CM_DRP_}-prefixed constant value that identifies the
* device property to be obtained from the registry. These constants
* are defined in Cfgmgr32.h.
* @return An {@link Object} containing the specified registry property for the
* device.
* <p>
* If the property is of type {@link WinNT.REG_SZ}, a
* {@link java.lang.String} is returned.
* <p>
* If the property is of type {@link WinNT.REG_MULTI_SZ}, an array of
* {@link java.lang.String} is returned.
* <p>
* If the property is of type {@link WinNT.REG_DWORD}, an
* {@link java.lang.Integer} is returned.
* <p>
* If the property is of type {@link WinNT.REG_BINARY}, an array of
* {@link java.lang.Byte} is returned.
* <p>
* If no value exists for this property (error
* {@link Cfgmgr32.CR_NO_SUCH_VALUE}), returns {@code null}.
* @throws Cfgmgr32Exception
* on any errors other than {@link Cfgmgr32.CR_NO_SUCH_VALUE}
*/
public static Object CM_Get_DevNode_Registry_Property(int devInst, int ulProperty) throws Cfgmgr32Exception {

// Get byte count and type
IntByReference size = new IntByReference();
IntByReference type = new IntByReference();
int ret = Cfgmgr32.INSTANCE.CM_Get_DevNode_Registry_Property(devInst, ulProperty, type, null, size, 0);
// If this property does not exist return null
if (ret == Cfgmgr32.CR_NO_SUCH_VALUE) {
return null;
}
// If successful in retrieving type and size, should fail with CR_BUFFER_SMALL,
// otherwise throw an exception
if (ret != Cfgmgr32.CR_BUFFER_SMALL) {
throw new Cfgmgr32Exception(ret);
}

// It is possible to have a valid value with registry data type, but 0 size.
// Leave the memory buffer null in that case
Memory buffer = null;
if (size.getValue() > 0) {
buffer = new Memory(size.getValue());
ret = Cfgmgr32.INSTANCE.CM_Get_DevNode_Registry_Property(devInst, ulProperty, type, buffer, size, 0);
if (ret != Cfgmgr32.CR_SUCCESS) {
throw new Cfgmgr32Exception(ret);
}
}

// Get the appropriate type of data from the buffer
switch (type.getValue()) {
case WinNT.REG_SZ:
// Convert buffer to Java String
if (buffer == null) {
return "";
}
return W32APITypeMapper.DEFAULT == W32APITypeMapper.UNICODE ? buffer.getWideString(0)
: buffer.getString(0);
case WinNT.REG_MULTI_SZ:
// Convert buffer to String Array
if (buffer == null) {
return new String[0];
}
return Advapi32Util.regMultiSzBufferToStringArray(buffer);
case WinNT.REG_DWORD:
// Convert buffer to int
if (buffer == null) {
return 0;
}
return buffer.getInt(0);
case WinNT.REG_NONE:
return null;
default:
// Intended for WinNT.REG_BINARY but safe default for any data
if (buffer == null) {
return new byte[0];
}
// Convert buffer to array of bytes
return buffer.getByteArray(0, (int) buffer.size());
}
}
}
Loading

0 comments on commit 7a33efb

Please sign in to comment.