do not call on NtQuerySecurityObject in RegGetKeySecurity for it will always fail...
[reactos.git] / reactos / lib / advapi32 / reg / reg.c
index 71038c5..9f14c5e 100644 (file)
@@ -5,6 +5,7 @@
  * FILE:            lib/advapi32/reg/reg.c
  * PURPOSE:         Registry functions
  * PROGRAMMER:      Ariadne ( ariadne@xs4all.nl)
+ *                  Thomas Weidenmueller <w3seek@reactos.com>
  * UPDATE HISTORY:
  *                  Created 01/11/98
  *                  19990309 EA Stubs
@@ -13,9 +14,9 @@
 
 /* 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 RTL_CRITICAL_SECTION HandleTableCS;
 static HANDLE DefaultHandleTable[MAX_DEFAULT_HANDLES];
 static HANDLE ProcessHeap;
+static BOOLEAN DefaultHandlesDisabled = FALSE;
 
 /* PROTOTYPES ***************************************************************/
 
 static NTSTATUS MapDefaultKey (PHANDLE ParentKey, HKEY Key);
 static VOID CloseDefaultKeys(VOID);
+#define ClosePredefKey(Handle)                                                 \
+    if ((ULONG_PTR)Handle & 0x1) {                                             \
+        NtClose(Handle);                                                       \
+    }
+#define IsPredefKey(HKey)                                                      \
+    (((ULONG)(HKey) & 0xF0000000) == 0x80000000)
+#define GetPredefKeyIndex(HKey)                                                \
+    ((ULONG)(HKey) & 0x0FFFFFFF)
 
 static NTSTATUS OpenClassesRootKey(PHANDLE KeyHandle);
 static NTSTATUS OpenLocalMachineKey (PHANDLE KeyHandle);
@@ -45,7 +52,7 @@ static NTSTATUS OpenCurrentConfigKey(PHANDLE KeyHandle);
 
 /* FUNCTIONS ****************************************************************/
 /* check if value type needs string conversion (Ansi<->Unicode) */
-inline static int is_string( DWORD type )
+__inline static int is_string( DWORD type )
 {
     return (type == REG_SZ) || (type == REG_EXPAND_SZ) || (type == REG_MULTI_SZ);
 }
@@ -56,7 +63,7 @@ inline static int is_string( DWORD type )
 BOOL
 RegInitialize (VOID)
 {
-  DPRINT("RegInitialize()\n");
+  TRACE("RegInitialize()\n");
 
   ProcessHeap = RtlGetProcessHeap();
   RtlZeroMemory (DefaultHandleTable,
@@ -73,7 +80,7 @@ RegInitialize (VOID)
 BOOL
 RegCleanup (VOID)
 {
-  DPRINT("RegCleanup()\n");
+  TRACE("RegCleanup()\n");
 
   CloseDefaultKeys ();
   RtlDeleteCriticalSection (&HandleTableCS);
@@ -83,75 +90,106 @@ RegCleanup (VOID)
 
 
 static NTSTATUS
-MapDefaultKey (PHANDLE RealKey,
-              HKEY Key)
+OpenPredefinedKey(IN ULONG Index,
+                  OUT HANDLE Handle)
+{
+    NTSTATUS Status;
+
+    switch (Index)
+    {
+        case 0: /* HKEY_CLASSES_ROOT */
+            Status = OpenClassesRootKey (Handle);
+            break;
+
+        case 1: /* HKEY_CURRENT_USER */
+            Status = RtlOpenCurrentUser (MAXIMUM_ALLOWED,
+                                         Handle);
+            break;
+
+        case 2: /* HKEY_LOCAL_MACHINE */
+            Status = OpenLocalMachineKey (Handle);
+            break;
+
+        case 3: /* HKEY_USERS */
+            Status = OpenUsersKey (Handle);
+            break;
+#if 0
+        case 4: /* HKEY_PERFORMANCE_DATA */
+            Status = OpenPerformanceDataKey (Handle);
+            break;
+#endif
+
+        case 5: /* HKEY_CURRENT_CONFIG */
+            Status = OpenCurrentConfigKey (Handle);
+            break;
+
+        case 6: /* HKEY_DYN_DATA */
+            Status = STATUS_NOT_IMPLEMENTED;
+            break;
+
+        default:
+            WARN("MapDefaultHandle() no handle creator\n");
+            Status = STATUS_INVALID_PARAMETER;
+            break;
+    }
+    
+    return Status;
+}
+
+
+static NTSTATUS
+MapDefaultKey (OUT PHANDLE RealKey,
+               IN HKEY Key)
 {
   PHANDLE Handle;
   ULONG Index;
+  BOOLEAN DoOpen;
   NTSTATUS Status = STATUS_SUCCESS;
 
-  DPRINT("MapDefaultKey (Key %x)\n", Key);
+  TRACE("MapDefaultKey (Key %x)\n", Key);
 
-  if (((ULONG)Key & 0xF0000000) != 0x80000000)
+  if (!IsPredefKey(Key))
     {
-      *RealKey = (HANDLE)Key;
+      *RealKey = (HANDLE)((ULONG_PTR)Key & ~0x1);
       return STATUS_SUCCESS;
     }
 
   /* Handle special cases here */
-  Index = (ULONG)Key & 0x0FFFFFFF;
+  Index = GetPredefKeyIndex(Key);
   if (Index >= MAX_DEFAULT_HANDLES)
     {
       return STATUS_INVALID_PARAMETER;
     }
 
   RtlEnterCriticalSection (&HandleTableCS);
-  Handle = &DefaultHandleTable[Index];
-  if (*Handle == NULL)
+  
+  if (!DefaultHandlesDisabled)
     {
-      /* create/open the default handle */
-      switch (Index)
-       {
-         case 0: /* HKEY_CLASSES_ROOT */
-           Status = OpenClassesRootKey (Handle);
-           break;
-
-         case 1: /* HKEY_CURRENT_USER */
-           Status = RtlOpenCurrentUser (MAXIMUM_ALLOWED,
-                                        Handle);
-           break;
-
-         case 2: /* HKEY_LOCAL_MACHINE */
-           Status = OpenLocalMachineKey (Handle);
-           break;
-
-         case 3: /* HKEY_USERS */
-           Status = OpenUsersKey (Handle);
-           break;
-#if 0
-         case 4: /* HKEY_PERFORMANCE_DATA */
-           Status = OpenPerformanceDataKey (Handle);
-           break;
-#endif
-         case 5: /* HKEY_CURRENT_CONFIG */
-           Status = OpenCurrentConfigKey (Handle);
-           break;
-
-         case 6: /* HKEY_DYN_DATA */
-           Status = STATUS_NOT_IMPLEMENTED;
-           break;
-
-         default:
-           DPRINT("MapDefaultHandle() no handle creator\n");
-           Status = STATUS_INVALID_PARAMETER;
-       }
+      Handle = &DefaultHandleTable[Index];
+      DoOpen = (*Handle == NULL);
     }
-  RtlLeaveCriticalSection (&HandleTableCS);
-
-  if (NT_SUCCESS(Status))
+  else
     {
-      *RealKey = *Handle;
+      Handle = RealKey;
+      DoOpen = TRUE;
     }
+  
+  if (DoOpen)
+    {
+      /* create/open the default handle */
+      Status = OpenPredefinedKey(Index,
+                                 Handle);
+    }
+
+   if (NT_SUCCESS(Status))
+     {
+       if (!DefaultHandlesDisabled)
+          *RealKey = *Handle;
+       else
+          *(PULONG_PTR)Handle |= 0x1;
+     }
+  
+   RtlLeaveCriticalSection (&HandleTableCS);
 
    return Status;
 }
@@ -179,9 +217,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,
@@ -198,10 +236,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,
@@ -212,7 +250,7 @@ OpenLocalMachineKey (PHANDLE KeyHandle)
                      MAXIMUM_ALLOWED,
                      &Attributes);
 
-  DPRINT("NtOpenKey(%wZ) => %08x\n", &KeyName, Status);
+  TRACE("NtOpenKey(%wZ) => %08x\n", &KeyName, Status);
   return Status;
 }
 
@@ -221,9 +259,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,
@@ -241,9 +279,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,
@@ -256,6 +294,79 @@ OpenCurrentConfigKey (PHANDLE KeyHandle)
 }
 
 
+/************************************************************************
+ *  RegDisablePredefinedCacheEx
+ *
+ * @implemented
+ */
+LONG STDCALL
+RegDisablePredefinedCacheEx(VOID)
+{
+    RtlEnterCriticalSection (&HandleTableCS);
+    DefaultHandlesDisabled = TRUE;
+    RtlLeaveCriticalSection (&HandleTableCS);
+    return ERROR_SUCCESS;
+}
+
+
+/************************************************************************
+ *  RegOverridePredefKey
+ *
+ * @implemented
+ */
+LONG STDCALL
+RegOverridePredefKey(IN HKEY hKey,
+                     IN HKEY hNewHKey  OPTIONAL)
+{
+    LONG ErrorCode = ERROR_SUCCESS;
+    
+    if ((hKey == HKEY_CLASSES_ROOT ||
+         hKey == HKEY_CURRENT_CONFIG ||
+         hKey == HKEY_CURRENT_USER ||
+         hKey == HKEY_LOCAL_MACHINE ||
+         hKey == HKEY_PERFORMANCE_DATA ||
+         hKey == HKEY_USERS) &&
+        !IsPredefKey(hNewHKey))
+    {
+        PHANDLE Handle;
+        ULONG Index;
+
+        Index = GetPredefKeyIndex(hKey);
+        Handle = &DefaultHandleTable[Index];
+
+        if (hNewHKey == NULL)
+        {
+            /* restore the default mapping */
+            NTSTATUS Status = OpenPredefinedKey(Index,
+                                                &hNewHKey);
+            if (!NT_SUCCESS(Status))
+            {
+                return RtlNtStatusToDosError(Status);
+            }
+            
+            ASSERT(hNewHKey != NULL);
+        }
+
+        RtlEnterCriticalSection (&HandleTableCS);
+
+        /* close the currently mapped handle if existing */
+        if (*Handle != NULL)
+        {
+            NtClose(*Handle);
+        }
+        
+        /* update the mapping */
+        *Handle = hNewHKey;
+
+        RtlLeaveCriticalSection (&HandleTableCS);
+    }
+    else
+        ErrorCode = ERROR_INVALID_HANDLE;
+
+    return ErrorCode;
+}
+
+
 /************************************************************************
  *  RegCloseKey
  *
@@ -264,7 +375,6 @@ OpenCurrentConfigKey (PHANDLE KeyHandle)
 LONG STDCALL
 RegCloseKey (HKEY hKey)
 {
-  LONG ErrorCode;
   NTSTATUS Status;
 
   /* don't close null handle or a pseudo handle */
