You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by mt...@apache.org on 2011/04/30 17:27:42 UTC

svn commit: r1098121 - in /commons/sandbox/runtime/trunk/src/main: java/org/apache/commons/runtime/platform/windows/ native/os/win32/ test/org/apache/commons/runtime/

Author: mturk
Date: Sat Apr 30 15:27:42 2011
New Revision: 1098121

URL: http://svn.apache.org/viewvc?rev=1098121&view=rev
Log:
Finish win32 Registry api

Added:
    commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/platform/windows/Registry.java   (with props)
Modified:
    commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/platform/windows/RegistryKey.java
    commons/sandbox/runtime/trunk/src/main/native/os/win32/registry.c
    commons/sandbox/runtime/trunk/src/main/test/org/apache/commons/runtime/TestRegistry.java

Added: commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/platform/windows/Registry.java
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/platform/windows/Registry.java?rev=1098121&view=auto
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/platform/windows/Registry.java (added)
+++ commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/platform/windows/Registry.java Sat Apr 30 15:27:42 2011
@@ -0,0 +1,73 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.runtime.platform.windows;
+
+import java.io.Closeable;
+import java.io.Flushable;
+import java.io.IOException;
+import java.io.SyncFailedException;
+import java.util.EnumSet;
+import java.util.List;
+import org.apache.commons.runtime.Errno;
+import org.apache.commons.runtime.Status;
+import org.apache.commons.runtime.SystemException;
+import org.apache.commons.runtime.util.Utils;
+
+/**
+ * Registry key class.
+ * <p>
+ * An application can use handles to these keys as entry points to the
+ * registry. These handles are valid for all implementations of the
+ * registry, although the use of the handles may vary from platform to
+ * platform. In addition, other predefined handles have been defined
+ * for specific platforms. The following are handles to the predefined
+ * keys.
+ * </p>
+ */
+public final class Registry
+{
+
+    private Registry()
+    {
+    }
+
+
+    private static native int unlink0(long key, String name, boolean onlyIfEmpty);
+    /**
+     * Delete the Registry subkey
+     * @param root Root key, one of HKEY_*
+     * @param name Subkey to delete
+     * @param onlyIfEmpty If true will not delete a key if
+     *                    it contains any subkeys or values
+     * @return {@code true} if the function succeeds.
+     */
+    public static boolean delete(RegistryKey root, String name, boolean onlyIfEmpty)
+        throws NullPointerException, IOException
+    {
+        if (name == null)
+            throw new NullPointerException();
+        long hKey = root.handle();
+        if (hKey == 0L || hKey == -1L)
+            throw new InvalidHandleException();
+        int rc = unlink0(hKey, name, onlyIfEmpty);
+        if (rc == 0)
+            return true;
+        else
+            return false;
+    }
+
+}

Propchange: commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/platform/windows/Registry.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/platform/windows/RegistryKey.java
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/platform/windows/RegistryKey.java?rev=1098121&r1=1098120&r2=1098121&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/platform/windows/RegistryKey.java (original)
+++ commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/platform/windows/RegistryKey.java Sat Apr 30 15:27:42 2011
@@ -21,6 +21,7 @@ import java.io.Flushable;
 import java.io.IOException;
 import java.io.SyncFailedException;
 import java.util.EnumSet;
+import java.util.List;
 import org.apache.commons.runtime.Errno;
 import org.apache.commons.runtime.Status;
 import org.apache.commons.runtime.SystemException;
@@ -37,7 +38,7 @@ import org.apache.commons.runtime.util.U
  * keys.
  * </p>
  */
