Skip to content

Commit a97f459

Browse files
committed
Added CM_Get_DevNode_Registry_Property to Cfgmgr32 and Cfgmgr32Util
1 parent b56891b commit a97f459

File tree

5 files changed

+282
-27
lines changed

5 files changed

+282
-27
lines changed

CHANGES.md

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ Features
1010
* [#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).
1111
* [#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).
1212
* [#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).
13+
* [#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).
1314

1415
Bug Fixes
1516
---------

contrib/platform/src/com/sun/jna/platform/win32/Advapi32Util.java

+13
Original file line numberDiff line numberDiff line change
@@ -961,6 +961,19 @@ public static String[] registryGetStringArray(HKEY hKey, String value) {
961961
&& rc != W32Errors.ERROR_INSUFFICIENT_BUFFER) {
962962
throw new Win32Exception(rc);
963963
}
964+
return regMultiSzBufferToStringArray(data);
965+
}
966+
967+
/**
968+
* Convert the null-delimited buffer of strings returned from registry values of
969+
* type {@link WinNT.REG_MULTI_SZ} to an array of strings.
970+
*
971+
* @param data
972+
* A buffer containing strings delimited by a null character, ending
973+
* with two null characters.
974+
* @return An array of strings corresponding to the strings in the buffer.
975+
*/
976+
public static String[] regMultiSzBufferToStringArray(Memory data) {
964977
ArrayList<String> result = new ArrayList<String>();
965978
int offset = 0;
966979
while (offset < data.size()) {

contrib/platform/src/com/sun/jna/platform/win32/Cfgmgr32.java

+82-7
Original file line numberDiff line numberDiff line change
@@ -37,14 +37,50 @@
3737
public interface Cfgmgr32 extends Library {
3838
Cfgmgr32 INSTANCE = Native.load("Cfgmgr32", Cfgmgr32.class, W32APIOptions.DEFAULT_OPTIONS);
3939

40-
public final static int CR_SUCCESS = 0;
41-
public final static int CR_BUFFER_SMALL = 0x0000001A;
40+
int CR_SUCCESS = 0;
41+
int CR_BUFFER_SMALL = 0x0000001A;
42+
int CR_NO_SUCH_VALUE = 0x00000025;
4243

43-
public final static int CM_LOCATE_DEVNODE_NORMAL = 0;
44-
public final static int CM_LOCATE_DEVNODE_PHANTOM = 1;
45-
public final static int CM_LOCATE_DEVNODE_CANCELREMOVE = 2;
46-
public final static int CM_LOCATE_DEVNODE_NOVALIDATION = 4;
47-
public final static int CM_LOCATE_DEVNODE_BITS = 7;
44+
int CM_LOCATE_DEVNODE_NORMAL = 0;
45+
int CM_LOCATE_DEVNODE_PHANTOM = 1;
46+
int CM_LOCATE_DEVNODE_CANCELREMOVE = 2;
47+
int CM_LOCATE_DEVNODE_NOVALIDATION = 4;
48+
int CM_LOCATE_DEVNODE_BITS = 7;
49+
50+
int CM_DRP_DEVICEDESC = 0x00000001; // DeviceDesc REG_SZ property (RW)
51+
int CM_DRP_HARDWAREID = 0x00000002; // HardwareID REG_MULTI_SZ property (RW)
52+
int CM_DRP_COMPATIBLEIDS = 0x00000003; // CompatibleIDs REG_MULTI_SZ property (RW)
53+
int CM_DRP_SERVICE = 0x00000005; // Service REG_SZ property (RW)
54+
int CM_DRP_CLASS = 0x00000008; // Class REG_SZ property (RW)
55+
int CM_DRP_CLASSGUID = 0x00000009; // ClassGUID REG_SZ property (RW)
56+
int CM_DRP_DRIVER = 0x0000000A; // Driver REG_SZ property (RW)
57+
int CM_DRP_CONFIGFLAGS = 0x0000000B; // ConfigFlags REG_DWORD property (RW)
58+
int CM_DRP_MFG = 0x0000000C; // Mfg REG_SZ property (RW)
59+
int CM_DRP_FRIENDLYNAME = 0x0000000D; // FriendlyName REG_SZ property (RW)
60+
int CM_DRP_LOCATION_INFORMATION = 0x0000000E; // LocationInformation REG_SZ property (RW)
61+
int CM_DRP_PHYSICAL_DEVICE_OBJECT_NAME = 0x0000000F; // PhysicalDeviceObjectName REG_SZ property (R)
62+
int CM_DRP_CAPABILITIES = 0x00000010; // Capabilities REG_DWORD property (R)
63+
int CM_DRP_UI_NUMBER = 0x00000011; // UiNumber REG_DWORD property (R)
64+
int CM_DRP_UPPERFILTERS = 0x00000012; // UpperFilters REG_MULTI_SZ property (RW)
65+
int CM_DRP_LOWERFILTERS = 0x00000013; // LowerFilters REG_MULTI_SZ property (RW)
66+
int CM_DRP_BUSTYPEGUID = 0x00000014; // Bus Type Guid, GUID, (R)
67+
int CM_DRP_LEGACYBUSTYPE = 0x00000015; // Legacy bus type, INTERFACE_TYPE, (R)
68+
int CM_DRP_BUSNUMBER = 0x00000016; // Bus Number, DWORD, (R)
69+
int CM_DRP_ENUMERATOR_NAME = 0x00000017; // Enumerator Name REG_SZ property (R)
70+
int CM_DRP_SECURITY = 0x00000018; // Security - Device override (RW)
71+
int CM_DRP_SECURITY_SDS = 0x00000019; // Security - Device override (RW)
72+
int CM_DRP_DEVTYPE = 0x0000001A; // Device Type - Device override (RW)
73+
int CM_DRP_EXCLUSIVE = 0x0000001B; // Exclusivity - Device override (RW)
74+
int CM_DRP_CHARACTERISTICS = 0x0000001C; // Characteristics - Device Override (RW)
75+
int CM_DRP_ADDRESS = 0x0000001D; // Device Address (R)
76+
int CM_DRP_UI_NUMBER_DESC_FORMAT = 0x0000001E; // UINumberDescFormat REG_SZ property (RW)
77+
int CM_DRP_DEVICE_POWER_DATA = 0x0000001F; // CM_POWER_DATA REG_BINARY property (R)
78+
int CM_DRP_REMOVAL_POLICY = 0x00000020; // CM_DEVICE_REMOVAL_POLICY REG_DWORD (R)
79+
int CM_DRP_REMOVAL_POLICY_HW_DEFAULT = 0x00000021; // CM_DRP_REMOVAL_POLICY_HW_DEFAULT REG_DWORD (R)
80+
int CM_DRP_REMOVAL_POLICY_OVERRIDE = 0x00000022; // CM_DRP_REMOVAL_POLICY_OVERRIDE REG_DWORD (RW)
81+
int CM_DRP_INSTALL_STATE = 0x00000023; // CM_DRP_INSTALL_STATE REG_DWORD (R)
82+
int CM_DRP_LOCATION_PATHS = 0x00000024; // CM_DRP_LOCATION_PATHS REG_MULTI_SZ (R)
83+
int CM_DRP_BASE_CONTAINERID = 0x00000025; // Base ContainerID REG_SZ property (R)
4884

4985
/**
5086
* The CM_Locate_DevNode function obtains a device instance handle to the
@@ -189,4 +225,43 @@ public interface Cfgmgr32 extends Library {
189225
* CM_Get_Device_ID_Size</A>
190226
*/
191227
int CM_Get_Device_ID_Size(IntByReference pulLen, int dnDevInst, int ulFlags);
228+
229+
/**
230+
* The CM_Get_DevNode_Registry_Property function retrieves a specified device
231+
* property from the registry.
232+
*
233+
* @param dnDevInst
234+
* A caller-supplied device instance handle that is bound to the
235+
* local machine.
236+
* @param ulProperty
237+
* A {@code CM_DRP_}-prefixed constant value that identifies the
238+
* device property to be obtained from the registry. These constants
239+
* are defined in Cfgmgr32.h.
240+
* @param pulRegDataType
241+
* Optional, can be {@code null}. A pointer to a location that
242+
* receives the registry data type, specified as a
243+
* {@code REG_}-prefixed constant defined in Winnt.h.
244+
* @param buffer
245+
* Optional, can be {@code null}. A pointer to a caller-supplied
246+
* buffer that receives the requested device property. If this value
247+
* is {@code null}, the function supplies only the length of the
248+
* requested data in the address pointed to by {@code pulLength}.
249+
* @param pulLength
250+
* A pointer to a {@code ULONG} variable into which the function
251+
* stores the length, in bytes, of the requested device property.
252+
* <p>
253+
* If the Buffer parameter is set to {@code null}, the ULONG variable
254+
* must be set to zero.
255+
* <p>
256+
* If the Buffer parameter is not set to {@code null}, the
257+
* {@code ULONG} variable must be set to the length, in bytes, of the
258+
* caller-supplied buffer.
259+
* @param ulFlags
260+
* Not used, must be zero.
261+
* @return If the operation succeeds, the function returns {@code CR_SUCCESS}.
262+
* Otherwise, it returns one of the {@code CR_}-prefixed error codes
263+
* that are defined in Cfgmgr32.h.
264+
*/
265+
int CM_Get_DevNode_Registry_Property(int dnDevInst, int ulProperty, IntByReference pulRegDataType, Pointer buffer,
266+
IntByReference pulLength, int ulFlags);
192267
}

contrib/platform/src/com/sun/jna/platform/win32/Cfgmgr32Util.java

+91-6
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Copyright (c) 2018 Daniel Widdis, All Rights Reserved
1+
/* Copyright (c) 2018, 2021 Daniel Widdis, All Rights Reserved
22
*
33
* The contents of this file is dual-licensed under 2
44
* alternative Open Source/Free licenses: LGPL 2.1 or later and
@@ -26,11 +26,10 @@
2626
import com.sun.jna.Memory;
2727
import com.sun.jna.Native;
2828
import com.sun.jna.ptr.IntByReference;
29+
import com.sun.jna.win32.W32APITypeMapper;
2930

3031
/**
3132
* Cfgmgr32 utility API.
32-
*
33-
* @author widdis[at]gmail[dot]com
3433
*/
3534
public abstract class Cfgmgr32Util {
3635
@SuppressWarnings("serial")
@@ -47,13 +46,13 @@ public int getErrorCode() {
4746
}
4847

4948
/**
50-
* Utility method to call Cfgmgr32's CM_Get_Device_ID that allocates the
49+
* Utility method to call Cfgmgr32's CM_Get_Device_ID_Size, allocates the
5150
* required memory for the Buffer parameter based on the type mapping used,
5251
* calls to CM_Get_Device_ID, and returns the received string.
5352
*
5453
* @param devInst
55-
* Caller-supplied device instance handle that is bound to the
56-
* local machine.
54+
* Caller-supplied device instance handle that is bound to the local
55+
* machine.
5756
* @return The device instance ID string.
5857
* @throws Cfgmgr32Exception
5958
*/
@@ -96,4 +95,90 @@ public static String CM_Get_Device_ID(int devInst) throws Cfgmgr32Exception {
9695
return buffer.getWideString(0);
9796
}
9897
}
98+
99+
/**
100+
* Utility method to call Cfgmgr32's CM_Get_DevNode_Registry_Property that
101+
* allocates the required memory for the Buffer parameter, and returns values of
102+
* the appropriate type.
103+
*
104+
* @param devInst
105+
* Caller-supplied device instance handle that is bound to the local
106+
* machine.
107+
* @param ulProperty
108+
* A {@code CM_DRP_}-prefixed constant value that identifies the
109+
* device property to be obtained from the registry. These constants
110+
* are defined in Cfgmgr32.h.
111+
* @return An {@link Object} containing the specified registry property for the
112+
* device.
113+
* <p>
114+
* If the property is of type {@link WinNT.REG_SZ}, a
115+
* {@link java.lang.String} is returned.
116+
* <p>
117+
* If the property is of type {@link WinNT.REG_MULTI_SZ}, an array of
118+
* {@link java.lang.String} is returned.
119+
* <p>
120+
* If the property is of type {@link WinNT.REG_DWORD}, an
121+
* {@link java.lang.Integer} is returned.
122+
* <p>
123+
* If the property is of type {@link WinNT.REG_BINARY}, an array of
124+
* {@link java.lang.Byte} is returned.
125+
* <p>
126+
* If no value exists for this property, or an error is encountered,
127+
* returns {@code null}.
128+
* @throws Cfgmgr32Exception
129+
*/
130+
public static Object CM_Get_DevNode_Registry_Property(int devInst, int ulProperty) throws Cfgmgr32Exception {
131+
132+
// Get byte count and type
133+
IntByReference size = new IntByReference();
134+
IntByReference type = new IntByReference();
135+
int ret = Cfgmgr32.INSTANCE.CM_Get_DevNode_Registry_Property(devInst, ulProperty, type, null, size, 0);
136+
// If successful in retrieving type and size, should fail with CR_BUFFER_SMALL
137+
// Other errors such as CR_NO_SUCH_VALUE should return null
138+
if (ret != Cfgmgr32.CR_BUFFER_SMALL) {
139+
return null;
140+
}
141+
142+
// It is possible to have a valid value with registry data type, but 0 size.
143+
// Leave the memory buffer null in that case
144+
Memory buffer = null;
145+
if (size.getValue() > 0) {
146+
buffer = new Memory(size.getValue());
147+
ret = Cfgmgr32.INSTANCE.CM_Get_DevNode_Registry_Property(devInst, ulProperty, type, buffer, size, 0);
148+
if (ret != Cfgmgr32.CR_SUCCESS) {
149+
throw new Cfgmgr32Exception(ret);
150+
}
151+
}
152+
153+
// Get the appropriate type of data from the buffer
154+
switch (type.getValue()) {
155+
case WinNT.REG_SZ:
156+
// Convert buffer to Java String
157+
if (buffer == null) {
158+
return "";
159+
}
160+
return W32APITypeMapper.DEFAULT == W32APITypeMapper.UNICODE ? buffer.getWideString(0) : buffer.getString(0);
161+
case WinNT.REG_MULTI_SZ:
162+
// Convert buffer to String Array
163+
if (buffer == null) {
164+
return new String[0];
165+
}
166+
return Advapi32Util.regMultiSzBufferToStringArray(buffer);
167+
case WinNT.REG_DWORD:
168+
// Convert buffer to int
169+
if (buffer == null) {
170+
return 0;
171+
}
172+
return buffer.getInt(0);
173+
case WinNT.REG_NONE:
174+
return null;
175+
default:
176+
// Intended for WinNT.REG_BINARY but safe default for any data
177+
if (buffer == null) {
178+
return new byte[0];
179+
}
180+
// Convert buffer to array of bytes
181+
return buffer.getByteArray(0, (int) buffer.size());
182+
}
183+
}
99184
}

0 commit comments

Comments
 (0)