Skip to content

Commit c1f8cc2

Browse files
widdisddbwiddis
widdisd
authored andcommitted
Add Cfgmgr32 functions for navigating device tree
1 parent 2287b92 commit c1f8cc2

File tree

4 files changed

+348
-0
lines changed

4 files changed

+348
-0
lines changed

CHANGES.md

+1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ Features
2323
* [#980](https://github.com/java-native-access/jna/issues/980): Added `PERF_OBJECT_TYPE`, `PERF_COUNTER_BLOCK`, and `PERF_COUNTER_DEFINITION` to `c.s.j.platform.win32.WinPerf` and added `Pointer` constructors to ``PERF_INSTANCE_DEFINITION` and `PERF_DATA_BLOCK` - [@dbwiddis](https://github.com/dbwiddis).
2424
* [#981](https://github.com/java-native-access/jna/issues/981): Added `WTS_PROCESS_INFO_EX`, `WTSEnumerateProcessesEx`, and `WTSFreeMemoryEx` to `c.s.j.platform.win32.Wtsapi32` - [@dbwiddis](https://github.com/dbwiddis).
2525
* [#983](https://github.com/java-native-access/jna/issues/983): Added `GetIfEntry`, `GetIfEntry2`, and `GetNetworkParams` and supporting structures `MIB_IFROW`, `MIB_IF_ROW2`, and `FIXED_INFO` to `c.s.j.platform.win32.IPHlpAPI.java` - [@dbwiddis](https://github.com/dbwiddis).
26+
* [#984](https://github.com/java-native-access/jna/issues/984): Added `CM_Locate_DevNode`, `CM_Get_Parent`, `CM_Get_Child`, `CM_Get_Sibling`, `CM_Get_Device_ID`, and `CM_Get_Device_ID_Size` to `c.s.j.platform.win32.Cfgmgr32.java` and a `c.s.j.platform.win32.Cfgmgr32Util` class for `CM_Get_Device_ID` - [@dbwiddis](https://github.com/dbwiddis).
2627

2728
Bug Fixes
2829
---------
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
1+
/* Copyright (c) 2018 Daniel Widdis, All Rights Reserved
2+
*
3+
* The contents of this file is dual-licensed under 2
4+
* alternative Open Source/Free licenses: LGPL 2.1 or later and
5+
* Apache License 2.0. (starting with JNA version 4.0.0).
6+
*
7+
* You can freely decide which license you want to apply to
8+
* the project.
9+
*
10+
* You may obtain a copy of the LGPL License at:
11+
*
12+
* http://www.gnu.org/licenses/licenses.html
13+
*
14+
* A copy is also included in the downloadable source code package
15+
* containing JNA, in file "LGPL2.1".
16+
*
17+
* You may obtain a copy of the Apache License at:
18+
*
19+
* http://www.apache.org/licenses/
20+
*
21+
* A copy is also included in the downloadable source code package
22+
* containing JNA, in file "AL2.0".
23+
*/
24+
package com.sun.jna.platform.win32;
25+
26+
import com.sun.jna.Library;
27+
import com.sun.jna.Native;
28+
import com.sun.jna.Pointer;
29+
import com.sun.jna.ptr.IntByReference;
30+
import com.sun.jna.win32.W32APIOptions;
31+
32+
/**
33+
* Windows Cfgmgr32.
34+
*
35+
* @author widdis[at]gmail[dot]com
36+
*/
37+
public interface Cfgmgr32 extends Library {
38+
Cfgmgr32 INSTANCE = Native.load("Cfgmgr32", Cfgmgr32.class, W32APIOptions.DEFAULT_OPTIONS);
39+
40+
public final static int CR_SUCCESS = 0;
41+
42+
public final static int CM_LOCATE_DEVNODE_NORMAL = 0;
43+
public final static int CM_LOCATE_DEVNODE_PHANTOM = 1;
44+
public final static int CM_LOCATE_DEVNODE_CANCELREMOVE = 2;
45+
public final static int CM_LOCATE_DEVNODE_NOVALIDATION = 4;
46+
public final static int CM_LOCATE_DEVNODE_BITS = 7;
47+
48+
/**
49+
* The CM_Locate_DevNode function obtains a device instance handle to the
50+
* device node that is associated with a specified device instance ID on the
51+
* local machine.
52+
*
53+
* @param pdnDevInst
54+
* A pointer to a device instance handle that CM_Locate_DevNode
55+
* retrieves. The retrieved handle is bound to the local machine.
56+
* @param pDeviceID
57+
* A pointer to a NULL-terminated string representing a device
58+
* instance ID. If this value is NULL, or if it points to a
59+
* zero-length string, the function retrieves a device instance
60+
* handle to the device at the root of the device tree. *
61+
* @param ulFlags
62+
* A variable of ULONG type that supplies one of the following
63+
* flag values that apply if the caller supplies a device
64+
* instance identifier: CM_LOCATE_DEVNODE_NORMAL,
65+
* CM_LOCATE_DEVNODE_PHANTOM, CM_LOCATE_DEVNODE_CANCELREMOVE, or
66+
* CM_LOCATE_DEVNODE_NOVALIDATION
67+
* @return If the operation succeeds, CM_Locate_DevNode returns CR_SUCCESS.
68+
* Otherwise, the function returns one of the CR_Xxx error codes
69+
* that are defined in Cfgmgr32.h.
70+
* @see <A HREF=
71+
* "https://docs.microsoft.com/en-us/windows/desktop/api/cfgmgr32/nf-cfgmgr32-cm_locate_devnodea">
72+
* CM_Locate_DevNode</A>
73+
*/
74+
int CM_Locate_DevNode(IntByReference pdnDevInst, String pDeviceID, int ulFlags);
75+
76+
/**
77+
* The CM_Get_Parent function obtains a device instance handle to the parent
78+
* node of a specified device node (devnode) in the local machine's device
79+
* tree.
80+
*
81+
* @param pdnDevInst
82+
* Caller-supplied pointer to the device instance handle to the
83+
* parent node that this function retrieves. The retrieved handle
84+
* is bound to the local machine.
85+
* @param dnDevInst
86+
* Caller-supplied device instance handle that is bound to the
87+
* local machine.
88+
* @param ulFlags
89+
* Not used, must be zero.
90+
* @return If the operation succeeds, the function returns CR_SUCCESS.
91+
* Otherwise, it returns one of the CR_-prefixed error codes defined
92+
* in Cfgmgr32.h.
93+
* @see <A HREF=
94+
* "https://docs.microsoft.com/en-us/windows/desktop/api/cfgmgr32/nf-cfgmgr32-cm_get_parent">
95+
* CM_Get_Parent</A>
96+
*/
97+
int CM_Get_Parent(IntByReference pdnDevInst, int dnDevInst, int ulFlags);
98+
99+
/**
100+
* The CM_Get_Child function is used to retrieve a device instance handle to
101+
* the first child node of a specified device node (devnode) in the local
102+
* machine's device tree.
103+
*
104+
* @param pdnDevInst
105+
* Caller-supplied pointer to the device instance handle to the
106+
* child node that this function retrieves. The retrieved handle
107+
* is bound to the local machine.
108+
* @param dnDevInst
109+
* Caller-supplied device instance handle that is bound to the
110+
* local machine.
111+
* @param ulFlags
112+
* Not used, must be zero.
113+
* @return If the operation succeeds, the function returns CR_SUCCESS.
114+
* Otherwise, it returns one of the CR_-prefixed error codes defined
115+
* in Cfgmgr32.h.
116+
* @see <A HREF=
117+
* "https://docs.microsoft.com/en-us/windows/desktop/api/cfgmgr32/nf-cfgmgr32-cm_get_child">
118+
* CM_Get_Child</A>
119+
*/
120+
int CM_Get_Child(IntByReference pdnDevInst, int dnDevInst, int ulFlags);
121+
122+
/**
123+
* The CM_Get_Sibling function obtains a device instance handle to the next
124+
* sibling node of a specified device node (devnode) in the local machine's
125+
* device tree.
126+
*
127+
* @param pdnDevInst
128+
* Caller-supplied pointer to the device instance handle to the
129+
* sibling node that this function retrieves. The retrieved
130+
* handle is bound to the local machine.
131+
* @param dnDevInst
132+
* Caller-supplied device instance handle that is bound to the
133+
* local machine.
134+
* @param ulFlags
135+
* Not used, must be zero.
136+
* @return If the operation succeeds, the function returns CR_SUCCESS.
137+
* Otherwise, it returns one of the CR_-prefixed error codes defined
138+
* in Cfgmgr32.h.
139+
* @see <A HREF=
140+
* "https://docs.microsoft.com/en-us/windows/desktop/api/cfgmgr32/nf-cfgmgr32-cm_get_sibling">
141+
* CM_Get_Sibling</A>
142+
*/
143+
int CM_Get_Sibling(IntByReference pdnDevInst, int dnDevInst, int ulFlags);
144+
145+
/**
146+
* The CM_Get_Device_ID function retrieves the device instance ID for a
147+
* specified device instance on the local machine.
148+
*
149+
* @param devInst
150+
* Caller-supplied device instance handle that is bound to the
151+
* local machine.
152+
* @param Buffer
153+
* Address of a buffer to receive a device instance ID string.
154+
* The required buffer size can be obtained by calling
155+
* CM_Get_Device_ID_Size, then incrementing the received value to
156+
* allow room for the string's terminating NULL.
157+
* @param BufferLen
158+
* Caller-supplied length, in characters, of the buffer specified
159+
* by Buffer.
160+
* @param ulFlags
161+
* Not used, must be zero.
162+
* @return If the operation succeeds, the function returns CR_SUCCESS.
163+
* Otherwise, it returns one of the CR_-prefixed error codes defined
164+
* in Cfgmgr32.h.
165+
* @see <A HREF=
166+
* "https://docs.microsoft.com/en-us/windows/desktop/api/cfgmgr32/nf-cfgmgr32-cm_get_device_idw">
167+
* CM_Get_Device_ID</A>
168+
*/
169+
int CM_Get_Device_ID(int devInst, Pointer Buffer, int BufferLen, int ulFlags);
170+
171+
/**
172+
* The CM_Get_Device_ID_Size function retrieves the buffer size required to
173+
* hold a device instance ID for a device instance on the local machine.
174+
*
175+
* @param pulLen
176+
* Receives a value representing the required buffer size, in
177+
* characters.
178+
* @param dnDevInst
179+
* Caller-supplied device instance handle that is bound to the
180+
* local machine.
181+
* @param ulFlags
182+
* Not used, must be zero.
183+
* @return If the operation succeeds, the function returns CR_SUCCESS.
184+
* Otherwise, it returns one of the CR_-prefixed error codes defined
185+
* in Cfgmgr32.h.
186+
* @see <A HREF=
187+
* "https://docs.microsoft.com/en-us/windows/desktop/api/cfgmgr32/nf-cfgmgr32-cm_get_device_id_size">
188+
* CM_Get_Device_ID_Size</A>
189+
*/
190+
int CM_Get_Device_ID_Size(IntByReference pulLen, int dnDevInst, int ulFlags);
191+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/* Copyright (c) 2018 Daniel Widdis, All Rights Reserved
2+
*
3+
* The contents of this file is dual-licensed under 2
4+
* alternative Open Source/Free licenses: LGPL 2.1 or later and
5+
* Apache License 2.0. (starting with JNA version 4.0.0).
6+
*
7+
* You can freely decide which license you want to apply to
8+
* the project.
9+
*
10+
* You may obtain a copy of the LGPL License at:
11+
*
12+
* http://www.gnu.org/licenses/licenses.html
13+
*
14+
* A copy is also included in the downloadable source code package
15+
* containing JNA, in file "LGPL2.1".
16+
*
17+
* You may obtain a copy of the Apache License at:
18+
*
19+
* http://www.apache.org/licenses/
20+
*
21+
* A copy is also included in the downloadable source code package
22+
* containing JNA, in file "AL2.0".
23+
*/
24+
package com.sun.jna.platform.win32;
25+
26+
import com.sun.jna.Memory;
27+
import com.sun.jna.Native;
28+
import com.sun.jna.ptr.IntByReference;
29+
30+
/**
31+
* Cfgmgr32 utility API.
32+
*
33+
* @author widdis[at]gmail[dot]com
34+
*/
35+
public abstract class Cfgmgr32Util {
36+
37+
/**
38+
* Utility method to call Cfgmgr32's CM_Get_Device_ID that allocates the
39+
* required memory for the Buffer parameter based on the type mapping used,
40+
* calls to CM_Get_Device_ID, and returns the received string.
41+
*
42+
* @param devInst
43+
* Caller-supplied device instance handle that is bound to the
44+
* local machine.
45+
* @return The device instance ID string.
46+
*/
47+
public static String CM_Get_Device_ID(int devInst) {
48+
int charToBytes = Boolean.getBoolean("w32.ascii") ? 1 : Native.WCHAR_SIZE;
49+
50+
// Get Device ID character count
51+
IntByReference pulLen = new IntByReference();
52+
Cfgmgr32.INSTANCE.CM_Get_Device_ID_Size(pulLen, devInst, 0);
53+
54+
// Allocate buffer including null terminator
55+
int deviceIdLength = pulLen.getValue() + 1;
56+
Memory buffer = new Memory(deviceIdLength * charToBytes);
57+
58+
// Fetch the buffer
59+
Cfgmgr32.INSTANCE.CM_Get_Device_ID(devInst, buffer, deviceIdLength, 0);
60+
61+
// Convert buffer to Java String
62+
if (charToBytes == 1) {
63+
return buffer.getString(0);
64+
} else {
65+
return buffer.getWideString(0);
66+
}
67+
}
68+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
/* Copyright (c) 2018 Daniel Widdis, All Rights Reserved
2+
*
3+
* The contents of this file is dual-licensed under 2
4+
* alternative Open Source/Free licenses: LGPL 2.1 or later and
5+
* Apache License 2.0. (starting with JNA version 4.0.0).
6+
*
7+
* You can freely decide which license you want to apply to
8+
* the project.
9+
*
10+
* You may obtain a copy of the LGPL License at:
11+
*
12+
* http://www.gnu.org/licenses/licenses.html
13+
*
14+
* A copy is also included in the downloadable source code package
15+
* containing JNA, in file "LGPL2.1".
16+
*
17+
* You may obtain a copy of the Apache License at:
18+
*
19+
* http://www.apache.org/licenses/
20+
*
21+
* A copy is also included in the downloadable source code package
22+
* containing JNA, in file "AL2.0".
23+
*/
24+
package com.sun.jna.platform.win32;
25+
26+
import static org.junit.Assert.assertEquals;
27+
import static org.junit.Assert.assertTrue;
28+
29+
import org.junit.Test;
30+
31+
import com.sun.jna.ptr.IntByReference;
32+
33+
import oshi.jna.platform.windows.Cfgmgr32;
34+
35+
/**
36+
* Tests methods in Cfgmgr32
37+
*
38+
* @author widdis[at]gmail[dot]com
39+
*/
40+
public class Cfgmgr32Test {
41+
/**
42+
* Tests CM_Locate_DevNode, CM_Get_Parent, CM_Get_Child, CM_Get_Sibling
43+
*/
44+
@Test
45+
public void testDevNode() {
46+
// Fetch the root node
47+
IntByReference outputNode = new IntByReference();
48+
assertEquals(Cfgmgr32.CR_SUCCESS,
49+
Cfgmgr32.INSTANCE.CM_Locate_DevNode(outputNode, null, Cfgmgr32.CM_LOCATE_DEVNODE_NORMAL));
50+
// Get first child
51+
int rootNode = outputNode.getValue();
52+
int inputNode = rootNode;
53+
assertEquals(Cfgmgr32.CR_SUCCESS, Cfgmgr32.INSTANCE.CM_Get_Child(outputNode, inputNode, 0));
54+
// Iterate this child and its siblings
55+
do {
56+
inputNode = outputNode.getValue();
57+
// Get parent, confirm it matches root
58+
assertEquals(Cfgmgr32.CR_SUCCESS, Cfgmgr32.INSTANCE.CM_Get_Parent(outputNode, inputNode, 0));
59+
assertEquals(rootNode, outputNode.getValue());
60+
} while (Cfgmgr32.CR_SUCCESS == Cfgmgr32.INSTANCE.CM_Get_Sibling(outputNode, inputNode, 0));
61+
}
62+
63+
/**
64+
* Tests CM_Locate_DevNode, CM_Get_Device_ID_Size, CM_Get_Device_ID
65+
*/
66+
@Test
67+
public void testDeviceID() {
68+
// Fetch the root node
69+
IntByReference outputNode = new IntByReference();
70+
assertEquals(Cfgmgr32.CR_SUCCESS,
71+
Cfgmgr32.INSTANCE.CM_Locate_DevNode(outputNode, null, Cfgmgr32.CM_LOCATE_DEVNODE_NORMAL));
72+
int rootNode = outputNode.getValue();
73+
74+
// Get Device ID character count
75+
IntByReference pulLen = new IntByReference();
76+
Cfgmgr32.INSTANCE.CM_Get_Device_ID_Size(pulLen, rootNode, 0);
77+
assertTrue(pulLen.getValue() > 0);
78+
79+
// Get Device ID from util
80+
String deviceId = Cfgmgr32Util.CM_Get_Device_ID(rootNode);
81+
assertEquals(pulLen.getValue(), deviceId.length());
82+
83+
// Look up node from device ID
84+
assertEquals(Cfgmgr32.CR_SUCCESS,
85+
Cfgmgr32.INSTANCE.CM_Locate_DevNode(outputNode, deviceId, Cfgmgr32.CM_LOCATE_DEVNODE_NORMAL));
86+
assertEquals(rootNode, outputNode.getValue());
87+
}
88+
}

0 commit comments

Comments
 (0)