-public class RegistryKey implements Closeable, Flushable
+public final class RegistryKey implements Closeable, Flushable
 {
 
     /** Registry entries subordinate to this key define types (or classes)
@@ -209,6 +210,7 @@ public class RegistryKey implements Clos
     private static native byte[] gets2(long key, String name);
     private static native int    gets3(long key, String name, int[]  pval);
     private static native int    gets4(long key, String name, long[] pval);
+    private static native int    unlink0(long key, String name);
 
     public RegistryKey open(String name, EnumSet<RegistryKeyAccessRights> mode)
         throws NullPointerException, IOException, SystemException
@@ -346,4 +348,131 @@ public class RegistryKey implements Clos
         return rp[0];
     }
 
+    private static native String[] enum0(long key);
+    private static native String[] enum1(long key);
+
+    /**
+     * Enumerate the Registry subkeys
+     * @return Array of all subkey names
+     */
+    public String[] getKeys()
+        throws NullPointerException, IOException
+    {
+        if (hKey == 0L || hKey == -1L)
+            throw new InvalidHandleException();
+        String[] s = enum0(hKey);
+
+        return s;
+    }
+
+    /**
+     * Enumerate the Registry values
+     * @return Array of all value names
+     */
+    public String[] getValues()
+        throws NullPointerException, IOException
+    {
+        if (hKey == 0L || hKey == -1L)
+            throw new InvalidHandleException();
+        String[] s = enum1(hKey);
+
+        return s;
+    }
+
+    private static native int   setv0(long key, String name, String value);
+    private static native int   setv1(long key, String name, int value);
+    private static native int   setv2(long key, String name, long value);
+    private static native int   setv3(long key, String name, byte[] value);
+    private static native int   setv4(long key, String name, char[] value);
+
+    public void setValue(String name, String value)
+        throws NullPointerException, IOException
+    {
+        if (name == null || value == null)
+            throw new NullPointerException();
+        if (hKey == 0L || hKey == -1L)
+            throw new InvalidHandleException();
+        if (hKey == 0L || hKey == -1L)
+            throw new InvalidHandleException();
+        int rc = setv0(hKey, name, value);
+        if (rc != 0)
+            throw new IOException(Status.describe(rc));
+    }
+
+    public void setValue(String name, byte[] value)
+        throws NullPointerException, IOException
+    {
+        if (name == null || value == null)
+            throw new NullPointerException();
+        if (hKey == 0L || hKey == -1L)
+            throw new InvalidHandleException();
+        if (hKey == 0L || hKey == -1L)
+            throw new InvalidHandleException();
+        int rc = setv3(hKey, name, value);
+        if (rc != 0)
+            throw new IOException(Status.describe(rc));
+    }
+
+    public void setValue(String name, List<String> value)
+        throws NullPointerException, IOException
+    {
+        if (name == null || value == null)
+            throw new NullPointerException();
+        if (hKey == 0L || hKey == -1L)
+            throw new InvalidHandleException();
+        if (hKey == 0L || hKey == -1L)
+            throw new InvalidHandleException();
+        char[] msz = Utils.stringArrayToCharBlock(value);
+        int rc = setv4(hKey, name, msz);
+        if (rc != 0)
+            throw new IOException(Status.describe(rc));
+    }
+
+    public void setValue(String name, int value)
+        throws NullPointerException, IOException
+    {
+        if (name == null)
+            throw new NullPointerException();
+        if (hKey == 0L || hKey == -1L)
+            throw new InvalidHandleException();
+        if (hKey == 0L || hKey == -1L)
+            throw new InvalidHandleException();
+        int rc = setv1(hKey, name, value);
+        if (rc != 0)
+            throw new IOException(Status.describe(rc));
+    }
+
+    public void setValue(String name, long value)
+        throws NullPointerException, IOException
+    {
+        if (name == null)
+            throw new NullPointerException();
+        if (hKey == 0L || hKey == -1L)
+            throw new InvalidHandleException();
+        if (hKey == 0L || hKey == -1L)
+            throw new InvalidHandleException();
+        int rc = setv2(hKey, name, value);
+        if (rc != 0)
+            throw new IOException(Status.describe(rc));
+    }
+
+    /**
+     * Delete the Registry value
+     * @param name The name of the value to delete
+     * @return {@code true} if the function succeeds.
+     */
+    public boolean deleteValue(String name)
+        throws NullPointerException, IOException
+    {
+        if (name == null)
+            throw new NullPointerException();
+        if (hKey == 0L || hKey == -1L)
+            throw new InvalidHandleException();
+        int rc = unlink0(hKey, name);
+        if (rc == 0)
+            return true;
+        else
+            return false;
+    }
+
 }

