Ticket #23725: 23725.patch
| File 23725.patch, 14.3 KB (added by , 19 months ago) |
|---|
-
src/org/openstreetmap/josm/tools/WinRegistry.java
Subject: [PATCH] 23725 --- IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 diff --git a/src/org/openstreetmap/josm/tools/WinRegistry.java b/src/org/openstreetmap/josm/tools/WinRegistry.java
a b 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 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 /** 50 * Wrapper for Windows registry API RegOpenKey(long, byte[], int) 51 * Returns {@code long[]} 52 */ 53 private static final Method REG_OPEN_KEY; 54 /** 55 * Wrapper for Windows registry API RegCloseKey(long) 56 * Returns {@code int} 57 */ 58 private static final Method REG_CLOSE_KEY; 59 /** 60 * Wrapper for Windows registry API RegQueryValueEx(long, byte[]) 61 * Returns {@code byte[]} 62 */ 63 private static final Method REG_QUERY_VALUE_EX; 64 /** 65 * Wrapper for Windows registry API RegEnumValue(long, int, int) 66 * Returns {@code byte[]} 67 */ 68 private static final Method REG_ENUM_VALUE; 69 /** 70 * Wrapper for RegQueryInfoKey(long) 71 * Returns {@code long[]} 72 */ 73 private static final Method REG_QUERY_INFO_KEY; 74 /** 75 * Wrapper for RegEnumKeyEx(long, int, int) 76 * Returns {@code byte[]} 77 */ 78 private static final Method REG_ENUM_KEY_EX; 57 79 58 80 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);81 REG_OPEN_KEY = getDeclaredMethod("WindowsRegOpenKey", long.class, byte[].class, int.class); 82 REG_CLOSE_KEY = getDeclaredMethod("WindowsRegCloseKey", long.class); 83 REG_QUERY_VALUE_EX = getDeclaredMethod("WindowsRegQueryValueEx", long.class, byte[].class); 84 REG_ENUM_VALUE = getDeclaredMethod("WindowsRegEnumValue", long.class, int.class, int.class); 85 REG_QUERY_INFO_KEY = getDeclaredMethod("WindowsRegQueryInfoKey1", long.class); 86 REG_ENUM_KEY_EX = getDeclaredMethod("WindowsRegEnumKeyEx", long.class, int.class, int.class); 87 ReflectionUtils.setObjectsAccessible(REG_OPEN_KEY, REG_CLOSE_KEY, REG_QUERY_VALUE_EX, REG_ENUM_VALUE, REG_QUERY_INFO_KEY, REG_ENUM_KEY_EX); 66 88 } 67 89 68 90 private static Method getDeclaredMethod(String name, Class<?>... parameterTypes) { 69 91 try { 70 return userClass.getDeclaredMethod(name, parameterTypes);92 return USER_CLASS.getDeclaredMethod(name, parameterTypes); 71 93 } 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 94 Logging.log(Logging.LEVEL_ERROR, "Unable to find WindowsReg method", e); 80 95 return null; 81 96 } catch (RuntimeException e) { … … 84 99 } 85 100 } 86 101 87 private static Number hkey(int key) {88 return java11 ? ((Number) Long.valueOf(key)) : ((Number) Integer.valueOf(key));89 }90 91 102 private WinRegistry() { 92 103 // Hide default constructor for utilities classes 93 104 } … … 101 112 * @throws IllegalArgumentException if hkey not HKEY_CURRENT_USER/HKEY_LOCAL_MACHINE 102 113 * @throws IllegalAccessException if Java language access control is enforced and the underlying method is inaccessible 103 114 * @throws InvocationTargetException if the underlying method throws an exception 115 * @since xxx (method definition) 104 116 */ 105 public static String readString( inthkey, String key, String valueName)117 public static String readString(long hkey, String key, String valueName) 106 118 throws IllegalAccessException, InvocationTargetException { 107 119 if (hkey == HKEY_LOCAL_MACHINE) { 108 return readString( systemRoot, hkey, key, valueName);120 return readString(SYSTEM_ROOT, hkey, key, valueName); 109 121 } else if (hkey == HKEY_CURRENT_USER) { 110 return readString( userRoot, hkey, key, valueName);122 return readString(USER_ROOT, hkey, key, valueName); 111 123 } else { 112 124 throw new IllegalArgumentException("hkey=" + hkey); 113 125 } … … 122 134 * @throws IllegalAccessException if Java language access control is enforced and the underlying method is inaccessible 123 135 * @throws InvocationTargetException if the underlying method throws an exception 124 136 */ 125 public static Map<String, String> readStringValues( inthkey, String key)137 public static Map<String, String> readStringValues(long hkey, String key) 126 138 throws IllegalAccessException, InvocationTargetException { 127 139 if (hkey == HKEY_LOCAL_MACHINE) { 128 return readStringValues( systemRoot, hkey, key);140 return readStringValues(SYSTEM_ROOT, hkey, key); 129 141 } else if (hkey == HKEY_CURRENT_USER) { 130 return readStringValues( userRoot, hkey, key);142 return readStringValues(USER_ROOT, hkey, key); 131 143 } else { 132 144 throw new IllegalArgumentException("hkey=" + hkey); 133 145 } … … 142 154 * @throws IllegalAccessException if Java language access control is enforced and the underlying method is inaccessible 143 155 * @throws InvocationTargetException if the underlying method throws an exception 144 156 */ 145 public static List<String> readStringSubKeys( inthkey, String key)157 public static List<String> readStringSubKeys(long hkey, String key) 146 158 throws IllegalAccessException, InvocationTargetException { 147 159 if (hkey == HKEY_LOCAL_MACHINE) { 148 return readStringSubKeys( systemRoot, hkey, key);160 return readStringSubKeys(SYSTEM_ROOT, hkey, key); 149 161 } else if (hkey == HKEY_CURRENT_USER) { 150 return readStringSubKeys( userRoot, hkey, key);162 return readStringSubKeys(USER_ROOT, hkey, key); 151 163 } else { 152 164 throw new IllegalArgumentException("hkey=" + hkey); 153 165 } … … 155 167 156 168 // ===================== 157 169 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[]) { 170 private static long getNumber(Object array, int index) { 171 if (array instanceof long[]) { 162 172 return ((long[]) array)[index]; 163 173 } 164 174 throw new IllegalArgumentException(); 165 175 } 166 176 167 private static String readString(Preferences root, inthkey, String key, String value)177 private static String readString(Preferences root, long hkey, String key, String value) 168 178 throws IllegalAccessException, InvocationTargetException { 169 if ( regOpenKey == null || regQueryValueEx == null || regCloseKey== null) {179 if (REG_OPEN_KEY == null || REG_QUERY_VALUE_EX == null || REG_CLOSE_KEY == null) { 170 180 return null; 171 181 } 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) { 182 Object handles = REG_OPEN_KEY.invoke(root, hkey, toCstr(key), KEY_READ); 183 if (getNumber(handles, 1) != REG_SUCCESS) { 175 184 return null; 176 185 } 177 byte[] valb = (byte[]) regQueryValueEx.invoke(root, getNumber(handles, 0), toCstr(value));178 regCloseKey.invoke(root, getNumber(handles, 0));186 byte[] valb = (byte[]) REG_QUERY_VALUE_EX.invoke(root, getNumber(handles, 0), toCstr(value)); 187 REG_CLOSE_KEY.invoke(root, getNumber(handles, 0)); 179 188 return (valb != null ? new String(valb, StandardCharsets.UTF_8).trim() : null); 180 189 } 181 190 182 private static Map<String, String> readStringValues(Preferences root, inthkey, String key)191 private static Map<String, String> readStringValues(Preferences root, long hkey, String key) 183 192 throws IllegalAccessException, InvocationTargetException { 184 if ( regOpenKey == null || regQueryInfoKey == null || regEnumValue == null || regCloseKey== null) {193 if (REG_OPEN_KEY == null || REG_QUERY_INFO_KEY == null || REG_ENUM_VALUE == null || REG_CLOSE_KEY == null) { 185 194 return Collections.emptyMap(); 186 195 } 187 196 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) { 197 Object handles = REG_OPEN_KEY.invoke(root, hkey, toCstr(key), KEY_READ); 198 if (getNumber(handles, 1) != REG_SUCCESS) { 191 199 return Collections.emptyMap(); 192 200 } 193 // Need to capture both int[] (Java 8-10) and long[] (Java 11+) 194 Object info = regQueryInfoKey.invoke(root, getNumber(handles, 0)); 201 Object info = REG_QUERY_INFO_KEY.invoke(root, getNumber(handles, 0)); 195 202 196 int count = getNumber(info, 0).intValue();197 int maxlen = getNumber(info, 3).intValue();203 int count = Math.toIntExact(getNumber(info, 0)); 204 int maxlen = Math.toIntExact(getNumber(info, 3)); 198 205 for (int index = 0; index < count; index++) { 199 byte[] name = (byte[]) regEnumValue.invoke(root, getNumber(handles, 0), Integer.valueOf(index), Integer.valueOf(maxlen + 1));206 byte[] name = (byte[]) REG_ENUM_VALUE.invoke(root, getNumber(handles, 0), index, maxlen + 1); 200 207 String value = readString(hkey, key, new String(name, StandardCharsets.UTF_8)); 201 208 results.put(new String(name, StandardCharsets.UTF_8).trim(), value); 202 209 } 203 regCloseKey.invoke(root, getNumber(handles, 0));210 REG_CLOSE_KEY.invoke(root, getNumber(handles, 0)); 204 211 return Collections.unmodifiableMap(results); 205 212 } 206 213 207 private static List<String> readStringSubKeys(Preferences root, inthkey, String key)214 private static List<String> readStringSubKeys(Preferences root, long hkey, String key) 208 215 throws IllegalAccessException, InvocationTargetException { 209 if ( regOpenKey == null || regQueryInfoKey == null || regEnumKeyEx == null || regCloseKey== null) {216 if (REG_OPEN_KEY == null || REG_QUERY_INFO_KEY == null || REG_ENUM_KEY_EX == null || REG_CLOSE_KEY == null) { 210 217 return Collections.emptyList(); 211 218 } 212 219 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) { 220 Object handles = REG_OPEN_KEY.invoke(root, hkey, toCstr(key), KEY_READ); 221 if (getNumber(handles, 1) != REG_SUCCESS) { 216 222 return Collections.emptyList(); 217 223 } 218 // Need to capture both int[] (Java 8-10) and long[] (Java 11+) 219 Object info = regQueryInfoKey.invoke(root, getNumber(handles, 0)); 224 Object info = REG_QUERY_INFO_KEY.invoke(root, getNumber(handles, 0)); 220 225 221 int count = getNumber(info, 0).intValue();222 int maxlen = getNumber(info, 3).intValue();226 int count = Math.toIntExact(getNumber(info, 0)); 227 int maxlen = Math.toIntExact(getNumber(info, 3)); 223 228 for (int index = 0; index < count; index++) { 224 byte[] name = (byte[]) regEnumKeyEx.invoke(root, getNumber(handles, 0), Integer.valueOf(index), Integer.valueOf(maxlen + 1));229 byte[] name = (byte[]) REG_ENUM_KEY_EX.invoke(root, getNumber(handles, 0), index, maxlen + 1); 225 230 results.add(new String(name, StandardCharsets.UTF_8).trim()); 226 231 } 227 regCloseKey.invoke(root, getNumber(handles, 0));232 REG_CLOSE_KEY.invoke(root, getNumber(handles, 0)); 228 233 return Collections.unmodifiableList(results); 229 234 } 230 235