@@ -276,27 +386,428 @@ RegCloseKey (HKEY hKey)
   Status = NtClose (hKey);
   if (!NT_SUCCESS(Status))
     {
-      ErrorCode = RtlNtStatusToDosError (Status);
-      SetLastError (ErrorCode);
-      return ErrorCode;
+      return RtlNtStatusToDosError (Status);
     }
 
   return ERROR_SUCCESS;
 }
 
 
+static NTSTATUS
+RegpCopyTree(IN HKEY hKeySrc,
+             IN HKEY hKeyDest)
+{
+    typedef struct
+    {
+        LIST_ENTRY ListEntry;
+        HANDLE hKeySrc;
+        HANDLE hKeyDest;
+    } REGP_COPY_KEYS, *PREGP_COPY_KEYS;
+
+    LIST_ENTRY copyQueueHead;
+    PREGP_COPY_KEYS copyKeys, newCopyKeys;
+    union
+    {
+        KEY_VALUE_FULL_INFORMATION *KeyValue;
+        KEY_NODE_INFORMATION *KeyNode;
+        PVOID Buffer;
+    } Info;
+    ULONG Index, BufferSizeRequired, BufferSize = 0x200;
+    NTSTATUS Status = STATUS_SUCCESS;
+    NTSTATUS Status2 = STATUS_SUCCESS;
+    
+    InitializeListHead(&copyQueueHead);
+    
+    Info.Buffer = RtlAllocateHeap(ProcessHeap,
+                                  0,
+                                  BufferSize);
+    if (Info.Buffer == NULL)
+    {
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+    
+    copyKeys = RtlAllocateHeap(ProcessHeap,
+                               0,
+                               sizeof(REGP_COPY_KEYS));
+    if (copyKeys != NULL)
+    {
+        copyKeys->hKeySrc = hKeySrc;
+        copyKeys->hKeyDest = hKeyDest;
+        InsertHeadList(&copyQueueHead,
+                       &copyKeys->ListEntry);
+        
+        /* FIXME - copy security from hKeySrc to hKeyDest or just for the subkeys? */
+        
+        do
+        {
+            copyKeys = CONTAINING_RECORD(copyQueueHead.Flink,
+                                         REGP_COPY_KEYS,
+                                         ListEntry);
+
+            /* enumerate all values and copy them */
+            Index = 0;
+            for (;;)
+            {
+                Status2 = NtEnumerateValueKey(copyKeys->hKeySrc,
+                                              Index,
+                                              KeyValueFullInformation,
+                                              Info.KeyValue,
+                                              BufferSize,
+                                              &BufferSizeRequired);
+                if (NT_SUCCESS(Status2))
+                {
+                    UNICODE_STRING ValueName;
+                    PVOID Data;
+                    
+                    /* don't use RtlInitUnicodeString as the string is not NULL-terminated! */
+                    ValueName.Length = Info.KeyValue->NameLength;
+                    ValueName.MaximumLength = ValueName.Length;
+                    ValueName.Buffer = Info.KeyValue->Name;
+                    
+                    Data = (PVOID)((ULONG_PTR)Info.KeyValue + Info.KeyValue->DataOffset);
+                    
+                    Status2 = NtSetValueKey(copyKeys->hKeyDest,
+                                            &ValueName,
+                                            Info.KeyValue->TitleIndex,
+                                            Info.KeyValue->Type,
+                                            Data,
+                                            Info.KeyValue->DataLength);
+
+                    /* don't break, let's try to copy as many values as possible */
+                    if (!NT_SUCCESS(Status2) && NT_SUCCESS(Status))
+                    {
+                        Status = Status2;
+                    }
+
+                    Index++;
+                }
+                else if (Status2 == STATUS_BUFFER_OVERFLOW)
+                {
+                    PVOID Buffer;
+
+                    ASSERT(BufferSize < BufferSizeRequired);
+
+                    Buffer = RtlReAllocateHeap(ProcessHeap,
+                                               0,
+                                               Info.Buffer,
+                                               BufferSizeRequired);
+                    if (Buffer != NULL)
+                    {
+                        Info.Buffer = Buffer;
+                        /* try again */
+                    }
+                    else
+                    {
+                        /* don't break, let's try to copy as many values as possible */
+                        Status2 = STATUS_INSUFFICIENT_RESOURCES;
+                        Index++;
+                        
+                        if (NT_SUCCESS(Status))
+                        {
+                            Status = Status2;
+                        }
+                    }
+                }
+                else
+                {
+                    /* break to avoid an infinite loop in case of denied access or
+                       other errors! */
+                    if (Status2 != STATUS_NO_MORE_ENTRIES && NT_SUCCESS(Status))
+                    {
+                        Status = Status2;
+                    }
+                    
+                    break;
+                }
+            }
+            
+            /* enumerate all subkeys and open and enqueue them */
+            Index = 0;
+            for (;;)
+            {
+                Status2 = NtEnumerateKey(copyKeys->hKeySrc,
+                                         Index,
+                                         KeyNodeInformation,
+                                         Info.KeyNode,
+                                         BufferSize,
+                                         &BufferSizeRequired);
+                if (NT_SUCCESS(Status2))
+                {
+                    HANDLE KeyHandle, NewKeyHandle;
+                    OBJECT_ATTRIBUTES ObjectAttributes;
+                    UNICODE_STRING SubKeyName, ClassName;
+                    
+                    /* don't use RtlInitUnicodeString as the string is not NULL-terminated! */
+                    SubKeyName.Length = Info.KeyNode->NameLength;
+                    SubKeyName.MaximumLength = SubKeyName.Length;
+                    SubKeyName.Buffer = Info.KeyNode->Name;
+                    ClassName.Length = Info.KeyNode->ClassLength;
+                    ClassName.MaximumLength = ClassName.Length;
+                    ClassName.Buffer = (PWSTR)((ULONG_PTR)Info.KeyNode + Info.KeyNode->ClassOffset);
+                    
+                    /* open the subkey with sufficient rights */
+                    
+                    InitializeObjectAttributes(&ObjectAttributes,
+                                               &SubKeyName,
+                                               OBJ_CASE_INSENSITIVE,
+                                               copyKeys->hKeySrc,
+                                               NULL);
+                    
+                    Status2 = NtOpenKey(&KeyHandle,
+                                        KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE,
+                                        &ObjectAttributes);
+                    if (NT_SUCCESS(Status2))
+                    {
+                        /* FIXME - attempt to query the security information */
+                        
+                        InitializeObjectAttributes(&ObjectAttributes,
+                                               &SubKeyName,
+                                               OBJ_CASE_INSENSITIVE,
+                                               copyKeys->hKeyDest,
+                                               NULL);
+
+                        Status2 = NtCreateKey(&NewKeyHandle,
+                                              KEY_ALL_ACCESS,
+                                              &ObjectAttributes,
+                                              Info.KeyNode->TitleIndex,
+                                              &ClassName,
+                                              0,
+                                              NULL);
+                        if (NT_SUCCESS(Status2))
+                        {
+                            newCopyKeys = RtlAllocateHeap(ProcessHeap,
+                                                          0,
+                                                          sizeof(REGP_COPY_KEYS));
+                            if (newCopyKeys != NULL)
+                            {
+                                /* save the handles and enqueue the subkey */
+                                newCopyKeys->hKeySrc = KeyHandle;
+                                newCopyKeys->hKeyDest = NewKeyHandle;
+                                InsertTailList(&copyQueueHead,
+                                               &newCopyKeys->ListEntry);
+                            }
+                            else
+                            {
+                                NtClose(KeyHandle);
+                                NtClose(NewKeyHandle);
+                                
+                                Status2 = STATUS_INSUFFICIENT_RESOURCES;
+                            }
+                        }
+                        else
+                        {
+                            NtClose(KeyHandle);
+                        }
+                    }
+                    
+                    if (!NT_SUCCESS(Status2) && NT_SUCCESS(Status))
+                    {
+                        Status = Status2;
+                    }
+                    
+                    Index++;
+                }
+                else if (Status2 == STATUS_BUFFER_OVERFLOW)
+                {
+                    PVOID Buffer;
+
+                    ASSERT(BufferSize < BufferSizeRequired);
+
+                    Buffer = RtlReAllocateHeap(ProcessHeap,
+                                               0,
+                                               Info.Buffer,
+                                               BufferSizeRequired);
+                    if (Buffer != NULL)
+                    {
+                        Info.Buffer = Buffer;
+                        /* try again */
+                    }
+                    else
+                    {
+                        /* don't break, let's try to copy as many keys as possible */
+                        Status2 = STATUS_INSUFFICIENT_RESOURCES;
+                        Index++;
+
+                        if (NT_SUCCESS(Status))
+                        {
+                            Status = Status2;
+                        }
+                    }
+                }
+                else
+                {
+                    /* break to avoid an infinite loop in case of denied access or
+                       other errors! */
+                    if (Status2 != STATUS_NO_MORE_ENTRIES && NT_SUCCESS(Status))
+                    {
+                        Status = Status2;
+                    }
+
+                    break;
+                }
+            }
+
+            /* close the handles and remove the entry from the list */
+            if (copyKeys->hKeySrc != hKeySrc)
+            {
+                NtClose(copyKeys->hKeySrc);
+            }
+            if (copyKeys->hKeyDest != hKeyDest)
+            {
+                NtClose(copyKeys->hKeyDest);
+            }
+            
+            RemoveEntryList(&copyKeys->ListEntry);
+
+            RtlFreeHeap(ProcessHeap,
+                        0,
+                        copyKeys);
+        } while (!IsListEmpty(&copyQueueHead));
+    }
+    else
+        Status = STATUS_INSUFFICIENT_RESOURCES;
+    
+    RtlFreeHeap(ProcessHeap,
+                0,
+                Info.Buffer);
+
+    return Status;
+}
+
+
+/************************************************************************
+ *  RegCopyTreeW
+ *
+ * @implemented
+ */
+LONG STDCALL
+RegCopyTreeW(IN HKEY hKeySrc,
+             IN LPCWSTR lpSubKey  OPTIONAL,
+             IN HKEY hKeyDest)
+{
+    HANDLE DestKeyHandle, KeyHandle, CurKey, SubKeyHandle = NULL;
+    NTSTATUS Status;
+    
+    Status = MapDefaultKey(&KeyHandle,
+                           hKeySrc);
+    if (!NT_SUCCESS(Status))
+    {
+        return RtlNtStatusToDosError(Status);
+    }
+    
+    Status = MapDefaultKey(&DestKeyHandle,
+                           hKeyDest);
+    if (!NT_SUCCESS(Status))
+    {
+        goto Cleanup2;
+    }
+
+    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_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE,
+                           &ObjectAttributes);
+        if (!NT_SUCCESS(Status))
+        {
+            goto Cleanup;
+        }
+        
+        CurKey = SubKeyHandle;
+    }
+    else
+        CurKey = KeyHandle;
+    
+    Status = RegpCopyTree(CurKey,
+                          hKeyDest);
+    
+    if (SubKeyHandle != NULL)
+    {
+        NtClose(SubKeyHandle);
+    }
+    
+Cleanup:
+    ClosePredefKey(DestKeyHandle);
+Cleanup2:
+    ClosePredefKey(KeyHandle);
+    
+    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 = {0};
+    LONG Ret;
+    
+    if (lpSubKey != NULL &&
+        !RtlCreateUnicodeStringFromAsciiz(&SubKeyName,
+                                          (LPSTR)lpSubKey))
+    {
+        return ERROR_NOT_ENOUGH_MEMORY;
+    }
+
+    Ret = RegCopyTreeW(hKeySrc,
+                       SubKeyName.Buffer,
+                       hKeyDest);
+
+    RtlFreeUnicodeString(&SubKeyName);
+    
+    return Ret;
+}
+
+
 /************************************************************************
  *  RegConnectRegistryA
  *
- * @unimplemented
+ * @implemented
  */
 LONG STDCALL
