open subkey with sufficient rights in RegDeleteTree
[reactos.git] / reactos / lib / advapi32 / reg / reg.c
index 2d568da..81d43af 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: reg.c,v 1.60 2004/10/10 10:10:52 hbirr Exp $
+/* $Id$
  *
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS system libraries
@@ -8,13 +8,14 @@
  * UPDATE HISTORY:
  *                  Created 01/11/98
  *                  19990309 EA Stubs
+ *                  20050502 Fireball imported some stuff from WINE
  */
 
 /* INCLUDES *****************************************************************/
 
-#include "advapi32.h"
+#include <advapi32.h>
 #define NDEBUG
-#include <debug.h>
+#include <wine/debug.h>
 
 /* DEFINES ******************************************************************/
 
 #define REG_MAX_NAME_SIZE     256
 #define REG_MAX_DATA_SIZE     2048
 
+/* FIXME: should go into msvcrt.h header? */
+#define offsetof(s,m)       (size_t)&(((s*)NULL)->m)
+
 /* GLOBALS ******************************************************************/
 
-static CRITICAL_SECTION HandleTableCS;
+static RTL_CRITICAL_SECTION HandleTableCS;
 static HANDLE DefaultHandleTable[MAX_DEFAULT_HANDLES];
 static HANDLE ProcessHeap;
 
@@ -40,6 +44,11 @@ static NTSTATUS OpenCurrentConfigKey(PHANDLE KeyHandle);
 
 
 /* FUNCTIONS ****************************************************************/
+/* check if value type needs string conversion (Ansi<->Unicode) */
+inline static int is_string( DWORD type )
+{
+    return (type == REG_SZ) || (type == REG_EXPAND_SZ) || (type == REG_MULTI_SZ);
+}
 
 /************************************************************************
  *  RegInitDefaultHandles
@@ -47,7 +56,7 @@ static NTSTATUS OpenCurrentConfigKey(PHANDLE KeyHandle);
 BOOL
 RegInitialize (VOID)
 {
-  DPRINT("RegInitialize()\n");
+  TRACE("RegInitialize()\n");
 
   ProcessHeap = RtlGetProcessHeap();
   RtlZeroMemory (DefaultHandleTable,
@@ -64,7 +73,7 @@ RegInitialize (VOID)
 BOOL
 RegCleanup (VOID)
 {
-  DPRINT("RegCleanup()\n");
+  TRACE("RegCleanup()\n");
 
   CloseDefaultKeys ();
   RtlDeleteCriticalSection (&HandleTableCS);
@@ -81,7 +90,7 @@ MapDefaultKey (PHANDLE RealKey,
   ULONG Index;
   NTSTATUS Status = STATUS_SUCCESS;
 
-  DPRINT("MapDefaultKey (Key %x)\n", Key);
+  TRACE("MapDefaultKey (Key %x)\n", Key);
 
   if (((ULONG)Key & 0xF0000000) != 0x80000000)
     {
@@ -133,7 +142,7 @@ MapDefaultKey (PHANDLE RealKey,
            break;
 
          default:
-           DPRINT("MapDefaultHandle() no handle creator\n");
+           WARN("MapDefaultHandle() no handle creator\n");
            Status = STATUS_INVALID_PARAMETER;
        }
     }
@@ -170,9 +179,9 @@ static NTSTATUS
 OpenClassesRootKey (PHANDLE KeyHandle)
 {
   OBJECT_ATTRIBUTES Attributes;
-  UNICODE_STRING KeyName = ROS_STRING_INITIALIZER(L"\\Registry\\Machine\\Software\\CLASSES");
+  UNICODE_STRING KeyName = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\Software\\CLASSES");
 
-  DPRINT("OpenClassesRootKey()\n");
+  TRACE("OpenClassesRootKey()\n");
 
   InitializeObjectAttributes (&Attributes,
                              &KeyName,
@@ -189,10 +198,10 @@ static NTSTATUS
 OpenLocalMachineKey (PHANDLE KeyHandle)
 {
   OBJECT_ATTRIBUTES Attributes;
-  UNICODE_STRING KeyName = ROS_STRING_INITIALIZER(L"\\Registry\\Machine");
+  UNICODE_STRING KeyName = RTL_CONSTANT_STRING(L"\\Registry\\Machine");
   NTSTATUS Status;
 
-  DPRINT("OpenLocalMachineKey()\n");
+  TRACE("OpenLocalMachineKey()\n");
 
   InitializeObjectAttributes (&Attributes,
                              &KeyName,
@@ -203,7 +212,7 @@ OpenLocalMachineKey (PHANDLE KeyHandle)
                      MAXIMUM_ALLOWED,
                      &Attributes);
 
-  DPRINT("NtOpenKey(%wZ) => %08x\n", &KeyName, Status);
+  TRACE("NtOpenKey(%wZ) => %08x\n", &KeyName, Status);
   return Status;
 }
 
@@ -212,9 +221,9 @@ static NTSTATUS
 OpenUsersKey (PHANDLE KeyHandle)
 {
   OBJECT_ATTRIBUTES Attributes;
-  UNICODE_STRING KeyName = ROS_STRING_INITIALIZER(L"\\Registry\\User");
+  UNICODE_STRING KeyName = RTL_CONSTANT_STRING(L"\\Registry\\User");
 
-  DPRINT("OpenUsersKey()\n");
+  TRACE("OpenUsersKey()\n");
 
   InitializeObjectAttributes (&Attributes,
                              &KeyName,
@@ -222,7 +231,7 @@ OpenUsersKey (PHANDLE KeyHandle)
                              NULL,
                              NULL);
   return NtOpenKey (KeyHandle,
-                   KEY_ALL_ACCESS,
+                   MAXIMUM_ALLOWED,
                    &Attributes);
 }
 
@@ -232,9 +241,9 @@ OpenCurrentConfigKey (PHANDLE KeyHandle)
 {
   OBJECT_ATTRIBUTES Attributes;
   UNICODE_STRING KeyName =
-  ROS_STRING_INITIALIZER(L"\\Registry\\Machine\\System\\CurrentControlSet\\Hardware Profiles\\Current");
+  RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\CurrentControlSet\\Hardware Profiles\\Current");
 
-  DPRINT("OpenCurrentConfigKey()\n");
+  TRACE("OpenCurrentConfigKey()\n");
 
   InitializeObjectAttributes (&Attributes,
                              &KeyName,
@@ -255,7 +264,6 @@ OpenCurrentConfigKey (PHANDLE KeyHandle)
 LONG STDCALL
 RegCloseKey (HKEY hKey)
 {
-  LONG ErrorCode;
   NTSTATUS Status;
 
   /* don't close null handle or a pseudo handle */
@@ -267,9 +275,7 @@ RegCloseKey (HKEY hKey)
   Status = NtClose (hKey);
   if (!NT_SUCCESS(Status))
     {
-      ErrorCode = RtlNtStatusToDosError (Status);
-      SetLastError (ErrorCode);
-      return ErrorCode;
+      return RtlNtStatusToDosError (Status);
     }
 
   return ERROR_SUCCESS;
@@ -291,6 +297,108 @@ RegConnectRegistryA (LPCSTR lpMachineName,
 }
 
 
+/************************************************************************
+ *  RegCopyTreeW
+ *
+ * @unimplemented
+ */
+LONG STDCALL
+RegCopyTreeW(IN HKEY hKeySrc,
+             IN LPCWSTR lpSubKey  OPTIONAL,
+             IN HKEY hKeyDest)
+{
+    HANDLE DestKeyHandle, KeyHandle, SubKeyHandle = NULL;
+    NTSTATUS Status;
+    
+    Status = MapDefaultKey(&KeyHandle,
+                           hKeySrc);
+    if (!NT_SUCCESS(Status))
+    {
+        return RtlNtStatusToDosError(Status);
+    }
+    
+    Status = MapDefaultKey(&DestKeyHandle,
+                           hKeyDest);
+    if (!NT_SUCCESS(Status))
+    {
+        return RtlNtStatusToDosError(Status);
+    }
+
+    if (lpSubKey != NULL)
+    {
+        OBJECT_ATTRIBUTES ObjectAttributes;
+        UNICODE_STRING SubKeyName;
+
+        RtlInitUnicodeString(&SubKeyName,
+                             (LPWSTR)lpSubKey);
+
+        InitializeObjectAttributes(&ObjectAttributes,
+                                   &SubKeyName,
+                                   OBJ_CASE_INSENSITIVE,
+                                   KeyHandle,
+                                   NULL);
+
+        Status = NtOpenKey(&SubKeyHandle,
+                           KEY_READ,
+                           &ObjectAttributes);
+        if (!NT_SUCCESS(Status))
+        {
+            return RtlNtStatusToDosError(Status);
+        }
+    }
+    
+    /* FIXME - copy all keys and values recursively */
+    Status = STATUS_NOT_IMPLEMENTED;
+    
+    if (SubKeyHandle != NULL)
+    {
+        NtClose(SubKeyHandle);
+    }
+    
+    if (!NT_SUCCESS(Status))
+    {
+        return RtlNtStatusToDosError(Status);
+    }
+    
+    return ERROR_SUCCESS;
+}
+
+
+/************************************************************************
+ *  RegCopyTreeA
+ *
+ * @implemented
+ */
+LONG STDCALL
+RegCopyTreeA(IN HKEY hKeySrc,
+             IN LPCSTR lpSubKey  OPTIONAL,
+             IN HKEY hKeyDest)
+{
+    UNICODE_STRING SubKeyName;
+    LONG Ret;
+    
+    if (lpSubKey != NULL)
+    {
+        if (!RtlCreateUnicodeStringFromAsciiz(&SubKeyName,
+                                              (LPSTR)lpSubKey))
+        {
+            return ERROR_NOT_ENOUGH_MEMORY;
+        }
+    }
+    else
+        RtlInitUnicodeString(&SubKeyName,
+                             NULL);
+
+    Ret = RegCopyTreeW(hKeySrc,
+                       SubKeyName.Buffer,
+                       hKeyDest);
+
+    RtlFreeUnicodeString(&SubKeyName);
+    
+    return Ret;
+}
+
+
 /************************************************************************
  *  RegConnectRegistryW
  *
@@ -335,7 +443,7 @@ CreateNestedKey(PHKEY KeyHandle,
                        ClassString,
                        dwOptions,
                        (PULONG)lpdwDisposition);
-  DPRINT("NtCreateKey(%wZ) called (Status %lx)\n", ObjectAttributes->ObjectName, Status);
+  TRACE("NtCreateKey(%wZ) called (Status %lx)\n", ObjectAttributes->ObjectName, Status);
   if (Status != STATUS_OBJECT_NAME_NOT_FOUND)
     return Status;
 
@@ -367,7 +475,7 @@ CreateNestedKey(PHKEY KeyHandle,
                            NULL,
                            0,
                            &Disposition);
-      DPRINT("NtCreateKey(%wZ) called (Status %lx)\n", &LocalKeyName, Status);
+      TRACE("NtCreateKey(%wZ) called (Status %lx)\n", &LocalKeyName, Status);
     }
 
   if (!NT_SUCCESS(Status))
@@ -398,13 +506,13 @@ CreateNestedKey(PHKEY KeyHandle,
           break;
         }
       Status = NtCreateKey (&LocalKeyHandle,
-                           KEY_ALL_ACCESS,
+                           KEY_CREATE_SUB_KEY,
                            &LocalObjectAttributes,
                            0,
                            NULL,
                            0,
                            &Disposition);
-      DPRINT("NtCreateKey(%wZ) called (Status %lx)\n", &LocalKeyName, Status);
+      TRACE("NtCreateKey(%wZ) called (Status %lx)\n", &LocalKeyName, Status);
       if (!NT_SUCCESS(Status))
        break;
     }
@@ -435,51 +543,48 @@ RegCreateKeyExA (HKEY hKey,
   UNICODE_STRING ClassString;
   OBJECT_ATTRIBUTES Attributes;
   HANDLE ParentKey;
-  LONG ErrorCode;
   NTSTATUS Status;
 
-  DPRINT("RegCreateKeyExA() called\n");
+  TRACE("RegCreateKeyExA() called\n");
 
   /* get the real parent key */
   Status = MapDefaultKey (&ParentKey,
                          hKey);
   if (!NT_SUCCESS(Status))
     {
-      ErrorCode = RtlNtStatusToDosError (Status);
-      SetLastError (ErrorCode);
-      return ErrorCode;
+      return RtlNtStatusToDosError (Status);
     }
-  DPRINT("ParentKey %x\n", (ULONG)ParentKey);
+  TRACE("ParentKey %x\n", (ULONG)ParentKey);
 
   if (lpClass != NULL)
     {
       RtlCreateUnicodeStringFromAsciiz (&ClassString,
                                        lpClass);
     }
-  RtlCreateUnicodeStringFromAsciiz (&SubKeyString,
-                                   (LPSTR)lpSubKey);
+
+  RtlCreateUnicodeStringFromAsciiz(&SubKeyString,
+                                  (LPSTR)lpSubKey);
   InitializeObjectAttributes (&Attributes,
                              &SubKeyString,
                              OBJ_CASE_INSENSITIVE,
                              (HANDLE)ParentKey,
                              (PSECURITY_DESCRIPTOR)lpSecurityAttributes);
   Status = CreateNestedKey(phkResult,
-                          &Attributes,
-                           (lpClass == NULL)? NULL : &ClassString,
-                           dwOptions,
-                           samDesired,
-                           lpdwDisposition);
+                          &Attributes,
+                          (lpClass == NULL)? NULL : &ClassString,
+                          dwOptions,
+                          samDesired,
+                          lpdwDisposition);
   RtlFreeUnicodeString (&SubKeyString);
   if (lpClass != NULL)
     {
       RtlFreeUnicodeString (&ClassString);
     }
-  DPRINT("Status %x\n", Status);
+
+  TRACE("Status %x\n", Status);
   if (!NT_SUCCESS(Status))
     {
-      ErrorCode = RtlNtStatusToDosError (Status);
-      SetLastError (ErrorCode);
-      return ErrorCode;
+      return RtlNtStatusToDosError (Status);
     }
 
   return ERROR_SUCCESS;
