Changeset 19100 in josm for trunk/src/org/openstreetmap
- Timestamp:
- 2024-06-11T21:21:51+02:00 (5 months ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/tools/WinRegistry.java
r16628 r19100 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 /** … … 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 1174 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; … … 83 101 return null; 84 102 } 85 }86 87 private static Number hkey(int key) {88 return java11 ? ((Number) Long.valueOf(key)) : ((Number) Integer.valueOf(key));89 103 } 90 104 … … 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 104 */ 105 public static String readString(int hkey, String key, String valueName) 118 * @since 19100 (method definition) 119 */ 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 } … … 123 138 * @throws InvocationTargetException if the underlying method throws an exception 124 139 */ 125 public static Map<String, String> readStringValues( inthkey, 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 } … … 143 158 * @throws InvocationTargetException if the underlying method throws an exception 144 159 */ 145 public static List<String> readStringSubKeys( inthkey, 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 } … … 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 } … … 165 178 } 166 179 167 private static String readString(Preferences root, int hkey, String key, String value) 168 throws IllegalAccessException, InvocationTargetException { 169 if (regOpenKey == null || regQueryValueEx == null || regCloseKey == null) { 170 return null; 171 } 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) { 175 return null; 176 } 177 byte[] valb = (byte[]) regQueryValueEx.invoke(root, getNumber(handles, 0), toCstr(value)); 178 regCloseKey.invoke(root, getNumber(handles, 0)); 180 private static String readString(Preferences root, long hkey, String key, String value) 181 throws IllegalAccessException, InvocationTargetException { 182 if (REG_OPEN_KEY == null || REG_QUERY_VALUE_EX == null || REG_CLOSE_KEY == null) { 183 return null; 184 } 185 Object handles = REG_OPEN_KEY.invoke(root, hkey, toCstr(key), KEY_READ); 186 if (getNumber(handles, 1) != REG_SUCCESS) { 187 return null; 188 } 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, inthkey, String key)183 throws IllegalAccessException, InvocationTargetException { 184 if ( regOpenKey == null || regQueryInfoKey == null || regEnumValue == null || regCloseKey== null) {194 private static Map<String, String> readStringValues(Preferences root, long hkey, String key) 195 throws IllegalAccessException, InvocationTargetException { 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)); 195 196 int count = getNumber(info, 0).intValue(); 197 int maxlen = getNumber(info, 3).intValue(); 204 Object info = REG_QUERY_INFO_KEY.invoke(root, getNumber(handles, 0)); 205 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, inthkey, String key)208 throws IllegalAccessException, InvocationTargetException { 209 if ( regOpenKey == null || regQueryInfoKey == null || regEnumKeyEx == null || regCloseKey== null) {217 private static List<String> readStringSubKeys(Preferences root, long hkey, String key) 218 throws IllegalAccessException, InvocationTargetException { 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)); 220 221 int count = getNumber(info, 0).intValue(); 222 int maxlen = getNumber(info, 3).intValue(); 227 Object info = REG_QUERY_INFO_KEY.invoke(root, getNumber(handles, 0)); 228 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 }
Note:
See TracChangeset
for help on using the changeset viewer.