Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added CM_Get_DevNode_Registry_Property to Cfgmgr32 and Cfgmgr32Util #1340

Merged
merged 1 commit into from
Apr 21, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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