Skip to content

Commit

Permalink
Use a RegistryProperty return class
Browse files Browse the repository at this point in the history
  • Loading branch information
dbwiddis committed Apr 18, 2021
1 parent 3dba590 commit 5ac24f4
Show file tree
Hide file tree
Showing 4 changed files with 304 additions and 33 deletions.
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.
*/
public static String[] regMultiSzBufferToStringArray(Memory data) {
ArrayList<String> result = new ArrayList<String>();
int offset = 0;
while (offset < data.size()) {
Expand Down
19 changes: 19 additions & 0 deletions contrib/platform/src/com/sun/jna/platform/win32/Cfgmgr32.java
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,25 @@ public interface Cfgmgr32 extends Library {
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
153 changes: 134 additions & 19 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 @@ -48,7 +47,7 @@ public int getErrorCode() {

/**
* 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, and
* 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
Expand Down Expand Up @@ -99,8 +98,8 @@ public static String CM_Get_Device_ID(int devInst) throws Cfgmgr32Exception {

/**
* Utility method to call Cfgmgr32's CM_Get_DevNode_Registry_Property that
* allocates the required memory for the Buffer parameter, and and returns the
* received string.
* allocates the required memory for the Buffer parameter, and provides getters
* to retrieve values of the appropriate type.
*
* @param devInst
* Caller-supplied device instance handle that is bound to the local
Expand All @@ -109,31 +108,147 @@ public static String CM_Get_Device_ID(int devInst) throws Cfgmgr32Exception {
* 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 The device instance ID string.
* @return A {@link RegistryProperty} object encapsulating information about the
* specified registry property for the device. If no value exists for
* this property, returns null
* @throws Cfgmgr32Exception
*/
public static String CM_Get_DevNode_Registry_Property(int devInst, int ulProperty) throws Cfgmgr32Exception {
int charToBytes = Boolean.getBoolean("w32.ascii") ? 1 : Native.WCHAR_SIZE;
public static RegistryProperty CM_Get_DevNode_Registry_Property(int devInst, int ulProperty)
throws Cfgmgr32Exception {

// Get byte count
// Get byte count and type
IntByReference size = new IntByReference();
int ret = Cfgmgr32.INSTANCE.CM_Get_DevNode_Registry_Property(devInst, ulProperty, null, null, size, 0);
IntByReference type = new IntByReference();
int ret = Cfgmgr32.INSTANCE.CM_Get_DevNode_Registry_Property(devInst, ulProperty, type, null, size, 0);
// This should fail with CR_BUFFER_SMALL
// Other errors such as CR_NO_SUCH_VALUE should return null
if (ret != Cfgmgr32.CR_BUFFER_SMALL) {
throw new Cfgmgr32Exception(ret);
return null;
}
// It is possible to have a valid value with type but 0 size
if (size.getValue() == 0) {
return new RegistryProperty(null, type.getValue());
}

Memory buffer = new Memory(size.getValue());

ret = Cfgmgr32.INSTANCE.CM_Get_DevNode_Registry_Property(devInst, ulProperty, null, buffer, size, 0);
ret = Cfgmgr32.INSTANCE.CM_Get_DevNode_Registry_Property(devInst, ulProperty, type, buffer, size, 0);
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);
return new RegistryProperty(buffer, type.getValue());
}

/**
* A class encapsulating the buffer returned from
* {@link Cfgmgr32#CM_Get_DevNode_Registry_Property()} with type safe getters
* for convenience.
*/
public static class RegistryProperty {

private final Memory buffer;
private final int dataType;

private RegistryProperty(Memory buffer, int type) {
this.buffer = buffer;
this.dataType = type;
}

/**
* Returns the value of the property as a String, for registry data type
* {@link WinNT.REG_SZ}
*
* @return The value as a string.
*/
public String stringValue() {
// Check if valid type to convert
if (dataType != WinNT.REG_SZ) {
throw new ClassCastException("Property data type " + dataType + " is not REG_SZ");
}
if (buffer == null) {
return "";
}
// Convert buffer to Java String
return W32APITypeMapper.DEFAULT == W32APITypeMapper.UNICODE ? buffer.getWideString(0) : buffer.getString(0);
}

/**
* Returns the value of the property as an array of Strings, for registry data
* type {@link WinNT.REG_MULTI_SZ}
*
* @return The value as a string array
*/
public String[] stringArrayValue() {
// Check if valid type to convert
if (dataType != WinNT.REG_MULTI_SZ) {
throw new ClassCastException("Property data type " + dataType + " is not REG_MULTI_SZ");
}
if (buffer == null) {
return new String[0];
}
// Convert buffer to String Array
return Advapi32Util.regMultiSzBufferToStringArray(buffer);
}

/**
* Returns the value of the property as a 32-bit integer, for registry data type
* {@link WinNT.REG_DWORD}
*
* @return The value as an int.
*/
public int intValue() {
// Check if valid type to convert
if (dataType != WinNT.REG_DWORD) {
throw new ClassCastException("Property data type " + dataType + " is not REG_DWORD");
}
if (buffer == null) {
return 0;
}
// Convert buffer to int
return buffer.getInt(0);
}

/**
* Returns the value of the property as a byte array, for registry data type
* {@link WinNT.REG_BINARY}. No type checking is performed.
*
* @return The value as a byte array.
*/
public byte[] binaryValue() {
// No type checking is required for a fixed size byte array
if (buffer == null) {
return new byte[0];
}
return buffer.getByteArray(0, (int) buffer.size());
}

/**
* Returns the value of the property as an Object, depending on its data type.
*
* @return The value as an object. If the data type is {@link WinNT.REG_NONE},
* returns {@code null}.
*/
public Object getValue() {
if (dataType == WinNT.REG_SZ) {
return stringValue();
} else if (dataType == WinNT.REG_MULTI_SZ) {
return stringArrayValue();
} else if (dataType == WinNT.REG_DWORD) {
return intValue();
} else if (dataType == WinNT.REG_NONE) {
return null;
} else {
return binaryValue();
}
}

/**
* Returns the registry data type, one of the {@code REG_}-prefixed constants in
* {@link WinNT}.
*
* @return the data type
*/
public int getDataType() {
return dataType;
}
}
}
Loading

0 comments on commit 5ac24f4

Please sign in to comment.