-RegConnectRegistryA (LPCSTR lpMachineName,
-                    HKEY hKey,
-                    PHKEY phkResult)
+RegConnectRegistryA (IN LPCSTR lpMachineName,
+                     IN HKEY hKey,
+                     OUT PHKEY phkResult)
 {
-  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-  return ERROR_CALL_NOT_IMPLEMENTED;
+    UNICODE_STRING MachineName = {0};
+    LONG Ret;
+    
+    if (lpMachineName != NULL &&
+        !RtlCreateUnicodeStringFromAsciiz(&MachineName,
+                                          (LPSTR)lpMachineName))
+    {
+        return ERROR_NOT_ENOUGH_MEMORY;
+    }
+
+    Ret = RegConnectRegistryW(MachineName.Buffer,
+                              hKey,
+                              phkResult);
+
+    RtlFreeUnicodeString(&MachineName);
+    
+    return Ret;
 }
 
 
@@ -344,7 +855,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;
 
@@ -376,7 +887,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))
@@ -407,13 +918,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;
     }
@@ -444,21 +955,18 @@ 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);
+                          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)
     {
@@ -485,12 +993,12 @@ RegCreateKeyExA (HKEY hKey,
       RtlFreeUnicodeString (&ClassString);
     }
 
-  DPRINT("Status %x\n", Status);
+  ClosePredefKey(ParentKey);
+
+  TRACE("Status %x\n", Status);
   if (!NT_SUCCESS(Status))
     {
-      ErrorCode = RtlNtStatusToDosError (Status);
-      SetLastError (ErrorCode);
-      return ErrorCode;
+      return RtlNtStatusToDosError (Status);
     }
 
   return ERROR_SUCCESS;
@@ -517,21 +1025,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);
+                          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);
@@ -548,12 +1053,13 @@ RegCreateKeyExW (HKEY hKey,
                            dwOptions,
                            samDesired,
                            lpdwDisposition);
-  DPRINT("Status %x\n", Status);
+
+  ClosePredefKey(ParentKey);
+
+  TRACE("Status %x\n", Status);
   if (!NT_SUCCESS(Status))
     {
-      ErrorCode = RtlNtStatusToDosError (Status);
-      SetLastError (ErrorCode);
-      return ErrorCode;
+      return RtlNtStatusToDosError (Status);
     }
 
   return ERROR_SUCCESS;
@@ -575,7 +1081,7 @@ RegCreateKeyA (HKEY hKey,
                          0,
                          NULL,
                          0,
-                         KEY_ALL_ACCESS,
+                         MAXIMUM_ALLOWED,
                          NULL,
                          phkResult,
                          NULL);
@@ -597,7 +1103,7 @@ RegCreateKeyW (HKEY hKey,
                          0,
                          NULL,
                          0,
-                         KEY_ALL_ACCESS,
+                         MAXIMUM_ALLOWED,
                          NULL,
                          phkResult,
                          NULL);
