Skip to content

Commit 46b27fa

Browse files
committed
Better way to handle no null
1 parent 1e9cb70 commit 46b27fa

File tree

1 file changed

+34
-22
lines changed

1 file changed

+34
-22
lines changed

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

+34-22
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
*/
2424
package com.sun.jna.platform.win32;
2525

26+
import java.io.UnsupportedEncodingException;
27+
2628
import com.sun.jna.Memory;
2729
import com.sun.jna.Native;
2830
import com.sun.jna.ptr.IntByReference;
@@ -33,6 +35,17 @@
3335
* @author widdis[at]gmail[dot]com
3436
*/
3537
public abstract class Cfgmgr32Util {
38+
public static class Cfgmgr32Exception extends RuntimeException {
39+
private final int errorCode;
40+
41+
public Cfgmgr32Exception(int errorCode) {
42+
this.errorCode = errorCode;
43+
}
44+
45+
public int getErrorCode() {
46+
return errorCode;
47+
}
48+
}
3649

3750
/**
3851
* Utility method to call Cfgmgr32's CM_Get_Device_ID that allocates the
@@ -43,41 +56,40 @@ public abstract class Cfgmgr32Util {
4356
* Caller-supplied device instance handle that is bound to the
4457
* local machine.
4558
* @return The device instance ID string.
59+
* @throws UnsupportedEncodingException
4660
*/
47-
public static String CM_Get_Device_ID(int devInst) {
61+
public static String CM_Get_Device_ID(int devInst) throws UnsupportedEncodingException {
4862
int charToBytes = Boolean.getBoolean("w32.ascii") ? 1 : Native.WCHAR_SIZE;
4963

5064
// Get Device ID character count
5165
IntByReference pulLen = new IntByReference();
5266
Cfgmgr32.INSTANCE.CM_Get_Device_ID_Size(pulLen, devInst, 0);
5367

54-
// Add 1 for null terminator
55-
int deviceIdLength = pulLen.getValue() + 1;
56-
Memory buffer = new Memory(deviceIdLength * charToBytes);
57-
// Fetch the buffer
58-
int ret = Cfgmgr32.INSTANCE.CM_Get_Device_ID(devInst, buffer, deviceIdLength, 0);
68+
// Fetch the buffer and zero it
69+
Memory buffer = new Memory(pulLen.getValue() * charToBytes);
70+
buffer.clear();
71+
int ret = Cfgmgr32.INSTANCE.CM_Get_Device_ID(devInst, buffer, pulLen.getValue(), 0);
5972
// In the unlikely event the device id changes this might not be big
60-
// enough, try again
61-
while (ret == Cfgmgr32.CR_BUFFER_SMALL) {
73+
// enough, try again. This happens rarely enough one retry should be
74+
// sufficient.
75+
if (ret == Cfgmgr32.CR_BUFFER_SMALL) {
6276
Cfgmgr32.INSTANCE.CM_Get_Device_ID_Size(pulLen, devInst, 0);
63-
deviceIdLength = pulLen.getValue() + 1;
64-
buffer = new Memory(deviceIdLength * charToBytes);
65-
ret = Cfgmgr32.INSTANCE.CM_Get_Device_ID(devInst, buffer, deviceIdLength, 0);
77+
buffer = new Memory(pulLen.getValue() * charToBytes);
78+
buffer.clear();
79+
ret = Cfgmgr32.INSTANCE.CM_Get_Device_ID(devInst, buffer, pulLen.getValue(), 0);
6680
}
67-
68-
// Convert buffer to Java String
81+
// If we still aren't successful throw an exception
82+
if (ret != Cfgmgr32.CR_SUCCESS) {
83+
throw new Cfgmgr32Exception(ret);
84+
}
85+
// Convert buffer to Java String (may include a null). Since we've
86+
// cleared it we can rely on trim()
6987
String deviceId;
7088
if (charToBytes == 1) {
71-
deviceId = buffer.getString(0);
89+
deviceId = new String(buffer.getByteArray(0, pulLen.getValue()), "US-ASCII");
7290
} else {
73-
deviceId = buffer.getWideString(0);
74-
}
75-
// Edge case where there's not enough room for null terminator
76-
// but returns successfully. In this case getString() grabs stray
77-
// characters from memory outside our buffer.
78-
if (deviceId.length() > deviceIdLength) {
79-
deviceId = deviceId.substring(0, deviceIdLength);
91+
deviceId = new String(buffer.getCharArray(0, pulLen.getValue()));
8092
}
81-
return deviceId;
93+
return deviceId.trim();
8294
}
8395
}

0 commit comments

Comments
 (0)