@@ -506,21 +611,18 @@ RegCreateKeyExW (HKEY hKey,
   UNICODE_STRING ClassString;
   OBJECT_ATTRIBUTES Attributes;
   HANDLE ParentKey;
-  LONG ErrorCode;
   NTSTATUS Status;
 
-  DPRINT("RegCreateKeyExW() called\n");
+  TRACE("RegCreateKeyExW() called\n");
 
   /* get the real parent key */
   Status = MapDefaultKey (&ParentKey,
                          hKey);
   if (!NT_SUCCESS(Status))
     {
-      ErrorCode = RtlNtStatusToDosError(Status);
-      SetLastError (ErrorCode);
-      return ErrorCode;
+      return RtlNtStatusToDosError(Status);
     }
-  DPRINT("ParentKey %x\n", (ULONG)ParentKey);
+  TRACE("ParentKey %x\n", (ULONG)ParentKey);
 
   RtlInitUnicodeString (&ClassString,
                        lpClass);
@@ -537,12 +639,10 @@ RegCreateKeyExW (HKEY hKey,
                            dwOptions,
                            samDesired,
                            lpdwDisposition);
-  DPRINT("Status %x\n", Status);
+  TRACE("Status %x\n", Status);
   if (!NT_SUCCESS(Status))
     {
-      ErrorCode = RtlNtStatusToDosError (Status);
-      SetLastError (ErrorCode);
-      return ErrorCode;
+      return RtlNtStatusToDosError (Status);
     }
 
   return ERROR_SUCCESS;
@@ -564,7 +664,7 @@ RegCreateKeyA (HKEY hKey,
                          0,
                          NULL,
                          0,
-                         KEY_ALL_ACCESS,
+                         MAXIMUM_ALLOWED,
                          NULL,
                          phkResult,
                          NULL);
@@ -586,7 +686,7 @@ RegCreateKeyW (HKEY hKey,
                          0,
                          NULL,
                          0,
-                         KEY_ALL_ACCESS,
+                         MAXIMUM_ALLOWED,
                          NULL,
                          phkResult,
                          NULL);
@@ -607,15 +707,12 @@ RegDeleteKeyA (HKEY hKey,
   HANDLE ParentKey;
   HANDLE TargetKey;
   NTSTATUS Status;
-  LONG ErrorCode;
 
   Status = MapDefaultKey (&ParentKey,
                          hKey);
   if (!NT_SUCCESS(Status))
     {
-      ErrorCode = RtlNtStatusToDosError (Status);
-      SetLastError (ErrorCode);
-      return ErrorCode;
+      return RtlNtStatusToDosError (Status);
     }
 
   RtlCreateUnicodeStringFromAsciiz (&SubKeyName,
@@ -623,7 +720,7 @@ RegDeleteKeyA (HKEY hKey,
   InitializeObjectAttributes(&ObjectAttributes,
                             &SubKeyName,
                             OBJ_CASE_INSENSITIVE,
-                            (HANDLE)ParentKey,
+                            ParentKey,
                             NULL);
 
   Status = NtOpenKey (&TargetKey,
@@ -632,18 +729,14 @@ RegDeleteKeyA (HKEY hKey,
   RtlFreeUnicodeString (&SubKeyName);
   if (!NT_SUCCESS(Status))
     {
-      ErrorCode = RtlNtStatusToDosError (Status);
-      SetLastError (ErrorCode);
-      return ErrorCode;
+      return RtlNtStatusToDosError (Status);
     }
 
   Status = NtDeleteKey (TargetKey);
   NtClose (TargetKey);
   if (!NT_SUCCESS(Status))
     {
-      ErrorCode = RtlNtStatusToDosError(Status);
-      SetLastError (ErrorCode);
-      return ErrorCode;
+      return RtlNtStatusToDosError(Status);
     }
 
   return ERROR_SUCCESS;
@@ -664,15 +757,12 @@ RegDeleteKeyW (HKEY hKey,
   HANDLE ParentKey;
   HANDLE TargetKey;
   NTSTATUS Status;
-  LONG ErrorCode;
 
   Status = MapDefaultKey (&ParentKey,
                          hKey);
   if (!NT_SUCCESS(Status))
     {
-      ErrorCode = RtlNtStatusToDosError (Status);
-      SetLastError (ErrorCode);
-      return ErrorCode;
+      return RtlNtStatusToDosError (Status);
     }
 
   RtlInitUnicodeString (&SubKeyName,
@@ -680,31 +770,364 @@ RegDeleteKeyW (HKEY hKey,
   InitializeObjectAttributes (&ObjectAttributes,
                              &SubKeyName,
                              OBJ_CASE_INSENSITIVE,
-                             (HANDLE)ParentKey,
+                             ParentKey,
                              NULL);
   Status = NtOpenKey (&TargetKey,
                      DELETE,
                      &ObjectAttributes);
   if (!NT_SUCCESS(Status))
     {
-      ErrorCode = RtlNtStatusToDosError (Status);
-      SetLastError (ErrorCode);
-      return ErrorCode;
+      return RtlNtStatusToDosError (Status);
     }
 
   Status = NtDeleteKey (TargetKey);
   NtClose (TargetKey);
   if (!NT_SUCCESS(Status))
     {
-      ErrorCode = RtlNtStatusToDosError (Status);
-      SetLastError (ErrorCode);
-      return ErrorCode;
+      return RtlNtStatusToDosError (Status);
     }
 
   return ERROR_SUCCESS;
 }
 
 
+/************************************************************************
+ *  RegDeleteKeyValueW
+ *
+ * @implemented
+ */
+LONG STDCALL
+RegDeleteKeyValueW(IN HKEY hKey,
+                   IN LPCWSTR lpSubKey  OPTIONAL,
+                   IN LPCWSTR lpValueName  OPTIONAL)
+{
+    UNICODE_STRING ValueName;
+    HANDLE KeyHandle, SubKeyHandle = NULL;
+    NTSTATUS Status;
+
+    Status = MapDefaultKey(&KeyHandle,
+                           hKey);
+    if (!NT_SUCCESS(Status))
+    {
+        return RtlNtStatusToDosError(Status);
+    }
+
+    if (lpSubKey != NULL)
+    {
+        OBJECT_ATTRIBUTES ObjectAttributes;
+        UNICODE_STRING SubKeyName;
+
+        RtlInitUnicodeString(&SubKeyName,
+                             (LPWSTR)lpSubKey);
+
+        InitializeObjectAttributes(&ObjectAttributes,
+                                   &SubKeyName,
+                                   OBJ_CASE_INSENSITIVE,
+                                   KeyHandle,
+                                   NULL);
+
+        Status = NtOpenKey(&SubKeyHandle,
+                           KEY_SET_VALUE,
+                           &ObjectAttributes);
+        if (!NT_SUCCESS(Status))
+        {
+            return RtlNtStatusToDosError(Status);
+        }
+    }
+
+    RtlInitUnicodeString(&ValueName,
+                         (LPWSTR)lpValueName);
+
+    Status = NtDeleteValueKey((SubKeyHandle != NULL) ? SubKeyHandle : KeyHandle,
+                              &ValueName);
+
+    if (SubKeyHandle != NULL)
+    {
+        NtClose(SubKeyHandle);
+    }
+
+    if (!NT_SUCCESS(Status))
+    {
+        return RtlNtStatusToDosError(Status);
+    }
+
+    return ERROR_SUCCESS;
+}
+
+
+/************************************************************************
+ *  RegDeleteKeyValueA
+ *
+ * @implemented
+ */
+LONG STDCALL
+RegDeleteKeyValueA(IN HKEY hKey,
+                   IN LPCSTR lpSubKey  OPTIONAL,
+                   IN LPCSTR lpValueName  OPTIONAL)
+{
+    UNICODE_STRING SubKey, ValueName;
+    LONG Ret;
+    
+    if (lpSubKey != NULL)
+    {
+        if (!RtlCreateUnicodeStringFromAsciiz(&SubKey,
+                                              (LPSTR)lpSubKey))
+        {
+            return ERROR_NOT_ENOUGH_MEMORY;
+        }
+    }
+    else
+        RtlInitUnicodeString(&SubKey,
+                             NULL);
+
+    if (lpValueName != NULL)
+    {
+        if (!RtlCreateUnicodeStringFromAsciiz(&ValueName,
+                                              (LPSTR)lpValueName))
+        {
+            RtlFreeUnicodeString(&SubKey);
+            return ERROR_NOT_ENOUGH_MEMORY;
+        }
+    }
+    else
+        RtlInitUnicodeString(&ValueName,
+                             NULL);
+
+    Ret = RegDeleteKeyValueW(hKey,
+                             SubKey.Buffer,
+                             SubKey.Buffer);
+
+    RtlFreeUnicodeString(&SubKey);
+    RtlFreeUnicodeString(&ValueName);
+    
+    return Ret;
+}
+
+
+/************************************************************************
+ *  RegDeleteTreeW
+ *
+ * @unimplemented
+ */
+LONG STDCALL
+RegDeleteTreeW(IN HKEY hKey,
+               IN LPCWSTR lpSubKey  OPTIONAL)
+{
+    HANDLE KeyHandle, SubKeyHandle = NULL;
+    NTSTATUS Status;
+
+    Status = MapDefaultKey(&KeyHandle,
+                           hKey);
+    if (!NT_SUCCESS(Status))
+    {
+        return RtlNtStatusToDosError(Status);
+    }
+
+    if (lpSubKey != NULL)
+    {
+        OBJECT_ATTRIBUTES ObjectAttributes;
+        UNICODE_STRING SubKeyName;
+
+        RtlInitUnicodeString(&SubKeyName,
+                             (LPWSTR)lpSubKey);
+
+        InitializeObjectAttributes(&ObjectAttributes,
+                                   &SubKeyName,
+                                   OBJ_CASE_INSENSITIVE,
+                                   KeyHandle,
+                                   NULL);
+
+        Status = NtOpenKey(&SubKeyHandle,
+                           DELETE | KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE,
+                           &ObjectAttributes);
+        if (!NT_SUCCESS(Status))
+        {
+            return RtlNtStatusToDosError(Status);
+        }
+    }
+
+    /* FIXME - delete all keys recursively */
+    Status = STATUS_NOT_IMPLEMENTED;
+
+    if (SubKeyHandle != NULL)
+    {
+        NtClose(SubKeyHandle);
+    }
+
+    if (!NT_SUCCESS(Status))
+    {
+        return RtlNtStatusToDosError(Status);
+    }
+
+    return ERROR_SUCCESS;
+}
+
+
+/************************************************************************
+ *  RegDeleteTreeA
+ *
+ * @implemented
+ */
+LONG STDCALL
+RegDeleteTreeA(IN HKEY hKey,
+               IN LPCSTR lpSubKey  OPTIONAL)
+{
+    UNICODE_STRING SubKeyName;
+    LONG Ret;
+
+    if (lpSubKey != NULL)
+    {
+        if (!RtlCreateUnicodeStringFromAsciiz(&SubKeyName,
+                                              (LPSTR)lpSubKey))
+        {
+            return ERROR_NOT_ENOUGH_MEMORY;
+        }
+    }
+    else
+        RtlInitUnicodeString(&SubKeyName,
+                             NULL);
+
+    Ret = RegDeleteTreeW(hKey,
+                         SubKeyName.Buffer);
+
+    RtlFreeUnicodeString(&SubKeyName);
+
+    return Ret;
+}
+
+
+/************************************************************************
+ *  RegSetKeyValueW
+ *
+ * @implemented
+ */
+LONG STDCALL
+RegSetKeyValueW(IN HKEY hKey,
+                IN LPCWSTR lpSubKey  OPTIONAL,
+                IN LPCWSTR lpValueName  OPTIONAL,
+                IN DWORD dwType,
+                IN LPCVOID lpData  OPTIONAL,
+                IN DWORD cbData)
+{
+    HANDLE KeyHandle, SubKeyHandle = NULL;
+    NTSTATUS Status;
+    LONG Ret;
+
+    Status = MapDefaultKey(&KeyHandle,
+                           hKey);
+    if (!NT_SUCCESS(Status))
+    {
+        return RtlNtStatusToDosError(Status);
+    }
+    
+    if (lpSubKey != NULL)
+    {
+        OBJECT_ATTRIBUTES ObjectAttributes;
+        UNICODE_STRING SubKeyName;
+
+        RtlInitUnicodeString(&SubKeyName,
+                             (LPWSTR)lpSubKey);
+
+        InitializeObjectAttributes(&ObjectAttributes,
+                                   &SubKeyName,
+                                   OBJ_CASE_INSENSITIVE,
+                                   KeyHandle,
+                                   NULL);
+
+        Status = NtOpenKey(&SubKeyHandle,
+                           KEY_SET_VALUE,
+                           &ObjectAttributes);
+        if (!NT_SUCCESS(Status))
+        {
+            return RtlNtStatusToDosError(Status);
+        }
+    }
+    
+    Ret = RegSetValueExW((SubKeyHandle != NULL) ? SubKeyHandle : KeyHandle,
+                         lpValueName,
+                         0,
+                         dwType,
+                         lpData,
+                         cbData);
+
+    if (SubKeyHandle != NULL)
+    {
+        NtClose(SubKeyHandle);
+    }
+
+    return Ret;
+}
+
+
+/************************************************************************
+ *  RegSetKeyValueA
+ *
+ * @implemented
+ */
+LONG STDCALL
+RegSetKeyValueA(IN HKEY hKey,
+                IN LPCSTR lpSubKey  OPTIONAL,
+                IN LPCSTR lpValueName  OPTIONAL,
+                IN DWORD dwType,
+                IN LPCVOID lpData  OPTIONAL,
+                IN DWORD cbData)
+{
+    HANDLE KeyHandle, SubKeyHandle = NULL;
+    NTSTATUS Status;
+    LONG Ret;
+
+    Status = MapDefaultKey(&KeyHandle,
+                           hKey);
+    if (!NT_SUCCESS(Status))
+    {
+        return RtlNtStatusToDosError(Status);
+    }
+
+    if (lpSubKey != NULL)
+    {
+        OBJECT_ATTRIBUTES ObjectAttributes;
+        UNICODE_STRING SubKeyName;
+
+        if (!RtlCreateUnicodeStringFromAsciiz(&SubKeyName,
+                                              (LPSTR)lpSubKey))
+        {
+            return ERROR_NOT_ENOUGH_MEMORY;
+        }
+
+        InitializeObjectAttributes(&ObjectAttributes,
+                                   &SubKeyName,
+                                   OBJ_CASE_INSENSITIVE,
+                                   KeyHandle,
+                                   NULL);
+
+        Status = NtOpenKey(&SubKeyHandle,
+                           KEY_SET_VALUE,
+                           &ObjectAttributes);
+
+        RtlFreeUnicodeString(&SubKeyName);
+
+        if (!NT_SUCCESS(Status))
+        {
+            return RtlNtStatusToDosError(Status);
+        }
+    }
+
+    Ret = RegSetValueExA((SubKeyHandle != NULL) ? SubKeyHandle : KeyHandle,
+                         lpValueName,
+                         0,
+                         dwType,
+                         lpData,
+                         cbData);
+
+    if (SubKeyHandle != NULL)
+    {
+        NtClose(SubKeyHandle);
+    }
+
+    return Ret;
+}
+
+
 /************************************************************************
  *  RegDeleteValueA
  *
@@ -716,16 +1139,13 @@ RegDeleteValueA (HKEY hKey,
 {
   UNICODE_STRING ValueName;
   HANDLE KeyHandle;
-  LONG ErrorCode;
   NTSTATUS Status;
 
   Status = MapDefaultKey (&KeyHandle,
                          hKey);
   if (!NT_SUCCESS(Status))
     {
-      ErrorCode = RtlNtStatusToDosError (Status);
-      SetLastError (ErrorCode);
-      return ErrorCode;
+      return RtlNtStatusToDosError (Status);
     }
 
   RtlCreateUnicodeStringFromAsciiz (&ValueName,
@@ -735,9 +1155,7 @@ RegDeleteValueA (HKEY hKey,
   RtlFreeUnicodeString (&ValueName);
   if (!NT_SUCCESS(Status))
     {
-      ErrorCode = RtlNtStatusToDosError (Status);
-      SetLastError (ErrorCode);
-      return ErrorCode;
+      return RtlNtStatusToDosError (Status);
     }
 
   return ERROR_SUCCESS;
@@ -755,16 +1173,13 @@ RegDeleteValueW (HKEY hKey,
 {
   UNICODE_STRING ValueName;
   NTSTATUS Status;
-  LONG ErrorCode;
   HANDLE KeyHandle;
 
   Status = MapDefaultKey (&KeyHandle,
                          hKey);
   if (!NT_SUCCESS(Status))
     {
-      ErrorCode = RtlNtStatusToDosError (Status);
-      SetLastError (ErrorCode);
-      return ErrorCode;
+      return RtlNtStatusToDosError (Status);
     }
 
   RtlInitUnicodeString (&ValueName,
@@ -774,9 +1189,7 @@ RegDeleteValueW (HKEY hKey,
                             &ValueName);
   if (!NT_SUCCESS(Status))
     {
-      ErrorCode = RtlNtStatusToDosError (Status);
-      SetLastError (ErrorCode);
-      return ErrorCode;
+      return RtlNtStatusToDosError (Status);
     }
 
   return ERROR_SUCCESS;
@@ -848,166 +1261,154 @@ RegEnumKeyExA (HKEY hKey,
               LPDWORD lpcbClass,
               PFILETIME lpftLastWriteTime)
 {
-  union
-  {
-    KEY_NODE_INFORMATION Node;
-    KEY_BASIC_INFORMATION Basic;
-  } *KeyInfo;
-
-  UNICODE_STRING StringU;
-  ANSI_STRING StringA;
-  LONG ErrorCode = ERROR_SUCCESS;
-  DWORD NameLength;
-  DWORD ClassLength = 0;
-  DWORD BufferSize;
-  DWORD ResultSize;
-  HANDLE KeyHandle;
-  NTSTATUS Status;
+       union
+       {
+               KEY_NODE_INFORMATION Node;
+               KEY_BASIC_INFORMATION Basic;
+       } *KeyInfo;
+
+       UNICODE_STRING StringU;
+       ANSI_STRING StringA;
+       LONG ErrorCode = ERROR_SUCCESS;
+       DWORD NameLength;
+       DWORD ClassLength = 0;
+       DWORD BufferSize;
+       DWORD ResultSize;
+       HANDLE KeyHandle;
+       NTSTATUS Status;
+
+       TRACE("RegEnumKeyExA(hKey 0x%x, dwIndex %d, lpName 0x%x, *lpcbName %d, lpClass 0x%x, lpcbClass %d)\n",
+               hKey, dwIndex, lpName, *lpcbName, lpClass, lpcbClass ? *lpcbClass : 0);
+
+       if ((lpClass) && (!lpcbClass))
+       {
+               return ERROR_INVALID_PARAMETER;
+       }
 
-  DPRINT("RegEnumKeyExA(hKey 0x%x, dwIndex %d, lpName 0x%x, *lpcbName %d, lpClass 0x%x, lpcbClass %d)\n",
-         hKey, dwIndex, lpName, *lpcbName, lpClass, lpcbClass ? *lpcbClass : 0);
+       Status = MapDefaultKey(&KeyHandle, hKey);
+       if (!NT_SUCCESS(Status))
+       {
+               return RtlNtStatusToDosError (Status);
+       }
 
-  if ((lpClass) && (!lpcbClass))
-    {
-      SetLastError (ERROR_INVALID_PARAMETER);
-      return ERROR_INVALID_PARAMETER;
-    }
+       if (*lpcbName > 0)
+       {
+               NameLength = min (*lpcbName - 1 , REG_MAX_NAME_SIZE) * sizeof (WCHAR);
+       }
+       else
+       {
+               NameLength = 0;
+       }
 
-  Status = MapDefaultKey(&KeyHandle,
-                        hKey);
-  if (!NT_SUCCESS(Status))
-    {
-      ErrorCode = RtlNtStatusToDosError (Status);
-      SetLastError (ErrorCode);
-      return ErrorCode;
-    }
-
-  if (*lpcbName > 0)
-    {
-      NameLength = min (*lpcbName - 1 , REG_MAX_NAME_SIZE) * sizeof (WCHAR);
-    }
-  else
-    {
-      NameLength = 0;
-    }
-
-  if (lpClass)
-    {
-      if (*lpcbClass > 0)
+       if (lpClass)
        {
-         ClassLength = min (*lpcbClass -1, REG_MAX_NAME_SIZE) * sizeof(WCHAR);
+               if (*lpcbClass > 0)
+               {
+                       ClassLength = min (*lpcbClass -1, REG_MAX_NAME_SIZE) * sizeof(WCHAR);
+               }
+               else
+               {
+                       ClassLength = 0;
+               }
+
+               /* The class name should start at a dword boundary */
+               BufferSize = ((sizeof(KEY_NODE_INFORMATION) + NameLength + 3) & ~3) + ClassLength;
        }
-      else
+       else
        {
-         ClassLength = 0;
+               BufferSize = sizeof(KEY_BASIC_INFORMATION) + NameLength;
        }
 
-      /* The class name should start at a dword boundary */
-      BufferSize = ((sizeof(KEY_NODE_INFORMATION) + NameLength + 3) & ~3) + ClassLength;
-    }
-  else
-    {
-      BufferSize = sizeof(KEY_BASIC_INFORMATION) + NameLength;
-    }
-
-  KeyInfo = RtlAllocateHeap (ProcessHeap,
-                            0,
-                            BufferSize);
-  if (KeyInfo == NULL)
-    {
-      SetLastError (ERROR_OUTOFMEMORY);
-      return ERROR_OUTOFMEMORY;
-    }
-
-  Status = NtEnumerateKey (KeyHandle,
-                          (ULONG)dwIndex,
-                          lpClass == NULL ? KeyBasicInformation : KeyNodeInformation,
-                          KeyInfo,
-                          BufferSize,
-                          &ResultSize);
-  DPRINT("NtEnumerateKey() returned status 0x%X\n", Status);
-  if (!NT_SUCCESS(Status))
-    {
-      ErrorCode = RtlNtStatusToDosError (Status);
-    }
-  else
-    {
-      if (lpClass == NULL)
+       KeyInfo = RtlAllocateHeap (ProcessHeap, 0, BufferSize);
+       if (KeyInfo == NULL)
        {
-         if (KeyInfo->Basic.NameLength > NameLength)
-           {
-             ErrorCode = ERROR_BUFFER_OVERFLOW;
-           }
-         else
-           {
-             StringU.Buffer = KeyInfo->Basic.Name;
-             StringU.Length = KeyInfo->Basic.NameLength;
-             StringU.MaximumLength = KeyInfo->Basic.NameLength;
-           }
+               return ERROR_OUTOFMEMORY;
        }
-      else
+
+       Status = NtEnumerateKey (KeyHandle,
+                                                               (ULONG)dwIndex,
+                                                               lpClass == NULL ? KeyBasicInformation : KeyNodeInformation,
+                                                               KeyInfo,
+                                                               BufferSize,
+                                                               &ResultSize);
+       TRACE("NtEnumerateKey() returned status 0x%X\n", Status);
+       if (!NT_SUCCESS(Status))
        {
-         if (KeyInfo->Node.NameLength > NameLength ||
-             KeyInfo->Node.ClassLength > ClassLength)
-           {
-             ErrorCode = ERROR_BUFFER_OVERFLOW;
-           }
-         else
-           {
-             StringA.Buffer = lpClass;
-             StringA.Length = 0;
-             StringA.MaximumLength = *lpcbClass;
-             StringU.Buffer = (PWCHAR)((ULONG_PTR)KeyInfo->Node.Name + KeyInfo->Node.ClassOffset);
-             StringU.Length = KeyInfo->Node.ClassLength;
-             StringU.MaximumLength = KeyInfo->Node.ClassLength;
-             RtlUnicodeStringToAnsiString (&StringA, &StringU, FALSE);
-             lpClass[StringA.Length] = 0;
-             *lpcbClass = StringA.Length;
-             StringU.Buffer = KeyInfo->Node.Name;
-             StringU.Length = KeyInfo->Node.NameLength;
-             StringU.MaximumLength = KeyInfo->Node.NameLength;
-           }
+               ErrorCode = RtlNtStatusToDosError (Status);
        }
-
-      if (ErrorCode == ERROR_SUCCESS)
+       else
        {
-         StringA.Buffer = lpName;
-         StringA.Length = 0;
-         StringA.MaximumLength = *lpcbName;
-         RtlUnicodeStringToAnsiString (&StringA, &StringU, FALSE);
-         lpName[StringA.Length] = 0;
-         *lpcbName = StringA.Length;
-         if (lpftLastWriteTime != NULL)
-           {
-             if (lpClass == NULL)
+               if (lpClass == NULL)
                {
-                 lpftLastWriteTime->dwLowDateTime = KeyInfo->Basic.LastWriteTime.u.LowPart;
-                 lpftLastWriteTime->dwHighDateTime = KeyInfo->Basic.LastWriteTime.u.HighPart;
+                       if (KeyInfo->Basic.NameLength > NameLength)
+                       {
+                               ErrorCode = ERROR_BUFFER_OVERFLOW;
+                       }
+                       else
+                       {
+                               StringU.Buffer = KeyInfo->Basic.Name;
+                               StringU.Length = KeyInfo->Basic.NameLength;
+                               StringU.MaximumLength = KeyInfo->Basic.NameLength;
+                       }
                }
-             else
+               else
                {
-                 lpftLastWriteTime->dwLowDateTime = KeyInfo->Node.LastWriteTime.u.LowPart;
-                 lpftLastWriteTime->dwHighDateTime = KeyInfo->Node.LastWriteTime.u.HighPart;
+                       if (KeyInfo->Node.NameLength > NameLength ||
+                               KeyInfo->Node.ClassLength > ClassLength)
+                       {
+                               ErrorCode = ERROR_BUFFER_OVERFLOW;
+                       }
+                       else
+                       {
+                               StringA.Buffer = lpClass;
+                               StringA.Length = 0;
+                               StringA.MaximumLength = *lpcbClass;
+                               StringU.Buffer = (PWCHAR)((ULONG_PTR)KeyInfo->Node.Name + KeyInfo->Node.ClassOffset);
+                               StringU.Length = KeyInfo->Node.ClassLength;
+                               StringU.MaximumLength = KeyInfo->Node.ClassLength;
+                               RtlUnicodeStringToAnsiString (&StringA, &StringU, FALSE);
+                               lpClass[StringA.Length] = 0;
+                               *lpcbClass = StringA.Length;
+                               StringU.Buffer = KeyInfo->Node.Name;
+                               StringU.Length = KeyInfo->Node.NameLength;
+                               StringU.MaximumLength = KeyInfo->Node.NameLength;
+                       }
                }
-           }
-       }
-    }
 
-  DPRINT("Key Namea0 Length %d\n", StringU.Length);
-  DPRINT("Key Namea1 Length %d\n", NameLength);
-  DPRINT("Key Namea Length %d\n", *lpcbName);
-  DPRINT("Key Namea %s\n", lpName);
+               if (ErrorCode == ERROR_SUCCESS)
+               {
+                       StringA.Buffer = lpName;
+                       StringA.Length = 0;
+                       StringA.MaximumLength = *lpcbName;
+                       RtlUnicodeStringToAnsiString (&StringA, &StringU, FALSE);
+                       lpName[StringA.Length] = 0;
+                       *lpcbName = StringA.Length;
+                       if (lpftLastWriteTime != NULL)
+                       {
+                               if (lpClass == NULL)
+                               {
+                                       lpftLastWriteTime->dwLowDateTime = KeyInfo->Basic.LastWriteTime.u.LowPart;
+                                       lpftLastWriteTime->dwHighDateTime = KeyInfo->Basic.LastWriteTime.u.HighPart;
+                               }
+                               else
+                               {
+                                       lpftLastWriteTime->dwLowDateTime = KeyInfo->Node.LastWriteTime.u.LowPart;
+                                       lpftLastWriteTime->dwHighDateTime = KeyInfo->Node.LastWriteTime.u.HighPart;
+                               }
+                       }
+               }
+       }
 
-  RtlFreeHeap (ProcessHeap,
-              0,
-              KeyInfo);
+       TRACE("Key Namea0 Length %d\n", StringU.Length);
+       TRACE("Key Namea1 Length %d\n", NameLength);
+       TRACE("Key Namea Length %d\n", *lpcbName);
+       TRACE("Key Namea %s\n", lpName);
 
-  if (ErrorCode != ERROR_SUCCESS)
-    {
-      SetLastError(ErrorCode);
-    }
+       RtlFreeHeap (ProcessHeap,
+               0,
+               KeyInfo);
 
-  return ErrorCode;
+       return ErrorCode;
 }
 
 
@@ -1044,9 +1445,7 @@ RegEnumKeyExW (HKEY hKey,
                         hKey);
   if (!NT_SUCCESS(Status))
     {
-      ErrorCode = RtlNtStatusToDosError (Status);
-      SetLastError (ErrorCode);
-      return ErrorCode;
+      return RtlNtStatusToDosError (Status);
     }
 
   if (*lpcbName > 0)
@@ -1081,7 +1480,6 @@ RegEnumKeyExW (HKEY hKey,
                             BufferSize);
   if (KeyInfo == NULL)
     {
-      SetLastError (ERROR_OUTOFMEMORY);
       return ERROR_OUTOFMEMORY;
     }
 
@@ -1091,7 +1489,7 @@ RegEnumKeyExW (HKEY hKey,
                           KeyInfo,
                           BufferSize,
                           &ResultSize);
-  DPRINT("NtEnumerateKey() returned status 0x%X\n", Status);
+  TRACE("NtEnumerateKey() returned status 0x%X\n", Status);
   if (!NT_SUCCESS(Status))
     {
       ErrorCode = RtlNtStatusToDosError (Status);
@@ -1154,320 +1552,222 @@ RegEnumKeyExW (HKEY hKey,
               0,
               KeyInfo);
 
-  if (ErrorCode != ERROR_SUCCESS)
-    {
-      SetLastError(ErrorCode);
-    }
-
   return ErrorCode;
 }
 
-
 /************************************************************************
  *  RegEnumValueA
  *
  * @implemented
  */
 LONG STDCALL
-RegEnumValueA (HKEY hKey,
-              DWORD dwIndex,
-              LPSTR lpValueName,
-              LPDWORD lpcbValueName,
-              LPDWORD lpReserved,
-              LPDWORD lpType,
-              LPBYTE lpData,
-              LPDWORD lpcbData)
+RegEnumValueA( HKEY hKey, DWORD index, LPSTR value, LPDWORD val_count,
+               LPDWORD reserved, LPDWORD type, LPBYTE data, LPDWORD count )
 {
-  union
-  {
-    KEY_VALUE_FULL_INFORMATION Full;
-    KEY_VALUE_BASIC_INFORMATION Basic;
-  } *ValueInfo;
+       HANDLE KeyHandle;
+    NTSTATUS status;
+    DWORD total_size;
+    char buffer[256], *buf_ptr = buffer;
+    KEY_VALUE_FULL_INFORMATION *info = (KEY_VALUE_FULL_INFORMATION *)buffer;
+    static const int info_size = offsetof( KEY_VALUE_FULL_INFORMATION, Name );
+
+    //TRACE("(%p,%ld,%p,%p,%p,%p,%p,%p)\n",
+      //    hkey, index, value, val_count, reserved, type, data, count );
+
+    /* NT only checks count, not val_count */
+    if ((data && !count) || reserved) return ERROR_INVALID_PARAMETER;
+       status = MapDefaultKey (&KeyHandle, hKey);
+       if (!NT_SUCCESS(status))
+       {
+               return RtlNtStatusToDosError (status);
+       }
 
-  ULONG NameLength;
-  ULONG BufferSize;
-  ULONG DataLength = 0;
-  ULONG ResultSize;
-  HANDLE KeyHandle;
-  LONG ErrorCode;
-  NTSTATUS Status;
-  UNICODE_STRING StringU;
-  ANSI_STRING StringA;
-  BOOL IsStringType;
+    total_size = info_size + (MAX_PATH + 1) * sizeof(WCHAR);
+    if (data) total_size += *count;
+    total_size = min( sizeof(buffer), total_size );
 
-  ErrorCode = ERROR_SUCCESS;
+    status = NtEnumerateValueKey( KeyHandle, index, KeyValueFullInformation,
+                                  buffer, total_size, &total_size );
+    if (status && status != STATUS_BUFFER_OVERFLOW) goto done;
 
-  Status = MapDefaultKey (&KeyHandle,
-                         hKey);
-  if (!NT_SUCCESS(Status))
+    /* we need to fetch the contents for a string type even if not requested,
+     * because we need to compute the length of the ASCII string. */
+    if (value || data || is_string(info->Type))
     {
-      ErrorCode = RtlNtStatusToDosError (Status);
-      SetLastError (ErrorCode);
-      return ErrorCode;
-    }
-
-  if (*lpcbValueName > 0)
-    {
-      NameLength = min (*lpcbValueName - 1, REG_MAX_NAME_SIZE) * sizeof(WCHAR);
-    }
-  else
-    {
-      NameLength = 0;
-    }
-
-  if (lpData)
-    {
-      DataLength = min (*lpcbData * sizeof(WCHAR), REG_MAX_DATA_SIZE);
-      BufferSize = ((sizeof(KEY_VALUE_FULL_INFORMATION) + NameLength + 3) & ~3) + DataLength;
-    }
-  else
-    {
-      BufferSize = sizeof(KEY_VALUE_BASIC_INFORMATION) + NameLength;
-    }
-
-  ValueInfo = RtlAllocateHeap (ProcessHeap,
-                              0,
-                              BufferSize);
-  if (ValueInfo == NULL)
-    {
-      SetLastError(ERROR_OUTOFMEMORY);
-      return ERROR_OUTOFMEMORY;
-    }
+        /* retry with a dynamically allocated buffer */
+        while (status == STATUS_BUFFER_OVERFLOW)
+        {
+            if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
+            if (!(buf_ptr = HeapAlloc( GetProcessHeap(), 0, total_size )))
+                return ERROR_NOT_ENOUGH_MEMORY;
+            info = (KEY_VALUE_FULL_INFORMATION *)buf_ptr;
+            status = NtEnumerateValueKey( KeyHandle, index, KeyValueFullInformation,
+                                          buf_ptr, total_size, &total_size );
+        }
 
-  Status = NtEnumerateValueKey (KeyHandle,
-                               (ULONG)dwIndex,
-                               lpData ? KeyValueFullInformation : KeyValueBasicInformation,
-                               ValueInfo,
-                               BufferSize,
-                               &ResultSize);
+        if (status) goto done;
 
-  DPRINT("NtEnumerateValueKey() returned status 0x%X\n", Status);
-  if (!NT_SUCCESS(Status))
-    {
-      ErrorCode = RtlNtStatusToDosError (Status);
-    }
-  else
-    {
-      if (lpData)
+        if (is_string(info->Type))
         {
-         IsStringType = (ValueInfo->Full.Type == REG_SZ) ||
-                        (ValueInfo->Full.Type == REG_MULTI_SZ) ||
-                        (ValueInfo->Full.Type == REG_EXPAND_SZ);
-         if (ValueInfo->Full.NameLength > NameLength ||
-             (!IsStringType && ValueInfo->Full.DataLength > *lpcbData) ||
-             ValueInfo->Full.DataLength > DataLength)
-           {
-             ErrorCode = ERROR_BUFFER_OVERFLOW;
-           }
-         else
-           {
-             if (IsStringType)
-               {
-                 StringU.Buffer = (PWCHAR)((ULONG_PTR)ValueInfo + ValueInfo->Full.DataOffset);
-                 StringU.Length = ValueInfo->Full.DataLength;
-                 StringU.MaximumLength = DataLength;
-                 StringA.Buffer = (PCHAR)lpData;
-                 StringA.Length = 0;
-                 StringA.MaximumLength = *lpcbData;
-                 RtlUnicodeStringToAnsiString (&StringA,
-                                               &StringU,
-                                               FALSE);
-                 *lpcbData = StringA.Length;
-               }
-             else
-               {
-                 RtlCopyMemory (lpData,
-                                (PVOID)((ULONG_PTR)ValueInfo + ValueInfo->Full.DataOffset),
-                                ValueInfo->Full.DataLength);
-                 *lpcbData = ValueInfo->Full.DataLength;
-               }
-
-             StringU.Buffer = ValueInfo->Full.Name;
-             StringU.Length = ValueInfo->Full.NameLength;
-             StringU.MaximumLength = NameLength;
-           }
-       }
-      else
-       {
-         if (ValueInfo->Basic.NameLength > NameLength)
-           {
-             ErrorCode = ERROR_BUFFER_OVERFLOW;
-           }
-         else
-           {
-             StringU.Buffer = ValueInfo->Basic.Name;
-             StringU.Length = ValueInfo->Basic.NameLength;
-             StringU.MaximumLength = NameLength;
-           }
-       }
+            DWORD len;
+            RtlUnicodeToMultiByteSize( &len, (WCHAR *)(buf_ptr + info->DataOffset),
+                                       total_size - info->DataOffset );
+            if (data && len)
+            {
+                if (len > *count) status = STATUS_BUFFER_OVERFLOW;
+                else
+                {
+                    RtlUnicodeToMultiByteN( (PCHAR)data, len, NULL, (WCHAR *)(buf_ptr + info->DataOffset),
+                                            total_size - info->DataOffset );
+                    /* if the type is REG_SZ and data is not 0-terminated
+                     * and there is enough space in the buffer NT appends a \0 */
+                    if (len < *count && data[len-1]) data[len] = 0;
+                }
+            }
+            info->DataLength = len;
+        }
+        else if (data)
+        {
+            if (total_size - info->DataOffset > *count) status = STATUS_BUFFER_OVERFLOW;
+            else memcpy( data, buf_ptr + info->DataOffset, total_size - info->DataOffset );
+        }
 
-      if (ErrorCode == ERROR_SUCCESS)
+        if (value && !status)
         {
-         StringA.Buffer = (PCHAR)lpValueName;
-         StringA.Length = 0;
-         StringA.MaximumLength = *lpcbValueName;
-         RtlUnicodeStringToAnsiString (&StringA,
-                                       &StringU,
-                                       FALSE);
-         StringA.Buffer[StringA.Length] = 0;
-         *lpcbValueName = StringA.Length;
-         if (lpType)
-           {
-             *lpType = lpData ? ValueInfo->Full.Type : ValueInfo->Basic.Type;
-           }
-       }
+            DWORD len;
+
+            RtlUnicodeToMultiByteSize( &len, info->Name, info->NameLength );
+            if (len >= *val_count)
+            {
+                status = STATUS_BUFFER_OVERFLOW;
+                if (*val_count)
+                {
+                    len = *val_count - 1;
+                    RtlUnicodeToMultiByteN( value, len, NULL, info->Name, info->NameLength );
+                    value[len] = 0;
+                }
+            }
+            else
+            {
+                RtlUnicodeToMultiByteN( value, len, NULL, info->Name, info->NameLength );
+                value[len] = 0;
+                *val_count = len;
+            }
+        }
     }
+    else status = STATUS_SUCCESS;
 
-  RtlFreeHeap (ProcessHeap,
-              0,
-              ValueInfo);
-  if (ErrorCode != ERROR_SUCCESS)
-    {
-      SetLastError(ErrorCode);
-    }
+    if (type) *type = info->Type;
+    if (count) *count = info->DataLength;
 
-  return ErrorCode;
+ done:
+    if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
+    return RtlNtStatusToDosError(status);
 }
 
-
-/************************************************************************
- *  RegEnumValueW
- *
+/******************************************************************************
+ * RegEnumValueW   [ADVAPI32.@]
  * @implemented
+ *
+ * PARAMS
+ *  hkey       [I] Handle to key to query
+ *  index      [I] Index of value to query
+ *  value      [O] Value string
+ *  val_count  [I/O] Size of value buffer (in wchars)
+ *  reserved   [I] Reserved
+ *  type       [O] Type code
+ *  data       [O] Value data
+ *  count      [I/O] Size of data buffer (in bytes)
+ *
+ * RETURNS
+ *  Success: ERROR_SUCCESS
+ *  Failure: nonzero error code from Winerror.h
  */
 LONG STDCALL
-RegEnumValueW (HKEY hKey,
-              DWORD dwIndex,
-              LPWSTR lpValueName,
-              LPDWORD lpcbValueName,
-              LPDWORD lpReserved,
-              LPDWORD lpType,
-              LPBYTE lpData,
-              LPDWORD lpcbData)
+RegEnumValueW( HKEY hKey, DWORD index, LPWSTR value, PDWORD val_count,
+               PDWORD reserved, PDWORD type, LPBYTE data, PDWORD count )
 {
-  union
-  {
-    KEY_VALUE_FULL_INFORMATION Full;
-    KEY_VALUE_BASIC_INFORMATION Basic;
-  } *ValueInfo;
+       HANDLE KeyHandle;
+    NTSTATUS status;
+    DWORD total_size;
+    char buffer[256], *buf_ptr = buffer;
+    KEY_VALUE_FULL_INFORMATION *info = (KEY_VALUE_FULL_INFORMATION *)buffer;
+    static const int info_size = offsetof( KEY_VALUE_FULL_INFORMATION, Name );
 
-  ULONG NameLength;
-  ULONG BufferSize;
-  ULONG DataLength = 0;
-  ULONG ResultSize;
-  HANDLE KeyHandle;
-  LONG ErrorCode;
-  NTSTATUS Status;
+    //TRACE("(%p,%ld,%p,%p,%p,%p,%p,%p)\n",
+    //      hkey, index, value, val_count, reserved, type, data, count );
 
-  ErrorCode = ERROR_SUCCESS;
+    /* NT only checks count, not val_count */
+    if ((data && !count) || reserved) return ERROR_INVALID_PARAMETER;
 
-  Status = MapDefaultKey (&KeyHandle,
-                         hKey);
-  if (!NT_SUCCESS(Status))
-    {
-      ErrorCode = RtlNtStatusToDosError (Status);
-      SetLastError (ErrorCode);
-      return ErrorCode;
-    }
+       status = MapDefaultKey (&KeyHandle, hKey);
+       if (!NT_SUCCESS(status))
+       {
+               return RtlNtStatusToDosError (status);
+       }
 
-  if (*lpcbValueName > 0)
-    {
-      NameLength = min (*lpcbValueName - 1, REG_MAX_NAME_SIZE) * sizeof(WCHAR);
-    }
-  else
-    {
-      NameLength = 0;
-    }
+    total_size = info_size + (MAX_PATH + 1) * sizeof(WCHAR);
+    if (data) total_size += *count;
+    total_size = min( sizeof(buffer), total_size );
 
-  if (lpData)
-    {
-      DataLength = min(*lpcbData, REG_MAX_DATA_SIZE);
-      BufferSize = ((sizeof(KEY_VALUE_FULL_INFORMATION) + NameLength + 3) & ~3) + DataLength;
-    }
-  else
-    {
-      BufferSize = sizeof(KEY_VALUE_BASIC_INFORMATION) + NameLength;
-    }
-  ValueInfo = RtlAllocateHeap (ProcessHeap,
-                              0,
-                              BufferSize);
-  if (ValueInfo == NULL)
-    {
-      SetLastError (ERROR_OUTOFMEMORY);
-      return ERROR_OUTOFMEMORY;
-    }
-  Status = NtEnumerateValueKey (KeyHandle,
-                               (ULONG)dwIndex,
-                               lpData ? KeyValueFullInformation : KeyValueBasicInformation,
-                               ValueInfo,
-                               BufferSize,
-                               &ResultSize);
+    status = NtEnumerateValueKey( KeyHandle, index, KeyValueFullInformation,
+                                  buffer, total_size, &total_size );
+    if (status && status != STATUS_BUFFER_OVERFLOW) goto done;
 
-  DPRINT("NtEnumerateValueKey() returned status 0x%X\n", Status);
-  if (!NT_SUCCESS(Status))
-    {
-      ErrorCode = RtlNtStatusToDosError (Status);
-    }
-  else
+    if (value || data)
     {
-      if (lpData)
-       {
-         if (ValueInfo->Full.DataLength > DataLength ||
-             ValueInfo->Full.NameLength > NameLength)
-           {
-             ErrorCode = ERROR_BUFFER_OVERFLOW;
-           }
-         else
-           {
-             RtlCopyMemory (lpValueName,
-                            ValueInfo->Full.Name,
-                            ValueInfo->Full.NameLength);
-             *lpcbValueName = (DWORD)(ValueInfo->Full.NameLength / sizeof(WCHAR));
-             lpValueName[*lpcbValueName] = 0;
-             RtlCopyMemory (lpData,
-                            (PVOID)((ULONG_PTR)ValueInfo + ValueInfo->Full.DataOffset),
-                            ValueInfo->Full.DataLength);
-             *lpcbData = (DWORD)ValueInfo->Full.DataLength;
-           }
-       }
-      else
-       {
-         if (ValueInfo->Basic.NameLength > NameLength)
-           {
-             ErrorCode = ERROR_BUFFER_OVERFLOW;
-           }
-         else
-           {
-             RtlCopyMemory (lpValueName,
-                            ValueInfo->Basic.Name,
-                            ValueInfo->Basic.NameLength);
-             *lpcbValueName = (DWORD)(ValueInfo->Basic.NameLength / sizeof(WCHAR));
-             lpValueName[*lpcbValueName] = 0;
-           }
-         if (NULL != lpcbData)
-           {
-             *lpcbData = (DWORD)ValueInfo->Full.DataLength;
-           }
-       }
+        /* retry with a dynamically allocated buffer */
+        while (status == STATUS_BUFFER_OVERFLOW)
+        {
+            if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
+            if (!(buf_ptr = HeapAlloc( GetProcessHeap(), 0, total_size )))
+                return ERROR_NOT_ENOUGH_MEMORY;
+            info = (KEY_VALUE_FULL_INFORMATION *)buf_ptr;
+            status = NtEnumerateValueKey( KeyHandle, index, KeyValueFullInformation,
+                                          buf_ptr, total_size, &total_size );
+        }
 
-      if (ErrorCode == ERROR_SUCCESS && lpType != NULL)
-       {
-         *lpType = lpData ? ValueInfo->Full.Type : ValueInfo->Basic.Type;
-       }
-    }
+        if (status) goto done;
 
-  RtlFreeHeap (ProcessHeap,
-              0,
-              ValueInfo);
+        if (value)
+        {
+            if (info->NameLength/sizeof(WCHAR) >= *val_count)
+            {
+                status = STATUS_BUFFER_OVERFLOW;
+                goto overflow;
+            }
+            memcpy( value, info->Name, info->NameLength );
+            *val_count = info->NameLength / sizeof(WCHAR);
+            value[*val_count] = 0;
+        }
 
-  if (ErrorCode != ERROR_SUCCESS)
-    {
-      SetLastError (ErrorCode);
+        if (data)
+        {
+            if (total_size - info->DataOffset > *count)
+            {
+                status = STATUS_BUFFER_OVERFLOW;
+                goto overflow;
+            }
+            memcpy( data, buf_ptr + info->DataOffset, total_size - info->DataOffset );
+            if (total_size - info->DataOffset <= *count-sizeof(WCHAR) && is_string(info->Type))
+            {
+                /* if the type is REG_SZ and data is not 0-terminated
+                 * and there is enough space in the buffer NT appends a \0 */
+                WCHAR *ptr = (WCHAR *)(data + total_size - info->DataOffset);
+                if (ptr > (WCHAR *)data && ptr[-1]) *ptr = 0;
+            }
+        }
     }
+    else status = STATUS_SUCCESS;
 
-  return ErrorCode;
-}
+ overflow:
+    if (type) *type = info->Type;
+    if (count) *count = info->DataLength;
 
+ done:
+    if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
+    return RtlNtStatusToDosError(status);
+}
 
 /************************************************************************
  *  RegFlushKey
@@ -1478,7 +1778,6 @@ LONG STDCALL
 RegFlushKey(HKEY hKey)
 {
   HANDLE KeyHandle;
-  LONG ErrorCode;
   NTSTATUS Status;
 
   if (hKey == HKEY_PERFORMANCE_DATA)
@@ -1490,17 +1789,13 @@ RegFlushKey(HKEY hKey)
                          hKey);
   if (!NT_SUCCESS(Status))
     {
-      ErrorCode = RtlNtStatusToDosError (Status);
-      SetLastError (ErrorCode);
-      return ErrorCode;
+      return RtlNtStatusToDosError (Status);
     }
 
   Status = NtFlushKey (KeyHandle);
   if (!NT_SUCCESS(Status))
     {
-      ErrorCode = RtlNtStatusToDosError (Status);
-      SetLastError (ErrorCode);
-      return ErrorCode;
+      return RtlNtStatusToDosError (Status);
     }
 
   return ERROR_SUCCESS;
@@ -1519,12 +1814,10 @@ RegGetKeySecurity(HKEY hKey,
                  LPDWORD lpcbSecurityDescriptor)
 {
   HANDLE KeyHandle;
-  LONG ErrorCode;
   NTSTATUS Status;
 
   if (hKey == HKEY_PERFORMANCE_DATA)
     {
-      SetLastError(ERROR_INVALID_HANDLE);
       return ERROR_INVALID_HANDLE;
     }
 
@@ -1532,10 +1825,8 @@ RegGetKeySecurity(HKEY hKey,
                         hKey);
   if (!NT_SUCCESS(Status))
     {
-      DPRINT("MapDefaultKey() failed (Status %lx)\n", Status);
-      ErrorCode = RtlNtStatusToDosError(Status);
-      SetLastError(ErrorCode);
-      return ErrorCode;
+      TRACE("MapDefaultKey() failed (Status %lx)\n", Status);
+      return RtlNtStatusToDosError (Status);
     }
 
   Status = NtQuerySecurityObject(KeyHandle,
@@ -1545,10 +1836,8 @@ RegGetKeySecurity(HKEY hKey,
                                 lpcbSecurityDescriptor);
   if (!NT_SUCCESS(Status))
     {
-      DPRINT("NtQuerySecurityObject() failed (Status %lx)\n", Status);
-      ErrorCode = RtlNtStatusToDosError(Status);
-      SetLastError(ErrorCode);
-      return ErrorCode;
+      WARN("NtQuerySecurityObject() failed (Status %lx)\n", Status);
+      return RtlNtStatusToDosError (Status);
     }
 
   return ERROR_SUCCESS;
@@ -1600,12 +1889,10 @@ RegLoadKeyW (HKEY hKey,
   UNICODE_STRING FileName;
   UNICODE_STRING KeyName;
   HANDLE KeyHandle;
-  LONG ErrorCode;
   NTSTATUS Status;
 
   if (hKey == HKEY_PERFORMANCE_DATA)
     {
-      SetLastError(ERROR_INVALID_HANDLE);
       return ERROR_INVALID_HANDLE;
     }
 
@@ -1613,9 +1900,7 @@ RegLoadKeyW (HKEY hKey,
                          hKey);
   if (!NT_SUCCESS(Status))
     {
-      ErrorCode = RtlNtStatusToDosError (Status);
-      SetLastError (ErrorCode);
-      return ErrorCode;
+      return RtlNtStatusToDosError (Status);
     }
 
   if (!RtlDosPathNameToNtPathName_U ((LPWSTR)lpFile,
@@ -1623,7 +1908,6 @@ RegLoadKeyW (HKEY hKey,
                                     NULL,
                                     NULL))
     {
-      SetLastError (ERROR_BAD_PATHNAME);
       return ERROR_BAD_PATHNAME;
     }
 
@@ -1649,9 +1933,7 @@ RegLoadKeyW (HKEY hKey,
 
   if (!NT_SUCCESS(Status))
     {
-      ErrorCode = RtlNtStatusToDosError (Status);
-      SetLastError (ErrorCode);
-      return ErrorCode;
+      return RtlNtStatusToDosError (Status);
     }
 
   return ERROR_SUCCESS;
@@ -1713,98 +1995,74 @@ RegNotifyChangeKeyValue (HKEY hKey,
 
 
 /************************************************************************
- *  RegOpenKeyA
+ *  RegOpenCurrentUser
  *
  * @implemented
  */
 LONG STDCALL
-RegOpenKeyA (HKEY hKey,
-            LPCSTR lpSubKey,
-            PHKEY phkResult)
+RegOpenCurrentUser (IN REGSAM samDesired,
+                    OUT PHKEY phkResult)
 {
-  OBJECT_ATTRIBUTES ObjectAttributes;
-  UNICODE_STRING SubKeyString;
-  HANDLE KeyHandle;
-  LONG ErrorCode;
   NTSTATUS Status;
 
-  Status = MapDefaultKey (&KeyHandle,
-                         hKey);
+  Status = RtlOpenCurrentUser((ACCESS_MASK)samDesired,
+                              (PHANDLE)phkResult);
   if (!NT_SUCCESS(Status))
-    {
-      ErrorCode = RtlNtStatusToDosError (Status);
-      SetLastError (ErrorCode);
-      return ErrorCode;
-    }
-
-  RtlCreateUnicodeStringFromAsciiz (&SubKeyString,
-                                   (LPSTR)lpSubKey);
-  InitializeObjectAttributes (&ObjectAttributes,
-                             &SubKeyString,
-                             OBJ_CASE_INSENSITIVE,
-                             KeyHandle,
-                             NULL);
-  Status = NtOpenKey ((PHANDLE)phkResult,
-                     MAXIMUM_ALLOWED,
-                     &ObjectAttributes);
-  RtlFreeUnicodeString (&SubKeyString);
-  if (!NT_SUCCESS(Status))
-    {
-      ErrorCode = RtlNtStatusToDosError (Status);
-      SetLastError (ErrorCode);
-      return ErrorCode;
-    }
+  {
+    /* NOTE - don't set the last error code! just return the error! */
+    return RtlNtStatusToDosError(Status);
+  }
 
   return ERROR_SUCCESS;
 }
 
 
 /************************************************************************
- *  RegOpenKeyW
+ *  RegOpenKeyA
  *
- *  19981101 Ariadne
- *  19990525 EA
+ *  20050503 Fireball - imported from WINE
  *
  * @implemented
  */
 LONG STDCALL
-RegOpenKeyW (HKEY hKey,
-            LPCWSTR lpSubKey,
+RegOpenKeyA (HKEY hKey,
+            LPCSTR lpSubKey,
             PHKEY phkResult)
 {
-  OBJECT_ATTRIBUTES ObjectAttributes;
-  UNICODE_STRING SubKeyString;
-  HANDLE KeyHandle;
-  LONG ErrorCode;
-  NTSTATUS Status;
-
-  Status = MapDefaultKey (&KeyHandle,
-                         hKey);
-  if (!NT_SUCCESS(Status))
-    {
-      ErrorCode = RtlNtStatusToDosError (Status);
-      SetLastError (ErrorCode);
-      return ErrorCode;
-    }
-
-  RtlInitUnicodeString (&SubKeyString,
-                       (LPWSTR)lpSubKey);
-  InitializeObjectAttributes (&ObjectAttributes,
-                             &SubKeyString,
-                             OBJ_CASE_INSENSITIVE,
-                             KeyHandle,
-                             NULL);
-  Status = NtOpenKey ((PHANDLE)phkResult,
-                     MAXIMUM_ALLOWED,
-                     &ObjectAttributes);
-  if (!NT_SUCCESS(Status))
-    {
-      ErrorCode = RtlNtStatusToDosError (Status);
-      SetLastError(ErrorCode);
-      return ErrorCode;
-    }
+       TRACE("RegOpenKeyA hKey 0x%x lpSubKey %s phkResult %p\n", hKey, lpSubKey, phkResult);
 
-  return ERROR_SUCCESS;
+       if (!lpSubKey || !*lpSubKey)
+       {
+               *phkResult = hKey;
+               return ERROR_SUCCESS;
+       }
+
+       return RegOpenKeyExA( hKey, lpSubKey, 0, MAXIMUM_ALLOWED, phkResult);
+}
+
+
+/************************************************************************
+ *  RegOpenKeyW
+ *
+ *  19981101 Ariadne
+ *  19990525 EA
+ *  20050503 Fireball - imported from WINE
+ *
+ * @implemented
+ */
+LONG STDCALL
+RegOpenKeyW (HKEY hKey,
+            LPCWSTR lpSubKey,
+            PHKEY phkResult)
+{
+       TRACE("RegOpenKeyW hKey 0x%x lpSubKey %S phkResult %p\n", hKey, lpSubKey, phkResult);
+
+       if (!lpSubKey || !*lpSubKey)
+       {
+               *phkResult = hKey;
+               return ERROR_SUCCESS;
+       }
+       return RegOpenKeyExW(hKey, lpSubKey, 0, MAXIMUM_ALLOWED, phkResult);
 }
 
 
@@ -1820,40 +2078,35 @@ RegOpenKeyExA (HKEY hKey,
               REGSAM samDesired,
               PHKEY phkResult)
 {
-  OBJECT_ATTRIBUTES ObjectAttributes;
-  UNICODE_STRING SubKeyString;
-  HANDLE KeyHandle;
-  LONG ErrorCode;
-  NTSTATUS Status;
+       OBJECT_ATTRIBUTES ObjectAttributes;
+       UNICODE_STRING SubKeyString;
+       HANDLE KeyHandle;
+       NTSTATUS Status;
 
-  Status = MapDefaultKey (&KeyHandle,
-                         hKey);
-  if (!NT_SUCCESS(Status))
-    {
-      ErrorCode = RtlNtStatusToDosError (Status);
-      SetLastError (ErrorCode);
-      return ErrorCode;
-    }
+       TRACE("RegOpenKeyExA hKey 0x%x lpSubKey %s ulOptions 0x%x samDesired 0x%x phkResult %p\n",
+               hKey, lpSubKey, ulOptions, samDesired, phkResult);
 
-  RtlCreateUnicodeStringFromAsciiz (&SubKeyString,
-                                   (LPSTR)lpSubKey);
-  InitializeObjectAttributes (&ObjectAttributes,
-                             &SubKeyString,
-                             OBJ_CASE_INSENSITIVE,
-                             KeyHandle,
-                             NULL);
-  Status = NtOpenKey ((PHANDLE)phkResult,
-                     samDesired,
-                     &ObjectAttributes);
-  RtlFreeUnicodeString (&SubKeyString);
-  if (!NT_SUCCESS(Status))
-    {
-      ErrorCode = RtlNtStatusToDosError (Status);
-      SetLastError (ErrorCode);
-      return ErrorCode;
-   }
+       Status = MapDefaultKey (&KeyHandle, hKey);
+       if (!NT_SUCCESS(Status))
+       {
+               return RtlNtStatusToDosError (Status);
+       }
 
-  return ERROR_SUCCESS;
+       RtlCreateUnicodeStringFromAsciiz (&SubKeyString, (LPSTR)lpSubKey);
+       InitializeObjectAttributes (&ObjectAttributes,
+               &SubKeyString,
+               OBJ_CASE_INSENSITIVE,
+               KeyHandle,
+               NULL);
+
+       Status = NtOpenKey ((PHANDLE)phkResult, samDesired, &ObjectAttributes);
+       RtlFreeUnicodeString (&SubKeyString);
+       if (!NT_SUCCESS(Status))
+       {
+               return RtlNtStatusToDosError (Status);
+       }
+
+       return ERROR_SUCCESS;
 }
 
 
@@ -1869,45 +2122,183 @@ RegOpenKeyExW (HKEY hKey,
               REGSAM samDesired,
               PHKEY phkResult)
 {
+       OBJECT_ATTRIBUTES ObjectAttributes;
+       UNICODE_STRING SubKeyString;
+       HANDLE KeyHandle;
+       NTSTATUS Status;
+
+       TRACE("RegOpenKeyExW hKey 0x%x lpSubKey %S ulOptions 0x%x samDesired 0x%x phkResult %p\n",
+               hKey, lpSubKey, ulOptions, samDesired, phkResult);
+
+       Status = MapDefaultKey (&KeyHandle, hKey);
+       if (!NT_SUCCESS(Status))
+       {
+               return RtlNtStatusToDosError (Status);
+       }
+
+       if (lpSubKey != NULL)
+               RtlInitUnicodeString (&SubKeyString, (LPWSTR)lpSubKey);
+       else
+               RtlInitUnicodeString (&SubKeyString, (LPWSTR)L"");
+
+       InitializeObjectAttributes (&ObjectAttributes,
+               &SubKeyString,
+               OBJ_CASE_INSENSITIVE,
+               KeyHandle,
+               NULL);
+
+       Status = NtOpenKey ((PHANDLE)phkResult, samDesired,     &ObjectAttributes);
+
+       if (!NT_SUCCESS(Status))
+       {
+               return RtlNtStatusToDosError (Status);
+       }
+
+       return ERROR_SUCCESS;
+}
+
+
+/************************************************************************
+ *  RegOpenUserClassesRoot
+ *
+ * @implemented
+ */
+LONG STDCALL
+RegOpenUserClassesRoot (IN HANDLE hToken,
+                        IN DWORD dwOptions,
+                        IN REGSAM samDesired,
+                        OUT PHKEY phkResult)
+{
+  const WCHAR UserClassesKeyPrefix[] = L"\\Registry\\User\\";
+  const WCHAR UserClassesKeySuffix[] = L"_Classes";
+  PTOKEN_USER TokenUserData;
+  ULONG RequiredLength;
+  UNICODE_STRING UserSidString, UserClassesKeyRoot;
   OBJECT_ATTRIBUTES ObjectAttributes;
-  UNICODE_STRING SubKeyString;
-  HANDLE KeyHandle;
   LONG ErrorCode;
   NTSTATUS Status;
 
-  Status = MapDefaultKey (&KeyHandle,
-                         hKey);
+  /* check parameters */
+  if (hToken == NULL || dwOptions != 0 || phkResult == NULL)
+  {
+    return ERROR_INVALID_PARAMETER;
+  }
+
+  /*
+   * Get the user sid from the token
+   */
+
+ReadTokenSid:
+  /* determine how much memory we need */
+  Status = NtQueryInformationToken(hToken,
+                                   TokenUser,
+                                   NULL,
+                                   0,
+                                   &RequiredLength);
+  if (!NT_SUCCESS(Status) && (Status != STATUS_BUFFER_TOO_SMALL))
+  {
+    /* NOTE - as opposed to all other registry functions windows does indeed
+              change the last error code in case the caller supplied a invalid
+              handle for example! */
+    ErrorCode = RtlNtStatusToDosError (Status);
+    return ErrorCode;
+  }
+
+  TokenUserData = RtlAllocateHeap(ProcessHeap,
+                                  0,
+                                  RequiredLength);
+  if (TokenUserData == NULL)
+  {
+    return ERROR_NOT_ENOUGH_MEMORY;
+  }
+
+  /* attempt to read the information */
+  Status = NtQueryInformationToken(hToken,
+                                   TokenUser,
+                                   TokenUserData,
+                                   RequiredLength,
+                                   &RequiredLength);
   if (!NT_SUCCESS(Status))
-    {
-      ErrorCode = RtlNtStatusToDosError (Status);
-      SetLastError (ErrorCode);
-      return ErrorCode;
-    }
+  {
+    RtlFreeHeap(ProcessHeap,
+                0,
+                TokenUserData);
+    if (Status == STATUS_BUFFER_TOO_SMALL)
+    {
+      /* the information appears to have changed?! try again */
+      goto ReadTokenSid;
+    }
+
+    /* NOTE - as opposed to all other registry functions windows does indeed
+              change the last error code in case the caller supplied a invalid
+              handle for example! */
+    ErrorCode = RtlNtStatusToDosError (Status);
+    return ErrorCode;
+  }
+
+  /*
+   * Build the absolute path for the user's registry in the form
+   * "\Registry\User\<SID>_Classes"
+   */
+  Status = RtlConvertSidToUnicodeString(&UserSidString,
+                                        TokenUserData->User.Sid,
+                                        TRUE);
+
+  /* we don't need the user data anymore, free it */
+  RtlFreeHeap(ProcessHeap,
+              0,
+              TokenUserData);
+
+  if (!NT_SUCCESS(Status))
+  {
+    return RtlNtStatusToDosError (Status);
+  }
+
+  /* allocate enough memory for the entire key string */
+  UserClassesKeyRoot.Length = 0;
+  UserClassesKeyRoot.MaximumLength = UserSidString.Length +
+                                     sizeof(UserClassesKeyPrefix) +
+                                     sizeof(UserClassesKeySuffix);
+  UserClassesKeyRoot.Buffer = RtlAllocateHeap(ProcessHeap,
+                                              0,
+                                              UserClassesKeyRoot.MaximumLength);
+  if (UserClassesKeyRoot.Buffer == NULL)
+  {
+    RtlFreeUnicodeString(&UserSidString);
+    return RtlNtStatusToDosError (Status);
+  }
+
+  /* build the string */
+  RtlAppendUnicodeToString(&UserClassesKeyRoot,
+                           UserClassesKeyPrefix);
+  RtlAppendUnicodeStringToString(&UserClassesKeyRoot,
+                                 &UserSidString);
+  RtlAppendUnicodeToString(&UserClassesKeyRoot,
+                           UserClassesKeySuffix);
+
+  TRACE("RegOpenUserClassesRoot: Absolute path: %wZ\n", &UserClassesKeyRoot);
+
+  /*
+   * Open the key
+   */
 
-  if (lpSubKey != NULL)
-    {
-      RtlInitUnicodeString (&SubKeyString,
-                           (LPWSTR)lpSubKey);
-    }
-  else
-    {
-      RtlInitUnicodeString (&SubKeyString,
-                           (LPWSTR)L"");
-    }
   InitializeObjectAttributes (&ObjectAttributes,
-                             &SubKeyString,
+                             &UserClassesKeyRoot,
                              OBJ_CASE_INSENSITIVE,
-                             KeyHandle,
+                             NULL,
                              NULL);
-  Status = NtOpenKey ((PHANDLE)phkResult,
-                     samDesired,
-                     &ObjectAttributes);
+
+  Status = NtOpenKey((PHANDLE)phkResult,
+                     samDesired,
+                     &ObjectAttributes);
+
+  RtlFreeUnicodeString(&UserSidString);
+  RtlFreeUnicodeString(&UserClassesKeyRoot);
+
   if (!NT_SUCCESS(Status))
-    {
-      ErrorCode = RtlNtStatusToDosError (Status);
-      SetLastError (ErrorCode);
-      return ErrorCode;
-    }
+  {
+    return RtlNtStatusToDosError (Status);
+  }
 
   return ERROR_SUCCESS;
 }
@@ -1999,12 +2390,11 @@ RegQueryInfoKeyW (HKEY hKey,
   ULONG ClassLength = 0;
   HANDLE KeyHandle;
   NTSTATUS Status;
-  LONG ErrorCode = ERROR_SUCCESS;
   ULONG Length;
+  LONG ErrorCode = ERROR_SUCCESS;
 
   if ((lpClass) && (!lpcbClass))
     {
-      SetLastError(ERROR_INVALID_PARAMETER);
       return ERROR_INVALID_PARAMETER;
     }
 
@@ -2012,9 +2402,7 @@ RegQueryInfoKeyW (HKEY hKey,
                          hKey);
   if (!NT_SUCCESS(Status))
     {
-      ErrorCode = RtlNtStatusToDosError (Status);
-      SetLastError (ErrorCode);
-      return ErrorCode;
+      return RtlNtStatusToDosError (Status);
     }
 
   if (lpClass != NULL)
@@ -2034,7 +2422,6 @@ RegQueryInfoKeyW (HKEY hKey,
                                  FullInfoSize);
       if (FullInfo == NULL)
        {
-         SetLastError (ERROR_OUTOFMEMORY);
          return ERROR_OUTOFMEMORY;
        }
 
@@ -2053,7 +2440,7 @@ RegQueryInfoKeyW (HKEY hKey,
                       FullInfo,
                       FullInfoSize,
                       &Length);
-  DPRINT("NtQueryKey() returned status 0x%X\n", Status);
+  TRACE("NtQueryKey() returned status 0x%X\n", Status);
   if (!NT_SUCCESS(Status))
     {
       if (lpClass != NULL)
@@ -2063,42 +2450,40 @@ RegQueryInfoKeyW (HKEY hKey,
                       FullInfo);
        }
 
-      ErrorCode = RtlNtStatusToDosError (Status);
-      SetLastError (ErrorCode);
-      return ErrorCode;
+      return RtlNtStatusToDosError (Status);
     }
 
-  DPRINT("SubKeys %d\n", FullInfo->SubKeys);
+  TRACE("SubKeys %d\n", FullInfo->SubKeys);
   if (lpcSubKeys != NULL)
     {
       *lpcSubKeys = FullInfo->SubKeys;
     }
 
-  DPRINT("MaxNameLen %lu\n", FullInfo->MaxNameLen);
+  TRACE("MaxNameLen %lu\n", FullInfo->MaxNameLen);
   if (lpcbMaxSubKeyLen != NULL)
     {
       *lpcbMaxSubKeyLen = FullInfo->MaxNameLen / sizeof(WCHAR) + 1;
     }
 
-  DPRINT("MaxClassLen %lu\n", FullInfo->MaxClassLen);
+  TRACE("MaxClassLen %lu\n", FullInfo->MaxClassLen);
   if (lpcbMaxClassLen != NULL)
     {
       *lpcbMaxClassLen = FullInfo->MaxClassLen / sizeof(WCHAR) + 1;
     }
 
-  DPRINT("Values %lu\n", FullInfo->Values);
+  TRACE("Values %lu\n", FullInfo->Values);
   if (lpcValues != NULL)
     {
       *lpcValues = FullInfo->Values;
     }
 
-  DPRINT("MaxValueNameLen %lu\n", FullInfo->MaxValueNameLen);
+  TRACE("MaxValueNameLen %lu\n", FullInfo->MaxValueNameLen);
   if (lpcbMaxValueNameLen != NULL)
     {
       *lpcbMaxValueNameLen = FullInfo->MaxValueNameLen / sizeof(WCHAR) + 1;
     }
 
-  DPRINT("MaxValueDataLen %lu\n", FullInfo->MaxValueDataLen);
+  TRACE("MaxValueDataLen %lu\n", FullInfo->MaxValueDataLen);
   if (lpcbMaxValueLen != NULL)
     {
       *lpcbMaxValueLen = FullInfo->MaxValueDataLen;
@@ -2122,9 +2507,7 @@ RegQueryInfoKeyW (HKEY hKey,
                          FullInfo);
            }
 
-         ErrorCode = RtlNtStatusToDosError(Status);
-         SetLastError(ErrorCode);
-         return ErrorCode;
+         return RtlNtStatusToDosError (Status);
        }
     }
 
