23
23
*/
24
24
package com .sun .jna .platform .win32 ;
25
25
26
+ import java .io .UnsupportedEncodingException ;
27
+
26
28
import com .sun .jna .Memory ;
27
29
import com .sun .jna .Native ;
28
30
import com .sun .jna .ptr .IntByReference ;
33
35
* @author widdis[at]gmail[dot]com
34
36
*/
35
37
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
+ }
36
49
37
50
/**
38
51
* Utility method to call Cfgmgr32's CM_Get_Device_ID that allocates the
@@ -43,41 +56,40 @@ public abstract class Cfgmgr32Util {
43
56
* Caller-supplied device instance handle that is bound to the
44
57
* local machine.
45
58
* @return The device instance ID string.
59
+ * @throws UnsupportedEncodingException
46
60
*/
47
- public static String CM_Get_Device_ID (int devInst ) {
61
+ public static String CM_Get_Device_ID (int devInst ) throws UnsupportedEncodingException {
48
62
int charToBytes = Boolean .getBoolean ("w32.ascii" ) ? 1 : Native .WCHAR_SIZE ;
49
63
50
64
// Get Device ID character count
51
65
IntByReference pulLen = new IntByReference ();
52
66
Cfgmgr32 .INSTANCE .CM_Get_Device_ID_Size (pulLen , devInst , 0 );
53
67
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 );
59
72
// 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 ) {
62
76
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 );
66
80
}
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()
69
87
String deviceId ;
70
88
if (charToBytes == 1 ) {
71
- deviceId = buffer .getString ( 0 );
89
+ deviceId = new String ( buffer .getByteArray ( 0 , pulLen . getValue ()), "US-ASCII" );
72
90
} 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 ()));
80
92
}
81
- return deviceId ;
93
+ return deviceId . trim () ;
82
94
}
83
95
}
0 commit comments