@@ -28,7 +28,7 @@ public final class WinRegistry {
28
28
* colors, printers, network connections, and application preferences.
29
29
* See <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/ms724836(v=vs.85).aspx">Predefined Keys</a>
30
30
*/
31
- public static final int HKEY_CURRENT_USER = 0x80000001 ;
31
+ public static final long HKEY_CURRENT_USER = 0x80000001L ;
32
32
33
33
/**
34
34
* Registry entries subordinate to this key define the physical state of the computer, including data about the bus type,
@@ -38,44 +38,62 @@ public final class WinRegistry {
38
38
* names and the location of the server), and other system information.
39
39
* See <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/ms724836(v=vs.85).aspx">Predefined Keys</a>
40
40
*/
41
- public static final int HKEY_LOCAL_MACHINE = 0x80000002 ;
41
+ public static final long HKEY_LOCAL_MACHINE = 0x80000002L ;
42
42
43
43
private static final long REG_SUCCESS = 0L ;
44
44
45
45
private static final int KEY_READ = 0x20019 ;
46
- private static final Preferences userRoot = Preferences .userRoot ();
47
- private static final Preferences systemRoot = Preferences .systemRoot ();
48
- private static final Class <? extends Preferences > userClass = userRoot .getClass ();
49
- private static final Method regOpenKey ;
50
- private static final Method regCloseKey ;
51
- private static final Method regQueryValueEx ;
52
- private static final Method regEnumValue ;
53
- private static final Method regQueryInfoKey ;
54
- private static final Method regEnumKeyEx ;
55
-
56
- private static boolean java11 ;
46
+ private static final Preferences USER_ROOT = Preferences .userRoot ();
47
+ private static final Preferences SYSTEM_ROOT = Preferences .systemRoot ();
48
+ private static final Class <? extends Preferences > USER_CLASS = USER_ROOT .getClass ();
49
+ private static final String HKEY_EQ = "hkey=" ;
50
+
51
+ /**
52
+ * Wrapper for Windows registry API RegOpenKey(long, byte[], int)
53
+ * Returns {@code long[]}
54
+ */
55
+ private static final Method REG_OPEN_KEY ;
56
+ /**
57
+ * Wrapper for Windows registry API RegCloseKey(long)
58
+ * Returns {@code int}
59
+ */
60
+ private static final Method REG_CLOSE_KEY ;
61
+ /**
62
+ * Wrapper for Windows registry API RegQueryValueEx(long, byte[])
63
+ * Returns {@code byte[]}
64
+ */
65
+ private static final Method REG_QUERY_VALUE_EX ;
66
+ /**
67
+ * Wrapper for Windows registry API RegEnumValue(long, int, int)
68
+ * Returns {@code byte[]}
69
+ */
70
+ private static final Method REG_ENUM_VALUE ;
71
+ /**
72
+ * Wrapper for RegQueryInfoKey(long)
73
+ * Returns {@code long[]}
74
+ */
75
+ private static final Method REG_QUERY_INFO_KEY ;
76
+ /**
77
+ * Wrapper for RegEnumKeyEx(long, int, int)
78
+ * Returns {@code byte[]}
79
+ */
80
+ private static final Method REG_ENUM_KEY_EX ;
57
81
58
82
static {
59
- regOpenKey = getDeclaredMethod ("WindowsRegOpenKey" , int .class , byte [].class , int .class );
60
- regCloseKey = getDeclaredMethod ("WindowsRegCloseKey" , int .class );
61
- regQueryValueEx = getDeclaredMethod ("WindowsRegQueryValueEx" , int .class , byte [].class );
62
- regEnumValue = getDeclaredMethod ("WindowsRegEnumValue" , int .class , int .class , int .class );
63
- regQueryInfoKey = getDeclaredMethod ("WindowsRegQueryInfoKey1" , int .class );
64
- regEnumKeyEx = getDeclaredMethod ("WindowsRegEnumKeyEx" , int .class , int .class , int .class );
65
- ReflectionUtils .setObjectsAccessible (regOpenKey , regCloseKey , regQueryValueEx , regEnumValue , regQueryInfoKey , regEnumKeyEx );
83
+ REG_OPEN_KEY = getDeclaredMethod ("WindowsRegOpenKey" , long .class , byte [].class , int .class );
84
+ REG_CLOSE_KEY = getDeclaredMethod ("WindowsRegCloseKey" , long .class );
85
+ REG_QUERY_VALUE_EX = getDeclaredMethod ("WindowsRegQueryValueEx" , long .class , byte [].class );
86
+ REG_ENUM_VALUE = getDeclaredMethod ("WindowsRegEnumValue" , long .class , int .class , int .class );
87
+ REG_QUERY_INFO_KEY = getDeclaredMethod ("WindowsRegQueryInfoKey1" , long .class );
88
+ REG_ENUM_KEY_EX = getDeclaredMethod ("WindowsRegEnumKeyEx" , long .class , int .class , int .class );
89
+ ReflectionUtils .setObjectsAccessible (REG_OPEN_KEY , REG_CLOSE_KEY , REG_QUERY_VALUE_EX , REG_ENUM_VALUE ,
90
+ REG_QUERY_INFO_KEY , REG_ENUM_KEY_EX );
66
91
}
67
92
68
93
private static Method getDeclaredMethod (String name , Class <?>... parameterTypes ) {
69
94
try {
70
- return userClass .getDeclaredMethod (name , parameterTypes );
95
+ return USER_CLASS .getDeclaredMethod (name , parameterTypes );
71
96
} catch (NoSuchMethodException e ) {
72
- if (parameterTypes .length > 0 && parameterTypes [0 ] == int .class ) {
73
- // JDK-8198899: change of signature in Java 11. Old signature to drop when we switch to Java 11
74
- Class <?>[] parameterTypesCopy = Utils .copyArray (parameterTypes );
75
- parameterTypesCopy [0 ] = long .class ;
76
- java11 = true ;
77
- return getDeclaredMethod (name , parameterTypesCopy );
78
- }
79
97
Logging .log (Logging .LEVEL_ERROR , "Unable to find WindowsReg method" , e );
80
98
return null ;
81
99
} catch (RuntimeException e ) {
@@ -84,10 +102,6 @@ private static Method getDeclaredMethod(String name, Class<?>... parameterTypes)
84
102
}
85
103
}
86
104
87
- private static Number hkey (int key ) {
88
- return java11 ? ((Number ) Long .valueOf (key )) : ((Number ) Integer .valueOf (key ));
89
- }
90
-
91
105
private WinRegistry () {
92
106
// Hide default constructor for utilities classes
93
107
}
@@ -101,15 +115,16 @@ private WinRegistry() {
101
115
* @throws IllegalArgumentException if hkey not HKEY_CURRENT_USER/HKEY_LOCAL_MACHINE
102
116
* @throws IllegalAccessException if Java language access control is enforced and the underlying method is inaccessible
103
117
* @throws InvocationTargetException if the underlying method throws an exception
118
+ * @since 19100 (method definition)
104
119
*/
105
- public static String readString (int hkey , String key , String valueName )
120
+ public static String readString (long hkey , String key , String valueName )
106
121
throws IllegalAccessException , InvocationTargetException {
107
122
if (hkey == HKEY_LOCAL_MACHINE ) {
108
- return readString (systemRoot , hkey , key , valueName );
123
+ return readString (SYSTEM_ROOT , hkey , key , valueName );
109
124
} else if (hkey == HKEY_CURRENT_USER ) {
110
- return readString (userRoot , hkey , key , valueName );
125
+ return readString (USER_ROOT , hkey , key , valueName );
111
126
} else {
112
- throw new IllegalArgumentException ("hkey=" + hkey );
127
+ throw new IllegalArgumentException (HKEY_EQ + hkey );
113
128
}
114
129
}
115
130
@@ -122,14 +137,14 @@ public static String readString(int hkey, String key, String valueName)
122
137
* @throws IllegalAccessException if Java language access control is enforced and the underlying method is inaccessible
123
138
* @throws InvocationTargetException if the underlying method throws an exception
124
139
*/
125
- public static Map <String , String > readStringValues (int hkey , String key )
140
+ public static Map <String , String > readStringValues (long hkey , String key )
126
141
throws IllegalAccessException , InvocationTargetException {
127
142
if (hkey == HKEY_LOCAL_MACHINE ) {
128
- return readStringValues (systemRoot , hkey , key );
143
+ return readStringValues (SYSTEM_ROOT , hkey , key );
129
144
} else if (hkey == HKEY_CURRENT_USER ) {
130
- return readStringValues (userRoot , hkey , key );
145
+ return readStringValues (USER_ROOT , hkey , key );
131
146
} else {
132
- throw new IllegalArgumentException ("hkey=" + hkey );
147
+ throw new IllegalArgumentException (HKEY_EQ + hkey );
133
148
}
134
149
}
135
150
@@ -142,89 +157,82 @@ public static Map<String, String> readStringValues(int hkey, String key)
142
157
* @throws IllegalAccessException if Java language access control is enforced and the underlying method is inaccessible
143
158
* @throws InvocationTargetException if the underlying method throws an exception
144
159
*/
145
- public static List <String > readStringSubKeys (int hkey , String key )
160
+ public static List <String > readStringSubKeys (long hkey , String key )
146
161
throws IllegalAccessException , InvocationTargetException {
147
162
if (hkey == HKEY_LOCAL_MACHINE ) {
148
- return readStringSubKeys (systemRoot , hkey , key );
163
+ return readStringSubKeys (SYSTEM_ROOT , hkey , key );
149
164
} else if (hkey == HKEY_CURRENT_USER ) {
150
- return readStringSubKeys (userRoot , hkey , key );
165
+ return readStringSubKeys (USER_ROOT , hkey , key );
151
166
} else {
152
- throw new IllegalArgumentException ("hkey=" + hkey );
167
+ throw new IllegalArgumentException (HKEY_EQ + hkey );
153
168
}
154
169
}
155
170
156
171
// =====================
157
172
158
- private static Number getNumber (Object array , int index ) {
159
- if (array instanceof int []) {
160
- return ((int []) array )[index ];
161
- } else if (array instanceof long []) {
173
+ private static long getNumber (Object array , int index ) {
174
+ if (array instanceof long []) {
162
175
return ((long []) array )[index ];
163
176
}
164
177
throw new IllegalArgumentException ();
165
178
}
166
179
167
- private static String readString (Preferences root , int hkey , String key , String value )
180
+ private static String readString (Preferences root , long hkey , String key , String value )
168
181
throws IllegalAccessException , InvocationTargetException {
169
- if (regOpenKey == null || regQueryValueEx == null || regCloseKey == null ) {
182
+ if (REG_OPEN_KEY == null || REG_QUERY_VALUE_EX == null || REG_CLOSE_KEY == null ) {
170
183
return null ;
171
184
}
172
- // Need to capture both int[] (Java 8-10) and long[] (Java 11+)
173
- Object handles = regOpenKey .invoke (root , hkey (hkey ), toCstr (key ), Integer .valueOf (KEY_READ ));
174
- if (getNumber (handles , 1 ).longValue () != REG_SUCCESS ) {
185
+ Object handles = REG_OPEN_KEY .invoke (root , hkey , toCstr (key ), KEY_READ );
186
+ if (getNumber (handles , 1 ) != REG_SUCCESS ) {
175
187
return null ;
176
188
}
177
- byte [] valb = (byte []) regQueryValueEx .invoke (root , getNumber (handles , 0 ), toCstr (value ));
178
- regCloseKey .invoke (root , getNumber (handles , 0 ));
189
+ byte [] valb = (byte []) REG_QUERY_VALUE_EX .invoke (root , getNumber (handles , 0 ), toCstr (value ));
190
+ REG_CLOSE_KEY .invoke (root , getNumber (handles , 0 ));
179
191
return (valb != null ? new String (valb , StandardCharsets .UTF_8 ).trim () : null );
180
192
}
181
193
182
- private static Map <String , String > readStringValues (Preferences root , int hkey , String key )
194
+ private static Map <String , String > readStringValues (Preferences root , long hkey , String key )
183
195
throws IllegalAccessException , InvocationTargetException {
184
- if (regOpenKey == null || regQueryInfoKey == null || regEnumValue == null || regCloseKey == null ) {
196
+ if (REG_OPEN_KEY == null || REG_QUERY_INFO_KEY == null || REG_ENUM_VALUE == null || REG_CLOSE_KEY == null ) {
185
197
return Collections .emptyMap ();
186
198
}
187
199
HashMap <String , String > results = new HashMap <>();
188
- // Need to capture both int[] (Java 8-10) and long[] (Java 11+)
189
- Object handles = regOpenKey .invoke (root , hkey (hkey ), toCstr (key ), Integer .valueOf (KEY_READ ));
190
- if (getNumber (handles , 1 ).longValue () != REG_SUCCESS ) {
200
+ Object handles = REG_OPEN_KEY .invoke (root , hkey , toCstr (key ), KEY_READ );
201
+ if (getNumber (handles , 1 ) != REG_SUCCESS ) {
191
202
return Collections .emptyMap ();
192
203
}
193
- // Need to capture both int[] (Java 8-10) and long[] (Java 11+)
194
- Object info = regQueryInfoKey .invoke (root , getNumber (handles , 0 ));
204
+ Object info = REG_QUERY_INFO_KEY .invoke (root , getNumber (handles , 0 ));
195
205
196
- int count = getNumber (info , 0 ). intValue ( );
197
- int maxlen = getNumber (info , 3 ). intValue ( );
206
+ int count = Math . toIntExact ( getNumber (info , 0 ));
207
+ int maxlen = Math . toIntExact ( getNumber (info , 3 ));
198
208
for (int index = 0 ; index < count ; index ++) {
199
- byte [] name = (byte []) regEnumValue .invoke (root , getNumber (handles , 0 ), Integer . valueOf ( index ), Integer . valueOf ( maxlen + 1 ) );
209
+ byte [] name = (byte []) REG_ENUM_VALUE .invoke (root , getNumber (handles , 0 ), index , maxlen + 1 );
200
210
String value = readString (hkey , key , new String (name , StandardCharsets .UTF_8 ));
201
211
results .put (new String (name , StandardCharsets .UTF_8 ).trim (), value );
202
212
}
203
- regCloseKey .invoke (root , getNumber (handles , 0 ));
213
+ REG_CLOSE_KEY .invoke (root , getNumber (handles , 0 ));
204
214
return Collections .unmodifiableMap (results );
205
215
}
206
216
207
- private static List <String > readStringSubKeys (Preferences root , int hkey , String key )
217
+ private static List <String > readStringSubKeys (Preferences root , long hkey , String key )
208
218
throws IllegalAccessException , InvocationTargetException {
209
- if (regOpenKey == null || regQueryInfoKey == null || regEnumKeyEx == null || regCloseKey == null ) {
219
+ if (REG_OPEN_KEY == null || REG_QUERY_INFO_KEY == null || REG_ENUM_KEY_EX == null || REG_CLOSE_KEY == null ) {
210
220
return Collections .emptyList ();
211
221
}
212
222
List <String > results = new ArrayList <>();
213
- // Need to capture both int[] (Java 8-10) and long[] (Java 11+)
214
- Object handles = regOpenKey .invoke (root , hkey (hkey ), toCstr (key ), Integer .valueOf (KEY_READ ));
215
- if (getNumber (handles , 1 ).longValue () != REG_SUCCESS ) {
223
+ Object handles = REG_OPEN_KEY .invoke (root , hkey , toCstr (key ), KEY_READ );
224
+ if (getNumber (handles , 1 ) != REG_SUCCESS ) {
216
225
return Collections .emptyList ();
217
226
}
218
- // Need to capture both int[] (Java 8-10) and long[] (Java 11+)
219
- Object info = regQueryInfoKey .invoke (root , getNumber (handles , 0 ));
227
+ Object info = REG_QUERY_INFO_KEY .invoke (root , getNumber (handles , 0 ));
220
228
221
- int count = getNumber (info , 0 ). intValue ( );
222
- int maxlen = getNumber (info , 3 ). intValue ( );
229
+ int count = Math . toIntExact ( getNumber (info , 0 ));
230
+ int maxlen = Math . toIntExact ( getNumber (info , 3 ));
223
231
for (int index = 0 ; index < count ; index ++) {
224
- byte [] name = (byte []) regEnumKeyEx .invoke (root , getNumber (handles , 0 ), Integer . valueOf ( index ), Integer . valueOf ( maxlen + 1 ) );
232
+ byte [] name = (byte []) REG_ENUM_KEY_EX .invoke (root , getNumber (handles , 0 ), index , maxlen + 1 );
225
233
results .add (new String (name , StandardCharsets .UTF_8 ).trim ());
226
234
}
227
- regCloseKey .invoke (root , getNumber (handles , 0 ));
235
+ REG_CLOSE_KEY .invoke (root , getNumber (handles , 0 ));
228
236
return Collections .unmodifiableList (results );
229
237
}
230
238
0 commit comments