001package com.randomnoun.common; 002 003/* (c) 2013 randomnoun. All Rights Reserved. This work is licensed under a 004 * BSD Simplified License. (http://www.randomnoun.com/bsd-simplified.html) 005 */ 006 007/** Java hack to access windows registries. Relies on the sun implementation 008 * of the Preferences class. 009 * 010 * <p>Technique stolen from 011 * http://snipplr.com/view/6620/accessing-windows-registry-in-java/ 012 * 013 * <p>Probably better to JNI-wrap this, but hey, who has time for that. 014 * 015 * 016 */ 017 018import java.lang.reflect.Method; 019import java.util.prefs.Preferences; 020 021public class Registry { 022 023 // private static final int HKEY_CURRENT_USER = 0x80000001; 024 // private static final int KEY_QUERY_VALUE = 1; 025 // private static final int KEY_SET_VALUE = 2; 026 private static final int KEY_READ = 0x20019; 027 028 private static int initialisationState = 0; 029 030 // java internals, bit nasty all of this being static 031 private static final Preferences userRoot = Preferences.userRoot(); 032 private static final Preferences systemRoot = Preferences.systemRoot(); 033 private static final Class<?> clz = userRoot.getClass(); 034 private static Method winRegQueryValue; 035 private static Method winRegEnumValue; 036 private static Method winRegQueryInfo; 037 private static Method openKey; 038 private static Method closeKey; 039 040 041 // you'd better hope these methods are threadsafe 042 public static String getSystemValue(String registryKey, String key) { 043 initialise(); 044 045 byte[] valb = null; 046 String vals = null; 047 Integer handle = -1; 048 049 // Query for IE version 050 // key = "SOFTWARE\\Microsoft\\Internet Explorer#Version"; 051 try { 052 handle = (Integer) openKey.invoke(systemRoot, toCstr(registryKey), 053 KEY_READ, KEY_READ); 054 valb = (byte[]) winRegQueryValue.invoke(systemRoot, handle, 055 toCstr(key)); 056 vals = (valb != null ? new String(valb).trim() : null); 057 closeKey.invoke(Preferences.systemRoot(), handle); 058 } catch (Exception e) { 059 if (handle!=-1) { 060 try { 061 closeKey.invoke(Preferences.systemRoot(), handle); 062 } catch (Exception e2) { 063 throw new IllegalArgumentException("Error reading registry '" + registryKey + "', key '" + key + "'; (and could not close handle " + handle + ": " + e2.getMessage() + ")", e); 064 } 065 } 066 throw new IllegalArgumentException("Error reading registry key '" + registryKey + "', key '" + key + "'", e); 067 } 068 return vals; 069 } 070 071 public static String getUserValue(String registryKey, String key) { 072 initialise(); 073 074 byte[] valb = null; 075 String vals = null; 076 Integer handle = -1; 077 078 // Query Internet Settings for Proxy 079 //key = "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings#ProxyServer"; 080 try { 081 handle = (Integer) openKey.invoke(userRoot, toCstr(registryKey), KEY_READ, 082 KEY_READ); 083 valb = (byte[]) winRegQueryValue.invoke(userRoot, 084 handle.intValue(), toCstr(key)); 085 vals = (valb != null ? new String(valb).trim() : null); 086 closeKey.invoke(Preferences.userRoot(), handle); 087 } catch (Exception e) { 088 if (handle!=-1) { 089 try { 090 closeKey.invoke(Preferences.systemRoot(), handle); 091 } catch (Exception e2) { 092 throw new IllegalArgumentException("Error reading registry '" + registryKey + "', key '" + key + "'; (and could not close handle " + handle + ": " + e2.getMessage() + ")", e); 093 } 094 } 095 throw new IllegalArgumentException("Error reading registry key '" + registryKey + "', key '" + key + "'", e); 096 } 097 return vals; 098 } 099 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}