@@ -2154,11 +2537,6 @@ RegQueryInfoKeyW (HKEY hKey,
                   FullInfo);
     }
 
-  if (ErrorCode != ERROR_SUCCESS)
-    {
-      SetLastError (ErrorCode);
-    }
-
   return ErrorCode;
 }
 
@@ -2166,7 +2544,7 @@ RegQueryInfoKeyW (HKEY hKey,
 /************************************************************************
  *  RegQueryMultipleValuesA
  *
- * @unimplemented
+ * @implemented
  */
 LONG STDCALL
 RegQueryMultipleValuesA (HKEY hKey,
@@ -2175,9 +2553,55 @@ RegQueryMultipleValuesA (HKEY hKey,
                         LPSTR lpValueBuf,
                         LPDWORD ldwTotsize)
 {
-  UNIMPLEMENTED;
-  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-  return ERROR_CALL_NOT_IMPLEMENTED;
+  ULONG i;
+  DWORD maxBytes = *ldwTotsize;
+  LPSTR bufptr = (LPSTR)lpValueBuf;
+  LONG ErrorCode;
+
+  if (maxBytes >= (1024*1024))
+    return ERROR_TRANSFER_TOO_LONG;
+
+  *ldwTotsize = 0;
+
+  TRACE("RegQueryMultipleValuesA(%p,%p,%ld,%p,%p=%ld)\n",
+         hKey, val_list, num_vals, lpValueBuf, ldwTotsize, *ldwTotsize);
+
+  for (i = 0; i < num_vals; i++)
+    {
+      val_list[i].ve_valuelen = 0;
+      ErrorCode = RegQueryValueExA (hKey,
+                                   val_list[i].ve_valuename,
+                                   NULL,
+                                   NULL,
+                                   NULL,
+                                   &val_list[i].ve_valuelen);
+      if (ErrorCode != ERROR_SUCCESS)
+       {
+         return ErrorCode;
+       }
+
+      if (lpValueBuf != NULL && *ldwTotsize + val_list[i].ve_valuelen <= maxBytes)
+       {
+         ErrorCode = RegQueryValueExA (hKey,
+                                       val_list[i].ve_valuename,
+                                       NULL,
+                                       &val_list[i].ve_type,
+                                       (LPBYTE)bufptr,
+                                       &val_list[i].ve_valuelen);
+         if (ErrorCode != ERROR_SUCCESS)
+           {
+             return ErrorCode;
+           }
+
+         val_list[i].ve_valueptr = (DWORD_PTR)bufptr;
+
+         bufptr += val_list[i].ve_valuelen;
+       }
+
+      *ldwTotsize += val_list[i].ve_valuelen;
+    }
+
+  return (lpValueBuf != NULL && *ldwTotsize <= maxBytes) ? ERROR_SUCCESS : ERROR_MORE_DATA;
 }
 
 
@@ -2203,10 +2627,10 @@ RegQueryMultipleValuesW (HKEY hKey,
 
   *ldwTotsize = 0;
 
-  DPRINT ("RegQueryMultipleValuesW(%p,%p,%ld,%p,%p=%ld)\n",
+  TRACE ("RegQueryMultipleValuesW(%p,%p,%ld,%p,%p=%ld)\n",
          hKey, val_list, num_vals, lpValueBuf, ldwTotsize, *ldwTotsize);
 
-  for (i = 0; i < num_vals; ++i)
+  for (i = 0; i < num_vals; i++)
     {
       val_list[i].ve_valuelen = 0;
       ErrorCode = RegQueryValueExW (hKey,
@@ -2226,7 +2650,7 @@ RegQueryMultipleValuesW (HKEY hKey,
                                        val_list[i].ve_valuename,
                                        NULL,
                                        &val_list[i].ve_type,
-                                       bufptr,
+                                       (LPBYTE)bufptr,
                                        &val_list[i].ve_valuelen);
          if (ErrorCode != ERROR_SUCCESS)
            {
@@ -2261,27 +2685,24 @@ RegQueryValueExW (HKEY hKey,
   PKEY_VALUE_PARTIAL_INFORMATION ValueInfo;
   UNICODE_STRING ValueName;
   NTSTATUS Status;
-  LONG ErrorCode = ERROR_SUCCESS;
   ULONG BufferSize;
   ULONG ResultSize;
   HANDLE KeyHandle;
+  LONG ErrorCode = ERROR_SUCCESS;
   ULONG MaxCopy = lpcbData != NULL && lpData != NULL ? *lpcbData : 0;
 
-  DPRINT("hKey 0x%X  lpValueName %S  lpData 0x%X  lpcbData %d\n",
+  TRACE("hKey 0x%X  lpValueName %S  lpData 0x%X  lpcbData %d\n",
         hKey, lpValueName, lpData, lpcbData ? *lpcbData : 0);
 
   Status = MapDefaultKey (&KeyHandle,
                          hKey);
   if (!NT_SUCCESS(Status))
     {
-      ErrorCode = RtlNtStatusToDosError (Status);
-      SetLastError (ErrorCode);
-      return ErrorCode;
+      return RtlNtStatusToDosError (Status);
     }
 
   if (lpData != NULL && lpcbData == NULL)
     {
-      SetLastError (ERROR_INVALID_PARAMETER);
       return ERROR_INVALID_PARAMETER;
     }
 
@@ -2293,17 +2714,16 @@ RegQueryValueExW (HKEY hKey,
                               BufferSize);
   if (ValueInfo == NULL)
     {
-      SetLastError(ERROR_OUTOFMEMORY);
       return ERROR_OUTOFMEMORY;
     }
 
-  Status = NtQueryValueKey (hKey,
+  Status = NtQueryValueKey (KeyHandle,
                            &ValueName,
                            KeyValuePartialInformation,
                            ValueInfo,
                            BufferSize,
                            &ResultSize);
-  DPRINT("Status 0x%X\n", Status);
+  TRACE("Status 0x%X\n", Status);
   if (Status == STATUS_BUFFER_OVERFLOW)
     {
       /* Return ERROR_SUCCESS and the buffer space needed for a successful call */
@@ -2313,7 +2733,6 @@ RegQueryValueExW (HKEY hKey,
   else if (!NT_SUCCESS(Status))
     {
       ErrorCode = RtlNtStatusToDosError (Status);
-      SetLastError (ErrorCode);
       MaxCopy = 0;
       if (lpcbData != NULL)
        {
@@ -2345,7 +2764,7 @@ RegQueryValueExW (HKEY hKey,
       if (lpcbData != NULL)
        {
          *lpcbData = (ResultSize - FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[0]));
-         DPRINT("(string) Returning Size: %lu\n", *lpcbData);
+         TRACE("(string) Returning Size: %lu\n", *lpcbData);
        }
     }
   else
@@ -2353,11 +2772,11 @@ RegQueryValueExW (HKEY hKey,
       if (lpcbData != NULL)
        {
          *lpcbData = ResultSize - FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[0]);
-         DPRINT("(other) Returning Size: %lu\n", *lpcbData);
+         TRACE("(other) Returning Size: %lu\n", *lpcbData);
        }
     }
 
-  DPRINT("Type %d  Size %d\n", ValueInfo->Type, ValueInfo->DataLength);
+  TRACE("Type %d  Size %d\n", ValueInfo->Type, ValueInfo->DataLength);
 
   RtlFreeHeap (ProcessHeap,
               0,
@@ -2387,22 +2806,23 @@ RegQueryValueExA (HKEY hKey,
   DWORD Length;
   DWORD Type;
 
+  TRACE("hKey 0x%X  lpValueName %s  lpData 0x%X  lpcbData %d\n",
+        hKey, lpValueName, lpData, lpcbData ? *lpcbData : 0);
+
   if (lpData != NULL && lpcbData == NULL)
     {
-      SetLastError(ERROR_INVALID_PARAMETER);
       return ERROR_INVALID_PARAMETER;
     }
 
   if (lpData)
     {
-      ValueData.Length = *lpcbData * sizeof(WCHAR);
-      ValueData.MaximumLength = ValueData.Length + sizeof(WCHAR);
+      ValueData.Length = 0;
+      ValueData.MaximumLength = (*lpcbData + 1) * sizeof(WCHAR);
       ValueData.Buffer = RtlAllocateHeap (ProcessHeap,
                                          0,
                                          ValueData.MaximumLength);
       if (!ValueData.Buffer)
        {
-         SetLastError(ERROR_OUTOFMEMORY);
          return ERROR_OUTOFMEMORY;
        }
     }
@@ -2416,17 +2836,15 @@ RegQueryValueExA (HKEY hKey,
   RtlCreateUnicodeStringFromAsciiz (&ValueName,
                                    (LPSTR)lpValueName);
 
-  if (NULL != lpcbData)
-    {
-      Length = *lpcbData * sizeof(WCHAR);
-    }
+  Length = (lpcbData == NULL) ? 0 : *lpcbData * sizeof(WCHAR);
   ErrorCode = RegQueryValueExW (hKey,
                                ValueName.Buffer,
                                lpReserved,
                                &Type,
-                               (LPBYTE)ValueData.Buffer,
-                               NULL == lpcbData ? NULL : &Length);
-  DPRINT("ErrorCode %lu\n", ErrorCode);
+                               (lpData == NULL) ? NULL : (LPBYTE)ValueData.Buffer,
+                               &Length);
+  TRACE("ErrorCode %lu\n", ErrorCode);
+  RtlFreeUnicodeString(&ValueName);
 
   if (ErrorCode == ERROR_SUCCESS ||
       ErrorCode == ERROR_MORE_DATA)
@@ -2441,7 +2859,7 @@ RegQueryValueExA (HKEY hKey,
          if (ErrorCode == ERROR_SUCCESS && ValueData.Buffer != NULL)
            {
              RtlInitAnsiString(&AnsiString, NULL);
-             AnsiString.Buffer = lpData;
+             AnsiString.Buffer = (LPSTR)lpData;
              AnsiString.MaximumLength = *lpcbData;
              ValueData.Length = Length;
              ValueData.MaximumLength = ValueData.Length + sizeof(WCHAR);
@@ -2449,13 +2867,16 @@ RegQueryValueExA (HKEY hKey,
            }
          Length = Length / sizeof(WCHAR);
        }
-      else if (lpcbData != NULL)
+      else if (ErrorCode == ERROR_SUCCESS && ValueData.Buffer != NULL)
        {
-         Length = min(*lpcbData, Length);
-         if (ErrorCode == ERROR_SUCCESS && ValueData.Buffer != NULL)
-           {
-             RtlMoveMemory(lpData, ValueData.Buffer, Length);
-           }
+          if (*lpcbData < Length)
+            {
+              ErrorCode = ERROR_MORE_DATA;
+            }
+          else
+            {
+              RtlMoveMemory(lpData, ValueData.Buffer, Length);
+            }
        }
 
       if (lpcbData != NULL)
@@ -2491,10 +2912,12 @@ RegQueryValueA (HKEY hKey,
   LONG ValueSize;
   LONG ErrorCode;
 
+  TRACE("hKey 0x%X lpSubKey %s lpValue %p lpcbValue %d\n",
+        hKey, lpSubKey, lpValue, lpcbValue ? *lpcbValue : 0);
+
   if (lpValue != NULL &&
       lpcbValue == NULL)
     {
-      SetLastError(ERROR_INVALID_PARAMETER);
       return ERROR_INVALID_PARAMETER;
     }
 
@@ -2523,7 +2946,6 @@ RegQueryValueA (HKEY hKey,
                                      ValueSize);
       if (Value.Buffer == NULL)
        {
-         SetLastError(ERROR_OUTOFMEMORY);
          return ERROR_OUTOFMEMORY;
        }
     }
@@ -2579,13 +3001,14 @@ RegQueryValueW (HKEY hKey,
   BOOL CloseRealKey;
   NTSTATUS Status;
 
+  TRACE("hKey 0x%X lpSubKey %S lpValue %p lpcbValue %d\n",
+        hKey, lpSubKey, lpValue, lpcbValue ? *lpcbValue : 0);
+
   Status = MapDefaultKey (&KeyHandle,
                          hKey);
   if (!NT_SUCCESS(Status))
     {
-      ErrorCode = RtlNtStatusToDosError (Status);
-      SetLastError (ErrorCode);
-      return ErrorCode;
+      return RtlNtStatusToDosError (Status);
     }
 
   if (lpSubKey != NULL &&
@@ -2599,13 +3022,11 @@ RegQueryValueW (HKEY hKey,
                                  KeyHandle,
                                  NULL);
       Status = NtOpenKey (&RealKey,
-                         KEY_ALL_ACCESS,
+                         KEY_QUERY_VALUE,
                          &ObjectAttributes);
       if (!NT_SUCCESS(Status))
        {
-         ErrorCode = RtlNtStatusToDosError (Status);
-         SetLastError (ErrorCode);
-         return ErrorCode;
+         return RtlNtStatusToDosError (Status);
        }
       CloseRealKey = TRUE;
     }
@@ -2686,7 +3107,6 @@ RegReplaceKeyW (HKEY hKey,
   BOOLEAN CloseRealKey;
   HANDLE RealKeyHandle;
   HANDLE KeyHandle;
-  LONG ErrorCode;
   NTSTATUS Status;
 
   if (hKey == HKEY_PERFORMANCE_DATA)
@@ -2698,9 +3118,7 @@ RegReplaceKeyW (HKEY hKey,
                          hKey);
   if (!NT_SUCCESS(Status))
     {
-      ErrorCode = RtlNtStatusToDosError (Status);
-      SetLastError (ErrorCode);
-      return ErrorCode;
+      return RtlNtStatusToDosError (Status);
     }
 
   /* Open the real key */
@@ -2714,13 +3132,11 @@ RegReplaceKeyW (HKEY hKey,
                                  KeyHandle,
                                  NULL);
       Status = NtOpenKey (&RealKeyHandle,
-                         KEY_ALL_ACCESS,
+                         MAXIMUM_ALLOWED,
                          &KeyObjectAttributes);
       if (!NT_SUCCESS(Status))
        {
-         ErrorCode = RtlNtStatusToDosError (Status);
-         SetLastError (ErrorCode);
-         return ErrorCode;
+         return RtlNtStatusToDosError (Status);
        }
       CloseRealKey = TRUE;
     }
@@ -2740,7 +3156,6 @@ RegReplaceKeyW (HKEY hKey,
        {
          NtClose (RealKeyHandle);
        }
-      SetLastError (ERROR_INVALID_PARAMETER);
       return ERROR_INVALID_PARAMETER;
     }
 
@@ -2761,7 +3176,6 @@ RegReplaceKeyW (HKEY hKey,
        {
          NtClose (RealKeyHandle);
        }
-      SetLastError (ERROR_INVALID_PARAMETER);
       return ERROR_INVALID_PARAMETER;
     }
 
@@ -2785,9 +3199,7 @@ RegReplaceKeyW (HKEY hKey,
 
   if (!NT_SUCCESS(Status))
     {
-      ErrorCode = RtlNtStatusToDosError (Status);
-      SetLastError (ErrorCode);
-      return ErrorCode;
+      return RtlNtStatusToDosError (Status);
     }
 
   return ERROR_SUCCESS;
@@ -2835,7 +3247,6 @@ RegRestoreKeyW (HKEY hKey,
   UNICODE_STRING FileName;
   HANDLE FileHandle;
   HANDLE KeyHandle;
-  LONG ErrorCode;
   NTSTATUS Status;
 
   if (hKey == HKEY_PERFORMANCE_DATA)
@@ -2847,9 +3258,7 @@ RegRestoreKeyW (HKEY hKey,
                          hKey);
   if (!NT_SUCCESS(Status))
     {
-      ErrorCode = RtlNtStatusToDosError (Status);
-      SetLastError (ErrorCode);
-      return ErrorCode;
+      return RtlNtStatusToDosError (Status);
     }
 
   if (!RtlDosPathNameToNtPathName_U ((LPWSTR)lpFile,
@@ -2857,7 +3266,6 @@ RegRestoreKeyW (HKEY hKey,
                                     NULL,
                                     NULL))
     {
-      SetLastError (ERROR_INVALID_PARAMETER);
       return ERROR_INVALID_PARAMETER;
     }
 
@@ -2876,9 +3284,7 @@ RegRestoreKeyW (HKEY hKey,
   RtlFreeUnicodeString (&FileName);
   if (!NT_SUCCESS(Status))
     {
-      ErrorCode = RtlNtStatusToDosError (Status);
-      SetLastError (ErrorCode);
-      return ErrorCode;
+      return RtlNtStatusToDosError (Status);
     }
 
   Status = NtRestoreKey (KeyHandle,
@@ -2887,9 +3293,7 @@ RegRestoreKeyW (HKEY hKey,
   NtClose (FileHandle);
   if (!NT_SUCCESS(Status))
     {
-      ErrorCode = RtlNtStatusToDosError (Status);
-      SetLastError (ErrorCode);
-      return ErrorCode;
+      return RtlNtStatusToDosError (Status);
     }
 
   return ERROR_SUCCESS;
@@ -2937,15 +3341,12 @@ RegSaveKeyW (HKEY hKey,
   HANDLE FileHandle;
   HANDLE KeyHandle;
   NTSTATUS Status;
-  LONG ErrorCode;
 
   Status = MapDefaultKey (&KeyHandle,
                          hKey);
   if (!NT_SUCCESS(Status))
     {
-      ErrorCode = RtlNtStatusToDosError (Status);
-      SetLastError (ErrorCode);
-      return ErrorCode;
+      return RtlNtStatusToDosError (Status);
     }
 
   if (!RtlDosPathNameToNtPathName_U ((PWSTR)lpFile,
@@ -2953,7 +3354,6 @@ RegSaveKeyW (HKEY hKey,
                                     NULL,
                                     NULL))
     {
-      SetLastError (ERROR_INVALID_PARAMETER);
       return ERROR_INVALID_PARAMETER;
     }
 
@@ -2981,9 +3381,7 @@ RegSaveKeyW (HKEY hKey,
   RtlFreeUnicodeString (&FileName);
   if (!NT_SUCCESS(Status))
     {
-      ErrorCode = RtlNtStatusToDosError (Status);
-      SetLastError (ErrorCode);
-      return ErrorCode;
+      return RtlNtStatusToDosError (Status);
     }
 
   Status = NtSaveKey (KeyHandle,
@@ -2991,9 +3389,7 @@ RegSaveKeyW (HKEY hKey,
   NtClose (FileHandle);
   if (!NT_SUCCESS(Status))
     {
-      ErrorCode = RtlNtStatusToDosError (Status);
-      SetLastError (ErrorCode);
-      return ErrorCode;
+      return RtlNtStatusToDosError (Status);
     }
 
   return ERROR_SUCCESS;
@@ -3011,12 +3407,10 @@ RegSetKeySecurity (HKEY hKey,
                   PSECURITY_DESCRIPTOR pSecurityDescriptor)
 {
   HANDLE KeyHandle;
-  LONG ErrorCode;
   NTSTATUS Status;
 
   if (hKey == HKEY_PERFORMANCE_DATA)
     {
-      SetLastError(ERROR_INVALID_HANDLE);
       return ERROR_INVALID_HANDLE;
     }
 
@@ -3024,9 +3418,7 @@ RegSetKeySecurity (HKEY hKey,
                          hKey);
   if (!NT_SUCCESS(Status))
     {
-      ErrorCode = RtlNtStatusToDosError (Status);
-      SetLastError (ErrorCode);
-      return ErrorCode;
+      return RtlNtStatusToDosError (Status);
     }
 
   Status = NtSetSecurityObject (KeyHandle,
@@ -3034,9 +3426,7 @@ RegSetKeySecurity (HKEY hKey,
                                pSecurityDescriptor);
   if (!NT_SUCCESS(Status))
     {
-      ErrorCode = RtlNtStatusToDosError (Status);
-      SetLastError (ErrorCode);
-      return ErrorCode;
+      return RtlNtStatusToDosError (Status);
     }
 
   return ERROR_SUCCESS;
@@ -3064,12 +3454,6 @@ RegSetValueExA (HKEY hKey,
   LPBYTE pData;
   DWORD DataSize;
 
-  if (lpData == NULL)
-    {
-      SetLastError (ERROR_INVALID_PARAMETER);
-      return ERROR_INVALID_PARAMETER;
-    }
-
   if (lpValueName != NULL &&
       strlen(lpValueName) != 0)
     {
@@ -3082,14 +3466,21 @@ RegSetValueExA (HKEY hKey,
       pValueName = NULL;
     }
 
-  if ((dwType == REG_SZ) ||
-      (dwType == REG_MULTI_SZ) ||
-      (dwType == REG_EXPAND_SZ))
+  if (((dwType == REG_SZ) ||
+       (dwType == REG_MULTI_SZ) ||
+       (dwType == REG_EXPAND_SZ)) &&
+      (cbData != 0))
     {
+      /* NT adds one if the caller forgot the NULL-termination character */
+      if (lpData[cbData - 1] != '\0')
+      {
+         cbData++;
+      }
+
       RtlInitAnsiString (&AnsiString,
                         NULL);
       AnsiString.Buffer = (PSTR)lpData;
-      AnsiString.Length = cbData;
+      AnsiString.Length = cbData - 1;
       AnsiString.MaximumLength = cbData;
       RtlAnsiStringToUnicodeString (&Data,
                                    &AnsiString,
@@ -3146,15 +3537,12 @@ RegSetValueExW (HKEY hKey,
   PUNICODE_STRING pValueName;
   HANDLE KeyHandle;
   NTSTATUS Status;
-  LONG ErrorCode;
 
   Status = MapDefaultKey (&KeyHandle,
                          hKey);
   if (!NT_SUCCESS(Status))
     {
-      ErrorCode = RtlNtStatusToDosError (Status);
-      SetLastError (ErrorCode);
-      return ErrorCode;
+      return RtlNtStatusToDosError (Status);
     }
 
   if (lpValueName != NULL)
@@ -3168,6 +3556,15 @@ RegSetValueExW (HKEY hKey,
     }
   pValueName = &ValueName;
 
+  if (((dwType == REG_SZ) ||
+       (dwType == REG_MULTI_SZ) ||
+       (dwType == REG_EXPAND_SZ)) &&
+      (cbData != 0) && (*(((PWCHAR)lpData) + (cbData / sizeof(WCHAR)) - 1) != L'\0'))
+    {
+      /* NT adds one if the caller forgot the NULL-termination character */
+      cbData += sizeof(WCHAR);
+    }
+
   Status = NtSetValueKey (KeyHandle,
                          pValueName,
                          0,
@@ -3176,9 +3573,7 @@ RegSetValueExW (HKEY hKey,
                          (ULONG)cbData);
   if (!NT_SUCCESS(Status))
     {
-      ErrorCode = RtlNtStatusToDosError (Status);
-      SetLastError (ErrorCode);
-      return ErrorCode;
+      return RtlNtStatusToDosError (Status);
     }
 
   return ERROR_SUCCESS;
@@ -3197,51 +3592,41 @@ RegSetValueA (HKEY hKey,
              LPCSTR lpData,
              DWORD cbData)
 {
-  WCHAR SubKeyNameBuffer[MAX_PATH+1];
-  UNICODE_STRING SubKeyName;
-  UNICODE_STRING Data;
-  ANSI_STRING AnsiString;
-  LONG DataSize;
-  LONG ErrorCode;
-
-  if (lpData == NULL)
-    {
-      SetLastError (ERROR_INVALID_PARAMETER);
-      return ERROR_INVALID_PARAMETER;
-    }
+  LONG ret;
+  HKEY hSubKey;
 
-  RtlInitUnicodeString (&SubKeyName, NULL);
-  RtlInitUnicodeString (&Data, NULL);
-  if (lpSubKey != NULL && (strlen(lpSubKey) != 0))
-    {
-      RtlInitAnsiString (&AnsiString, (LPSTR)lpSubKey);
-      SubKeyName.Buffer = &SubKeyNameBuffer[0];
-      SubKeyName.MaximumLength = sizeof(SubKeyNameBuffer);
-      RtlAnsiStringToUnicodeString (&SubKeyName, &AnsiString, FALSE);
-    }
+  if (dwType != REG_SZ)
+  {
+     return ERROR_INVALID_PARAMETER;
+  }
 
-  DataSize = cbData * sizeof(WCHAR);
-  Data.MaximumLength = DataSize;
-  Data.Buffer = RtlAllocateHeap (ProcessHeap,
-                                0,
-                                DataSize);
-  if (Data.Buffer == NULL)
-    {
-      SetLastError (ERROR_OUTOFMEMORY);
-      return ERROR_OUTOFMEMORY;
-    }
+  if (lpSubKey != NULL && lpSubKey[0] != '\0')
+  {
+     ret = RegCreateKeyA(hKey,
+                         lpSubKey,
+                         &hSubKey);
+
+     if (ret != ERROR_SUCCESS)
+     {
+        return ret;
+     }
+  }
+  else
+     hSubKey = hKey;
 
-  ErrorCode = RegSetValueW (hKey,
-                           (LPCWSTR)SubKeyName.Buffer,
-                           dwType,
-                           Data.Buffer,
-                           DataSize);
+  ret = RegSetValueExA(hSubKey,
+                       NULL,
+                       0,
+                       REG_SZ,
+                       (CONST BYTE*)lpData,
+                       strlen(lpData) + 1);
 
-  RtlFreeHeap (ProcessHeap,
-              0,
-              Data.Buffer);
+  if (hSubKey != hKey)
+  {
+     RegCloseKey(hSubKey);
+  }
 
-  return ErrorCode;
+  return ret;
 }
 
 
@@ -3261,17 +3646,15 @@ RegSetValueW (HKEY hKey,
   UNICODE_STRING SubKeyString;
   HANDLE KeyHandle;
   HANDLE RealKey;
-  LONG ErrorCode;
   BOOL CloseRealKey;
   NTSTATUS Status;
+  LONG ErrorCode;
 
   Status = MapDefaultKey (&KeyHandle,
                          hKey);
   if (!NT_SUCCESS(Status))
     {
-      ErrorCode = RtlNtStatusToDosError (Status);
-      SetLastError (ErrorCode);
-      return ErrorCode;
+      return RtlNtStatusToDosError (Status);
     }
 
   if ((lpSubKey) && (wcslen(lpSubKey) != 0))
@@ -3284,13 +3667,11 @@ RegSetValueW (HKEY hKey,
                                  KeyHandle,
                                  NULL);
       Status = NtOpenKey (&RealKey,
-                         KEY_ALL_ACCESS,
+                         KEY_SET_VALUE,
                          &ObjectAttributes);
       if (!NT_SUCCESS(Status))
        {
-         ErrorCode = RtlNtStatusToDosError (Status);
-         SetLastError (ErrorCode);
-         return ErrorCode;
+         return RtlNtStatusToDosError (Status);
        }
       CloseRealKey = TRUE;
     }
@@ -3351,21 +3732,17 @@ RegUnLoadKeyW (HKEY hKey,
   OBJECT_ATTRIBUTES ObjectAttributes;
   UNICODE_STRING KeyName;
   HANDLE KeyHandle;
-  DWORD ErrorCode;
   NTSTATUS Status;
 
   if (hKey == HKEY_PERFORMANCE_DATA)
     {
-      SetLastError(ERROR_INVALID_HANDLE);
       return ERROR_INVALID_HANDLE;
     }
 
   Status = MapDefaultKey (&KeyHandle, hKey);
   if (!NT_SUCCESS(Status))
     {
-      ErrorCode = RtlNtStatusToDosError (Status);
-      SetLastError (ErrorCode);
-      return ErrorCode;
+      return RtlNtStatusToDosError (Status);
     }
 
   RtlInitUnicodeString (&KeyName,
@@ -3381,9 +3758,7 @@ RegUnLoadKeyW (HKEY hKey,
 
   if (!NT_SUCCESS(Status))
     {
-      ErrorCode = RtlNtStatusToDosError (Status);
-      SetLastError (ErrorCode);
-      return ErrorCode;
+      return RtlNtStatusToDosError (Status);
     }
 
   return ERROR_SUCCESS;