Modified: commons/sandbox/runtime/trunk/src/main/native/os/win32/registry.c
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/os/win32/registry.c?rev=1098121&r1=1098120&r2=1098121&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/os/win32/registry.c (original)
+++ commons/sandbox/runtime/trunk/src/main/native/os/win32/registry.c Sat Apr 30 15:27:42 2011
@@ -15,14 +15,14 @@
  */
 
 #include "acr/error.h"
-#include "acr/jniapi.h"
 #include "acr/memory.h"
 #include "acr/iodefs.h"
 #include "acr/port.h"
+#include "acr/jniapi.h"
 #include "acr/clazz.h"
 #include "acr/string.h"
 #include "arch_opts.h"
-
+#include <shlwapi.h>
 
 static REGSAM regsam_translate(int nsam)
 {
@@ -170,7 +170,7 @@ ACR_WIN_EXPORT(jstring, RegistryKey, get
                         rc = ACR_ENOMEM;
                     }
                     else {
-                        rc = RegQueryValueExW(hkey, J2S(name), 0, &rt, (LPBYTE)ss, &rs);
+                        rc = RegQueryValueExW(hkey, J2S(name), 0, 0, (LPBYTE)ss, &rs);
                         if (rc == 0) {
                             if (rt == REG_EXPAND_SZ) {
                                 DWORD xl = ExpandEnvironmentStringsW(ss, ss, rs);
@@ -220,7 +220,7 @@ ACR_WIN_EXPORT(jcharArray, RegistryKey, 
                         rc = ACR_ENOMEM;
                     }
                     else {
-                        rc = RegQueryValueExW(hkey, J2S(name), 0, &rt, (LPBYTE)ss, &rs);
+                        rc = RegQueryValueExW(hkey, J2S(name), 0, 0, (LPBYTE)ss, &rs);
                         if (rc == 0) {
                             (*env)->SetCharArrayRegion(env, r, 0, (jsize)rs, ss);
                         }
@@ -259,7 +259,7 @@ ACR_WIN_EXPORT(jbyteArray, RegistryKey, 
                         rc = ACR_ENOMEM;
                     }
                     else {
-                        rc = RegQueryValueExW(hkey, J2S(name), 0, &rt, (LPBYTE)ss, &rs);
+                        rc = RegQueryValueExW(hkey, J2S(name), 0, 0, (LPBYTE)ss, &rs);
                         if (rc == 0) {
                             (*env)->SetByteArrayRegion(env, r, 0, (jsize)rs, ss);
                         }
@@ -291,7 +291,7 @@ ACR_WIN_EXPORT(jint, RegistryKey, gets3)
         if (rc == 0) {
             if (rt == REG_DWORD && rs == 4) {
                 jint rv;
-                rc = RegQueryValueExW(hkey, J2S(name), 0, &rt, (LPBYTE)&rt, &rs);
+                rc = RegQueryValueExW(hkey, J2S(name), 0, 0, (LPBYTE)&rt, &rs);
                 if (rc == 0) {
                     (*env)->SetIntArrayRegion(env, pval, 0, 1, &rv);
                 }
@@ -315,17 +315,270 @@ ACR_WIN_EXPORT(jint, RegistryKey, gets4)
     WITH_WSTR(name) {
         rc = RegQueryValueExW(hkey, J2S(name), 0, &rt, 0, &rs);
         if (rc == 0) {
+            jlong rv;
             if (rt == REG_QWORD && rs == 8) {
-                jlong rv;
-                rc = RegQueryValueExW(hkey, J2S(name), 0, &rt, (LPBYTE)&rt, &rs);
-                if (rc == 0) {
-                    (*env)->SetLongArrayRegion(env, pval, 0, 1, &rv);
-                }
+                rc = RegQueryValueExW(hkey, J2S(name), 0, 0, (LPBYTE)&rv, &rs);
+            }
+            else if (rt == REG_DWORD && rs == 4) {
+                DWORD rd;
+                rc = RegQueryValueExW(hkey, J2S(name), 0, 0, (LPBYTE)&rd, &rs);
+                rv = rd;
             }
             else {
                 rc = ACR_EFTYPE;
             }
+            if (rc == 0) {
+                (*env)->SetLongArrayRegion(env, pval, 0, 1, &rv);
+            }
+        }
+    } DONE_WITH_STR(name);
+    return rc;
+}
+
+#define MAX_VALUE_NAME 4096
+
+ACR_WIN_EXPORT(jobjectArray, RegistryKey, enum0)(JNI_STDARGS, jlong key)
+{
+    HKEY hkey = J2P(key, HKEY);
+    LONG rc;
+    jobjectArray v = 0;
+    jsize cnt = 0;
+
+    WCHAR    achKey[MAX_PATH];
+    WCHAR    achClass[MAX_PATH] = L"";
+    DWORD    cchClassName = MAX_PATH;
+    DWORD    cSubKeys;
+    DWORD    cbMaxSubKey;
+    DWORD    cchMaxClass;
+    DWORD    cValues;
+    DWORD    cchMaxValue;
+    DWORD    cbMaxValueData;
+    DWORD    cbSecurityDescriptor;
+    FILETIME ftLastWriteTime;
+
+    DWORD cchValue = MAX_VALUE_NAME;
+
+    rc = RegQueryInfoKeyW(hkey,
+                          achClass,
+                          &cchClassName,
+                          0,
+                          &cSubKeys,
+                          &cbMaxSubKey,
+                          &cchMaxClass,
+                          &cValues,
+                          &cchMaxValue,
+                          &cbMaxValueData,
+                          &cbSecurityDescriptor,
+                          &ftLastWriteTime);
+    if (rc != ERROR_SUCCESS) {
+        ACR_SAVE_ERROR(rc);
+        return 0;
+    }
+    cnt = cSubKeys;
+    if (cnt) {
+        jsize idx = 0;
+        v = AcrNewCoreObjectArray(env, ACR_CC_STRING, cnt);
+        if (v == 0)
+            return 0;
+        for (idx = 0; idx < cnt; idx++) {
+            jstring s;
+            DWORD achKeyLen = MAX_PATH;
+            rc = RegEnumKeyExW(hkey,
+                               idx,
+                               achKey,
+                               &achKeyLen,
+                               0,
+                               0,
+                               0,
+                               &ftLastWriteTime);
+            if (rc == 0) {
+                s = WSTR_TO_JSTRING(achKey);
+                if (s != 0) {
+                    (*env)->SetObjectArrayElement(env, v, idx, s);
+                    if (IS_EXCEPTION_PENDING(env))
+                        return 0;
+                    (*env)->DeleteLocalRef(env, s);
+                }
+                else
+                    return 0;
+            }
         }
+    }
+    return v;
+}
+
+ACR_WIN_EXPORT(jobjectArray, RegistryKey, enum1)(JNI_STDARGS, jlong key)
+{
+    HKEY hkey = J2P(key, HKEY);
+    LONG rc;
+    jobjectArray v = 0;
+    jsize cnt = 0;
+
+    WCHAR    achClass[MAX_PATH] = L"";
+    DWORD    cchClassName = MAX_PATH;
+    DWORD    cSubKeys;
+    DWORD    cbMaxSubKey;
+    DWORD    cchMaxClass;
+    DWORD    cValues;
+    DWORD    cchMaxValue;
+    DWORD    cbMaxValueData;
+    DWORD    cbSecurityDescriptor;
+    FILETIME ftLastWriteTime;
+
+    WCHAR  achValue[MAX_VALUE_NAME];
+    DWORD  cchValue = MAX_VALUE_NAME;
+
+    /* Get the class name and the value count. */
+    rc = RegQueryInfoKeyW(hkey,
+                          achClass,
+                          &cchClassName,
+                          0,
+                          &cSubKeys,
+                          &cbMaxSubKey,
+                          &cchMaxClass,
+                          &cValues,
+                          &cchMaxValue,
+                          &cbMaxValueData,
+                          &cbSecurityDescriptor,
+                          &ftLastWriteTime);
+    if (rc != ERROR_SUCCESS) {
+        ACR_SAVE_ERROR(rc);
+        return 0;
+    }
+    cnt = cValues;
+    if (cnt) {
+        jsize idx = 0;
+        v = AcrNewCoreObjectArray(env, ACR_CC_STRING, cnt);
+        if (v == 0)
+            return 0;
+        for (idx = 0; idx < cnt; idx++) {
+            jstring s;
+            cchValue = MAX_VALUE_NAME;
+            achValue[0] = L'\0';
+            rc = RegEnumValueW(hkey, idx,
+                               achValue,
+                               &cchValue,
+                               0,
+                               0,
+                               0,
+                               0);
+            if (rc == 0) {
+                s = WSTR_TO_JSTRING(achValue);
+                if (s != 0) {
+                    (*env)->SetObjectArrayElement(env, v, idx, s);
+                    if (IS_EXCEPTION_PENDING(env))
+                        return 0;
+                    (*env)->DeleteLocalRef(env, s);
+                }
+                else
+                    return 0;
+            }
+        }
+    }
+    return v;
+}
+
+ACR_WIN_EXPORT(jint, RegistryKey, setv0)(JNI_STDARGS, jlong key,
+                                         jstring name, jstring val)
+{
+    jint rc   = ACR_EINVAL;
+    HKEY hkey = J2P(key, HKEY);
+    DWORD len;
+
+    WITH_WSTR(name) {
+    WITH_WSTR(val) {
+        len = (DWORD)(wcslen(J2S(val)) + 1) * 2;
+        rc = RegSetValueExW(hkey, J2S(name), 0, REG_SZ,
+                            (CONST BYTE *)J2S(val), len);
+    } DONE_WITH_STR(val);
+    } DONE_WITH_STR(name);
+    return rc;
+}
+
+ACR_WIN_EXPORT(jint, RegistryKey, setv1)(JNI_STDARGS, jlong key,
+                                         jstring name, jint val)
+{
+    jint rc   = ACR_EINVAL;
+    HKEY hkey = J2P(key, HKEY);
+
+    WITH_WSTR(name) {
+        rc = RegSetValueExW(hkey, J2S(name), 0, REG_DWORD,
+                            (CONST BYTE *)&val, 4);
+    } DONE_WITH_STR(name);
+    return rc;
+}
+
+ACR_WIN_EXPORT(jint, RegistryKey, setv2)(JNI_STDARGS, jlong key,
+                                         jstring name, jlong val)
+{
+    jint rc   = ACR_EINVAL;
+    HKEY hkey = J2P(key, HKEY);
+
+    WITH_WSTR(name) {
+        rc = RegSetValueExW(hkey, J2S(name), 0, REG_DWORD,
+                            (CONST BYTE *)&val, 8);
+    } DONE_WITH_STR(name);
+    return rc;
+}
+
+ACR_WIN_EXPORT(jint, RegistryKey, setv3)(JNI_STDARGS, jlong key,
+                                         jstring name, jbyteArray val)
+{
+    jint rc   = ACR_EINVAL;
+    HKEY hkey = J2P(key, HKEY);
+    DWORD  len;
+    BYTE  *jba;
+
+    WITH_WSTR(name) {
+        len = (*env)->GetArrayLength(env, val);
+        jba = (*env)->GetPrimitiveArrayCritical(env, val, 0);
+        rc  = RegSetValueExW(hkey, J2S(name), 0, REG_BINARY, jba, len);
+        (*env)->ReleasePrimitiveArrayCritical(env, val, jba, 0);
+    } DONE_WITH_STR(name);
+    return rc;
+}
+
+ACR_WIN_EXPORT(jint, RegistryKey, setv4)(JNI_STDARGS, jlong key,
+                                         jstring name, jcharArray val)
+{
+    jint rc   = ACR_EINVAL;
+    HKEY hkey = J2P(key, HKEY);
+    DWORD  len;
+    BYTE  *jba;
+
+    WITH_WSTR(name) {
+        len = (*env)->GetArrayLength(env, val);
+        jba = (*env)->GetPrimitiveArrayCritical(env, val, 0);
+        rc  = RegSetValueExW(hkey, J2S(name), 0, REG_MULTI_SZ, jba, len * 2);
+        (*env)->ReleasePrimitiveArrayCritical(env, val, jba, 0);
+    } DONE_WITH_STR(name);
+    return rc;
+}
+
+ACR_WIN_EXPORT(jint, RegistryKey, unlink0)(JNI_STDARGS, jlong key,
+                                           jstring name)
+{
+    jint rc   = ACR_EINVAL;
+    HKEY hkey = J2P(key, HKEY);
+
+    WITH_WSTR(name) {
+        rc = RegDeleteValueW(hkey, J2S(name));
+    } DONE_WITH_STR(name);
+    return rc;
+}
+
+ACR_WIN_EXPORT(jint, Registry, unlink0)(JNI_STDARGS, jlong key,
+                                        jstring name,
+                                        jboolean empty)
+{
+    jint rc   = ACR_EINVAL;
+    HKEY hkey = J2P(key, HKEY);
+
+    WITH_WSTR(name) {
+        if (empty == JNI_TRUE)
+            rc = SHDeleteEmptyKeyW(hkey, J2S(name));
+        else
+            rc = SHDeleteKeyW(hkey, J2S(name));
     } DONE_WITH_STR(name);
     return rc;
 }

Modified: commons/sandbox/runtime/trunk/src/main/test/org/apache/commons/runtime/TestRegistry.java
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/test/org/apache/commons/runtime/TestRegistry.java?rev=1098121&r1=1098120&r2=1098121&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/test/org/apache/commons/runtime/TestRegistry.java (original)
+++ commons/sandbox/runtime/trunk/src/main/test/org/apache/commons/runtime/TestRegistry.java Sat Apr 30 15:27:42 2011
@@ -65,7 +65,38 @@ public class TestRegistry extends Assert
         RegistryKey key = RegistryKey.LocalMachine.open("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion");
         assertNotNull(key);
         assertEquals(key.getValueType("InstallDate"), RegistryValueType.DWORD);
-        long val = key.getLongValue("InstallDate");
+        String val = key.getValue("InstallDate");
+    }
+
+    @Test(groups = { "windows" })
+    public void enumKeys()
+        throws Exception
+    {
+        RegistryKey key = RegistryKey.LocalMachine.open("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion");
+        assertNotNull(key);
+        String[] keys = key.getKeys();
+        assertTrue(keys.length > 10);
+    }
+
+    @Test(groups = { "windows" })
+    public void enumValues()
+        throws Exception
+    {
+        RegistryKey key = RegistryKey.LocalMachine.open("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion");
+        assertNotNull(key);
+        String[] vals = key.getValues();
+        assertTrue(vals.length > 10);
+    }
+
+    @Test(groups = { "windows" })
+    public void createValues()
+        throws Exception
+    {
+        RegistryKey key = RegistryKey.CurrentUser.create("SOFTWARE\\Apache Group\\CommonsTest\\Runtime");
+        assertNotNull(key);
+        key.setValue("TestString", "Some Value");
+        key.close();
+        Registry.delete(RegistryKey.CurrentUser, "SOFTWARE\\Apache Group\\CommonsTest", false);
     }
 
 }