jdk/src/java.prefs/windows/classes/java/util/prefs/WindowsPreferences.java
changeset 30641 701f6f90dc0b
parent 30043 b0dd05ec3db1
child 30789 9eca83469588
equal deleted inserted replaced
30640:3dba338b5d00 30641:701f6f90dc0b
    60     private static PlatformLogger logger;
    60     private static PlatformLogger logger;
    61 
    61 
    62     /**
    62     /**
    63      * Windows registry path to <tt>Preferences</tt>'s root nodes.
    63      * Windows registry path to <tt>Preferences</tt>'s root nodes.
    64      */
    64      */
    65     private static final byte[] WINDOWS_ROOT_PATH
    65     private static final byte[] WINDOWS_ROOT_PATH =
    66                                = stringToByteArray("Software\\JavaSoft\\Prefs");
    66         stringToByteArray("Software\\JavaSoft\\Prefs");
    67 
    67 
    68     /**
    68     /**
    69      * Windows handles to <tt>HKEY_CURRENT_USER</tt> and
    69      * Windows handles to <tt>HKEY_CURRENT_USER</tt> and
    70      * <tt>HKEY_LOCAL_MACHINE</tt> hives.
    70      * <tt>HKEY_LOCAL_MACHINE</tt> hives.
    71      */
    71      */
   145 
   145 
   146     /**
   146     /**
   147      * Java wrapper for Windows registry API RegOpenKey()
   147      * Java wrapper for Windows registry API RegOpenKey()
   148      */
   148      */
   149     private static native int[] WindowsRegOpenKey(int hKey, byte[] subKey,
   149     private static native int[] WindowsRegOpenKey(int hKey, byte[] subKey,
   150                                                          int securityMask);
   150                                                   int securityMask);
   151     /**
   151     /**
   152      * Retries RegOpenKey() MAX_ATTEMPTS times before giving up.
   152      * Retries RegOpenKey() MAX_ATTEMPTS times before giving up.
   153      */
   153      */
   154     private static int[] WindowsRegOpenKey1(int hKey, byte[] subKey,
   154     private static int[] WindowsRegOpenKey1(int hKey, byte[] subKey,
   155                                                       int securityMask) {
   155                                             int securityMask) {
   156         int[] result = WindowsRegOpenKey(hKey, subKey, securityMask);
   156         int[] result = WindowsRegOpenKey(hKey, subKey, securityMask);
   157         if (result[ERROR_CODE] == ERROR_SUCCESS) {
   157         if (result[ERROR_CODE] == ERROR_SUCCESS) {
   158             return result;
   158             return result;
   159         } else if (result[ERROR_CODE] == ERROR_FILE_NOT_FOUND) {
   159         } else if (result[ERROR_CODE] == ERROR_FILE_NOT_FOUND) {
   160             logger().warning("Trying to recreate Windows registry node " +
   160             logger().warning("Trying to recreate Windows registry node " +
   165             WindowsRegCloseKey(handle);
   165             WindowsRegCloseKey(handle);
   166             return WindowsRegOpenKey(hKey, subKey, securityMask);
   166             return WindowsRegOpenKey(hKey, subKey, securityMask);
   167         } else if (result[ERROR_CODE] != ERROR_ACCESS_DENIED) {
   167         } else if (result[ERROR_CODE] != ERROR_ACCESS_DENIED) {
   168             long sleepTime = INIT_SLEEP_TIME;
   168             long sleepTime = INIT_SLEEP_TIME;
   169             for (int i = 0; i < MAX_ATTEMPTS; i++) {
   169             for (int i = 0; i < MAX_ATTEMPTS; i++) {
   170             try {
   170                 try {
   171                 Thread.sleep(sleepTime);
   171                     Thread.sleep(sleepTime);
   172             } catch(InterruptedException e) {
   172                 } catch(InterruptedException e) {
   173                 return result;
   173                     return result;
   174             }
   174                 }
   175             sleepTime *= 2;
   175                 sleepTime *= 2;
   176             result = WindowsRegOpenKey(hKey, subKey, securityMask);
   176                 result = WindowsRegOpenKey(hKey, subKey, securityMask);
   177             if (result[ERROR_CODE] == ERROR_SUCCESS) {
   177                 if (result[ERROR_CODE] == ERROR_SUCCESS) {
   178                 return result;
   178                     return result;
   179             }
   179                 }
   180             }
   180             }
   181         }
   181         }
   182         return result;
   182         return result;
   183     }
   183     }
   184 
   184 
   196      * Retries RegCreateKeyEx() MAX_ATTEMPTS times before giving up.
   196      * Retries RegCreateKeyEx() MAX_ATTEMPTS times before giving up.
   197      */
   197      */
   198     private static int[] WindowsRegCreateKeyEx1(int hKey, byte[] subKey) {
   198     private static int[] WindowsRegCreateKeyEx1(int hKey, byte[] subKey) {
   199         int[] result = WindowsRegCreateKeyEx(hKey, subKey);
   199         int[] result = WindowsRegCreateKeyEx(hKey, subKey);
   200         if (result[ERROR_CODE] == ERROR_SUCCESS) {
   200         if (result[ERROR_CODE] == ERROR_SUCCESS) {
   201                 return result;
   201             return result;
   202             } else {
   202         } else {
   203                 long sleepTime = INIT_SLEEP_TIME;
   203             long sleepTime = INIT_SLEEP_TIME;
   204                 for (int i = 0; i < MAX_ATTEMPTS; i++) {
   204             for (int i = 0; i < MAX_ATTEMPTS; i++) {
   205                 try {
   205                 try {
   206                     Thread.sleep(sleepTime);
   206                     Thread.sleep(sleepTime);
   207                 } catch(InterruptedException e) {
   207                 } catch(InterruptedException e) {
   208                     return result;
   208                     return result;
   209                 }
   209                 }
   210                 sleepTime *= 2;
   210                 sleepTime *= 2;
   211                 result = WindowsRegCreateKeyEx(hKey, subKey);
   211                 result = WindowsRegCreateKeyEx(hKey, subKey);
   212                 if (result[ERROR_CODE] == ERROR_SUCCESS) {
   212                 if (result[ERROR_CODE] == ERROR_SUCCESS) {
   213                 return result;
   213                     return result;
   214                 }
   214                 }
   215             }
   215             }
   216         }
   216         }
   217         return result;
   217         return result;
   218     }
   218     }
   230      * Retries RegFlushKey() MAX_ATTEMPTS times before giving up.
   230      * Retries RegFlushKey() MAX_ATTEMPTS times before giving up.
   231      */
   231      */
   232     private static int WindowsRegFlushKey1(int hKey) {
   232     private static int WindowsRegFlushKey1(int hKey) {
   233         int result = WindowsRegFlushKey(hKey);
   233         int result = WindowsRegFlushKey(hKey);
   234         if (result == ERROR_SUCCESS) {
   234         if (result == ERROR_SUCCESS) {
   235                 return result;
   235             return result;
   236             } else {
   236         } else {
   237                 long sleepTime = INIT_SLEEP_TIME;
   237             long sleepTime = INIT_SLEEP_TIME;
   238                 for (int i = 0; i < MAX_ATTEMPTS; i++) {
   238             for (int i = 0; i < MAX_ATTEMPTS; i++) {
   239                 try {
   239                 try {
   240                     Thread.sleep(sleepTime);
   240                     Thread.sleep(sleepTime);
   241                 } catch(InterruptedException e) {
   241                 } catch(InterruptedException e) {
   242                     return result;
   242                     return result;
   243                 }
   243                 }
   244                 sleepTime *= 2;
   244                 sleepTime *= 2;
   245                 result = WindowsRegFlushKey(hKey);
   245                 result = WindowsRegFlushKey(hKey);
   246                 if (result == ERROR_SUCCESS) {
   246                 if (result == ERROR_SUCCESS) {
   247                 return result;
   247                     return result;
   248                 }
   248                 }
   249             }
   249             }
   250         }
   250         }
   251         return result;
   251         return result;
   252     }
   252     }
   253 
   253 
   254     /**
   254     /**
   255      * Java wrapper for Windows registry API RegQueryValueEx()
   255      * Java wrapper for Windows registry API RegQueryValueEx()
   256      */
   256      */
   257     private static native byte[] WindowsRegQueryValueEx(int hKey,
   257     private static native byte[] WindowsRegQueryValueEx(int hKey,
   258                                                               byte[] valueName);
   258                                                         byte[] valueName);
   259     /**
   259     /**
   260      * Java wrapper for Windows registry API RegSetValueEx()
   260      * Java wrapper for Windows registry API RegSetValueEx()
   261      */
   261      */
   262     private static native int WindowsRegSetValueEx(int hKey, byte[] valueName,
   262     private static native int WindowsRegSetValueEx(int hKey, byte[] valueName,
   263                                                          byte[] value);
   263                                                    byte[] value);
   264     /**
   264     /**
   265      * Retries RegSetValueEx() MAX_ATTEMPTS times before giving up.
   265      * Retries RegSetValueEx() MAX_ATTEMPTS times before giving up.
   266      */
   266      */
   267     private static int WindowsRegSetValueEx1(int hKey, byte[] valueName,
   267     private static int WindowsRegSetValueEx1(int hKey, byte[] valueName,
   268                                                          byte[] value) {
   268                                              byte[] value) {
   269         int result = WindowsRegSetValueEx(hKey, valueName, value);
   269         int result = WindowsRegSetValueEx(hKey, valueName, value);
   270         if (result == ERROR_SUCCESS) {
   270         if (result == ERROR_SUCCESS) {
   271                 return result;
   271             return result;
   272             } else {
   272         } else {
   273                 long sleepTime = INIT_SLEEP_TIME;
   273             long sleepTime = INIT_SLEEP_TIME;
   274                 for (int i = 0; i < MAX_ATTEMPTS; i++) {
   274             for (int i = 0; i < MAX_ATTEMPTS; i++) {
   275                 try {
   275                 try {
   276                     Thread.sleep(sleepTime);
   276                     Thread.sleep(sleepTime);
   277                 } catch(InterruptedException e) {
   277                 } catch(InterruptedException e) {
   278                     return result;
   278                     return result;
   279                 }
   279                 }
   280                 sleepTime *= 2;
   280                 sleepTime *= 2;
   281                 result = WindowsRegSetValueEx(hKey, valueName, value);
   281                 result = WindowsRegSetValueEx(hKey, valueName, value);
   282                 if (result == ERROR_SUCCESS) {
   282                 if (result == ERROR_SUCCESS) {
   283                 return result;
   283                     return result;
   284                 }
   284                 }
   285             }
   285             }
   286         }
   286         }
   287         return result;
   287         return result;
   288     }
   288     }
   301      * Retries RegQueryInfoKey() MAX_ATTEMPTS times before giving up.
   301      * Retries RegQueryInfoKey() MAX_ATTEMPTS times before giving up.
   302      */
   302      */
   303     private static int[] WindowsRegQueryInfoKey1(int hKey) {
   303     private static int[] WindowsRegQueryInfoKey1(int hKey) {
   304         int[] result = WindowsRegQueryInfoKey(hKey);
   304         int[] result = WindowsRegQueryInfoKey(hKey);
   305         if (result[ERROR_CODE] == ERROR_SUCCESS) {
   305         if (result[ERROR_CODE] == ERROR_SUCCESS) {
   306                 return result;
   306             return result;
   307             } else {
   307         } else {
   308                 long sleepTime = INIT_SLEEP_TIME;
   308             long sleepTime = INIT_SLEEP_TIME;
   309                 for (int i = 0; i < MAX_ATTEMPTS; i++) {
   309             for (int i = 0; i < MAX_ATTEMPTS; i++) {
   310                 try {
   310                 try {
   311                     Thread.sleep(sleepTime);
   311                     Thread.sleep(sleepTime);
   312                 } catch(InterruptedException e) {
   312                 } catch(InterruptedException e) {
   313                     return result;
   313                     return result;
   314                 }
   314                 }
   315                 sleepTime *= 2;
   315                 sleepTime *= 2;
   316                 result = WindowsRegQueryInfoKey(hKey);
   316                 result = WindowsRegQueryInfoKey(hKey);
   317                 if (result[ERROR_CODE] == ERROR_SUCCESS) {
   317                 if (result[ERROR_CODE] == ERROR_SUCCESS) {
   318                 return result;
   318                     return result;
   319                 }
   319                 }
   320             }
   320             }
   321         }
   321         }
   322         return result;
   322         return result;
   323     }
   323     }
   324 
   324 
   325     /**
   325     /**
   326      * Java wrapper for Windows registry API RegEnumKeyEx()
   326      * Java wrapper for Windows registry API RegEnumKeyEx()
   327      */
   327      */
   328     private static native byte[] WindowsRegEnumKeyEx(int hKey, int subKeyIndex,
   328     private static native byte[] WindowsRegEnumKeyEx(int hKey, int subKeyIndex,
   329                                       int maxKeyLength);
   329                                                      int maxKeyLength);
   330 
   330 
   331     /**
   331     /**
   332      * Retries RegEnumKeyEx() MAX_ATTEMPTS times before giving up.
   332      * Retries RegEnumKeyEx() MAX_ATTEMPTS times before giving up.
   333      */
   333      */
   334     private static byte[] WindowsRegEnumKeyEx1(int hKey, int subKeyIndex,
   334     private static byte[] WindowsRegEnumKeyEx1(int hKey, int subKeyIndex,
   335                                       int maxKeyLength) {
   335                                                int maxKeyLength) {
   336         byte[] result = WindowsRegEnumKeyEx(hKey, subKeyIndex, maxKeyLength);
   336         byte[] result = WindowsRegEnumKeyEx(hKey, subKeyIndex, maxKeyLength);
   337         if (result != null) {
   337         if (result != null) {
   338                 return result;
   338             return result;
   339             } else {
   339         } else {
   340                 long sleepTime = INIT_SLEEP_TIME;
   340             long sleepTime = INIT_SLEEP_TIME;
   341                 for (int i = 0; i < MAX_ATTEMPTS; i++) {
   341             for (int i = 0; i < MAX_ATTEMPTS; i++) {
   342                 try {
   342                 try {
   343                     Thread.sleep(sleepTime);
   343                     Thread.sleep(sleepTime);
   344                 } catch(InterruptedException e) {
   344                 } catch(InterruptedException e) {
   345                     return result;
   345                     return result;
   346                 }
   346                 }
   347                 sleepTime *= 2;
   347                 sleepTime *= 2;
   348                 result = WindowsRegEnumKeyEx(hKey, subKeyIndex, maxKeyLength);
   348                 result = WindowsRegEnumKeyEx(hKey, subKeyIndex, maxKeyLength);
   349                 if (result != null) {
   349                 if (result != null) {
   350                 return result;
   350                     return result;
   351                 }
   351                 }
   352             }
   352             }
   353         }
   353         }
   354         return result;
   354         return result;
   355     }
   355     }
   356 
   356 
   357     /**
   357     /**
   358      * Java wrapper for Windows registry API RegEnumValue()
   358      * Java wrapper for Windows registry API RegEnumValue()
   359      */
   359      */
   360     private static native byte[] WindowsRegEnumValue(int hKey, int valueIndex,
   360     private static native byte[] WindowsRegEnumValue(int hKey, int valueIndex,
   361                                       int maxValueNameLength);
   361                                                      int maxValueNameLength);
   362     /**
   362     /**
   363      * Retries RegEnumValueEx() MAX_ATTEMPTS times before giving up.
   363      * Retries RegEnumValueEx() MAX_ATTEMPTS times before giving up.
   364      */
   364      */
   365     private static byte[] WindowsRegEnumValue1(int hKey, int valueIndex,
   365     private static byte[] WindowsRegEnumValue1(int hKey, int valueIndex,
   366                                       int maxValueNameLength) {
   366                                                int maxValueNameLength) {
   367         byte[] result = WindowsRegEnumValue(hKey, valueIndex,
   367         byte[] result = WindowsRegEnumValue(hKey, valueIndex,
   368                                                             maxValueNameLength);
   368                                             maxValueNameLength);
   369         if (result != null) {
   369         if (result != null) {
   370                 return result;
   370             return result;
   371             } else {
   371         } else {
   372                 long sleepTime = INIT_SLEEP_TIME;
   372             long sleepTime = INIT_SLEEP_TIME;
   373                 for (int i = 0; i < MAX_ATTEMPTS; i++) {
   373             for (int i = 0; i < MAX_ATTEMPTS; i++) {
   374                 try {
   374                 try {
   375                     Thread.sleep(sleepTime);
   375                     Thread.sleep(sleepTime);
   376                 } catch(InterruptedException e) {
   376                 } catch(InterruptedException e) {
   377                     return result;
   377                     return result;
   378                 }
   378                 }
   379                 sleepTime *= 2;
   379                 sleepTime *= 2;
   380                 result = WindowsRegEnumValue(hKey, valueIndex,
   380                 result = WindowsRegEnumValue(hKey, valueIndex,
   381                                                             maxValueNameLength);
   381                                              maxValueNameLength);
   382                 if (result != null) {
   382                 if (result != null) {
   383                 return result;
   383                     return result;
   384                 }
   384                 }
   385             }
   385             }
   386         }
   386         }
   387         return result;
   387         return result;
   388     }
   388     }
   402             return;
   402             return;
   403         }
   403         }
   404         int[] result =
   404         int[] result =
   405                WindowsRegCreateKeyEx1(parentNativeHandle, toWindowsName(name));
   405                WindowsRegCreateKeyEx1(parentNativeHandle, toWindowsName(name));
   406         if (result[ERROR_CODE] != ERROR_SUCCESS) {
   406         if (result[ERROR_CODE] != ERROR_SUCCESS) {
   407             logger().warning("Could not create windows registry "
   407             logger().warning("Could not create windows registry node " +
   408             + "node " + byteArrayToString(windowsAbsolutePath()) +
   408                     byteArrayToString(windowsAbsolutePath()) +
   409             " at root 0x" + Integer.toHexString(rootNativeHandle()) +
   409                     " at root 0x" + Integer.toHexString(rootNativeHandle()) +
   410             ". Windows RegCreateKeyEx(...) returned error code " +
   410                     ". Windows RegCreateKeyEx(...) returned error code " +
   411             result[ERROR_CODE] + ".");
   411                     result[ERROR_CODE] + ".");
   412             isBackingStoreAvailable = false;
   412             isBackingStoreAvailable = false;
   413             return;
   413             return;
   414         }
   414         }
   415         newNode = (result[DISPOSITION] == REG_CREATED_NEW_KEY);
   415         newNode = (result[DISPOSITION] == REG_CREATED_NEW_KEY);
   416         closeKey(parentNativeHandle);
   416         closeKey(parentNativeHandle);
   424      * Logs a warning message, if Windows Registry is unavailable.
   424      * Logs a warning message, if Windows Registry is unavailable.
   425      * @param rootNativeHandle Native handle to one of Windows top level keys.
   425      * @param rootNativeHandle Native handle to one of Windows top level keys.
   426      * @param rootDirectory Path to root directory, as a byte-encoded string.
   426      * @param rootDirectory Path to root directory, as a byte-encoded string.
   427      */
   427      */
   428     private  WindowsPreferences(int rootNativeHandle, byte[] rootDirectory) {
   428     private  WindowsPreferences(int rootNativeHandle, byte[] rootDirectory) {
   429         super(null,"");
   429         super(null, "");
   430         int[] result =
   430         int[] result =
   431                 WindowsRegCreateKeyEx1(rootNativeHandle, rootDirectory);
   431                 WindowsRegCreateKeyEx1(rootNativeHandle, rootDirectory);
   432         if (result[ERROR_CODE] != ERROR_SUCCESS) {
   432         if (result[ERROR_CODE] != ERROR_SUCCESS) {
   433             logger().warning("Could not open/create prefs root node " +
   433             logger().warning("Could not open/create prefs root node " +
   434             byteArrayToString(windowsAbsolutePath()) + " at root 0x" +
   434                     byteArrayToString(windowsAbsolutePath()) +
   435             Integer.toHexString(rootNativeHandle()) +
   435                     " at root 0x" + Integer.toHexString(rootNativeHandle()) +
   436             ". Windows RegCreateKeyEx(...) returned error code " +
   436                     ". Windows RegCreateKeyEx(...) returned error code " +
   437             result[ERROR_CODE] + ".");
   437                     result[ERROR_CODE] + ".");
   438             isBackingStoreAvailable = false;
   438             isBackingStoreAvailable = false;
   439             return;
   439             return;
   440         }
   440         }
   441         // Check if a new node
   441         // Check if a new node
   442         newNode = (result[DISPOSITION] == REG_CREATED_NEW_KEY);
   442         newNode = (result[DISPOSITION] == REG_CREATED_NEW_KEY);
   449      * @see Preferences#absolutePath()
   449      * @see Preferences#absolutePath()
   450      */
   450      */
   451     private byte[] windowsAbsolutePath() {
   451     private byte[] windowsAbsolutePath() {
   452         ByteArrayOutputStream bstream = new ByteArrayOutputStream();
   452         ByteArrayOutputStream bstream = new ByteArrayOutputStream();
   453         bstream.write(WINDOWS_ROOT_PATH, 0, WINDOWS_ROOT_PATH.length-1);
   453         bstream.write(WINDOWS_ROOT_PATH, 0, WINDOWS_ROOT_PATH.length-1);
   454         StringTokenizer tokenizer = new StringTokenizer(absolutePath(),"/");
   454         StringTokenizer tokenizer = new StringTokenizer(absolutePath(), "/");
   455         while (tokenizer.hasMoreTokens()) {
   455         while (tokenizer.hasMoreTokens()) {
   456             bstream.write((byte)'\\');
   456             bstream.write((byte)'\\');
   457             String nextName = tokenizer.nextToken();
   457             String nextName = tokenizer.nextToken();
   458             byte[] windowsNextName = toWindowsName(nextName);
   458             byte[] windowsNextName = toWindowsName(nextName);
   459             bstream.write(windowsNextName, 0, windowsNextName.length-1);
   459             bstream.write(windowsNextName, 0, windowsNextName.length-1);
   503      */
   503      */
   504     private int openKey(byte[] windowsAbsolutePath, int mask1, int mask2) {
   504     private int openKey(byte[] windowsAbsolutePath, int mask1, int mask2) {
   505         /*  Check if key's path is short enough be opened at once
   505         /*  Check if key's path is short enough be opened at once
   506             otherwise use a path-splitting procedure */
   506             otherwise use a path-splitting procedure */
   507         if (windowsAbsolutePath.length <= MAX_WINDOWS_PATH_LENGTH + 1) {
   507         if (windowsAbsolutePath.length <= MAX_WINDOWS_PATH_LENGTH + 1) {
   508              int[] result = WindowsRegOpenKey1(rootNativeHandle(),
   508             int[] result = WindowsRegOpenKey1(rootNativeHandle(),
   509                                                windowsAbsolutePath, mask1);
   509                                               windowsAbsolutePath, mask1);
   510              if (result[ERROR_CODE] == ERROR_ACCESS_DENIED && mask2 != mask1)
   510             if (result[ERROR_CODE] == ERROR_ACCESS_DENIED && mask2 != mask1)
   511                  result = WindowsRegOpenKey1(rootNativeHandle(),
   511                 result = WindowsRegOpenKey1(rootNativeHandle(),
   512                                              windowsAbsolutePath, mask2);
   512                                             windowsAbsolutePath, mask2);
   513 
   513 
   514              if (result[ERROR_CODE] != ERROR_SUCCESS) {
   514             if (result[ERROR_CODE] != ERROR_SUCCESS) {
   515                 logger().warning("Could not open windows "
   515                 logger().warning("Could not open windows registry node " +
   516                 + "registry node " + byteArrayToString(windowsAbsolutePath()) +
   516                         byteArrayToString(windowsAbsolutePath()) +
   517                 " at root 0x" + Integer.toHexString(rootNativeHandle()) +
   517                         " at root 0x" +
   518                 ". Windows RegOpenKey(...) returned error code " +
   518                         Integer.toHexString(rootNativeHandle()) +
   519                 result[ERROR_CODE] + ".");
   519                         ". Windows RegOpenKey(...) returned error code " +
       
   520                         result[ERROR_CODE] + ".");
   520                 result[NATIVE_HANDLE] = NULL_NATIVE_HANDLE;
   521                 result[NATIVE_HANDLE] = NULL_NATIVE_HANDLE;
   521                 if (result[ERROR_CODE] == ERROR_ACCESS_DENIED) {
   522                 if (result[ERROR_CODE] == ERROR_ACCESS_DENIED) {
   522                     throw new SecurityException("Could not open windows "
   523                     throw new SecurityException(
   523                 + "registry node " + byteArrayToString(windowsAbsolutePath()) +
   524                             "Could not open windows registry node " +
   524                 " at root 0x" + Integer.toHexString(rootNativeHandle()) +
   525                             byteArrayToString(windowsAbsolutePath()) +
   525                 ": Access denied");
   526                             " at root 0x" +
   526                 }
   527                             Integer.toHexString(rootNativeHandle()) +
   527              }
   528                             ": Access denied");
   528              return result[NATIVE_HANDLE];
   529                 }
       
   530             }
       
   531             return result[NATIVE_HANDLE];
   529         } else {
   532         } else {
   530             return openKey(rootNativeHandle(), windowsAbsolutePath, mask1, mask2);
   533             return openKey(rootNativeHandle(), windowsAbsolutePath, mask1, mask2);
   531         }
   534         }
   532     }
   535     }
   533 
   536 
   546      */
   549      */
   547     private int openKey(int nativeHandle, byte[] windowsRelativePath,
   550     private int openKey(int nativeHandle, byte[] windowsRelativePath,
   548                         int mask1, int mask2) {
   551                         int mask1, int mask2) {
   549     /* If the path is short enough open at once. Otherwise split the path */
   552     /* If the path is short enough open at once. Otherwise split the path */
   550         if (windowsRelativePath.length <= MAX_WINDOWS_PATH_LENGTH + 1 ) {
   553         if (windowsRelativePath.length <= MAX_WINDOWS_PATH_LENGTH + 1 ) {
   551              int[] result = WindowsRegOpenKey1(nativeHandle,
   554             int[] result = WindowsRegOpenKey1(nativeHandle,
   552                                                windowsRelativePath, mask1);
   555                                               windowsRelativePath, mask1);
   553              if (result[ERROR_CODE] == ERROR_ACCESS_DENIED && mask2 != mask1)
   556             if (result[ERROR_CODE] == ERROR_ACCESS_DENIED && mask2 != mask1)
   554                  result = WindowsRegOpenKey1(nativeHandle,
   557                 result = WindowsRegOpenKey1(nativeHandle,
   555                                              windowsRelativePath, mask2);
   558                                             windowsRelativePath, mask2);
   556 
   559 
   557              if (result[ERROR_CODE] != ERROR_SUCCESS) {
   560             if (result[ERROR_CODE] != ERROR_SUCCESS) {
   558                 logger().warning("Could not open windows "
   561                 logger().warning("Could not open windows registry node " +
   559                 + "registry node " + byteArrayToString(windowsAbsolutePath()) +
   562                         byteArrayToString(windowsAbsolutePath()) +
   560                 " at root 0x" + Integer.toHexString(nativeHandle) +
   563                         " at root 0x" + Integer.toHexString(nativeHandle) +
   561                 ". Windows RegOpenKey(...) returned error code " +
   564                         ". Windows RegOpenKey(...) returned error code " +
   562                 result[ERROR_CODE] + ".");
   565                         result[ERROR_CODE] + ".");
   563                 result[NATIVE_HANDLE] = NULL_NATIVE_HANDLE;
   566                 result[NATIVE_HANDLE] = NULL_NATIVE_HANDLE;
   564              }
   567             }
   565              return result[NATIVE_HANDLE];
   568             return result[NATIVE_HANDLE];
   566         } else {
   569         } else {
   567             int separatorPosition = -1;
   570             int separatorPosition = -1;
   568             // Be greedy - open the longest possible path
   571             // Be greedy - open the longest possible path
   569             for (int i = MAX_WINDOWS_PATH_LENGTH; i > 0; i--) {
   572             for (int i = MAX_WINDOWS_PATH_LENGTH; i > 0; i--) {
   570                 if (windowsRelativePath[i] == ((byte)'\\')) {
   573                 if (windowsRelativePath[i] == ((byte)'\\')) {
   602      * @see #openKey(int, byte[],int)
   605      * @see #openKey(int, byte[],int)
   603     */
   606     */
   604     private void closeKey(int nativeHandle) {
   607     private void closeKey(int nativeHandle) {
   605         int result = WindowsRegCloseKey(nativeHandle);
   608         int result = WindowsRegCloseKey(nativeHandle);
   606         if (result != ERROR_SUCCESS) {
   609         if (result != ERROR_SUCCESS) {
   607             logger().warning("Could not close windows "
   610             logger().warning("Could not close windows registry node " +
   608             + "registry node " + byteArrayToString(windowsAbsolutePath()) +
   611                     byteArrayToString(windowsAbsolutePath()) +
   609             " at root 0x" + Integer.toHexString(rootNativeHandle()) +
   612                     " at root 0x" +
   610             ". Windows RegCloseKey(...) returned error code " + result + ".");
   613                     Integer.toHexString(rootNativeHandle()) +
       
   614                     ". Windows RegCloseKey(...) returned error code " +
       
   615                     result + ".");
   611         }
   616         }
   612     }
   617     }
   613 
   618 
   614      /**
   619      /**
   615      * Implements <tt>AbstractPreferences</tt> <tt>putSpi()</tt> method.
   620      * Implements <tt>AbstractPreferences</tt> <tt>putSpi()</tt> method.
   625         }
   630         }
   626         int result = WindowsRegSetValueEx1(nativeHandle,
   631         int result = WindowsRegSetValueEx1(nativeHandle,
   627                 toWindowsName(javaName), toWindowsValueString(value));
   632                 toWindowsName(javaName), toWindowsValueString(value));
   628         if (result != ERROR_SUCCESS) {
   633         if (result != ERROR_SUCCESS) {
   629             logger().warning("Could not assign value to key " +
   634             logger().warning("Could not assign value to key " +
   630             byteArrayToString(toWindowsName(javaName))+ " at Windows registry node "
   635                     byteArrayToString(toWindowsName(javaName)) +
   631            + byteArrayToString(windowsAbsolutePath()) + " at root 0x"
   636                     " at Windows registry node " +
   632            + Integer.toHexString(rootNativeHandle()) +
   637                     byteArrayToString(windowsAbsolutePath()) +
   633            ". Windows RegSetValueEx(...) returned error code " + result + ".");
   638                     " at root 0x" +
       
   639                     Integer.toHexString(rootNativeHandle()) +
       
   640                     ". Windows RegSetValueEx(...) returned error code " +
       
   641                     result + ".");
   634             isBackingStoreAvailable = false;
   642             isBackingStoreAvailable = false;
   635         }
   643         }
   636         closeKey(nativeHandle);
   644         closeKey(nativeHandle);
   637     }
   645     }
   638 
   646 
   670         return;
   678         return;
   671         }
   679         }
   672         int result =
   680         int result =
   673             WindowsRegDeleteValue(nativeHandle, toWindowsName(key));
   681             WindowsRegDeleteValue(nativeHandle, toWindowsName(key));
   674         if (result != ERROR_SUCCESS && result != ERROR_FILE_NOT_FOUND) {
   682         if (result != ERROR_SUCCESS && result != ERROR_FILE_NOT_FOUND) {
   675             logger().warning("Could not delete windows registry "
   683             logger().warning("Could not delete windows registry value " +
   676             + "value " + byteArrayToString(windowsAbsolutePath())+ "\\" +
   684                     byteArrayToString(windowsAbsolutePath()) + "\\" +
   677             toWindowsName(key) + " at root 0x" +
   685                     toWindowsName(key) + " at root 0x" +
   678             Integer.toHexString(rootNativeHandle()) +
   686                     Integer.toHexString(rootNativeHandle()) +
   679             ". Windows RegDeleteValue(...) returned error code " +
   687                     ". Windows RegDeleteValue(...) returned error code " +
   680             result + ".");
   688                     result + ".");
   681             isBackingStoreAvailable = false;
   689             isBackingStoreAvailable = false;
   682         }
   690         }
   683         closeKey(nativeHandle);
   691         closeKey(nativeHandle);
   684     }
   692     }
   685 
   693 
   691      */
   699      */
   692     protected String[] keysSpi() throws BackingStoreException{
   700     protected String[] keysSpi() throws BackingStoreException{
   693         // Find out the number of values
   701         // Find out the number of values
   694         int nativeHandle = openKey(KEY_QUERY_VALUE);
   702         int nativeHandle = openKey(KEY_QUERY_VALUE);
   695         if (nativeHandle == NULL_NATIVE_HANDLE) {
   703         if (nativeHandle == NULL_NATIVE_HANDLE) {
   696             throw new BackingStoreException("Could not open windows"
   704             throw new BackingStoreException(
   697             + "registry node " + byteArrayToString(windowsAbsolutePath()) +
   705                     "Could not open windows registry node " +
   698             " at root 0x" + Integer.toHexString(rootNativeHandle()) + ".");
   706                     byteArrayToString(windowsAbsolutePath()) +
       
   707                     " at root 0x" +
       
   708                     Integer.toHexString(rootNativeHandle()) + ".");
   699         }
   709         }
   700         int[] result =  WindowsRegQueryInfoKey1(nativeHandle);
   710         int[] result =  WindowsRegQueryInfoKey1(nativeHandle);
   701         if (result[ERROR_CODE] != ERROR_SUCCESS) {
   711         if (result[ERROR_CODE] != ERROR_SUCCESS) {
   702             String info = "Could not query windows"
   712             String info = "Could not query windows registry node " +
   703             + "registry node " + byteArrayToString(windowsAbsolutePath()) +
   713                     byteArrayToString(windowsAbsolutePath()) +
   704             " at root 0x" + Integer.toHexString(rootNativeHandle()) +
   714                     " at root 0x" +
   705             ". Windows RegQueryInfoKeyEx(...) returned error code " +
   715                     Integer.toHexString(rootNativeHandle()) +
   706             result[ERROR_CODE] + ".";
   716                     ". Windows RegQueryInfoKeyEx(...) returned error code " +
       
   717                     result[ERROR_CODE] + ".";
   707             logger().warning(info);
   718             logger().warning(info);
   708             throw new BackingStoreException(info);
   719             throw new BackingStoreException(info);
   709         }
   720         }
   710         int maxValueNameLength = result[MAX_VALUE_NAME_LENGTH];
   721         int maxValueNameLength = result[MAX_VALUE_NAME_LENGTH];
   711         int valuesNumber = result[VALUES_NUMBER];
   722         int valuesNumber = result[VALUES_NUMBER];
   712         if (valuesNumber == 0) {
   723         if (valuesNumber == 0) {
   713             closeKey(nativeHandle);
   724             closeKey(nativeHandle);
   714             return new String[0];
   725             return new String[0];
   715        }
   726         }
   716        // Get the values
   727         // Get the values
   717        String[] valueNames = new String[valuesNumber];
   728         String[] valueNames = new String[valuesNumber];
   718        for (int i = 0; i < valuesNumber; i++) {
   729         for (int i = 0; i < valuesNumber; i++) {
   719             byte[] windowsName = WindowsRegEnumValue1(nativeHandle, i,
   730             byte[] windowsName = WindowsRegEnumValue1(nativeHandle, i,
   720                                                         maxValueNameLength+1);
   731                                                       maxValueNameLength+1);
   721             if (windowsName == null) {
   732             if (windowsName == null) {
   722                 String info =
   733                 String info =
   723                 "Could not enumerate value #" + i + "  of windows node " +
   734                     "Could not enumerate value #" + i + "  of windows node " +
   724                 byteArrayToString(windowsAbsolutePath()) + " at root 0x" +
   735                     byteArrayToString(windowsAbsolutePath()) + " at root 0x" +
   725                 Integer.toHexString(rootNativeHandle()) + ".";
   736                     Integer.toHexString(rootNativeHandle()) + ".";
   726                 logger().warning(info);
   737                 logger().warning(info);
   727                 throw new BackingStoreException(info);
   738                 throw new BackingStoreException(info);
   728             }
   739             }
   729             valueNames[i] = toJavaName(windowsName);
   740             valueNames[i] = toJavaName(windowsName);
   730         }
   741         }
   738      * Throws a BackingStoreException and logs a warning message,
   749      * Throws a BackingStoreException and logs a warning message,
   739      * if Windows registry is not available.
   750      * if Windows registry is not available.
   740      */
   751      */
   741     protected String[] childrenNamesSpi() throws BackingStoreException {
   752     protected String[] childrenNamesSpi() throws BackingStoreException {
   742         // Open key
   753         // Open key
   743         int nativeHandle = openKey(KEY_ENUMERATE_SUB_KEYS| KEY_QUERY_VALUE);
   754         int nativeHandle = openKey(KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE);
   744         if (nativeHandle == NULL_NATIVE_HANDLE) {
   755         if (nativeHandle == NULL_NATIVE_HANDLE) {
   745             throw new BackingStoreException("Could not open windows"
   756             throw new BackingStoreException(
   746             + "registry node " + byteArrayToString(windowsAbsolutePath()) +
   757                     "Could not open windows registry node " +
   747             " at root 0x" + Integer.toHexString(rootNativeHandle()) + ".");
   758                     byteArrayToString(windowsAbsolutePath()) +
       
   759                     " at root 0x" +
       
   760                     Integer.toHexString(rootNativeHandle()) + ".");
   748         }
   761         }
   749         // Get number of children
   762         // Get number of children
   750         int[] result =  WindowsRegQueryInfoKey1(nativeHandle);
   763         int[] result =  WindowsRegQueryInfoKey1(nativeHandle);
   751         if (result[ERROR_CODE] != ERROR_SUCCESS) {
   764         if (result[ERROR_CODE] != ERROR_SUCCESS) {
   752             String info = "Could not query windows"
   765             String info = "Could not query windows registry node " +
   753             + "registry node " + byteArrayToString(windowsAbsolutePath()) +
   766                     byteArrayToString(windowsAbsolutePath()) +
   754             " at root 0x" + Integer.toHexString(rootNativeHandle()) +
   767                     " at root 0x" + Integer.toHexString(rootNativeHandle()) +
   755             ". Windows RegQueryInfoKeyEx(...) returned error code " +
   768                     ". Windows RegQueryInfoKeyEx(...) returned error code " +
   756             result[ERROR_CODE] + ".";
   769                     result[ERROR_CODE] + ".";
   757             logger().warning(info);
   770             logger().warning(info);
   758             throw new BackingStoreException(info);
   771             throw new BackingStoreException(info);
   759         }
   772         }
   760         int maxKeyLength = result[MAX_KEY_LENGTH];
   773         int maxKeyLength = result[MAX_KEY_LENGTH];
   761         int subKeysNumber = result[SUBKEYS_NUMBER];
   774         int subKeysNumber = result[SUBKEYS_NUMBER];
   766         String[] subkeys = new String[subKeysNumber];
   779         String[] subkeys = new String[subKeysNumber];
   767         String[] children = new String[subKeysNumber];
   780         String[] children = new String[subKeysNumber];
   768         // Get children
   781         // Get children
   769         for (int i = 0; i < subKeysNumber; i++) {
   782         for (int i = 0; i < subKeysNumber; i++) {
   770             byte[] windowsName = WindowsRegEnumKeyEx1(nativeHandle, i,
   783             byte[] windowsName = WindowsRegEnumKeyEx1(nativeHandle, i,
   771                                                                 maxKeyLength+1);
   784                                                       maxKeyLength+1);
   772             if (windowsName == null) {
   785             if (windowsName == null) {
   773                 String info =
   786                 String info =
   774                 "Could not enumerate key #" + i + "  of windows node " +
   787                     "Could not enumerate key #" + i + "  of windows node " +
   775                 byteArrayToString(windowsAbsolutePath()) + " at root 0x" +
   788                     byteArrayToString(windowsAbsolutePath()) + " at root 0x" +
   776                 Integer.toHexString(rootNativeHandle()) + ". ";
   789                     Integer.toHexString(rootNativeHandle()) + ". ";
   777                 logger().warning(info);
   790                 logger().warning(info);
   778                 throw new BackingStoreException(info);
   791                 throw new BackingStoreException(info);
   779             }
   792             }
   780             String javaName = toJavaName(windowsName);
   793             String javaName = toJavaName(windowsName);
   781             children[i] = javaName;
   794             children[i] = javaName;
   796             parent.flush();
   809             parent.flush();
   797             return;
   810             return;
   798         }
   811         }
   799         if (!isBackingStoreAvailable) {
   812         if (!isBackingStoreAvailable) {
   800             throw new BackingStoreException(
   813             throw new BackingStoreException(
   801                                        "flush(): Backing store not available.");
   814                     "flush(): Backing store not available.");
   802         }
   815         }
   803         int nativeHandle = openKey(KEY_READ);
   816         int nativeHandle = openKey(KEY_READ);
   804         if (nativeHandle == NULL_NATIVE_HANDLE) {
   817         if (nativeHandle == NULL_NATIVE_HANDLE) {
   805             throw new BackingStoreException("Could not open windows"
   818             throw new BackingStoreException(
   806             + "registry node " + byteArrayToString(windowsAbsolutePath()) +
   819                     "Could not open windows registry node " +
   807             " at root 0x" + Integer.toHexString(rootNativeHandle()) + ".");
   820                     byteArrayToString(windowsAbsolutePath()) +
       
   821                     " at root 0x" +
       
   822                     Integer.toHexString(rootNativeHandle()) + ".");
   808         }
   823         }
   809         int result = WindowsRegFlushKey1(nativeHandle);
   824         int result = WindowsRegFlushKey1(nativeHandle);
   810         if (result != ERROR_SUCCESS) {
   825         if (result != ERROR_SUCCESS) {
   811             String info = "Could not flush windows "
   826             String info = "Could not flush windows registry node " +
   812             + "registry node " + byteArrayToString(windowsAbsolutePath())
   827                     byteArrayToString(windowsAbsolutePath()) +
   813             + " at root 0x" + Integer.toHexString(rootNativeHandle()) +
   828                     " at root 0x" +
   814             ". Windows RegFlushKey(...) returned error code " + result + ".";
   829                     Integer.toHexString(rootNativeHandle()) +
       
   830                     ". Windows RegFlushKey(...) returned error code " +
       
   831                     result + ".";
   815             logger().warning(info);
   832             logger().warning(info);
   816             throw new BackingStoreException(info);
   833             throw new BackingStoreException(info);
   817         }
   834         }
   818         closeKey(nativeHandle);
   835         closeKey(nativeHandle);
   819     }
   836     }
   836      * given name and creates its underlying Windows registry node,
   853      * given name and creates its underlying Windows registry node,
   837      * if it does not exist.
   854      * if it does not exist.
   838      * Logs a warning message, if Windows Registry is unavailable.
   855      * Logs a warning message, if Windows Registry is unavailable.
   839      */
   856      */
   840     protected AbstractPreferences childSpi(String name) {
   857     protected AbstractPreferences childSpi(String name) {
   841             return new WindowsPreferences(this, name);
   858         return new WindowsPreferences(this, name);
   842     }
   859     }
   843 
   860 
   844     /**
   861     /**
   845      * Implements <tt>AbstractPreferences</tt> <tt>removeNodeSpi()</tt> method.
   862      * Implements <tt>AbstractPreferences</tt> <tt>removeNodeSpi()</tt> method.
   846      * Deletes underlying Windows registry node.
   863      * Deletes underlying Windows registry node.
   847      * Throws a BackingStoreException and logs a warning, if Windows registry
   864      * Throws a BackingStoreException and logs a warning, if Windows registry
   848      * is not available.
   865      * is not available.
   849      */
   866      */
   850     public void removeNodeSpi() throws BackingStoreException {
   867     public void removeNodeSpi() throws BackingStoreException {
   851         int parentNativeHandle =
   868         int parentNativeHandle =
   852                          ((WindowsPreferences)parent()).openKey(DELETE);
   869                 ((WindowsPreferences)parent()).openKey(DELETE);
   853         if (parentNativeHandle == NULL_NATIVE_HANDLE) {
   870         if (parentNativeHandle == NULL_NATIVE_HANDLE) {
   854             throw new BackingStoreException("Could not open parent windows"
   871             throw new BackingStoreException(
   855             + "registry node of " + byteArrayToString(windowsAbsolutePath()) +
   872                     "Could not open parent windows registry node of " +
   856             " at root 0x" + Integer.toHexString(rootNativeHandle()) + ".");
   873                     byteArrayToString(windowsAbsolutePath()) +
       
   874                     " at root 0x" +
       
   875                     Integer.toHexString(rootNativeHandle()) + ".");
   857         }
   876         }
   858         int result =
   877         int result =
   859                 WindowsRegDeleteKey(parentNativeHandle, toWindowsName(name()));
   878                 WindowsRegDeleteKey(parentNativeHandle, toWindowsName(name()));
   860         if (result != ERROR_SUCCESS) {
   879         if (result != ERROR_SUCCESS) {
   861             String info = "Could not delete windows "
   880             String info = "Could not delete windows registry node " +
   862             + "registry node " + byteArrayToString(windowsAbsolutePath()) +
   881                     byteArrayToString(windowsAbsolutePath()) +
   863             " at root 0x" + Integer.toHexString(rootNativeHandle()) +
   882                     " at root 0x" + Integer.toHexString(rootNativeHandle()) +
   864             ". Windows RegDeleteKeyEx(...) returned error code " +
   883                     ". Windows RegDeleteKeyEx(...) returned error code " +
   865             result + ".";
   884                     result + ".";
   866             logger().warning(info);
   885             logger().warning(info);
   867             throw new BackingStoreException(info);
   886             throw new BackingStoreException(info);
   868         }
   887         }
   869         closeKey(parentNativeHandle);
   888         closeKey(parentNativeHandle);
   870     }
   889     }
   877      * @param windowsNameArray Null-terminated byte array.
   896      * @param windowsNameArray Null-terminated byte array.
   878      */
   897      */
   879     private static String toJavaName(byte[] windowsNameArray) {
   898     private static String toJavaName(byte[] windowsNameArray) {
   880         String windowsName = byteArrayToString(windowsNameArray);
   899         String windowsName = byteArrayToString(windowsNameArray);
   881         // check if Alt64
   900         // check if Alt64
   882         if ((windowsName.length()>1) &&
   901         if ((windowsName.length() > 1) &&
   883                                    (windowsName.substring(0,2).equals("/!"))) {
   902                 (windowsName.substring(0, 2).equals("/!"))) {
   884             return toJavaAlt64Name(windowsName);
   903             return toJavaAlt64Name(windowsName);
   885         }
   904         }
   886         StringBuffer javaName = new StringBuffer();
   905         StringBuilder javaName = new StringBuilder();
   887         char ch;
   906         char ch;
   888         // Decode from simple encoding
   907         // Decode from simple encoding
   889         for (int i = 0; i < windowsName.length(); i++){
   908         for (int i = 0; i < windowsName.length(); i++) {
   890             if ((ch = windowsName.charAt(i)) == '/') {
   909             if ((ch = windowsName.charAt(i)) == '/') {
   891                 char next = ' ';
   910                 char next = ' ';
   892                 if ((windowsName.length() > i + 1) &&
   911                 if ((windowsName.length() > i + 1) &&
   893                    ((next = windowsName.charAt(i+1)) >= 'A') && (next <= 'Z')) {
   912                         ((next = windowsName.charAt(i+1)) >= 'A') &&
   894                 ch = next;
   913                         (next <= 'Z')) {
   895                 i++;
   914                     ch = next;
   896                 } else  if ((windowsName.length() > i + 1) && (next == '/')) {
   915                     i++;
   897                 ch = '\\';
   916                 } else if ((windowsName.length() > i + 1) &&
   898                 i++;
   917                            (next == '/')) {
       
   918                     ch = '\\';
       
   919                     i++;
   899                 }
   920                 }
   900             } else if (ch == '\\') {
   921             } else if (ch == '\\') {
   901                 ch = '/';
   922                 ch = '/';
   902             }
   923             }
   903             javaName.append(ch);
   924             javaName.append(ch);
   912      * description of encoding conventions.
   933      * description of encoding conventions.
   913      */
   934      */
   914 
   935 
   915     private static String toJavaAlt64Name(String windowsName) {
   936     private static String toJavaAlt64Name(String windowsName) {
   916         byte[] byteBuffer =
   937         byte[] byteBuffer =
   917                           Base64.altBase64ToByteArray(windowsName.substring(2));
   938                 Base64.altBase64ToByteArray(windowsName.substring(2));
   918         StringBuffer result = new StringBuffer();
   939         StringBuilder result = new StringBuilder();
   919         for (int i = 0; i < byteBuffer.length; i++) {
   940         for (int i = 0; i < byteBuffer.length; i++) {
   920             int firstbyte = (byteBuffer[i++] & 0xff);
   941             int firstbyte = (byteBuffer[i++] & 0xff);
   921             int secondbyte =  (byteBuffer[i] & 0xff);
   942             int secondbyte =  (byteBuffer[i] & 0xff);
   922             result.append((char)((firstbyte << 8) + secondbyte));
   943             result.append((char)((firstbyte << 8) + secondbyte));
   923         }
   944         }
   943      * Windows string to '/!'. The java name is then encoded using
   964      * Windows string to '/!'. The java name is then encoded using
   944      * byteArrayToAltBase64() method from
   965      * byteArrayToAltBase64() method from
   945      * Base64 class.
   966      * Base64 class.
   946      */
   967      */
   947     private static byte[] toWindowsName(String javaName) {
   968     private static byte[] toWindowsName(String javaName) {
   948         StringBuffer windowsName = new StringBuffer();
   969         StringBuilder windowsName = new StringBuilder();
   949         for (int i = 0; i < javaName.length(); i++) {
   970         for (int i = 0; i < javaName.length(); i++) {
   950             char ch =javaName.charAt(i);
   971             char ch = javaName.charAt(i);
   951             if ((ch < 0x0020)||(ch > 0x007f)) {
   972             if ((ch < 0x0020) || (ch > 0x007f)) {
   952                 // If a non-trivial character encountered, use altBase64
   973                 // If a non-trivial character encountered, use altBase64
   953                 return toWindowsAlt64Name(javaName);
   974                 return toWindowsAlt64Name(javaName);
   954             }
   975             }
   955             if (ch == '\\') {
   976             if (ch == '\\') {
   956                 windowsName.append("//");
   977                 windowsName.append("//");
   957             } else if (ch == '/') {
   978             } else if (ch == '/') {
   958                 windowsName.append('\\');
   979                 windowsName.append('\\');
   959             } else if ((ch >= 'A') && (ch <='Z')) {
   980             } else if ((ch >= 'A') && (ch <='Z')) {
   960                 windowsName.append("/" + ch);
   981                 windowsName.append('/').append(ch);
   961             } else {
   982             } else {
   962                 windowsName.append(ch);
   983                 windowsName.append(ch);
   963             }
   984             }
   964         }
   985         }
   965         return stringToByteArray(windowsName.toString());
   986         return stringToByteArray(windowsName.toString());
   974     private static byte[] toWindowsAlt64Name(String javaName) {
   995     private static byte[] toWindowsAlt64Name(String javaName) {
   975         byte[] javaNameArray = new byte[2*javaName.length()];
   996         byte[] javaNameArray = new byte[2*javaName.length()];
   976         // Convert to byte pairs
   997         // Convert to byte pairs
   977         int counter = 0;
   998         int counter = 0;
   978         for (int i = 0; i < javaName.length();i++) {
   999         for (int i = 0; i < javaName.length();i++) {
   979                 int ch = javaName.charAt(i);
  1000             int ch = javaName.charAt(i);
   980                 javaNameArray[counter++] = (byte)(ch >>> 8);
  1001             javaNameArray[counter++] = (byte)(ch >>> 8);
   981                 javaNameArray[counter++] = (byte)ch;
  1002             javaNameArray[counter++] = (byte)ch;
   982         }
  1003         }
   983 
  1004 
   984         return stringToByteArray(
  1005         return stringToByteArray("/!" +
   985                            "/!" + Base64.byteArrayToAltBase64(javaNameArray));
  1006                 Base64.byteArrayToAltBase64(javaNameArray));
   986     }
  1007     }
   987 
  1008 
   988     /**
  1009     /**
   989      * Converts value string from its Windows representation
  1010      * Converts value string from its Windows representation
   990      * to java string.  See
  1011      * to java string.  See
   992      * description of the encoding algorithm.
  1013      * description of the encoding algorithm.
   993      */
  1014      */
   994      private static String toJavaValueString(byte[] windowsNameArray) {
  1015      private static String toJavaValueString(byte[] windowsNameArray) {
   995         // Use modified native2ascii algorithm
  1016         // Use modified native2ascii algorithm
   996         String windowsName = byteArrayToString(windowsNameArray);
  1017         String windowsName = byteArrayToString(windowsNameArray);
   997         StringBuffer javaName = new StringBuffer();
  1018         StringBuilder javaName = new StringBuilder();
   998         char ch;
  1019         char ch;
   999         for (int i = 0; i < windowsName.length(); i++){
  1020         for (int i = 0; i < windowsName.length(); i++){
  1000             if ((ch = windowsName.charAt(i)) == '/') {
  1021             if ((ch = windowsName.charAt(i)) == '/') {
  1001                 char next = ' ';
  1022                 char next = ' ';
  1002 
  1023 
  1003                 if (windowsName.length() > i + 1 &&
  1024                 if (windowsName.length() > i + 1 &&
  1004                                     (next = windowsName.charAt(i + 1)) == 'u') {
  1025                         (next = windowsName.charAt(i + 1)) == 'u') {
  1005                     if (windowsName.length() < i + 6){
  1026                     if (windowsName.length() < i + 6) {
  1006                         break;
  1027                         break;
  1007                     } else {
  1028                     } else {
  1008                         ch = (char)Integer.parseInt
  1029                         ch = (char)Integer.parseInt(
  1009                                       (windowsName.substring(i + 2, i + 6), 16);
  1030                                 windowsName.substring(i + 2, i + 6), 16);
  1010                         i += 5;
  1031                         i += 5;
  1011                     }
  1032                     }
  1012                 } else
  1033                 } else
  1013                 if ((windowsName.length() > i + 1) &&
  1034                 if ((windowsName.length() > i + 1) &&
  1014                           ((windowsName.charAt(i+1)) >= 'A') && (next <= 'Z')) {
  1035                         ((windowsName.charAt(i+1)) >= 'A') &&
  1015                 ch = next;
  1036                         (next <= 'Z')) {
  1016                 i++;
  1037                     ch = next;
  1017                 } else  if ((windowsName.length() > i + 1) &&
  1038                     i++;
  1018                                                (next == '/')) {
  1039                 } else if ((windowsName.length() > i + 1) &&
  1019                 ch = '\\';
  1040                         (next == '/')) {
  1020                 i++;
  1041                     ch = '\\';
       
  1042                     i++;
  1021                 }
  1043                 }
  1022             } else if (ch == '\\') {
  1044             } else if (ch == '\\') {
  1023                 ch = '/';
  1045                 ch = '/';
  1024             }
  1046             }
  1025             javaName.append(ch);
  1047             javaName.append(ch);
  1035      * '/' is encoded as  '\'.
  1057      * '/' is encoded as  '\'.
  1036      * Then encoding scheme similar to jdk's native2ascii converter is used
  1058      * Then encoding scheme similar to jdk's native2ascii converter is used
  1037      * to convert java string to a byte array of ASCII characters.
  1059      * to convert java string to a byte array of ASCII characters.
  1038      */
  1060      */
  1039     private static byte[] toWindowsValueString(String javaName) {
  1061     private static byte[] toWindowsValueString(String javaName) {
  1040         StringBuffer windowsName = new StringBuffer();
  1062         StringBuilder windowsName = new StringBuilder();
  1041         for (int i = 0; i < javaName.length(); i++) {
  1063         for (int i = 0; i < javaName.length(); i++) {
  1042             char ch =javaName.charAt(i);
  1064             char ch = javaName.charAt(i);
  1043             if ((ch < 0x0020)||(ch > 0x007f)){
  1065             if ((ch < 0x0020) || (ch > 0x007f)){
  1044                 // write \udddd
  1066                 // write \udddd
  1045                 windowsName.append("/u");
  1067                 windowsName.append("/u");
  1046                 String hex = Integer.toHexString(javaName.charAt(i));
  1068                 String hex = Integer.toHexString(javaName.charAt(i));
  1047                 StringBuffer hex4 = new StringBuffer(hex);
  1069                 StringBuilder hex4 = new StringBuilder(hex);
  1048                 hex4.reverse();
  1070                 hex4.reverse();
  1049                 int len = 4 - hex4.length();
  1071                 int len = 4 - hex4.length();
  1050                 for (int j = 0; j < len; j++){
  1072                 for (int j = 0; j < len; j++){
  1051                     hex4.append('0');
  1073                     hex4.append('0');
  1052                 }
  1074                 }
  1056             } else if (ch == '\\') {
  1078             } else if (ch == '\\') {
  1057                 windowsName.append("//");
  1079                 windowsName.append("//");
  1058             } else if (ch == '/') {
  1080             } else if (ch == '/') {
  1059                 windowsName.append('\\');
  1081                 windowsName.append('\\');
  1060             } else if ((ch >= 'A') && (ch <='Z')) {
  1082             } else if ((ch >= 'A') && (ch <='Z')) {
  1061                 windowsName.append("/" + ch);
  1083                 windowsName.append('/').append(ch);
  1062             } else {
  1084             } else {
  1063                 windowsName.append(ch);
  1085                 windowsName.append(ch);
  1064             }
  1086             }
  1065         }
  1087         }
  1066         return stringToByteArray(windowsName.toString());
  1088         return stringToByteArray(windowsName.toString());
  1068 
  1090 
  1069     /**
  1091     /**
  1070      * Returns native handle for the top Windows node for this node.
  1092      * Returns native handle for the top Windows node for this node.
  1071      */
  1093      */
  1072     private int rootNativeHandle() {
  1094     private int rootNativeHandle() {
  1073         return (isUserNode()? USER_ROOT_NATIVE_HANDLE :
  1095         return (isUserNode()
  1074                               SYSTEM_ROOT_NATIVE_HANDLE);
  1096                 ? USER_ROOT_NATIVE_HANDLE
       
  1097                 : SYSTEM_ROOT_NATIVE_HANDLE);
  1075     }
  1098     }
  1076 
  1099 
  1077     /**
  1100     /**
  1078      * Returns this java string as a null-terminated byte array
  1101      * Returns this java string as a null-terminated byte array
  1079      */
  1102      */
  1088 
  1111 
  1089     /**
  1112     /**
  1090      * Converts a null-terminated byte array to java string
  1113      * Converts a null-terminated byte array to java string
  1091      */
  1114      */
  1092     private static String byteArrayToString(byte[] array) {
  1115     private static String byteArrayToString(byte[] array) {
  1093         StringBuffer result = new StringBuffer();
  1116         StringBuilder result = new StringBuilder();
  1094         for (int i = 0; i < array.length - 1; i++) {
  1117         for (int i = 0; i < array.length - 1; i++) {
  1095             result.append((char)array[i]);
  1118             result.append((char)array[i]);
  1096         }
  1119         }
  1097         return result.toString();
  1120         return result.toString();
  1098     }
  1121     }