@@ -618,15 +1124,12 @@ RegDeleteKeyA (HKEY hKey,
   HANDLE ParentKey;
   HANDLE TargetKey;
   NTSTATUS Status;
-  LONG ErrorCode;
 
   Status = MapDefaultKey (&ParentKey,
-                         hKey);
+                          hKey);
   if (!NT_SUCCESS(Status))
     {
-      ErrorCode = RtlNtStatusToDosError (Status);
-      SetLastError (ErrorCode);
-      return ErrorCode;
+      return RtlNtStatusToDosError (Status);
     }
 
   RtlCreateUnicodeStringFromAsciiz (&SubKeyName,
@@ -634,7 +1137,7 @@ RegDeleteKeyA (HKEY hKey,
   InitializeObjectAttributes(&ObjectAttributes,
                             &SubKeyName,
                             OBJ_CASE_INSENSITIVE,
-                            (HANDLE)ParentKey,
+                            ParentKey,
                             NULL);
 
   Status = NtOpenKey (&TargetKey,
@@ -643,18 +1146,18 @@ RegDeleteKeyA (HKEY hKey,
   RtlFreeUnicodeString (&SubKeyName);
   if (!NT_SUCCESS(Status))
     {
-      ErrorCode = RtlNtStatusToDosError (Status);
-      SetLastError (ErrorCode);
-      return ErrorCode;
+      goto Cleanup;
     }
 
   Status = NtDeleteKey (TargetKey);
   NtClose (TargetKey);
+  
+Cleanup:
+  ClosePredefKey(ParentKey);
+
   if (!NT_SUCCESS(Status))
     {
-      ErrorCode = RtlNtStatusToDosError(Status);
-      SetLastError (ErrorCode);
-      return ErrorCode;
+      return RtlNtStatusToDosError(Status);
     }
 
   return ERROR_SUCCESS;
@@ -675,15 +1178,12 @@ RegDeleteKeyW (HKEY hKey,
   HANDLE ParentKey;
   HANDLE TargetKey;
   NTSTATUS Status;
-  LONG ErrorCode;
 
   Status = MapDefaultKey (&ParentKey,
-                         hKey);
+                          hKey);
   if (!NT_SUCCESS(Status))
     {
-      ErrorCode = RtlNtStatusToDosError (Status);
-      SetLastError (ErrorCode);
-      return ErrorCode;
+      return RtlNtStatusToDosError (Status);
     }
 
   RtlInitUnicodeString (&SubKeyName,
@@ -691,28 +1191,594 @@ 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;
+      goto Cleanup;
+    }
+
+  Status = NtDeleteKey (TargetKey);
+  NtClose (TargetKey);
+  
+Cleanup:
+  ClosePredefKey(ParentKey);
+
+  if (!NT_SUCCESS(Status))
+    {
+      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, CurKey, 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))
+        {
+            goto Cleanup;
+        }
+        
+        CurKey = SubKeyHandle;
+    }
+    else
+        CurKey = KeyHandle;
+
+    RtlInitUnicodeString(&ValueName,
+                         (LPWSTR)lpValueName);
+
+    Status = NtDeleteValueKey(CurKey,
+                              &ValueName);
+
+    if (SubKeyHandle != NULL)
+    {
+        NtClose(SubKeyHandle);
+    }
+    
+Cleanup:
+    ClosePredefKey(KeyHandle);
+
+    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 = {0}, ValueName = {0};
+    LONG Ret;
+    
+    if (lpSubKey != NULL &&
+        !RtlCreateUnicodeStringFromAsciiz(&SubKey,
+                                          (LPSTR)lpSubKey))
+    {
+        return ERROR_NOT_ENOUGH_MEMORY;
+    }
+
+    if (lpValueName != NULL &&
+        !RtlCreateUnicodeStringFromAsciiz(&ValueName,
+                                          (LPSTR)lpValueName))
+    {
+        RtlFreeUnicodeString(&SubKey);
+        return ERROR_NOT_ENOUGH_MEMORY;
+    }
+
+    Ret = RegDeleteKeyValueW(hKey,
+                             SubKey.Buffer,
+                             SubKey.Buffer);
+
+    RtlFreeUnicodeString(&SubKey);
+    RtlFreeUnicodeString(&ValueName);
+    
+    return Ret;
+}
+
+
+static NTSTATUS
+RegpDeleteTree(IN HKEY hKey)
+{
+    typedef struct
+    {
+        LIST_ENTRY ListEntry;
+        HANDLE KeyHandle;
+    } REGP_DEL_KEYS, *PREG_DEL_KEYS;
+
+    LIST_ENTRY delQueueHead;
+    PREG_DEL_KEYS delKeys, newDelKeys;
+    HANDLE ProcessHeap;
+    ULONG BufferSize;
+    PKEY_BASIC_INFORMATION BasicInfo;
+    PREG_DEL_KEYS KeyDelRoot;
+    NTSTATUS Status = STATUS_SUCCESS;
+    NTSTATUS Status2 = STATUS_SUCCESS;
+    
+    InitializeListHead(&delQueueHead);
+    
+    ProcessHeap = RtlGetProcessHeap();
+    
+    /* NOTE: no need to allocate enough memory for an additional KEY_BASIC_INFORMATION
+             structure for the root key, we only do that for subkeys as we need to
+             allocate REGP_DEL_KEYS structures anyway! */
+    KeyDelRoot = RtlAllocateHeap(ProcessHeap,
+                                 0,
+                                 sizeof(REGP_DEL_KEYS));
+    if (KeyDelRoot != NULL)
+    {
+        KeyDelRoot->KeyHandle = hKey;
+        InsertTailList(&delQueueHead,
+                       &KeyDelRoot->ListEntry);
+
+        do
+        {
+            delKeys = CONTAINING_RECORD(delQueueHead.Flink,
+                                        REGP_DEL_KEYS,
+                                        ListEntry);
+
+            BufferSize = 0;
+            BasicInfo = NULL;
+            newDelKeys = NULL;
+
+ReadFirstSubKey:
+            /* check if this key contains subkeys and delete them first by queuing
+               them at the head of the list */
+            Status2 = NtEnumerateKey(delKeys->KeyHandle,
+                                     0,
+                                     KeyBasicInformation,
+                                     BasicInfo,
+                                     BufferSize,
+                                     &BufferSize);
+
+            if (NT_SUCCESS(Status2))
+            {
+                OBJECT_ATTRIBUTES ObjectAttributes;
+                UNICODE_STRING SubKeyName;
+                
+                ASSERT(newDelKeys != NULL);
+                ASSERT(BasicInfo != NULL);
+
+                /* don't use RtlInitUnicodeString as the string is not NULL-terminated! */
+                SubKeyName.Length = BasicInfo->NameLength;
+                SubKeyName.MaximumLength = BasicInfo->NameLength;
+                SubKeyName.Buffer = BasicInfo->Name;
+
+                InitializeObjectAttributes(&ObjectAttributes,
+                                           &SubKeyName,
+                                           OBJ_CASE_INSENSITIVE,
+                                           delKeys->KeyHandle,
+                                           NULL);
+
+                /* open the subkey */
+                Status2 = NtOpenKey(&newDelKeys->KeyHandle,
+                                    DELETE | KEY_ENUMERATE_SUB_KEYS,
+                                    &ObjectAttributes);
+                if (!NT_SUCCESS(Status2))
+                {
+                    goto SubKeyFailure;
+                }
+
+                /* enqueue this key to the head of the deletion queue */
+                InsertHeadList(&delQueueHead,
+                               &newDelKeys->ListEntry);
+
+                /* try again from the head of the list */
+                continue;
+            }
+            else
+            {
+                if (Status2 == STATUS_BUFFER_TOO_SMALL)
+                {
+                    newDelKeys = RtlAllocateHeap(ProcessHeap,
+                                                 0,
+                                                 BufferSize + sizeof(REGP_DEL_KEYS));
+                    if (newDelKeys != NULL)
+                    {
+                        BasicInfo = (PKEY_BASIC_INFORMATION)(newDelKeys + 1);
+
+                        /* try again */
+                        goto ReadFirstSubKey;
+                    }
+                    else
+                    {
+                        /* don't break, let's try to delete as many keys as possible */
+                        Status2 = STATUS_INSUFFICIENT_RESOURCES;
+                        goto SubKeyFailureNoFree;
+                    }
+                }
+                else if (Status2 == STATUS_BUFFER_OVERFLOW)
+                {
+                    PREG_DEL_KEYS newDelKeys2;
+
+                    ASSERT(newDelKeys != NULL);
+
+                    /* we need more memory to query the key name */
+                    newDelKeys2 = RtlReAllocateHeap(ProcessHeap,
+                                                    0,
+                                                    newDelKeys,
+                                                    BufferSize + sizeof(REGP_DEL_KEYS));
+                    if (newDelKeys2 != NULL)
+                    {
+                        newDelKeys = newDelKeys2;
+                        BasicInfo = (PKEY_BASIC_INFORMATION)(newDelKeys + 1);
+
+                        /* try again */
+                        goto ReadFirstSubKey;
+                    }
+                    else
+                    {
+                        /* don't break, let's try to delete as many keys as possible */
+                        Status2 = STATUS_INSUFFICIENT_RESOURCES;
+                    }
+                }
+                else if (Status2 == STATUS_NO_MORE_ENTRIES)
+                {
+                    /* in some race conditions where another thread would delete
+                       the same tree at the same time, newDelKeys could actually
+                       be != NULL! */
+                    if (newDelKeys != NULL)
+                    {
+                        RtlFreeHeap(ProcessHeap,
+                                    0,
+                                    newDelKeys);
+                    }
+                    break;
+                }
+
+SubKeyFailure:
+                /* newDelKeys can be NULL here when NtEnumerateKey returned an
+                   error other than STATUS_BUFFER_TOO_SMALL or STATUS_BUFFER_OVERFLOW! */
+                if (newDelKeys != NULL)
+                {
+                    RtlFreeHeap(ProcessHeap,
+                                0,
+                                newDelKeys);
+                }
+
+SubKeyFailureNoFree:
+                /* don't break, let's try to delete as many keys as possible */
+                if (NT_SUCCESS(Status))
+                {
+                    Status = Status2;
+                }
+            }
+
+            Status2 = NtDeleteKey(delKeys->KeyHandle);
+            
+            /* NOTE: do NOT close the handle anymore, it's invalid already! */
+
+            if (!NT_SUCCESS(Status2))
+            {
+                /* close the key handle so we don't leak handles for keys we were
+                   unable to delete. But only do this for handles not supplied
+                   by the caller! */
+
+                if (delKeys->KeyHandle != hKey)
+                {
+                    NtClose(delKeys->KeyHandle);
+                }
+
+                if (NT_SUCCESS(Status))
+                {
+                    /* don't break, let's try to delete as many keys as possible */
+                    Status = Status2;
+                }
+            }
+            
+            /* remove the entry from the list */
+            RemoveEntryList(&delKeys->ListEntry);
+
+            RtlFreeHeap(ProcessHeap,
+                        0,
+                        delKeys);
+        } while (!IsListEmpty(&delQueueHead));
+    }
+    else
+        Status = STATUS_INSUFFICIENT_RESOURCES;
+
+    return Status;
+}
+
+
+/************************************************************************
+ *  RegDeleteTreeW
+ *
+ * @implemented
+ */
+LONG STDCALL
+RegDeleteTreeW(IN HKEY hKey,
+               IN LPCWSTR lpSubKey  OPTIONAL)
+{
+    HANDLE KeyHandle, CurKey, 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,
+                           &ObjectAttributes);
+        if (!NT_SUCCESS(Status))
+        {
+            goto Cleanup;
+        }
+        
+        CurKey = SubKeyHandle;
+    }
+    else
+        CurKey = KeyHandle;
+
+    Status = RegpDeleteTree(CurKey);
+
+    if (NT_SUCCESS(Status))
+    {
+        /* make sure we only close hKey (KeyHandle) when the caller specified a
+           subkey, because the handle would be invalid already! */
+        if (CurKey != KeyHandle)
+        {
+            ClosePredefKey(KeyHandle);
+        }
+        
+        return ERROR_SUCCESS;
+    }
+    else
+    {
+        /* make sure we close all handles we created! */
+        if (SubKeyHandle != NULL)
+        {
+            NtClose(SubKeyHandle);
+        }
+
+Cleanup:
+        ClosePredefKey(KeyHandle);
+        
+        return RtlNtStatusToDosError(Status);
+    }
+}
+
+
+/************************************************************************
+ *  RegDeleteTreeA
+ *
+ * @implemented
+ */
+LONG STDCALL
+RegDeleteTreeA(IN HKEY hKey,
+               IN LPCSTR lpSubKey  OPTIONAL)
+{
+    UNICODE_STRING SubKeyName = {0};
+    LONG Ret;
+
+    if (lpSubKey != NULL &&
+        !RtlCreateUnicodeStringFromAsciiz(&SubKeyName,
+                                          (LPSTR)lpSubKey))
+    {
+        return ERROR_NOT_ENOUGH_MEMORY;
+    }
+
+    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, CurKey, 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))
+        {
+            Ret = RtlNtStatusToDosError(Status);
+            goto Cleanup;
+        }
+        
+        CurKey = SubKeyHandle;
+    }
+    else
+        CurKey = KeyHandle;
+    
+    Ret = RegSetValueExW(CurKey,
+                         lpValueName,
+                         0,
+                         dwType,
+                         lpData,
+                         cbData);
+
+    if (SubKeyHandle != NULL)
+    {
+        NtClose(SubKeyHandle);
+    }
+    
+Cleanup:
+    ClosePredefKey(KeyHandle);
+
+    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, CurKey, 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))
+        {
+            Ret = ERROR_NOT_ENOUGH_MEMORY;
+            goto Cleanup;
+        }
+
+        InitializeObjectAttributes(&ObjectAttributes,
+                                   &SubKeyName,
+                                   OBJ_CASE_INSENSITIVE,
+                                   KeyHandle,
+                                   NULL);
+
+        Status = NtOpenKey(&SubKeyHandle,
+                           KEY_SET_VALUE,
+                           &ObjectAttributes);
+
+        RtlFreeUnicodeString(&SubKeyName);
+
+        if (!NT_SUCCESS(Status))
+        {
+            Ret = RtlNtStatusToDosError(Status);
+            goto Cleanup;
+        }
+        
+        CurKey = SubKeyHandle;
     }
