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
+ @ SuppressWarnings ("serial" )
39
+ public static class Cfgmgr32Exception extends RuntimeException {
40
+ private final int errorCode ;
41
+
42
+ public Cfgmgr32Exception (int errorCode ) {
43
+ this .errorCode = errorCode ;
44
+ }
45
+
46
+ public int getErrorCode () {
47
+ return errorCode ;
48
+ }
49
+ }
36
50
37
51
/**
38
52
* Utility method to call Cfgmgr32's CM_Get_Device_ID that allocates the
@@ -43,41 +57,40 @@ public abstract class Cfgmgr32Util {
43
57
* Caller-supplied device instance handle that is bound to the
44
58
* local machine.
45
59
* @return The device instance ID string.
60
+ * @throws UnsupportedEncodingException
46
61
*/
47
- public static String CM_Get_Device_ID (int devInst ) {
62
+ public static String CM_Get_Device_ID (int devInst ) throws UnsupportedEncodingException {
48
63
int charToBytes = Boolean .getBoolean ("w32.ascii" ) ? 1 : Native .WCHAR_SIZE ;
49
64
50
65
// Get Device ID character count
51
66
IntByReference pulLen = new IntByReference ();
52
67
Cfgmgr32 .INSTANCE .CM_Get_Device_ID_Size (pulLen , devInst , 0 );
53
68
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 );
69
+ // Zero and Fetch the buffer
70
+ Memory buffer = new Memory (pulLen .getValue () * charToBytes );
71
+ buffer .clear ();
72
+ int ret = Cfgmgr32 .INSTANCE .CM_Get_Device_ID (devInst , buffer , pulLen .getValue (), 0 );
59
73
// In the unlikely event the device id changes this might not be big
60
- // enough, try again
61
- while (ret == Cfgmgr32 .CR_BUFFER_SMALL ) {
74
+ // enough, try again. This happens rarely enough one retry should be
75
+ // sufficient.
76
+ if (ret == Cfgmgr32 .CR_BUFFER_SMALL ) {
62
77
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 );
78
+ buffer = new Memory ( pulLen .getValue () * charToBytes ) ;
79
+ buffer . clear ( );
80
+ ret = Cfgmgr32 .INSTANCE .CM_Get_Device_ID (devInst , buffer , pulLen . getValue () , 0 );
66
81
}
67
-
68
- // Convert buffer to Java String
82
+ // If we still aren't successful throw an exception
83
+ if (ret != Cfgmgr32 .CR_SUCCESS ) {
84
+ throw new Cfgmgr32Exception (ret );
85
+ }
86
+ // Convert buffer to Java String (may include a null). Since we've
87
+ // cleared it we can rely on trim()
69
88
String deviceId ;
70
89
if (charToBytes == 1 ) {
71
- deviceId = buffer .getString ( 0 );
90
+ deviceId = new String ( buffer .getByteArray ( 0 , pulLen . getValue ()), "US-ASCII" );
72
91
} 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 );
92
+ deviceId = new String (buffer .getCharArray (0 , pulLen .getValue ()));
80
93
}
81
- return deviceId ;
94
+ return deviceId . trim () ;
82
95
}
83
96
}
0 commit comments