Ticket #23725: 23725.patch

File 23725.patch, 14.3 KB (added by taylor.smock, 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  
    2828     * colors, printers, network connections, and application preferences.
    2929     * See <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/ms724836(v=vs.85).aspx">Predefined Keys</a>
    3030     */
    31     public static final int HKEY_CURRENT_USER = 0x80000001;
     31    public static final long HKEY_CURRENT_USER = 0x80000001L;
    3232
    3333    /**
    3434     * Registry entries subordinate to this key define the physical state of the computer, including data about the bus type,
     
    3838     * names and the location of the server), and other system information.
    3939     * See <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/ms724836(v=vs.85).aspx">Predefined Keys</a>
    4040     */
    41     public static final int HKEY_LOCAL_MACHINE = 0x80000002;
     41    public static final long HKEY_LOCAL_MACHINE = 0x80000002L;
    4242
    4343    private static final long REG_SUCCESS = 0L;
    4444
    4545    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;
    5779
    5880    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);
    6688    }
    6789
    6890    private static Method getDeclaredMethod(String name, Class<?>... parameterTypes) {
    6991        try {
    70             return userClass.getDeclaredMethod(name, parameterTypes);
     92            return USER_CLASS.getDeclaredMethod(name, parameterTypes);
    7193        } 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 11
    74                 Class<?>[] parameterTypesCopy = Utils.copyArray(parameterTypes);
    75                 parameterTypesCopy[0] = long.class;
    76                 java11 = true;
    77                 return getDeclaredMethod(name, parameterTypesCopy);
    78             }
    7994            Logging.log(Logging.LEVEL_ERROR, "Unable to find WindowsReg method", e);
    8095            return null;
    8196        } catch (RuntimeException e) {
     
    8499        }
    85100    }
    86101
    87     private static Number hkey(int key) {
    88         return java11 ? ((Number) Long.valueOf(key)) : ((Number) Integer.valueOf(key));
    89     }
    90 
    91102    private WinRegistry() {
    92103        // Hide default constructor for utilities classes
    93104    }
     
    101112     * @throws IllegalArgumentException if hkey not HKEY_CURRENT_USER/HKEY_LOCAL_MACHINE
    102113     * @throws IllegalAccessException if Java language access control is enforced and the underlying method is inaccessible
    103114     * @throws InvocationTargetException if the underlying method throws an exception
     115     * @since xxx (method definition)
    104116     */
    105     public static String readString(int hkey, String key, String valueName)
     117    public static String readString(long hkey, String key, String valueName)
    106118            throws IllegalAccessException, InvocationTargetException {
    107119        if (hkey == HKEY_LOCAL_MACHINE) {
    108             return readString(systemRoot, hkey, key, valueName);
     120            return readString(SYSTEM_ROOT, hkey, key, valueName);
    109121        } else if (hkey == HKEY_CURRENT_USER) {
    110             return readString(userRoot, hkey, key, valueName);
     122            return readString(USER_ROOT, hkey, key, valueName);
    111123        } else {
    112124            throw new IllegalArgumentException("hkey=" + hkey);
    113125        }
     
    122134     * @throws IllegalAccessException if Java language access control is enforced and the underlying method is inaccessible
    123135     * @throws InvocationTargetException if the underlying method throws an exception
    124136     */
    125     public static Map<String, String> readStringValues(int hkey, String key)
     137    public static Map<String, String> readStringValues(long hkey, String key)
    126138            throws IllegalAccessException, InvocationTargetException {
    127139        if (hkey == HKEY_LOCAL_MACHINE) {
    128             return readStringValues(systemRoot, hkey, key);
     140            return readStringValues(SYSTEM_ROOT, hkey, key);
    129141        } else if (hkey == HKEY_CURRENT_USER) {
    130             return readStringValues(userRoot, hkey, key);
     142            return readStringValues(USER_ROOT, hkey, key);
    131143        } else {
    132144            throw new IllegalArgumentException("hkey=" + hkey);
    133145        }
     
    142154     * @throws IllegalAccessException if Java language access control is enforced and the underlying method is inaccessible
    143155     * @throws InvocationTargetException if the underlying method throws an exception
    144156     */
    145     public static List<String> readStringSubKeys(int hkey, String key)
     157    public static List<String> readStringSubKeys(long hkey, String key)
    146158            throws IllegalAccessException, InvocationTargetException {
    147159        if (hkey == HKEY_LOCAL_MACHINE) {
    148             return readStringSubKeys(systemRoot, hkey, key);
     160            return readStringSubKeys(SYSTEM_ROOT, hkey, key);
    149161        } else if (hkey == HKEY_CURRENT_USER) {
    150             return readStringSubKeys(userRoot, hkey, key);
     162            return readStringSubKeys(USER_ROOT, hkey, key);
    151163        } else {
    152164            throw new IllegalArgumentException("hkey=" + hkey);
    153165        }
     
    155167
    156168    // =====================
    157169
    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[]) {
    162172            return ((long[]) array)[index];
    163173        }
    164174        throw new IllegalArgumentException();
    165175    }
    166176
    167     private static String readString(Preferences root, int hkey, String key, String value)
     177    private static String readString(Preferences root, long hkey, String key, String value)
    168178            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) {
    170180            return null;
    171181        }
    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) {
    175184            return null;
    176185        }
    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));
    179188        return (valb != null ? new String(valb, StandardCharsets.UTF_8).trim() : null);
    180189    }
    181190
    182     private static Map<String, String> readStringValues(Preferences root, int hkey, String key)
     191    private static Map<String, String> readStringValues(Preferences root, long hkey, String key)
    183192            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) {
    185194            return Collections.emptyMap();
    186195        }
    187196        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) {
    191199            return Collections.emptyMap();
    192200        }
    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));
    195202
    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));
    198205        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);
    200207            String value = readString(hkey, key, new String(name, StandardCharsets.UTF_8));
    201208            results.put(new String(name, StandardCharsets.UTF_8).trim(), value);
    202209        }
    203         regCloseKey.invoke(root, getNumber(handles, 0));
     210        REG_CLOSE_KEY.invoke(root, getNumber(handles, 0));
    204211        return Collections.unmodifiableMap(results);
    205212    }
    206213
    207     private static List<String> readStringSubKeys(Preferences root, int hkey, String key)
     214    private static List<String> readStringSubKeys(Preferences root, long hkey, String key)
    208215            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) {
    210217            return Collections.emptyList();
    211218        }
    212219        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) {
    216222            return Collections.emptyList();
    217223        }
    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));
    220225
    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));
    223228        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);
    225230            results.add(new String(name, StandardCharsets.UTF_8).trim());
    226231        }
    227         regCloseKey.invoke(root, getNumber(handles, 0));
     232        REG_CLOSE_KEY.invoke(root, getNumber(handles, 0));
    228233        return Collections.unmodifiableList(results);
    229234    }
    230235