forked from java-native-access/jna
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add Cfgmgr32 functions for navigating device tree (java-native-access…
- Loading branch information
1 parent
57a9dd0
commit c7419af
Showing
4 changed files
with
382 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
192 changes: 192 additions & 0 deletions
192
contrib/platform/src/com/sun/jna/platform/win32/Cfgmgr32.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,192 @@ | ||
/* Copyright (c) 2018 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 | ||
* Apache License 2.0. (starting with JNA version 4.0.0). | ||
* | ||
* You can freely decide which license you want to apply to | ||
* the project. | ||
* | ||
* You may obtain a copy of the LGPL License at: | ||
* | ||
* http://www.gnu.org/licenses/licenses.html | ||
* | ||
* A copy is also included in the downloadable source code package | ||
* containing JNA, in file "LGPL2.1". | ||
* | ||
* You may obtain a copy of the Apache License at: | ||
* | ||
* http://www.apache.org/licenses/ | ||
* | ||
* A copy is also included in the downloadable source code package | ||
* containing JNA, in file "AL2.0". | ||
*/ | ||
package com.sun.jna.platform.win32; | ||
|
||
import com.sun.jna.Library; | ||
import com.sun.jna.Native; | ||
import com.sun.jna.Pointer; | ||
import com.sun.jna.ptr.IntByReference; | ||
import com.sun.jna.win32.W32APIOptions; | ||
|
||
/** | ||
* Windows Cfgmgr32. | ||
* | ||
* @author widdis[at]gmail[dot]com | ||
*/ | ||
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; | ||
|
||
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; | ||
|
||
/** | ||
* The CM_Locate_DevNode function obtains a device instance handle to the | ||
* device node that is associated with a specified device instance ID on the | ||
* local machine. | ||
* | ||
* @param pdnDevInst | ||
* A pointer to a device instance handle that CM_Locate_DevNode | ||
* retrieves. The retrieved handle is bound to the local machine. | ||
* @param pDeviceID | ||
* A pointer to a NULL-terminated string representing a device | ||
* instance ID. If this value is NULL, or if it points to a | ||
* zero-length string, the function retrieves a device instance | ||
* handle to the device at the root of the device tree. * | ||
* @param ulFlags | ||
* A variable of ULONG type that supplies one of the following | ||
* flag values that apply if the caller supplies a device | ||
* instance identifier: CM_LOCATE_DEVNODE_NORMAL, | ||
* CM_LOCATE_DEVNODE_PHANTOM, CM_LOCATE_DEVNODE_CANCELREMOVE, or | ||
* CM_LOCATE_DEVNODE_NOVALIDATION | ||
* @return If the operation succeeds, CM_Locate_DevNode returns CR_SUCCESS. | ||
* Otherwise, the function returns one of the CR_Xxx error codes | ||
* that are defined in Cfgmgr32.h. | ||
* @see <A HREF= | ||
* "https://docs.microsoft.com/en-us/windows/desktop/api/cfgmgr32/nf-cfgmgr32-cm_locate_devnodea"> | ||
* CM_Locate_DevNode</A> | ||
*/ | ||
int CM_Locate_DevNode(IntByReference pdnDevInst, String pDeviceID, int ulFlags); | ||
|
||
/** | ||
* The CM_Get_Parent function obtains a device instance handle to the parent | ||
* node of a specified device node (devnode) in the local machine's device | ||
* tree. | ||
* | ||
* @param pdnDevInst | ||
* Caller-supplied pointer to the device instance handle to the | ||
* parent node that this function retrieves. The retrieved handle | ||
* is bound to the local machine. | ||
* @param dnDevInst | ||
* Caller-supplied device instance handle that is bound to the | ||
* local machine. | ||
* @param ulFlags | ||
* Not used, must be zero. | ||
* @return If the operation succeeds, the function returns CR_SUCCESS. | ||
* Otherwise, it returns one of the CR_-prefixed error codes defined | ||
* in Cfgmgr32.h. | ||
* @see <A HREF= | ||
* "https://docs.microsoft.com/en-us/windows/desktop/api/cfgmgr32/nf-cfgmgr32-cm_get_parent"> | ||
* CM_Get_Parent</A> | ||
*/ | ||
int CM_Get_Parent(IntByReference pdnDevInst, int dnDevInst, int ulFlags); | ||
|
||
/** | ||
* The CM_Get_Child function is used to retrieve a device instance handle to | ||
* the first child node of a specified device node (devnode) in the local | ||
* machine's device tree. | ||
* | ||
* @param pdnDevInst | ||
* Caller-supplied pointer to the device instance handle to the | ||
* child node that this function retrieves. The retrieved handle | ||
* is bound to the local machine. | ||
* @param dnDevInst | ||
* Caller-supplied device instance handle that is bound to the | ||
* local machine. | ||
* @param ulFlags | ||
* Not used, must be zero. | ||
* @return If the operation succeeds, the function returns CR_SUCCESS. | ||
* Otherwise, it returns one of the CR_-prefixed error codes defined | ||
* in Cfgmgr32.h. | ||
* @see <A HREF= | ||
* "https://docs.microsoft.com/en-us/windows/desktop/api/cfgmgr32/nf-cfgmgr32-cm_get_child"> | ||
* CM_Get_Child</A> | ||
*/ | ||
int CM_Get_Child(IntByReference pdnDevInst, int dnDevInst, int ulFlags); | ||
|
||
/** | ||
* The CM_Get_Sibling function obtains a device instance handle to the next | ||
* sibling node of a specified device node (devnode) in the local machine's | ||
* device tree. | ||
* | ||
* @param pdnDevInst | ||
* Caller-supplied pointer to the device instance handle to the | ||
* sibling node that this function retrieves. The retrieved | ||
* handle is bound to the local machine. | ||
* @param dnDevInst | ||
* Caller-supplied device instance handle that is bound to the | ||
* local machine. | ||
* @param ulFlags | ||
* Not used, must be zero. | ||
* @return If the operation succeeds, the function returns CR_SUCCESS. | ||
* Otherwise, it returns one of the CR_-prefixed error codes defined | ||
* in Cfgmgr32.h. | ||
* @see <A HREF= | ||
* "https://docs.microsoft.com/en-us/windows/desktop/api/cfgmgr32/nf-cfgmgr32-cm_get_sibling"> | ||
* CM_Get_Sibling</A> | ||
*/ | ||
int CM_Get_Sibling(IntByReference pdnDevInst, int dnDevInst, int ulFlags); | ||
|
||
/** | ||
* The CM_Get_Device_ID function retrieves the device instance ID for a | ||
* specified device instance on the local machine. | ||
* | ||
* @param devInst | ||
* Caller-supplied device instance handle that is bound to the | ||
* local machine. | ||
* @param Buffer | ||
* Address of a buffer to receive a device instance ID string. | ||
* The required buffer size can be obtained by calling | ||
* CM_Get_Device_ID_Size, then incrementing the received value to | ||
* allow room for the string's terminating NULL. | ||
* @param BufferLen | ||
* Caller-supplied length, in characters, of the buffer specified | ||
* by Buffer. | ||
* @param ulFlags | ||
* Not used, must be zero. | ||
* @return If the operation succeeds, the function returns CR_SUCCESS. | ||
* Otherwise, it returns one of the CR_-prefixed error codes defined | ||
* in Cfgmgr32.h. | ||
* @see <A HREF= | ||
* "https://docs.microsoft.com/en-us/windows/desktop/api/cfgmgr32/nf-cfgmgr32-cm_get_device_idw"> | ||
* CM_Get_Device_ID</A> | ||
*/ | ||
int CM_Get_Device_ID(int devInst, Pointer Buffer, int BufferLen, int ulFlags); | ||
|
||
/** | ||
* The CM_Get_Device_ID_Size function retrieves the buffer size required to | ||
* hold a device instance ID for a device instance on the local machine. | ||
* | ||
* @param pulLen | ||
* Receives a value representing the required buffer size, in | ||
* characters. | ||
* @param dnDevInst | ||
* Caller-supplied device instance handle that is bound to the | ||
* local machine. | ||
* @param ulFlags | ||
* Not used, must be zero. | ||
* @return If the operation succeeds, the function returns CR_SUCCESS. | ||
* Otherwise, it returns one of the CR_-prefixed error codes defined | ||
* in Cfgmgr32.h. | ||
* @see <A HREF= | ||
* "https://docs.microsoft.com/en-us/windows/desktop/api/cfgmgr32/nf-cfgmgr32-cm_get_device_id_size"> | ||
* CM_Get_Device_ID_Size</A> | ||
*/ | ||
int CM_Get_Device_ID_Size(IntByReference pulLen, int dnDevInst, int ulFlags); | ||
} |
99 changes: 99 additions & 0 deletions
99
contrib/platform/src/com/sun/jna/platform/win32/Cfgmgr32Util.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
/* Copyright (c) 2018 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 | ||
* Apache License 2.0. (starting with JNA version 4.0.0). | ||
* | ||
* You can freely decide which license you want to apply to | ||
* the project. | ||
* | ||
* You may obtain a copy of the LGPL License at: | ||
* | ||
* http://www.gnu.org/licenses/licenses.html | ||
* | ||
* A copy is also included in the downloadable source code package | ||
* containing JNA, in file "LGPL2.1". | ||
* | ||
* You may obtain a copy of the Apache License at: | ||
* | ||
* http://www.apache.org/licenses/ | ||
* | ||
* A copy is also included in the downloadable source code package | ||
* containing JNA, in file "AL2.0". | ||
*/ | ||
package com.sun.jna.platform.win32; | ||
|
||
import com.sun.jna.Memory; | ||
import com.sun.jna.Native; | ||
import com.sun.jna.ptr.IntByReference; | ||
|
||
/** | ||
* Cfgmgr32 utility API. | ||
* | ||
* @author widdis[at]gmail[dot]com | ||
*/ | ||
public abstract class Cfgmgr32Util { | ||
@SuppressWarnings("serial") | ||
public static class Cfgmgr32Exception extends RuntimeException { | ||
private final int errorCode; | ||
|
||
public Cfgmgr32Exception(int errorCode) { | ||
this.errorCode = errorCode; | ||
} | ||
|
||
public int getErrorCode() { | ||
return errorCode; | ||
} | ||
} | ||
|
||
/** | ||
* Utility method to call Cfgmgr32's CM_Get_Device_ID that 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. | ||
* @return The device instance ID string. | ||
* @throws Cfgmgr32Exception | ||
*/ | ||
public static String CM_Get_Device_ID(int devInst) throws Cfgmgr32Exception { | ||
int charToBytes = Boolean.getBoolean("w32.ascii") ? 1 : Native.WCHAR_SIZE; | ||
|
||
// Get Device ID character count | ||
IntByReference pulLen = new IntByReference(); | ||
int ret = Cfgmgr32.INSTANCE.CM_Get_Device_ID_Size(pulLen, devInst, 0); | ||
if (ret != Cfgmgr32.CR_SUCCESS) { | ||
throw new Cfgmgr32Exception(ret); | ||
} | ||
|
||
// Add one to length to allow null terminator | ||
Memory buffer = new Memory((pulLen.getValue() + 1) * charToBytes); | ||
// Zero the buffer (including the extra character) | ||
buffer.clear(); | ||
// Fetch the buffer specifying only the current length | ||
ret = Cfgmgr32.INSTANCE.CM_Get_Device_ID(devInst, buffer, pulLen.getValue(), 0); | ||
// In the unlikely event the device id changes this might not be big | ||
// enough, try again. This happens rarely enough one retry should be | ||
// sufficient. | ||
if (ret == Cfgmgr32.CR_BUFFER_SMALL) { | ||
ret = Cfgmgr32.INSTANCE.CM_Get_Device_ID_Size(pulLen, devInst, 0); | ||
if (ret != Cfgmgr32.CR_SUCCESS) { | ||
throw new Cfgmgr32Exception(ret); | ||
} | ||
buffer = new Memory((pulLen.getValue() + 1) * charToBytes); | ||
buffer.clear(); | ||
ret = Cfgmgr32.INSTANCE.CM_Get_Device_ID(devInst, buffer, pulLen.getValue(), 0); | ||
} | ||
// If we still aren't successful throw an exception | ||
if (ret != Cfgmgr32.CR_SUCCESS) { | ||
throw new Cfgmgr32Exception(ret); | ||
} | ||
// Convert buffer to Java String | ||
if (charToBytes == 1) { | ||
return buffer.getString(0); | ||
} else { | ||
return buffer.getWideString(0); | ||
} | ||
} | ||
} |
90 changes: 90 additions & 0 deletions
90
contrib/platform/test/com/sun/jna/platform/win32/Cfgmgr32Test.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
/* Copyright (c) 2018 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 | ||
* Apache License 2.0. (starting with JNA version 4.0.0). | ||
* | ||
* You can freely decide which license you want to apply to | ||
* the project. | ||
* | ||
* You may obtain a copy of the LGPL License at: | ||
* | ||
* http://www.gnu.org/licenses/licenses.html | ||
* | ||
* A copy is also included in the downloadable source code package | ||
* containing JNA, in file "LGPL2.1". | ||
* | ||
* You may obtain a copy of the Apache License at: | ||
* | ||
* http://www.apache.org/licenses/ | ||
* | ||
* A copy is also included in the downloadable source code package | ||
* containing JNA, in file "AL2.0". | ||
*/ | ||
package com.sun.jna.platform.win32; | ||
|
||
import static org.junit.Assert.assertEquals; | ||
import static org.junit.Assert.assertTrue; | ||
|
||
import java.io.UnsupportedEncodingException; | ||
|
||
import org.junit.Test; | ||
|
||
import com.sun.jna.ptr.IntByReference; | ||
|
||
/** | ||
* Tests methods in Cfgmgr32 | ||
* | ||
* @author widdis[at]gmail[dot]com | ||
*/ | ||
public class Cfgmgr32Test { | ||
/** | ||
* Tests CM_Locate_DevNode, CM_Get_Parent, CM_Get_Child, CM_Get_Sibling | ||
*/ | ||
@Test | ||
public void testDevNode() { | ||
// Fetch the root node | ||
IntByReference outputNode = new IntByReference(); | ||
assertEquals(Cfgmgr32.CR_SUCCESS, | ||
Cfgmgr32.INSTANCE.CM_Locate_DevNode(outputNode, null, Cfgmgr32.CM_LOCATE_DEVNODE_NORMAL)); | ||
// Get first child | ||
int rootNode = outputNode.getValue(); | ||
int inputNode = rootNode; | ||
assertEquals(Cfgmgr32.CR_SUCCESS, Cfgmgr32.INSTANCE.CM_Get_Child(outputNode, inputNode, 0)); | ||
// Iterate this child and its siblings | ||
do { | ||
inputNode = outputNode.getValue(); | ||
// Get parent, confirm it matches root | ||
assertEquals(Cfgmgr32.CR_SUCCESS, Cfgmgr32.INSTANCE.CM_Get_Parent(outputNode, inputNode, 0)); | ||
assertEquals(rootNode, outputNode.getValue()); | ||
} while (Cfgmgr32.CR_SUCCESS == Cfgmgr32.INSTANCE.CM_Get_Sibling(outputNode, inputNode, 0)); | ||
} | ||
|
||
/** | ||
* Tests CM_Locate_DevNode, CM_Get_Device_ID_Size, CM_Get_Device_ID | ||
* | ||
* @throws UnsupportedEncodingException | ||
*/ | ||
@Test | ||
public void testDeviceID() { | ||
// Fetch the root node | ||
IntByReference outputNode = new IntByReference(); | ||
assertEquals(Cfgmgr32.CR_SUCCESS, | ||
Cfgmgr32.INSTANCE.CM_Locate_DevNode(outputNode, null, Cfgmgr32.CM_LOCATE_DEVNODE_NORMAL)); | ||
int rootNode = outputNode.getValue(); | ||
|
||
// Get Device ID character count | ||
IntByReference pulLen = new IntByReference(); | ||
Cfgmgr32.INSTANCE.CM_Get_Device_ID_Size(pulLen, rootNode, 0); | ||
assertTrue(pulLen.getValue() > 0); | ||
|
||
// Get Device ID from util | ||
String deviceId = Cfgmgr32Util.CM_Get_Device_ID(rootNode); | ||
assertEquals(pulLen.getValue(), deviceId.length()); | ||
|
||
// Look up node from device ID | ||
assertEquals(Cfgmgr32.CR_SUCCESS, | ||
Cfgmgr32.INSTANCE.CM_Locate_DevNode(outputNode, deviceId, Cfgmgr32.CM_LOCATE_DEVNODE_NORMAL)); | ||
assertEquals(rootNode, outputNode.getValue()); | ||
} | ||
} |