+    else
+        CurKey = KeyHandle;
 
-  Status = NtDeleteKey (TargetKey);
-  NtClose (TargetKey);
-  if (!NT_SUCCESS(Status))
+    Ret = RegSetValueExA(CurKey,
+                         lpValueName,
+                         0,
+                         dwType,
+                         lpData,
+                         cbData);
+
+    if (SubKeyHandle != NULL)
     {
-      ErrorCode = RtlNtStatusToDosError (Status);
-      SetLastError (ErrorCode);
-      return ErrorCode;
+        NtClose(SubKeyHandle);
     }
+    
+Cleanup:
+    ClosePredefKey(KeyHandle);
 
-  return ERROR_SUCCESS;
+    return Ret;
 }
 
 
@@ -727,16 +1793,13 @@ RegDeleteValueA (HKEY hKey,
 {
   UNICODE_STRING ValueName;
   HANDLE KeyHandle;
-  LONG ErrorCode;
   NTSTATUS Status;
 
   Status = MapDefaultKey (&KeyHandle,
-                         hKey);
+                          hKey);
   if (!NT_SUCCESS(Status))
     {
-      ErrorCode = RtlNtStatusToDosError (Status);
-      SetLastError (ErrorCode);
-      return ErrorCode;
+      return RtlNtStatusToDosError (Status);
     }
 
   RtlCreateUnicodeStringFromAsciiz (&ValueName,
@@ -744,11 +1807,12 @@ RegDeleteValueA (HKEY hKey,
   Status = NtDeleteValueKey (KeyHandle,
                             &ValueName);
   RtlFreeUnicodeString (&ValueName);
+  
+  ClosePredefKey(KeyHandle);
+  
   if (!NT_SUCCESS(Status))
     {
-      ErrorCode = RtlNtStatusToDosError (Status);
-      SetLastError (ErrorCode);
-      return ErrorCode;
+      return RtlNtStatusToDosError (Status);
     }
 
   return ERROR_SUCCESS;
@@ -766,16 +1830,13 @@ RegDeleteValueW (HKEY hKey,
 {
   UNICODE_STRING ValueName;
   NTSTATUS Status;
-  LONG ErrorCode;
   HANDLE KeyHandle;
 
   Status = MapDefaultKey (&KeyHandle,
-                         hKey);
+                          hKey);
   if (!NT_SUCCESS(Status))
     {
-      ErrorCode = RtlNtStatusToDosError (Status);
-      SetLastError (ErrorCode);
-      return ErrorCode;
+      return RtlNtStatusToDosError (Status);
     }
 
   RtlInitUnicodeString (&ValueName,
@@ -783,11 +1844,12 @@ RegDeleteValueW (HKEY hKey,
 
   Status = NtDeleteValueKey (KeyHandle,
                             &ValueName);
+
+  ClosePredefKey(KeyHandle);
+
   if (!NT_SUCCESS(Status))
     {
-      ErrorCode = RtlNtStatusToDosError (Status);
-      SetLastError (ErrorCode);
-      return ErrorCode;
+      return RtlNtStatusToDosError (Status);
     }
 
   return ERROR_SUCCESS;
@@ -875,21 +1937,18 @@ RegEnumKeyExA (HKEY hKey,
        HANDLE KeyHandle;
        NTSTATUS Status;
 
-       DPRINT("RegEnumKeyExA(hKey 0x%x, dwIndex %d, lpName 0x%x, *lpcbName %d, lpClass 0x%x, lpcbClass %d)\n",
+       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))
        {
-               SetLastError (ERROR_INVALID_PARAMETER);
                return ERROR_INVALID_PARAMETER;
        }
 
        Status = MapDefaultKey(&KeyHandle, hKey);
        if (!NT_SUCCESS(Status))
        {
-               ErrorCode = RtlNtStatusToDosError (Status);
-               SetLastError (ErrorCode);
-               return ErrorCode;
+               return RtlNtStatusToDosError (Status);
        }
 
        if (*lpcbName > 0)
@@ -923,8 +1982,8 @@ RegEnumKeyExA (HKEY hKey,
        KeyInfo = RtlAllocateHeap (ProcessHeap, 0, BufferSize);
        if (KeyInfo == NULL)
        {
-               SetLastError (ERROR_OUTOFMEMORY);
-               return ERROR_OUTOFMEMORY;
+               ErrorCode = ERROR_OUTOFMEMORY;
+               goto Cleanup;
        }
 
        Status = NtEnumerateKey (KeyHandle,
@@ -933,7 +1992,7 @@ RegEnumKeyExA (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);
@@ -1001,21 +2060,19 @@ RegEnumKeyExA (HKEY hKey,
                }
        }
 
-       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);
+       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);
 
        RtlFreeHeap (ProcessHeap,
                0,
                KeyInfo);
 
-       if (ErrorCode != ERROR_SUCCESS)
-       {
-               SetLastError(ErrorCode);
-       }
+Cleanup:
+    ClosePredefKey(KeyHandle);
 
-       return ErrorCode;
+    return ErrorCode;
 }
 
 
@@ -1049,12 +2106,10 @@ RegEnumKeyExW (HKEY hKey,
   NTSTATUS Status;
 
   Status = MapDefaultKey(&KeyHandle,
-                        hKey);
+                         hKey);
   if (!NT_SUCCESS(Status))
     {
-      ErrorCode = RtlNtStatusToDosError (Status);
-      SetLastError (ErrorCode);
-      return ErrorCode;
+      return RtlNtStatusToDosError (Status);
     }
 
   if (*lpcbName > 0)
@@ -1089,8 +2144,8 @@ RegEnumKeyExW (HKEY hKey,
                             BufferSize);
   if (KeyInfo == NULL)
     {
-      SetLastError (ERROR_OUTOFMEMORY);
-      return ERROR_OUTOFMEMORY;
+      ErrorCode = ERROR_OUTOFMEMORY;
+      goto Cleanup;
     }
 
   Status = NtEnumerateKey (KeyHandle,
@@ -1099,7 +2154,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);
@@ -1162,10 +2217,8 @@ RegEnumKeyExW (HKEY hKey,
               0,
               KeyInfo);
 
-  if (ErrorCode != ERROR_SUCCESS)
-    {
-      SetLastError(ErrorCode);
-    }
+Cleanup:
+  ClosePredefKey(KeyHandle);
 
   return ErrorCode;
 }
@@ -1184,7 +2237,7 @@ RegEnumValueA( HKEY hKey, DWORD index, LPSTR value, LPDWORD val_count,
     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 );
+    static const int info_size = FIELD_OFFSET( KEY_VALUE_FULL_INFORMATION, Name );
 
     //TRACE("(%p,%ld,%p,%p,%p,%p,%p,%p)\n",
       //    hkey, index, value, val_count, reserved, type, data, count );
@@ -1194,10 +2247,7 @@ RegEnumValueA( HKEY hKey, DWORD index, LPSTR value, LPDWORD val_count,
        status = MapDefaultKey (&KeyHandle, hKey);
        if (!NT_SUCCESS(status))
        {
-               LONG ErrorCode;
-               ErrorCode =     RtlNtStatusToDosError (status);
-               SetLastError (ErrorCode);
-               return ErrorCode;
+               return RtlNtStatusToDosError (status);
        }
 
     total_size = info_size + (MAX_PATH + 1) * sizeof(WCHAR);
@@ -1217,7 +2267,10 @@ RegEnumValueA( HKEY hKey, DWORD index, LPSTR value, LPDWORD val_count,
         {
             if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
             if (!(buf_ptr = HeapAlloc( GetProcessHeap(), 0, total_size )))
-                return ERROR_NOT_ENOUGH_MEMORY;
+            {
+                status = STATUS_INSUFFICIENT_RESOURCES;
+                goto done;
+            }
             info = (KEY_VALUE_FULL_INFORMATION *)buf_ptr;
             status = NtEnumerateValueKey( KeyHandle, index, KeyValueFullInformation,
                                           buf_ptr, total_size, &total_size );
@@ -1235,7 +2288,7 @@ RegEnumValueA( HKEY hKey, DWORD index, LPSTR value, LPDWORD val_count,
                 if (len > *count) status = STATUS_BUFFER_OVERFLOW;
                 else
                 {
-                    RtlUnicodeToMultiByteN( data, len, NULL, (WCHAR *)(buf_ptr + info->DataOffset),
+                    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 */
@@ -1280,13 +2333,14 @@ RegEnumValueA( HKEY hKey, DWORD index, LPSTR value, LPDWORD val_count,
 
  done:
     if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
+    ClosePredefKey(KeyHandle);
     return RtlNtStatusToDosError(status);
 }
 
 /******************************************************************************
  * RegEnumValueW   [ADVAPI32.@]
  * @implemented
- * 
+ *
  * PARAMS
  *  hkey       [I] Handle to key to query
  *  index      [I] Index of value to query
@@ -1310,21 +2364,18 @@ RegEnumValueW( HKEY hKey, DWORD index, LPWSTR value, PDWORD val_count,
     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 );
+    static const int info_size = FIELD_OFFSET( 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))
        {
-               LONG ErrorCode;
-               ErrorCode = RtlNtStatusToDosError (status);
-               SetLastError (ErrorCode);
-               return ErrorCode;
+               return RtlNtStatusToDosError (status);
        }
 
     total_size = info_size + (MAX_PATH + 1) * sizeof(WCHAR);
@@ -1342,7 +2393,10 @@ RegEnumValueW( HKEY hKey, DWORD index, LPWSTR value, PDWORD val_count,
         {
             if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
             if (!(buf_ptr = HeapAlloc( GetProcessHeap(), 0, total_size )))
-                return ERROR_NOT_ENOUGH_MEMORY;
+            {
+                status = ERROR_NOT_ENOUGH_MEMORY;
+                goto done;
+            }
             info = (KEY_VALUE_FULL_INFORMATION *)buf_ptr;
             status = NtEnumerateValueKey( KeyHandle, index, KeyValueFullInformation,
                                           buf_ptr, total_size, &total_size );
@@ -1387,6 +2441,7 @@ RegEnumValueW( HKEY hKey, DWORD index, LPWSTR value, PDWORD val_count,
 
  done:
     if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
+    ClosePredefKey(KeyHandle);
     return RtlNtStatusToDosError(status);
 }
 
@@ -1399,7 +2454,6 @@ LONG STDCALL
 RegFlushKey(HKEY hKey)
 {
   HANDLE KeyHandle;
-  LONG ErrorCode;
   NTSTATUS Status;
 
   if (hKey == HKEY_PERFORMANCE_DATA)
@@ -1408,20 +2462,19 @@ RegFlushKey(HKEY hKey)
     }
 
   Status = MapDefaultKey (&KeyHandle,
-                         hKey);
+                          hKey);
   if (!NT_SUCCESS(Status))
     {
-      ErrorCode = RtlNtStatusToDosError (Status);
-      SetLastError (ErrorCode);
-      return ErrorCode;
+      return RtlNtStatusToDosError (Status);
     }
 
   Status = NtFlushKey (KeyHandle);
+  
+  ClosePredefKey(KeyHandle);
+  
   if (!NT_SUCCESS(Status))
     {
-      ErrorCode = RtlNtStatusToDosError (Status);
-      SetLastError (ErrorCode);
-      return ErrorCode;
+      return RtlNtStatusToDosError (Status);
     }
 
   return ERROR_SUCCESS;
@@ -1440,36 +2493,34 @@ RegGetKeySecurity(HKEY hKey,
                  LPDWORD lpcbSecurityDescriptor)
 {
   HANDLE KeyHandle;
-  LONG ErrorCode;
   NTSTATUS Status;
 
   if (hKey == HKEY_PERFORMANCE_DATA)
     {
-      SetLastError(ERROR_INVALID_HANDLE);
       return ERROR_INVALID_HANDLE;
     }
 
   Status = MapDefaultKey(&KeyHandle,
-                        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);
     }
-
+#ifndef __REACTOS__
   Status = NtQuerySecurityObject(KeyHandle,
                                 SecurityInformation,
                                 pSecurityDescriptor,
                                 *lpcbSecurityDescriptor,
                                 lpcbSecurityDescriptor);
+#endif
+
+  ClosePredefKey(KeyHandle);
+
   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;
@@ -1521,31 +2572,28 @@ RegLoadKeyW (HKEY hKey,
   UNICODE_STRING FileName;
   UNICODE_STRING KeyName;
   HANDLE KeyHandle;
-  LONG ErrorCode;
   NTSTATUS Status;
+  LONG ErrorCode = ERROR_SUCCESS;
 
   if (hKey == HKEY_PERFORMANCE_DATA)
     {
-      SetLastError(ERROR_INVALID_HANDLE);
       return ERROR_INVALID_HANDLE;
     }
 
   Status = MapDefaultKey (&KeyHandle,
-                         hKey);
+                          hKey);
   if (!NT_SUCCESS(Status))
     {
-      ErrorCode = RtlNtStatusToDosError (Status);
-      SetLastError (ErrorCode);
-      return ErrorCode;
+      return RtlNtStatusToDosError (Status);
     }
 
-  if (!RtlDosPathNameToNtPathName_U ((LPWSTR)lpFile,
+  if (!RtlDosPathNameToNtPathName_U (lpFile,
                                     &FileName,
                                     NULL,
                                     NULL))
     {
-      SetLastError (ERROR_BAD_PATHNAME);
-      return ERROR_BAD_PATHNAME;
+      ErrorCode = ERROR_BAD_PATHNAME;
+      goto Cleanup;
     }
 
   InitializeObjectAttributes (&FileObjectAttributes,
@@ -1571,11 +2619,13 @@ RegLoadKeyW (HKEY hKey,
   if (!NT_SUCCESS(Status))
     {
       ErrorCode = RtlNtStatusToDosError (Status);
-      SetLastError (ErrorCode);
-      return ErrorCode;
+      goto Cleanup;
     }
 
-  return ERROR_SUCCESS;
+Cleanup:
+  ClosePredefKey(KeyHandle);
+
+  return ErrorCode;
 }
 
 
@@ -1594,6 +2644,7 @@ RegNotifyChangeKeyValue (HKEY hKey,
   IO_STATUS_BLOCK IoStatusBlock;
   HANDLE KeyHandle;
   NTSTATUS Status;
+  LONG ErrorCode = ERROR_SUCCESS;
 
   if (hKey == HKEY_PERFORMANCE_DATA)
     {
@@ -1606,7 +2657,7 @@ RegNotifyChangeKeyValue (HKEY hKey,
     }
 
   Status = MapDefaultKey (&KeyHandle,
-                         hKey);
+                          hKey);
   if (!NT_SUCCESS(Status))
     {
       return RtlNtStatusToDosError (Status);
@@ -1626,9 +2677,34 @@ RegNotifyChangeKeyValue (HKEY hKey,
                              fAsynchronous);
   if (!NT_SUCCESS(Status) && Status != STATUS_TIMEOUT)
     {
-      return RtlNtStatusToDosError (Status);
+      ErrorCode = RtlNtStatusToDosError (Status);
     }
 
+  ClosePredefKey(KeyHandle);
+
+  return ErrorCode;
+}
+
+
+/************************************************************************
+ *  RegOpenCurrentUser
+ *
+ * @implemented
+ */
+LONG STDCALL
+RegOpenCurrentUser (IN REGSAM samDesired,
+                    OUT PHKEY phkResult)
+{
+  NTSTATUS Status;
+
+  Status = RtlOpenCurrentUser((ACCESS_MASK)samDesired,
+                              (PHANDLE)phkResult);
+  if (!NT_SUCCESS(Status))
+  {
+    /* NOTE - don't set the last error code! just return the error! */
+    return RtlNtStatusToDosError(Status);
+  }
+
   return ERROR_SUCCESS;
 }
 
@@ -1645,7 +2721,7 @@ RegOpenKeyA (HKEY hKey,
             LPCSTR lpSubKey,
             PHKEY phkResult)
 {
-       DPRINT("RegOpenKeyA hKey 0x%x lpSubKey %s phkResult %p\n", hKey, lpSubKey, phkResult);
+       TRACE("RegOpenKeyA hKey 0x%x lpSubKey %s phkResult %p\n", hKey, lpSubKey, phkResult);
 
        if (!lpSubKey || !*lpSubKey)
        {
@@ -1653,7 +2729,7 @@ RegOpenKeyA (HKEY hKey,
                return ERROR_SUCCESS;
        }
 
-       return RegOpenKeyExA( hKey, lpSubKey, 0, KEY_ALL_ACCESS, phkResult);
+       return RegOpenKeyExA( hKey, lpSubKey, 0, MAXIMUM_ALLOWED, phkResult);
 }
 
 
@@ -1671,14 +2747,14 @@ RegOpenKeyW (HKEY hKey,
             LPCWSTR lpSubKey,
             PHKEY phkResult)
 {
-       DPRINT("RegOpenKeyW hKey 0x%x lpSubKey %S phkResult %p\n", hKey, lpSubKey, 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, KEY_ALL_ACCESS, phkResult);
+       return RegOpenKeyExW(hKey, lpSubKey, 0, MAXIMUM_ALLOWED, phkResult);
 }
 
 
@@ -1697,18 +2773,16 @@ RegOpenKeyExA (HKEY hKey,
        OBJECT_ATTRIBUTES ObjectAttributes;
        UNICODE_STRING SubKeyString;
        HANDLE KeyHandle;
-       LONG ErrorCode;
        NTSTATUS Status;
+       LONG ErrorCode = ERROR_SUCCESS;
 
-       DPRINT("RegOpenKeyExA hKey 0x%x lpSubKey %s ulOptions 0x%x samDesired 0x%x phkResult %p\n",
+       TRACE("RegOpenKeyExA 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))
        {
-               ErrorCode = RtlNtStatusToDosError (Status);
-               SetLastError (ErrorCode);
-               return ErrorCode;
+               return RtlNtStatusToDosError (Status);
        }
 
        RtlCreateUnicodeStringFromAsciiz (&SubKeyString, (LPSTR)lpSubKey);
@@ -1723,11 +2797,11 @@ RegOpenKeyExA (HKEY hKey,
        if (!NT_SUCCESS(Status))
        {
                ErrorCode = RtlNtStatusToDosError (Status);
-               SetLastError (ErrorCode);
-               return ErrorCode;
        }
+       
+       ClosePredefKey(KeyHandle);
 
-       return ERROR_SUCCESS;
+       return ErrorCode;
 }
 
 
@@ -1746,18 +2820,16 @@ RegOpenKeyExW (HKEY hKey,
        OBJECT_ATTRIBUTES ObjectAttributes;
        UNICODE_STRING SubKeyString;
        HANDLE KeyHandle;
-       LONG ErrorCode;
        NTSTATUS Status;
+       LONG ErrorCode = ERROR_SUCCESS;
 
-       DPRINT("RegOpenKeyExW hKey 0x%x lpSubKey %S ulOptions 0x%x samDesired 0x%x phkResult %p\n",
+       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))
        {
-               ErrorCode = RtlNtStatusToDosError (Status);
-               SetLastError (ErrorCode);
-               return ErrorCode;
+               return RtlNtStatusToDosError (Status);
        }
 
        if (lpSubKey != NULL)
@@ -1776,11 +2848,154 @@ RegOpenKeyExW (HKEY hKey,
        if (!NT_SUCCESS(Status))
        {
                ErrorCode = RtlNtStatusToDosError (Status);
-               SetLastError (ErrorCode);
-               return ErrorCode;
        }
+       
+       ClosePredefKey(KeyHandle);
+
+       return ErrorCode;
+}
+
+
+/************************************************************************
+ *  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;
+  NTSTATUS Status;
+
+  /* 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! */
+    return RtlNtStatusToDosError (Status);
+  }
+
+  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))
+  {
+    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! */
+    return RtlNtStatusToDosError (Status);
+  }
+
+  /*
+   * 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
+   */
+
+  InitializeObjectAttributes (&ObjectAttributes,
+                             &UserClassesKeyRoot,
+                             OBJ_CASE_INSENSITIVE,
+                             NULL,
+                             NULL);
+
+  Status = NtOpenKey((PHANDLE)phkResult,
+                     samDesired,
+                     &ObjectAttributes);
+
+  RtlFreeUnicodeString(&UserSidString);
+  RtlFreeUnicodeString(&UserClassesKeyRoot);
 
-       return ERROR_SUCCESS;
+  if (!NT_SUCCESS(Status))
+  {
+    return RtlNtStatusToDosError (Status);
+  }
+
+  return ERROR_SUCCESS;
 }
 
 
@@ -1870,12 +3085,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;
     }
 
@@ -1883,9 +3097,7 @@ RegQueryInfoKeyW (HKEY hKey,
                          hKey);
   if (!NT_SUCCESS(Status))
     {
-      ErrorCode = RtlNtStatusToDosError (Status);
-      SetLastError (ErrorCode);
-      return ErrorCode;
+      return RtlNtStatusToDosError (Status);
     }
 
   if (lpClass != NULL)
@@ -1905,8 +3117,8 @@ RegQueryInfoKeyW (HKEY hKey,
                                  FullInfoSize);
       if (FullInfo == NULL)
        {
-         SetLastError (ERROR_OUTOFMEMORY);
-         return ERROR_OUTOFMEMORY;
+         ErrorCode = ERROR_OUTOFMEMORY;
+         goto Cleanup;
        }
 
       FullInfo->ClassLength = ClassLength;
@@ -1924,7 +3136,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)
@@ -1935,46 +3147,45 @@ RegQueryInfoKeyW (HKEY hKey,
        }
 
       ErrorCode = RtlNtStatusToDosError (Status);
-      SetLastError (ErrorCode);
-      return ErrorCode;
+      goto Cleanup;
     }
 
-  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;
     }
-
+#ifndef __REACTOS__ 
   if (lpcbSecurityDescriptor != NULL)
     {
       Status = NtQuerySecurityObject(KeyHandle,
@@ -1993,11 +3204,11 @@ RegQueryInfoKeyW (HKEY hKey,
                          FullInfo);
            }
 
-         ErrorCode = RtlNtStatusToDosError(Status);
-         SetLastError(ErrorCode);
-         return ErrorCode;
+         ErrorCode = RtlNtStatusToDosError (Status);
+         goto Cleanup;
        }
     }
+#endif
 
   if (lpftLastWriteTime != NULL)
     {
@@ -2025,11 +3236,9 @@ RegQueryInfoKeyW (HKEY hKey,
                   FullInfo);
     }
 
-  if (ErrorCode != ERROR_SUCCESS)
-    {
-      SetLastError (ErrorCode);
-    }
-
+Cleanup:
+  ClosePredefKey(KeyHandle);
+  
   return ErrorCode;
 }
 
@@ -2056,7 +3265,7 @@ RegQueryMultipleValuesA (HKEY hKey,
 
   *ldwTotsize = 0;
 
-  DPRINT ("RegQueryMultipleValuesA(%p,%p,%ld,%p,%p=%ld)\n",
+  TRACE("RegQueryMultipleValuesA(%p,%p,%ld,%p,%p=%ld)\n",
          hKey, val_list, num_vals, lpValueBuf, ldwTotsize, *ldwTotsize);
 
   for (i = 0; i < num_vals; i++)
@@ -2120,7 +3329,7 @@ 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++)
@@ -2178,28 +3387,26 @@ 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;
+      ErrorCode = ERROR_INVALID_PARAMETER;
+      goto Cleanup;
     }
 
   RtlInitUnicodeString (&ValueName,
@@ -2210,17 +3417,17 @@ RegQueryValueExW (HKEY hKey,
                               BufferSize);
   if (ValueInfo == NULL)
     {
-      SetLastError(ERROR_OUTOFMEMORY);
-      return ERROR_OUTOFMEMORY;
+      ErrorCode = ERROR_OUTOFMEMORY;
+      goto Cleanup;
     }
 
-  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 */
@@ -2230,7 +3437,6 @@ RegQueryValueExW (HKEY hKey,
   else if (!NT_SUCCESS(Status))
     {
       ErrorCode = RtlNtStatusToDosError (Status);
-      SetLastError (ErrorCode);
       MaxCopy = 0;
       if (lpcbData != NULL)
        {
@@ -2262,7 +3468,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
@@ -2270,16 +3476,19 @@ 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,
               ValueInfo);
 
+Cleanup:
+  ClosePredefKey(KeyHandle);
+
   return ErrorCode;
 }
 
@@ -2304,12 +3513,11 @@ RegQueryValueExA (HKEY hKey,
   DWORD Length;
   DWORD Type;
 
-  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);
 
   if (lpData != NULL && lpcbData == NULL)
     {
-      SetLastError(ERROR_INVALID_PARAMETER);
       return ERROR_INVALID_PARAMETER;
     }
 
@@ -2322,7 +3530,6 @@ RegQueryValueExA (HKEY hKey,
                                          ValueData.MaximumLength);
       if (!ValueData.Buffer)
        {
-         SetLastError(ERROR_OUTOFMEMORY);
          return ERROR_OUTOFMEMORY;
        }
     }
@@ -2343,7 +3550,7 @@ RegQueryValueExA (HKEY hKey,
                                &Type,
                                (lpData == NULL) ? NULL : (LPBYTE)ValueData.Buffer,
                                &Length);
-  DPRINT("ErrorCode %lu\n", ErrorCode);
+  TRACE("ErrorCode %lu\n", ErrorCode);
   RtlFreeUnicodeString(&ValueName);
 
   if (ErrorCode == ERROR_SUCCESS ||
@@ -2412,13 +3619,12 @@ RegQueryValueA (HKEY hKey,
   LONG ValueSize;
   LONG ErrorCode;
 
-  DPRINT("hKey 0x%X lpSubKey %s lpValue %p lpcbValue %d\n",
+  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;
     }
 
@@ -2447,7 +3653,6 @@ RegQueryValueA (HKEY hKey,
                                      ValueSize);
       if (Value.Buffer == NULL)
        {
-         SetLastError(ERROR_OUTOFMEMORY);
          return ERROR_OUTOFMEMORY;
        }
     }
@@ -2503,16 +3708,14 @@ RegQueryValueW (HKEY hKey,
   BOOL CloseRealKey;
   NTSTATUS Status;
 
-  DPRINT("hKey 0x%X lpSubKey %S lpValue %p lpcbValue %d\n",
+  TRACE("hKey 0x%X lpSubKey %S lpValue %p lpcbValue %d\n",
         hKey, lpSubKey, lpValue, lpcbValue ? *lpcbValue : 0);
 
   Status = MapDefaultKey (&KeyHandle,
-                         hKey);
+                          hKey);
   if (!NT_SUCCESS(Status))
     {
-      ErrorCode = RtlNtStatusToDosError (Status);
-      SetLastError (ErrorCode);
-      return ErrorCode;
+      return RtlNtStatusToDosError (Status);
     }
 
   if (lpSubKey != NULL &&
@@ -2526,13 +3729,12 @@ 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;
+         goto Cleanup;
        }
       CloseRealKey = TRUE;
     }
@@ -2553,6 +3755,9 @@ RegQueryValueW (HKEY hKey,
       NtClose (RealKey);
     }
 
+Cleanup:
+  ClosePredefKey(KeyHandle);
+
   return ErrorCode;
 }
 
@@ -2613,8 +3818,8 @@ RegReplaceKeyW (HKEY hKey,
   BOOLEAN CloseRealKey;
   HANDLE RealKeyHandle;
   HANDLE KeyHandle;
-  LONG ErrorCode;
   NTSTATUS Status;
+  LONG ErrorCode = ERROR_SUCCESS;
 
   if (hKey == HKEY_PERFORMANCE_DATA)
     {
@@ -2622,12 +3827,10 @@ RegReplaceKeyW (HKEY hKey,
     }
 
   Status = MapDefaultKey (&KeyHandle,
-                         hKey);
+                          hKey);
   if (!NT_SUCCESS(Status))
     {
-      ErrorCode = RtlNtStatusToDosError (Status);
-      SetLastError (ErrorCode);
-      return ErrorCode;
+      return RtlNtStatusToDosError (Status);
     }
 
   /* Open the real key */
@@ -2641,13 +3844,12 @@ 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;
+         goto Cleanup;
        }
       CloseRealKey = TRUE;
     }
@@ -2658,7 +3860,7 @@ RegReplaceKeyW (HKEY hKey,
     }
 
   /* Convert new file name */
-  if (!RtlDosPathNameToNtPathName_U ((LPWSTR)lpNewFile,
+  if (!RtlDosPathNameToNtPathName_U (lpNewFile,
                                     &NewFileName,
                                     NULL,
                                     NULL))
@@ -2667,8 +3869,8 @@ RegReplaceKeyW (HKEY hKey,
        {
          NtClose (RealKeyHandle);
        }
-      SetLastError (ERROR_INVALID_PARAMETER);
-      return ERROR_INVALID_PARAMETER;
+      ErrorCode = ERROR_INVALID_PARAMETER;
+      goto Cleanup;
     }
 
   InitializeObjectAttributes (&NewObjectAttributes,
@@ -2678,7 +3880,7 @@ RegReplaceKeyW (HKEY hKey,
                              NULL);
 
   /* Convert old file name */
-  if (!RtlDosPathNameToNtPathName_U ((LPWSTR)lpOldFile,
+  if (!RtlDosPathNameToNtPathName_U (lpOldFile,
                                     &OldFileName,
                                     NULL,
                                     NULL))
@@ -2688,8 +3890,8 @@ RegReplaceKeyW (HKEY hKey,
        {
          NtClose (RealKeyHandle);
        }
-      SetLastError (ERROR_INVALID_PARAMETER);
-      return ERROR_INVALID_PARAMETER;
+      ErrorCode = ERROR_INVALID_PARAMETER;
+      goto Cleanup;
     }
 
   InitializeObjectAttributes (&OldObjectAttributes,
@@ -2712,12 +3914,13 @@ RegReplaceKeyW (HKEY hKey,
 
   if (!NT_SUCCESS(Status))
     {
-      ErrorCode = RtlNtStatusToDosError (Status);
-      SetLastError (ErrorCode);
-      return ErrorCode;
+      return RtlNtStatusToDosError (Status);
     }
 
-  return ERROR_SUCCESS;
+Cleanup:
+  ClosePredefKey(KeyHandle);
+
+  return ErrorCode;
 }
 
 
@@ -2762,7 +3965,6 @@ RegRestoreKeyW (HKEY hKey,
   UNICODE_STRING FileName;
   HANDLE FileHandle;
   HANDLE KeyHandle;
-  LONG ErrorCode;
   NTSTATUS Status;
 
   if (hKey == HKEY_PERFORMANCE_DATA)
@@ -2771,21 +3973,19 @@ RegRestoreKeyW (HKEY hKey,
     }
 
   Status = MapDefaultKey (&KeyHandle,
-                         hKey);
+                          hKey);
   if (!NT_SUCCESS(Status))
     {
-      ErrorCode = RtlNtStatusToDosError (Status);
-      SetLastError (ErrorCode);
-      return ErrorCode;
+      return RtlNtStatusToDosError (Status);
     }
 
-  if (!RtlDosPathNameToNtPathName_U ((LPWSTR)lpFile,
+  if (!RtlDosPathNameToNtPathName_U (lpFile,
                                     &FileName,
                                     NULL,
                                     NULL))
     {
-      SetLastError (ERROR_INVALID_PARAMETER);
-      return ERROR_INVALID_PARAMETER;
+      Status = STATUS_INVALID_PARAMETER;
+      goto Cleanup;
     }
 
   InitializeObjectAttributes (&ObjectAttributes,
@@ -2803,20 +4003,20 @@ RegRestoreKeyW (HKEY hKey,
   RtlFreeUnicodeString (&FileName);
   if (!NT_SUCCESS(Status))
     {
-      ErrorCode = RtlNtStatusToDosError (Status);
-      SetLastError (ErrorCode);
-      return ErrorCode;
+      goto Cleanup;
     }
 
   Status = NtRestoreKey (KeyHandle,
                         FileHandle,
                         (ULONG)dwFlags);
   NtClose (FileHandle);
+  
+Cleanup:
+  ClosePredefKey(KeyHandle);
+
   if (!NT_SUCCESS(Status))
     {
-      ErrorCode = RtlNtStatusToDosError (Status);
-      SetLastError (ErrorCode);
-      return ErrorCode;
+      return RtlNtStatusToDosError (Status);
     }
 
   return ERROR_SUCCESS;
@@ -2864,24 +4064,21 @@ RegSaveKeyW (HKEY hKey,
   HANDLE FileHandle;
   HANDLE KeyHandle;
   NTSTATUS Status;
-  LONG ErrorCode;
 
   Status = MapDefaultKey (&KeyHandle,
-                         hKey);
+                          hKey);
   if (!NT_SUCCESS(Status))
     {
-      ErrorCode = RtlNtStatusToDosError (Status);
-      SetLastError (ErrorCode);
-      return ErrorCode;
+      return RtlNtStatusToDosError (Status);
     }
 
-  if (!RtlDosPathNameToNtPathName_U ((PWSTR)lpFile,
+  if (!RtlDosPathNameToNtPathName_U (lpFile,
                                     &FileName,
                                     NULL,
                                     NULL))
     {
-      SetLastError (ERROR_INVALID_PARAMETER);
-      return ERROR_INVALID_PARAMETER;
+      Status = STATUS_INVALID_PARAMETER;
+      goto Cleanup;
     }
 
   if (lpSecurityAttributes != NULL)
@@ -2908,19 +4105,19 @@ RegSaveKeyW (HKEY hKey,
   RtlFreeUnicodeString (&FileName);
   if (!NT_SUCCESS(Status))
     {
-      ErrorCode = RtlNtStatusToDosError (Status);
-      SetLastError (ErrorCode);
-      return ErrorCode;
+      goto Cleanup;
     }
 
   Status = NtSaveKey (KeyHandle,
                      FileHandle);
   NtClose (FileHandle);
+
+Cleanup:
+  ClosePredefKey(KeyHandle);
+
   if (!NT_SUCCESS(Status))
     {
-      ErrorCode = RtlNtStatusToDosError (Status);
-      SetLastError (ErrorCode);
-      return ErrorCode;
+      return RtlNtStatusToDosError (Status);
     }
 
   return ERROR_SUCCESS;
@@ -2938,32 +4135,29 @@ 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;
     }
 
   Status = MapDefaultKey (&KeyHandle,
-                         hKey);
+                          hKey);
   if (!NT_SUCCESS(Status))
     {
-      ErrorCode = RtlNtStatusToDosError (Status);
-      SetLastError (ErrorCode);
-      return ErrorCode;
+      return RtlNtStatusToDosError (Status);
     }
 
   Status = NtSetSecurityObject (KeyHandle,
                                SecurityInformation,
                                pSecurityDescriptor);
+
+  ClosePredefKey(KeyHandle);
+  
   if (!NT_SUCCESS(Status))
     {
-      ErrorCode = RtlNtStatusToDosError (Status);
-      SetLastError (ErrorCode);
-      return ErrorCode;
+      return RtlNtStatusToDosError (Status);
     }
 
   return ERROR_SUCCESS;
@@ -3003,14 +4197,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,
@@ -3067,15 +4268,12 @@ RegSetValueExW (HKEY hKey,
   PUNICODE_STRING pValueName;
   HANDLE KeyHandle;
   NTSTATUS Status;
-  LONG ErrorCode;
 
   Status = MapDefaultKey (&KeyHandle,
-                         hKey);
+                          hKey);
   if (!NT_SUCCESS(Status))
     {
-      ErrorCode = RtlNtStatusToDosError (Status);
-      SetLastError (ErrorCode);
-      return ErrorCode;
+      return RtlNtStatusToDosError (Status);
     }
 
   if (lpValueName != NULL)
@@ -3089,17 +4287,27 @@ 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,
                          dwType,
                          (PVOID)lpData,
                          (ULONG)cbData);
+
+  ClosePredefKey(KeyHandle);
+
   if (!NT_SUCCESS(Status))
     {
-      ErrorCode = RtlNtStatusToDosError (Status);
-      SetLastError (ErrorCode);
-      return ErrorCode;
+      return RtlNtStatusToDosError (Status);
     }
 
   return ERROR_SUCCESS;
@@ -3118,51 +4326,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;
 }
 
 
@@ -3182,17 +4380,15 @@ RegSetValueW (HKEY hKey,
   UNICODE_STRING SubKeyString;
   HANDLE KeyHandle;
   HANDLE RealKey;
-  LONG ErrorCode;
   BOOL CloseRealKey;
   NTSTATUS Status;
+  LONG ErrorCode;
 
   Status = MapDefaultKey (&KeyHandle,
-                         hKey);
+                          hKey);
   if (!NT_SUCCESS(Status))
     {
-      ErrorCode = RtlNtStatusToDosError (Status);
-      SetLastError (ErrorCode);
-      return ErrorCode;
+      return RtlNtStatusToDosError (Status);
     }
 
   if ((lpSubKey) && (wcslen(lpSubKey) != 0))
@@ -3205,13 +4401,12 @@ 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;
+         goto Cleanup;
        }
       CloseRealKey = TRUE;
     }
@@ -3232,6 +4427,9 @@ RegSetValueW (HKEY hKey,
       NtClose (RealKey);
     }
 
+Cleanup:
+  ClosePredefKey(KeyHandle);
+
   return ErrorCode;
 }
 
@@ -3272,21 +4470,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,
@@ -3299,15 +4493,54 @@ RegUnLoadKeyW (HKEY hKey,
                              NULL);
 
   Status = NtUnloadKey (&ObjectAttributes);
+  
+  ClosePredefKey(KeyHandle);
 
   if (!NT_SUCCESS(Status))
     {
-      ErrorCode = RtlNtStatusToDosError (Status);
-      SetLastError (ErrorCode);
-      return ErrorCode;
+      return RtlNtStatusToDosError (Status);
     }
 
   return ERROR_SUCCESS;
 }
 
+
+/************************************************************************
+ *  RegLoadMUIStringW
+ *
+ * @unimplemented
+ */
+LONG STDCALL
+RegLoadMUIStringW(IN HKEY hKey,
+                  IN LPCWSTR pszValue  OPTIONAL,
+                  OUT LPWSTR pszOutBuf,
+                  IN ULONG cbOutBuf,
+                  IN ULONG Reserved,
+                  IN LPCWSTR pszDirectory  OPTIONAL)
+{
+    DPRINT1("RegLoadMUIStringW(0x%p, 0x%p, 0x%p, 0x%x, 0x%x, 0x%p) UNIMPLEMENTED!\n",
+            hKey, pszValue, pszOutBuf, cbOutBuf, Reserved, pszDirectory);
+    return ERROR_CALL_NOT_IMPLEMENTED;
+}
+
+
+/************************************************************************
+ *  RegLoadMUIStringA
+ *
+ * @unimplemented
+ */
+LONG STDCALL
+RegLoadMUIStringA(IN HKEY hKey,
+                  IN LPCSTR pszValue  OPTIONAL,
+                  OUT LPSTR pszOutBuf,
+                  IN ULONG cbOutBuf,
+                  IN ULONG Reserved,
+                  IN LPCSTR pszDirectory  OPTIONAL)
+{
+    DPRINT1("RegLoadMUIStringA(0x%p, 0x%p, 0x%p, 0x%x, 0x%x, 0x%p) UNIMPLEMENTED!\n",
+            hKey, pszValue, pszOutBuf, cbOutBuf, Reserved, pszDirectory);
+    return ERROR_CALL_NOT_IMPLEMENTED;
+}
+
+
 /* EOF */