source: AE/installer2/src/net/oni2/aeinstaller/backend/WinRegistry.java@ 629

Last change on this file since 629 was 594, checked in by alloc, 12 years ago

AEI2: .NET detection

File size: 17.6 KB
Line 
1package net.oni2.aeinstaller.backend;
2
3import java.lang.reflect.InvocationTargetException;
4import java.lang.reflect.Method;
5import java.util.ArrayList;
6import java.util.HashMap;
7import java.util.List;
8import java.util.Map;
9import java.util.prefs.Preferences;
10
11/**
12 * @author Unknown
13 */
14public class WinRegistry {
15 /**
16 * Constant for accessing HKCU
17 */
18 public static final int HKEY_CURRENT_USER = 0x80000001;
19 /**
20 * Constant for accessing HKLM
21 */
22 public static final int HKEY_LOCAL_MACHINE = 0x80000002;
23 /**
24 * Constant for successful accesses
25 */
26 public static final int REG_SUCCESS = 0;
27 /**
28 * Constant for not found
29 */
30 public static final int REG_NOTFOUND = 2;
31 /**
32 * Constant for access denied
33 */
34 public static final int REG_ACCESSDENIED = 5;
35
36 /**
37 * Access 32bit registry view when running as 64bit application
38 */
39 public static final int KEY_WOW64_32KEY = 0x0200;
40 /**
41 * Access 64bit registry view when running as 32bit application
42 */
43 public static final int KEY_WOW64_64KEY = 0x0100;
44
45 private static final int KEY_ALL_ACCESS = 0xf003f;
46 private static final int KEY_READ = 0x20019;
47 private static Preferences userRoot = Preferences.userRoot();
48 private static Preferences systemRoot = Preferences.systemRoot();
49 private static Class<? extends Preferences> userClass = userRoot.getClass();
50 private static Method regOpenKey = null;
51 private static Method regCloseKey = null;
52 private static Method regQueryValueEx = null;
53 private static Method regEnumValue = null;
54 private static Method regQueryInfoKey = null;
55 private static Method regEnumKeyEx = null;
56 private static Method regCreateKeyEx = null;
57 private static Method regSetValueEx = null;
58 private static Method regDeleteKey = null;
59 private static Method regDeleteValue = null;
60
61 private static boolean usable = false;
62
63 static {
64 try {
65 regOpenKey = userClass.getDeclaredMethod("WindowsRegOpenKey",
66 new Class[] { int.class, byte[].class, int.class });
67 regOpenKey.setAccessible(true);
68 regCloseKey = userClass.getDeclaredMethod("WindowsRegCloseKey",
69 new Class[] { int.class });
70 regCloseKey.setAccessible(true);
71 regQueryValueEx = userClass.getDeclaredMethod(
72 "WindowsRegQueryValueEx", new Class[] { int.class,
73 byte[].class });
74 regQueryValueEx.setAccessible(true);
75 regEnumValue = userClass.getDeclaredMethod("WindowsRegEnumValue",
76 new Class[] { int.class, int.class, int.class });
77 regEnumValue.setAccessible(true);
78 regQueryInfoKey = userClass.getDeclaredMethod(
79 "WindowsRegQueryInfoKey1", new Class[] { int.class });
80 regQueryInfoKey.setAccessible(true);
81 regEnumKeyEx = userClass.getDeclaredMethod("WindowsRegEnumKeyEx",
82 new Class[] { int.class, int.class, int.class });
83 regEnumKeyEx.setAccessible(true);
84 regCreateKeyEx = userClass.getDeclaredMethod(
85 "WindowsRegCreateKeyEx", new Class[] { int.class,
86 byte[].class });
87 regCreateKeyEx.setAccessible(true);
88 regSetValueEx = userClass.getDeclaredMethod("WindowsRegSetValueEx",
89 new Class[] { int.class, byte[].class, byte[].class });
90 regSetValueEx.setAccessible(true);
91 regDeleteValue = userClass.getDeclaredMethod(
92 "WindowsRegDeleteValue", new Class[] { int.class,
93 byte[].class });
94 regDeleteValue.setAccessible(true);
95 regDeleteKey = userClass.getDeclaredMethod("WindowsRegDeleteKey",
96 new Class[] { int.class, byte[].class });
97 regDeleteKey.setAccessible(true);
98 usable = true;
99 } catch (Exception e) {
100 // e.printStackTrace();
101 }
102 }
103
104 private WinRegistry() {
105 }
106
107 /**
108 * Read a value from key and value name
109 *
110 * @param hkey
111 * HKEY_CURRENT_USER/HKEY_LOCAL_MACHINE
112 * @param key
113 * Key to access
114 * @param valueName
115 * Name of value to read
116 * @param wow64
117 * 0 for standard registry access (32-bits for 32-bit app,
118 * 64-bits for 64-bits app) or KEY_WOW64_32KEY to force access to
119 * 32-bit registry view, or KEY_WOW64_64KEY to force access to
120 * 64-bit registry view
121 * @return the value
122 * @throws Exception
123 * If registry access impossible
124 * @throws IllegalArgumentException
125 * On illegal arguments
126 * @throws IllegalAccessException
127 * On illegal access
128 * @throws InvocationTargetException
129 * On reflection problems
130 */
131 public static String readString(int hkey, String key, String valueName,
132 int wow64) throws Exception, IllegalArgumentException,
133 IllegalAccessException, InvocationTargetException {
134 if (!usable)
135 throw new Exception(
136 "Registry access not supported (not a Windows OS?).");
137 if (hkey == HKEY_LOCAL_MACHINE) {
138 return readString(systemRoot, hkey, key, valueName, wow64);
139 } else if (hkey == HKEY_CURRENT_USER) {
140 return readString(userRoot, hkey, key, valueName, wow64);
141 } else {
142 throw new IllegalArgumentException("hkey=" + hkey);
143 }
144 }
145
146 /**
147 * Read value(s) and value name(s) form given key
148 *
149 * @param hkey
150 * HKEY_CURRENT_USER/HKEY_LOCAL_MACHINE
151 * @param key
152 * Key to access
153 * @param wow64
154 * 0 for standard registry access (32-bits for 32-bit app,
155 * 64-bits for 64-bits app) or KEY_WOW64_32KEY to force access to
156 * 32-bit registry view, or KEY_WOW64_64KEY to force access to
157 * 64-bit registry view
158 * @return the value name(s) plus the value(s)
159 * @throws Exception
160 * If registry access impossible
161 * @throws IllegalArgumentException
162 * On illegal arguments
163 * @throws IllegalAccessException
164 * On illegal access
165 * @throws InvocationTargetException
166 * On reflection problems
167 */
168 public static Map<String, String> readStringValues(int hkey, String key,
169 int wow64) throws Exception, IllegalArgumentException,
170 IllegalAccessException, InvocationTargetException {
171 if (!usable)
172 throw new Exception(
173 "Registry access not supported (not a Windows OS?).");
174 if (hkey == HKEY_LOCAL_MACHINE) {
175 return readStringValues(systemRoot, hkey, key, wow64);
176 } else if (hkey == HKEY_CURRENT_USER) {
177 return readStringValues(userRoot, hkey, key, wow64);
178 } else {
179 throw new IllegalArgumentException("hkey=" + hkey);
180 }
181 }
182
183 /**
184 * Read the value name(s) from a given key
185 *
186 * @param hkey
187 * HKEY_CURRENT_USER/HKEY_LOCAL_MACHINE
188 * @param key
189 * Key to access
190 * @param wow64
191 * 0 for standard registry access (32-bits for 32-bit app,
192 * 64-bits for 64-bits app) or KEY_WOW64_32KEY to force access to
193 * 32-bit registry view, or KEY_WOW64_64KEY to force access to
194 * 64-bit registry view
195 * @return the value name(s)
196 * @throws Exception
197 * If registry access impossible
198 * @throws IllegalArgumentException
199 * On illegal arguments
200 * @throws IllegalAccessException
201 * On illegal access
202 * @throws InvocationTargetException
203 * On reflection problems
204 */
205 public static List<String> readStringSubKeys(int hkey, String key, int wow64)
206 throws Exception, IllegalArgumentException, IllegalAccessException,
207 InvocationTargetException {
208 if (!usable)
209 throw new Exception(
210 "Registry access not supported (not a Windows OS?).");
211 if (hkey == HKEY_LOCAL_MACHINE) {
212 return readStringSubKeys(systemRoot, hkey, key, wow64);
213 } else if (hkey == HKEY_CURRENT_USER) {
214 return readStringSubKeys(userRoot, hkey, key, wow64);
215 } else {
216 throw new IllegalArgumentException("hkey=" + hkey);
217 }
218 }
219
220 /**
221 * Create a key
222 *
223 * @param hkey
224 * HKEY_CURRENT_USER/HKEY_LOCAL_MACHINE
225 * @param key
226 * Key to access
227 * @throws Exception
228 * If registry access impossible
229 * @throws IllegalArgumentException
230 * On illegal arguments
231 * @throws IllegalAccessException
232 * On illegal access
233 * @throws InvocationTargetException
234 * On reflection problems
235 */
236 public static void createKey(int hkey, String key) throws Exception,
237 IllegalArgumentException, IllegalAccessException,
238 InvocationTargetException {
239 int[] ret;
240 if (!usable)
241 throw new Exception(
242 "Registry access not supported (not a Windows OS?).");
243 if (hkey == HKEY_LOCAL_MACHINE) {
244 ret = createKey(systemRoot, hkey, key);
245 regCloseKey
246 .invoke(systemRoot, new Object[] { new Integer(ret[0]) });
247 } else if (hkey == HKEY_CURRENT_USER) {
248 ret = createKey(userRoot, hkey, key);
249 regCloseKey.invoke(userRoot, new Object[] { new Integer(ret[0]) });
250 } else {
251 throw new IllegalArgumentException("hkey=" + hkey);
252 }
253 if (ret[1] != REG_SUCCESS) {
254 throw new IllegalArgumentException("rc=" + ret[1] + " key=" + key);
255 }
256 }
257
258 /**
259 * Write a value in a given key/value name
260 *
261 * @param hkey
262 * HKEY_CURRENT_USER/HKEY_LOCAL_MACHINE
263 * @param key
264 * Key to access
265 * @param valueName
266 * Name of value to write to
267 * @param value
268 * String to write
269 * @param wow64
270 * 0 for standard registry access (32-bits for 32-bit app,
271 * 64-bits for 64-bits app) or KEY_WOW64_32KEY to force access to
272 * 32-bit registry view, or KEY_WOW64_64KEY to force access to
273 * 64-bit registry view
274 * @throws Exception
275 * If registry access impossible
276 * @throws IllegalArgumentException
277 * On illegal arguments
278 * @throws IllegalAccessException
279 * On illegal access
280 * @throws InvocationTargetException
281 * On reflection problems
282 */
283 public static void writeStringValue(int hkey, String key, String valueName,
284 String value, int wow64) throws Exception,
285 IllegalArgumentException, IllegalAccessException,
286 InvocationTargetException {
287 if (!usable)
288 throw new Exception(
289 "Registry access not supported (not a Windows OS?).");
290 if (hkey == HKEY_LOCAL_MACHINE) {
291 writeStringValue(systemRoot, hkey, key, valueName, value, wow64);
292 } else if (hkey == HKEY_CURRENT_USER) {
293 writeStringValue(userRoot, hkey, key, valueName, value, wow64);
294 } else {
295 throw new IllegalArgumentException("hkey=" + hkey);
296 }
297 }
298
299 /**
300 * Delete a given key
301 *
302 * @param hkey
303 * HKEY_CURRENT_USER/HKEY_LOCAL_MACHINE
304 * @param key
305 * Key to delete
306 * @throws Exception
307 * If registry access impossible
308 * @throws IllegalArgumentException
309 * On illegal arguments
310 * @throws IllegalAccessException
311 * On illegal access
312 * @throws InvocationTargetException
313 * On reflection problems
314 */
315 public static void deleteKey(int hkey, String key) throws Exception,
316 IllegalArgumentException, IllegalAccessException,
317 InvocationTargetException {
318 int rc = -1;
319 if (!usable)
320 throw new Exception(
321 "Registry access not supported (not a Windows OS?).");
322 if (hkey == HKEY_LOCAL_MACHINE) {
323 rc = deleteKey(systemRoot, hkey, key);
324 } else if (hkey == HKEY_CURRENT_USER) {
325 rc = deleteKey(userRoot, hkey, key);
326 }
327 if (rc != REG_SUCCESS) {
328 throw new IllegalArgumentException("rc=" + rc + " key=" + key);
329 }
330 }
331
332 /**
333 * delete a value from a given key/value name
334 *
335 * @param hkey
336 * HKEY_CURRENT_USER/HKEY_LOCAL_MACHINE
337 * @param key
338 * Key to access
339 * @param value
340 * Name of value to delete
341 * @param wow64
342 * 0 for standard registry access (32-bits for 32-bit app,
343 * 64-bits for 64-bits app) or KEY_WOW64_32KEY to force access to
344 * 32-bit registry view, or KEY_WOW64_64KEY to force access to
345 * 64-bit registry view
346 * @throws Exception
347 * If registry access impossible
348 * @throws IllegalArgumentException
349 * On illegal arguments
350 * @throws IllegalAccessException
351 * On illegal access
352 * @throws InvocationTargetException
353 * On reflection problems
354 */
355 public static void deleteValue(int hkey, String key, String value, int wow64)
356 throws Exception, IllegalArgumentException, IllegalAccessException,
357 InvocationTargetException {
358 if (!usable)
359 throw new Exception(
360 "Registry access not supported (not a Windows OS?).");
361 int rc = -1;
362 if (hkey == HKEY_LOCAL_MACHINE) {
363 rc = deleteValue(systemRoot, hkey, key, value, wow64);
364 } else if (hkey == HKEY_CURRENT_USER) {
365 rc = deleteValue(userRoot, hkey, key, value, wow64);
366 }
367 if (rc != REG_SUCCESS) {
368 throw new IllegalArgumentException("rc=" + rc + " key=" + key
369 + " value=" + value);
370 }
371 }
372
373 // ========================================================================
374 private static int deleteValue(Preferences root, int hkey, String key,
375 String value, int wow64) throws IllegalArgumentException,
376 IllegalAccessException, InvocationTargetException {
377 int[] handles = (int[]) regOpenKey.invoke(root, new Object[] {
378 new Integer(hkey), toCstr(key),
379 new Integer(KEY_ALL_ACCESS | wow64) });
380 if (handles[1] != REG_SUCCESS) {
381 return handles[1]; // can be REG_NOTFOUND, REG_ACCESSDENIED
382 }
383 int rc = ((Integer) regDeleteValue.invoke(root, new Object[] {
384 new Integer(handles[0]), toCstr(value) })).intValue();
385 regCloseKey.invoke(root, new Object[] { new Integer(handles[0]) });
386 return rc;
387 }
388
389 // ========================================================================
390 private static int deleteKey(Preferences root, int hkey, String key)
391 throws IllegalArgumentException, IllegalAccessException,
392 InvocationTargetException {
393 int rc = ((Integer) regDeleteKey.invoke(root, new Object[] {
394 new Integer(hkey), toCstr(key) })).intValue();
395 return rc; // can REG_NOTFOUND, REG_ACCESSDENIED, REG_SUCCESS
396 }
397
398 // ========================================================================
399 private static String readString(Preferences root, int hkey, String key,
400 String value, int wow64) throws IllegalArgumentException,
401 IllegalAccessException, InvocationTargetException {
402 int[] handles = (int[]) regOpenKey
403 .invoke(root, new Object[] { new Integer(hkey), toCstr(key),
404 new Integer(KEY_READ | wow64) });
405 if (handles[1] != REG_SUCCESS) {
406 return null;
407 }
408 byte[] valb = (byte[]) regQueryValueEx.invoke(root, new Object[] {
409 new Integer(handles[0]), toCstr(value) });
410 regCloseKey.invoke(root, new Object[] { new Integer(handles[0]) });
411 return (valb != null ? new String(valb).trim() : null);
412 }
413
414 // ========================================================================
415 private static Map<String, String> readStringValues(Preferences root,
416 int hkey, String key, int wow64) throws Exception,
417 IllegalArgumentException, IllegalAccessException,
418 InvocationTargetException {
419 HashMap<String, String> results = new HashMap<String, String>();
420 int[] handles = (int[]) regOpenKey
421 .invoke(root, new Object[] { new Integer(hkey), toCstr(key),
422 new Integer(KEY_READ | wow64) });
423 if (handles[1] != REG_SUCCESS) {
424 return null;
425 }
426 int[] info = (int[]) regQueryInfoKey.invoke(root,
427 new Object[] { new Integer(handles[0]) });
428
429 int count = info[2]; // count
430 int maxlen = info[4]; // value length max
431 for (int index = 0; index < count; index++) {
432 byte[] name = (byte[]) regEnumValue.invoke(root, new Object[] {
433 new Integer(handles[0]), new Integer(index),
434 new Integer(maxlen + 1) });
435 String value = readString(hkey, key, new String(name), wow64);
436 results.put(new String(name).trim(), value);
437 }
438 regCloseKey.invoke(root, new Object[] { new Integer(handles[0]) });
439 return results;
440 }
441
442 // ========================================================================
443 private static List<String> readStringSubKeys(Preferences root, int hkey,
444 String key, int wow64) throws IllegalArgumentException,
445 IllegalAccessException, InvocationTargetException {
446 List<String> results = new ArrayList<String>();
447 int[] handles = (int[]) regOpenKey
448 .invoke(root, new Object[] { new Integer(hkey), toCstr(key),
449 new Integer(KEY_READ | wow64) });
450 if (handles[1] != REG_SUCCESS) {
451 return null;
452 }
453 int[] info = (int[]) regQueryInfoKey.invoke(root,
454 new Object[] { new Integer(handles[0]) });
455
456 int count = info[0]; // Fix: info[2] was being used here with wrong
457 // results. Suggested by davenpcj, confirmed by
458 // Petrucio
459 int maxlen = info[3]; // value length max
460 for (int index = 0; index < count; index++) {
461 byte[] name = (byte[]) regEnumKeyEx.invoke(root, new Object[] {
462 new Integer(handles[0]), new Integer(index),
463 new Integer(maxlen + 1) });
464 results.add(new String(name).trim());
465 }
466 regCloseKey.invoke(root, new Object[] { new Integer(handles[0]) });
467 return results;
468 }
469
470 // ========================================================================
471 private static int[] createKey(Preferences root, int hkey, String key)
472 throws IllegalArgumentException, IllegalAccessException,
473 InvocationTargetException {
474 return (int[]) regCreateKeyEx.invoke(root, new Object[] {
475 new Integer(hkey), toCstr(key) });
476 }
477
478 // ========================================================================
479 private static void writeStringValue(Preferences root, int hkey,
480 String key, String valueName, String value, int wow64)
481 throws IllegalArgumentException, IllegalAccessException,
482 InvocationTargetException {
483 int[] handles = (int[]) regOpenKey.invoke(root, new Object[] {
484 new Integer(hkey), toCstr(key),
485 new Integer(KEY_ALL_ACCESS | wow64) });
486 regSetValueEx.invoke(root, new Object[] { new Integer(handles[0]),
487 toCstr(valueName), toCstr(value) });
488 regCloseKey.invoke(root, new Object[] { new Integer(handles[0]) });
489 }
490
491 // ========================================================================
492 // utility
493 private static byte[] toCstr(String str) {
494 byte[] result = new byte[str.length() + 1];
495
496 for (int i = 0; i < str.length(); i++) {
497 result[i] = (byte) str.charAt(i);
498 }
499 result[str.length()] = 0;
500 return result;
501 }
502}
Note: See TracBrowser for help on using the repository browser.