View Javadoc
1   package com.randomnoun.common;
2   
3   /* (c) 2013 randomnoun. All Rights Reserved. This work is licensed under a
4    * BSD Simplified License. (http://www.randomnoun.com/bsd-simplified.html)
5    */
6   
7   /** Java hack to access windows registries. Relies on the sun implementation
8    * of the Preferences class. 
9    * 
10   * <p>Technique stolen from
11   * http://snipplr.com/view/6620/accessing-windows-registry-in-java/
12   * 
13   * <p>Probably better to JNI-wrap this, but hey, who has time for that.
14   * 
15   * 
16   */
17  
18  import java.lang.reflect.Method;
19  import java.util.prefs.Preferences;
20  
21  public class Registry {
22      
23  	// private static final int HKEY_CURRENT_USER = 0x80000001;
24  	// private static final int KEY_QUERY_VALUE = 1;
25  	// private static final int KEY_SET_VALUE = 2;
26  	private static final int KEY_READ = 0x20019;
27  
28  	private static int initialisationState = 0;
29  	
30  	// java internals, bit nasty all of this being static
31  	private static final Preferences userRoot = Preferences.userRoot();
32  	private static final Preferences systemRoot = Preferences.systemRoot();
33  	private static final Class<?> clz = userRoot.getClass();
34  	private static Method winRegQueryValue;
35  	private static Method winRegEnumValue;
36  	private static Method winRegQueryInfo;	
37  	private static Method openKey;
38  	private static Method closeKey;
39  	
40  	
41  	// you'd better hope these methods are threadsafe
42  	public static String getSystemValue(String registryKey, String key) {
43  		initialise();
44  		
45  		byte[] valb = null;
46  		String vals = null;
47  		Integer handle = -1;
48  
49  		// Query for IE version
50  		// key = "SOFTWARE\\Microsoft\\Internet Explorer#Version";
51  		try {
52  			handle = (Integer) openKey.invoke(systemRoot, toCstr(registryKey),
53  					KEY_READ, KEY_READ);
54  			valb = (byte[]) winRegQueryValue.invoke(systemRoot, handle,
55  					toCstr(key));
56  			vals = (valb != null ? new String(valb).trim() : null);
57  			closeKey.invoke(Preferences.systemRoot(), handle);
58  		} catch (Exception e) {
59  			if (handle!=-1) {
60  				try {
61  					closeKey.invoke(Preferences.systemRoot(), handle);
62  				} catch (Exception e2) {
63  					throw new IllegalArgumentException("Error reading registry '" + registryKey + "', key '" + key + "'; (and could not close handle " + handle + ": " + e2.getMessage() + ")", e);
64  				}
65  			}
66  			throw new IllegalArgumentException("Error reading registry key '" + registryKey + "', key '" + key + "'", e);
67  		}
68  		return vals;
69  	}
70  	
71  	public static String getUserValue(String registryKey, String key) {
72  		initialise();
73  		
74  		byte[] valb = null;
75  		String vals = null;
76  		Integer handle = -1;
77  
78  		// Query Internet Settings for Proxy
79  		//key = "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings#ProxyServer";
80  		try {
81  			handle = (Integer) openKey.invoke(userRoot, toCstr(registryKey), KEY_READ,
82  					KEY_READ);
83  			valb = (byte[]) winRegQueryValue.invoke(userRoot,
84  					handle.intValue(), toCstr(key));
85  			vals = (valb != null ? new String(valb).trim() : null);
86  			closeKey.invoke(Preferences.userRoot(), handle);
87  		} catch (Exception e) {
88  			if (handle!=-1) {
89  				try {
90  					closeKey.invoke(Preferences.systemRoot(), handle);
91  				} catch (Exception e2) {
92  					throw new IllegalArgumentException("Error reading registry '" + registryKey + "', key '" + key + "'; (and could not close handle " + handle + ": " + e2.getMessage() + ")", e);
93  				}
94  			}
95  			throw new IllegalArgumentException("Error reading registry key '" + registryKey + "', key '" + key + "'", e);
96  		}
97  		return vals;
98  	}
99  	
100 	private static synchronized void initialise() {
101 		if (initialisationState == 2) { 
102 			return; 
103 		} else if (initialisationState == 1) {
104 			throw new IllegalStateException("Registry could not be initialised");
105 		} else {
106 			try {
107 				openKey = clz.getDeclaredMethod("openKey", byte[].class, int.class, int.class);
108 				openKey.setAccessible(true);
109 	
110 				closeKey = clz.getDeclaredMethod("closeKey", int.class);
111 				closeKey.setAccessible(true);
112 	
113 				winRegQueryValue = clz.getDeclaredMethod("WindowsRegQueryValueEx", int.class, byte[].class);
114 				winRegQueryValue.setAccessible(true);
115 				winRegEnumValue = clz.getDeclaredMethod("WindowsRegEnumValue1", int.class, int.class, int.class);
116 				winRegEnumValue.setAccessible(true);
117 				winRegQueryInfo = clz.getDeclaredMethod("WindowsRegQueryInfoKey1", int.class);
118 				winRegQueryInfo.setAccessible(true);
119 			} catch (Exception e) {
120 				initialisationState = 1;
121 				throw new IllegalStateException("Cannot access registry", e);
122 			}
123 		}
124 	}
125 	
126 	
127 	private static byte[] toCstr(String str) {
128 		byte[] result = new byte[str.length() + 1];
129 		for (int i = 0; i < str.length(); i++) {
130 			result[i] = (byte) str.charAt(i);
131 		}
132 		result[str.length()] = 0;
133 		return result;
134 	}
135 }