Skip to content

Added 'SetupDiOpenDevRegKey' and 'SetupDiEnumDeviceInfo' to SetupApi. #419

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

Closed
wants to merge 1 commit into from
Closed
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
2 changes: 2 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ Features
* [#400](https://github.com/twall/jna/pull/400): Added process-specific access rights constants in `com.sun.jna.platform.win32.WinNT` - [@PAX523](https://github.com/PAX523).
* [#400](https://github.com/twall/jna/pull/400): Added specific constants for request of icon settings in `com.sun.jna.platform.win32.WinUser` - [@PAX523](https://github.com/PAX523).
* [#400](https://github.com/twall/jna/pull/400): Added constants for `GetClassLong`, `SendMessageTimeout` and `GetIconInfo` in `com.sun.jna.platform.win32.WinUser` - [@PAX523](https://github.com/PAX523).
* [#419](https://github.com/twall/jna/pull/419): Added `SetupDiOpenDevRegKey` , `SetupDiEnumDeviceInfo` and related constants to `com.sun.jna.platform.win32.SetupApi` - [@ChristianSchwarz](https://github.com/ChristianSchwarz)


Bug Fixes
---------
Expand Down
169 changes: 153 additions & 16 deletions contrib/platform/src/com/sun/jna/platform/win32/SetupApi.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,16 @@
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.Structure;
import com.sun.jna.platform.win32.Guid.GUID;
import com.sun.jna.platform.win32.WinNT.HANDLE;
import com.sun.jna.platform.win32.WinReg.HKEY;
import com.sun.jna.ptr.IntByReference;
import com.sun.jna.win32.StdCallLibrary;
import com.sun.jna.win32.W32APIOptions;

/**
* The interface for the w32 setup API.
* @author Christian Schwarz
*/
public interface SetupApi extends StdCallLibrary {

Expand All @@ -31,49 +35,98 @@ public interface SetupApi extends StdCallLibrary {
/**
* The GUID_DEVINTERFACE_DISK device interface class is defined for hard disk storage devices.
*/
public static Guid.GUID GUID_DEVINTERFACE_DISK = new Guid.GUID(new byte[]
{
0x07, 0x63, (byte) 0xf5, 0x53, (byte) 0xbf, (byte) 0xb6, (byte) 0xd0, 0x11,
(byte) 0x94, (byte) 0xf2, 0x00, (byte) 0xa0, (byte) 0xc9, (byte) 0x1e, (byte) 0xfb, (byte) 0x8b
});

GUID GUID_DEVINTERFACE_DISK = new GUID("53F56307-B6BF-11D0-94F2-00A0C91EFB8B");


/**
* Drivers for serial ports register instances of this device interface
* class to notify the operating system and applications of the presence of
* COM ports.
*/
GUID GUID_DEVINTERFACE_COMPORT = new GUID("86E0D1E0-8089-11D0-9CE4-08003E301F73");

/**
* Return only the device that is associated with the system default device interface, if one is set, for the
* specified device interface classes.
*/
public int DIGCF_DEFAULT = 0x1;
int DIGCF_DEFAULT = 0x1;

/**
* Return only devices that are currently present in a system.
*/
public int DIGCF_PRESENT = 0x2;
int DIGCF_PRESENT = 0x2;

/**
* Return a list of installed devices for all device setup classes or all device interface classes.
*/
public int DIGCF_ALLCLASSES = 0x4;
int DIGCF_ALLCLASSES = 0x4;

/**
* Return only devices that are a part of the current hardware profile.
*/
public int DIGCF_PROFILE = 0x8;
int DIGCF_PROFILE = 0x8;

/**
* Return devices that support device interfaces for the specified device interface classes. This flag must be set
* in the Flags parameter if the Enumerator parameter specifies a device instance ID.
*/
public int DIGCF_DEVICEINTERFACE = 0x10;
int DIGCF_DEVICEINTERFACE = 0x10;

/**
* (Windows XP and later) The function retrieves the device's current removal policy as a DWORD that contains one of
* the CM_REMOVAL_POLICY_Xxx values that are defined in Cfgmgr32.h.
*/
public int SPDRP_REMOVAL_POLICY = 0x0000001F;
int SPDRP_REMOVAL_POLICY = 0x0000001F;

/**
* Removable.
*/
public int CM_DEVCAP_REMOVABLE = 0x00000004;
int CM_DEVCAP_REMOVABLE = 0x00000004;


/** make change in all hardware profiles */
int DICS_FLAG_GLOBAL = 0x00000001;
/** make change in specified profile only */
int DICS_FLAG_CONFIGSPECIFIC = 0x00000002;
/** 1 or more hardware profile-specific changes to follow. */
int DICS_FLAG_CONFIGGENERAL = 0x00000004;

/**
* Open/Create/Delete device key.
*
* @see SetupDiCreateDevRegKey , SetupDiOpenDevRegKey, and
* SetupDiDeleteDevRegKey.
*/

int DIREG_DEV = 0x00000001;
/**
* Open/Create/Delete driver key
*
* @see SetupDiCreateDevRegKey, SetupDiOpenDevRegKey, and
* SetupDiDeleteDevRegKey.
*/

int DIREG_DRV = 0x00000002;
/**
* Delete both driver and Device key
*
* @see SetupDiCreateDevRegKey, SetupDiOpenDevRegKey, and
* SetupDiDeleteDevRegKey.
*/

int DIREG_BOTH = 0x00000004;

/**
* DeviceDesc (R/W)
* <p>
* Device registry property codes (Codes marked as read-only (R) may only be
* used for SetupDiGetDeviceRegistryProperty)
* <p>
* These values should cover the same set of registry properties as defined
* by the CM_DRP codes in cfgmgr32.h.
*/
int SPDRP_DEVICEDESC = 0x00000000;


/**
* The SetupDiGetClassDevs function returns a handle to a device information set that contains requested device
Expand Down Expand Up @@ -236,10 +289,94 @@ boolean SetupDiGetDeviceInterfaceDetail(WinNT.HANDLE hDevInfo,
* ERROR_INVALID_DATA error code if the requested property does not exist for a device or if the property data is
* not valid.
*/
boolean SetupDiGetDeviceRegistryProperty(WinNT.HANDLE DeviceInfoSet, SP_DEVINFO_DATA DeviceInfoData,
boolean SetupDiGetDeviceRegistryProperty(HANDLE DeviceInfoSet, SP_DEVINFO_DATA DeviceInfoData,
int Property, IntByReference PropertyRegDataType, Pointer PropertyBuffer, int PropertyBufferSize,
IntByReference RequiredSize);

/**
* The SetupDiOpenDevRegKey function opens a registry key for device-specific configuration information.
* <p>
* Depending on the value that is passed in the samDesired parameter, it might be necessary for the caller of this
* function to be a member of the Administrators group.
* <p>
* Close the handle returned from this function by calling RegCloseKey.
* <p>
* The specified device instance must be registered before this function is called. However, be aware that the
* operating system automatically registers PnP device instances. For information about how to register non-PnP
* device instances, see SetupDiRegisterDeviceInfo.
*
* @param deviceInfoSet
* A handle to the device information set that contains a device information element that represents the
* device for which to open a registry key.
* @param deviceInfoData
* A pointer to an {@link SP_DEVINFO_DATA} structure that specifies the device information element in
* DeviceInfoSet.
* @param scope
* he scope of the registry key to open. The scope determines where the information is stored. The scope
* can be global or specific to a hardware profile. The scope is specified by one of the following
* values:
* <ul>
* <li>DICS_FLAG_GLOBAL Open a key to store global configuration information. This information is not
* specific to a particular hardware profile. This opens a key that is rooted at HKEY_LOCAL_MACHINE. The
* exact key opened depends on the value of the KeyType parameter. <li>DICS_FLAG_CONFIGSPECIFIC Open a
* key to store hardware profile-specific configuration information. This key is rooted at one of the
* hardware-profile specific branches, instead of HKEY_LOCAL_MACHINE. The exact key opened depends on the
* value of the KeyType parameter.
* </ul>
* @param hwProfile
* A hardware profile value, which is set as follows:
* <ul>
* <li>If Scope is set to DICS_FLAG_CONFIGSPECIFIC, HwProfile specifies the hardware profile of the key
* that is to be opened. <li>If HwProfile is 0, the key for the current hardware profile is opened. <li>
* If Scope is DICS_FLAG_GLOBAL, HwProfile is ignored.
* </ul>
* @param keyType
* The type of registry storage key to open, which can be one of the following values:
* <ul>
* <li> {@link #DIREG_DEV} Open a hardware key for the device. <li>{@link #DIREG_DRV} Open a software key
* for the device. For more information about a device's hardware and software keys, see Registry Trees
* and Keys for Devices and Drivers.
* </ul>
* @param samDesired
* The registry security access that is required for the requested key. For information about registry
* security access values of type REGSAM, see the Microsoft Windows SDK documentation.
* @return If the function is successful, it returns a handle to an opened registry key where private configuration
* data about this device instance can be stored/retrieved.
* <p>
* If the function fails, it returns INVALID_HANDLE_VALUE. To get extended error information, call
* GetLastError.
*/
HKEY SetupDiOpenDevRegKey(HANDLE deviceInfoSet, SP_DEVINFO_DATA deviceInfoData, int scope, int hwProfile, int keyType, int samDesired);

/**
* The SetupDiEnumDeviceInfo function returns a {@link SP_DEVINFO_DATA} structure that specifies a device
* information element in a device information set.
* <p>
* <b>Remarks</b><br>
* Repeated calls to this function return a device information element for a different device. This function can be
* called repeatedly to get information about all devices in the device information set.
* <p>
* To enumerate device information elements, an installer should initially call SetupDiEnumDeviceInfo with the
* MemberIndex parameter set to 0. The installer should then increment MemberIndex and call SetupDiEnumDeviceInfo
* until there are no more values (the function fails and a call to GetLastError returns ERROR_NO_MORE_ITEMS).
* <p>
* Call SetupDiEnumDeviceInterfaces to get a context structure for a device interface element (versus a device
* information element).
*
*
* @param deviceInfoSet
* A handle to the device information set for which to return an {@link SP_DEVINFO_DATA} structure that
* represents a device information element.
* @param memberIndex
* A zero-based index of the device information element to retrieve.
* @param deviceInfoData
* A pointer to an SP_DEVINFO_DATA structure to receive information about an enumerated device
* information element.
* @return The function returns TRUE if it is successful. Otherwise, it returns FALSE and the logged error can be
* retrieved with a call to GetLastError.
*/
boolean SetupDiEnumDeviceInfo(HANDLE deviceInfoSet, int memberIndex, SP_DEVINFO_DATA deviceInfoData);

/**
* An SP_DEVICE_INTERFACE_DATA structure defines a device interface in a device information set.
*/
Expand Down Expand Up @@ -286,7 +423,7 @@ public SP_DEVICE_INTERFACE_DATA(Pointer memory) {
*/
public Pointer Reserved;

protected List getFieldOrder() {
protected List<String> getFieldOrder() {
return Arrays.asList(new String[] { "cbSize", "InterfaceClassGuid", "Flags", "Reserved" });
}
}
Expand Down Expand Up @@ -338,7 +475,7 @@ public SP_DEVINFO_DATA(Pointer memory) {
*/
public Pointer Reserved;

protected List getFieldOrder() {
protected List<String> getFieldOrder() {
return Arrays.asList(new String[] { "cbSize", "InterfaceClassGuid", "DevInst", "Reserved" });
}
}
Expand Down
70 changes: 70 additions & 0 deletions contrib/platform/test/com/sun/jna/platform/win32/SetupApiTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package com.sun.jna.platform.win32;

import static com.sun.jna.Native.getLastError;
import static com.sun.jna.platform.win32.SetupApi.DICS_FLAG_GLOBAL;
import static com.sun.jna.platform.win32.SetupApi.DIGCF_ALLCLASSES;
import static com.sun.jna.platform.win32.SetupApi.DIGCF_DEVICEINTERFACE;
import static com.sun.jna.platform.win32.SetupApi.DIGCF_PRESENT;
import static com.sun.jna.platform.win32.SetupApi.DIREG_DEV;
import static com.sun.jna.platform.win32.SetupApi.GUID_DEVINTERFACE_COMPORT;
import static com.sun.jna.platform.win32.WinBase.INVALID_HANDLE_VALUE;
import static com.sun.jna.platform.win32.WinError.ERROR_NO_MORE_ITEMS;
import static com.sun.jna.platform.win32.WinNT.KEY_QUERY_VALUE;
import junit.framework.TestCase;

import com.sun.jna.platform.win32.SetupApi.SP_DEVINFO_DATA;
import com.sun.jna.platform.win32.WinNT.HANDLE;
import com.sun.jna.platform.win32.WinReg.HKEY;

public class SetupApiTest extends TestCase {
/**
* member index for the first device, see {@link SetupApi#SetupDiEnumDeviceInfo(HANDLE, int, SP_DEVINFO_DATA)}
*/
private static final int FIRST_MEMBER = 0;

public static void main(String[] args) {
junit.textui.TestRunner.run(SetupApiTest.class);
}

/**
* Tests the mapping of {@link SetupApi#SetupDiOpenDevRegKey(HANDLE, SP_DEVINFO_DATA, int, int, int, int)} .
* <p>
* The test pass if SetupDiOpenDevRegKey(..) returns a valid {@link HKEY} pointing to the first found device on the current machine.
* <p>
* NOTE: We only test the mapping of SetupDiOpenDevRegKey(..), not it's functionality.
*/
public void testSetupDiOpenDevRegKey() {
// hDevInfoSet repesents a list of installed devices for all device
// setup classes or all device interface classes
HANDLE hDevInfoSet = SetupApi.INSTANCE.SetupDiGetClassDevs(null, null, null, DIGCF_ALLCLASSES);
assertTrue(hDevInfoSet != INVALID_HANDLE_VALUE);

SP_DEVINFO_DATA devInfo = new SP_DEVINFO_DATA();
// there must be least one device (drive,processor,pci,usb,...) on the
// current machine
assertTrue(SetupApi.INSTANCE.SetupDiEnumDeviceInfo(hDevInfoSet, FIRST_MEMBER, devInfo));

HKEY hDeviceKey = SetupApi.INSTANCE.SetupDiOpenDevRegKey(hDevInfoSet, devInfo, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_QUERY_VALUE);
assertTrue(hDeviceKey != INVALID_HANDLE_VALUE);

Advapi32.INSTANCE.RegCloseKey(hDeviceKey);
}

/**
* Tests the mapping of {@link SetupApi#SetupDiEnumDeviceInfo(HANDLE, int, SP_DEVINFO_DATA)} .
* <p>
* There are 2 different results possible, depending availability of an COM-Port on the current machine:
* <ul>
* <li>If the current machine has no COM-Port the method must fail and the the last error indicate that there are no more values / COM-Ports.
* <li>If the current machine has at least one COM-Port the method must succeed. The test pass if no exception is thrown.
* </ul>
*/
public void testSetupDiEnumDeviceInfo() {
HANDLE hDevInfoSet = SetupApi.INSTANCE.SetupDiGetClassDevs(GUID_DEVINTERFACE_COMPORT, null, null, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
SP_DEVINFO_DATA devInfo = new SP_DEVINFO_DATA();
boolean succeed = SetupApi.INSTANCE.SetupDiEnumDeviceInfo(hDevInfoSet, FIRST_MEMBER, devInfo);
boolean hasNoMoreItems = (getLastError() == ERROR_NO_MORE_ITEMS);

assertTrue(succeed || hasNoMoreItems);
}
}