Fix for wide character streams.
[reactos.git] / reactos / lib / advapi32 / reg / reg.c
index f9f16c6..734fb3c 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: reg.c,v 1.9 2000/09/06 19:58:47 ekohl Exp $
+/* $Id: reg.c,v 1.21 2002/12/08 16:14:28 robd Exp $
  *
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS system libraries
@@ -9,6 +9,10 @@
  *                  Created 01/11/98
  *                  19990309 EA Stubs
  */
+#ifndef WIN32_REGDBG
+
+#define NTOS_MODE_USER
+#include <ntos.h>
 #include <ddk/ntddk.h>
 #include <ntdll/rtl.h>
 #include <windows.h>
 #define NDEBUG
 #include <debug.h>
 
+#else /*WIN32_REGDBG*/
+#include "cm_win32.h"
+#ifdef __GNUC__
+#define WINAPI __stdcall
+#define WINAPIV __cdecl
+#define APIENTRY __stdcall
+#define DECLSPEC_IMPORT __declspec(dllimport)
+#define DECLSPEC_EXPORT __declspec(dllexport)
+#define DECLARE_HANDLE(n) typedef HANDLE n
+#define HKEY_PERFORMANCE_DATA ((HKEY)0x80000004)
+#define ERROR_SUCCESS 0L
+#define ERROR_INVALID_HANDLE 6L
+#define ERROR_OUTOFMEMORY 14L
+#define ERROR_INVALID_PARAMETER 87L
+#define ERROR_CALL_NOT_IMPLEMENTED 120L
+#define ERROR_MORE_DATA 234L
+
+void WINAPI SetLastError(DWORD);
+BOOLEAN STDCALL RtlDosPathNameToNtPathName_U(PWSTR dosname, PUNICODE_STRING ntname, PWSTR* shortname, PCURDIR nah);
+NTSTATUS STDCALL RtlInitializeCriticalSection(LPCRITICAL_SECTION lpcs);
+NTSTATUS STDCALL RtlDeleteCriticalSection(LPCRITICAL_SECTION lpcs);
+NTSTATUS STDCALL RtlLeaveCriticalSection(LPCRITICAL_SECTION lpcs);
+NTSTATUS STDCALL RtlEnterCriticalSection(LPCRITICAL_SECTION lpcs);
+
+DECLARE_HANDLE(HKEY);
+typedef HKEY *PHKEY;
+typedef ACCESS_MASK REGSAM;
+
+typedef struct value_entA {
+  LPSTR ve_valuename;
+  DWORD ve_valuelen;
+  DWORD ve_valueptr;
+  DWORD ve_type;
+} VALENTA,*PVALENTA;
+typedef struct value_entW {
+  LPWSTR ve_valuename;
+  DWORD ve_valuelen;
+  DWORD ve_valueptr;
+  DWORD ve_type;
+} VALENTW,*PVALENTW;
+#endif
+#undef STDCALL
+#define STDCALL _stdcall
+#undef RegSetValueEx
+#undef RegCreateKeyEx
+#undef RegQueryInfoKey
+#undef RegDeleteKey
+#undef RegOpenKey
+#undef RegOpenKeyEx
+#undef RegEnumKeyEx
+#undef RegEnumValue
+#endif /*WIN32_REGDBG*/
+
+#define CHECK_STATUS \
+{ \
+  if (!NT_SUCCESS(Status)) \
+  { \
+    LONG _ErrorCode = RtlNtStatusToDosError(Status); \
+    SetLastError(_ErrorCode); \
+    return _ErrorCode; \
+  } \
+}
+
 /* GLOBALS *******************************************************************/
 
-#define MAX_DEFAULT_HANDLES   7
+#define MAX_DEFAULT_HANDLES   6
 
 static CRITICAL_SECTION HandleTableCS;
 static HANDLE DefaultHandleTable[MAX_DEFAULT_HANDLES];
@@ -30,35 +97,43 @@ static HANDLE DefaultHandleTable[MAX_DEFAULT_HANDLES];
 static NTSTATUS MapDefaultKey (PHKEY ParentKey, HKEY Key);
 static VOID CloseDefaultKeys(VOID);
 
+static NTSTATUS OpenClassesRootKey(PHANDLE KeyHandle);
 static NTSTATUS OpenLocalMachineKey (PHANDLE KeyHandle);
+static NTSTATUS OpenUsersKey (PHANDLE KeyHandle);
+static NTSTATUS OpenCurrentConfigKey(PHANDLE KeyHandle);
 
 
 /* FUNCTIONS *****************************************************************/
 
+inline RegiTerminateWideString(LPWSTR String, DWORD Length)
+{
+  LPWSTR AfterString = String + Length;
+  *AfterString = 0;
+}
+
 /************************************************************************
- *     RegInitDefaultHandles
+ *  RegInitDefaultHandles
  */
 
 BOOL
-RegInitialize (VOID)
+RegInitialize(VOID)
 {
-   DPRINT1("RegInitialize()\n");
+   DPRINT("RegInitialize()\n");
 
    RtlZeroMemory (DefaultHandleTable,
-                 MAX_DEFAULT_HANDLES * sizeof(HANDLE));
-
+      MAX_DEFAULT_HANDLES * sizeof(HANDLE));
    RtlInitializeCriticalSection(&HandleTableCS);
    return TRUE;
 }
 
 
 /************************************************************************
- *     RegInit
+ *  RegInit
  */
 BOOL
 RegCleanup(VOID)
 {
-   DPRINT1("RegCleanup()\n");
+   DPRINT("RegCleanup()\n");
 
    CloseDefaultKeys();
    RtlDeleteCriticalSection(&HandleTableCS);
@@ -67,870 +142,2033 @@ RegCleanup(VOID)
 
 
 static NTSTATUS
-MapDefaultKey (PHKEY ParentKey,
-               HKEY Key)
+MapDefaultKey(PHKEY RealKey,
+        HKEY Key)
 {
    PHANDLE Handle;
    ULONG Index;
    NTSTATUS Status = STATUS_SUCCESS;
 
-   DPRINT1("MapDefaultKey (Key %x)\n", Key);
+   DPRINT("MapDefaultKey (Key %x)\n", Key);
 
-   if (((ULONG)Key & 0xF0000000) != 0x80000000)
-     {
-        *ParentKey = Key;
+   if (((ULONG)Key & 0xF0000000) != 0x80000000) {
+        *RealKey = Key;
         return STATUS_SUCCESS;
-     }
-
+   }
    /* Handle special cases here */
    Index = (ULONG)Key & 0x0FFFFFFF;
-DPRINT1("Index %x\n", Index);
-
    if (Index >= MAX_DEFAULT_HANDLES)
      return STATUS_INVALID_PARAMETER;
-
    RtlEnterCriticalSection(&HandleTableCS);
-
    Handle = &DefaultHandleTable[Index];
-   if (*Handle == NULL)
-     {
+   if (*Handle == NULL) {
         /* create/open the default handle */
-        switch (Index)
-          {
-            case 2: /*HKEY_LOCAL_MACHINE */
+        switch (Index) {
+            case 0: /* HKEY_CLASSES_ROOT */
+              Status = OpenClassesRootKey(Handle);
+              break;
+            case 1: /* HKEY_CURRENT_USER */
+              Status = RtlOpenCurrentUser(KEY_ALL_ACCESS, 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;
             default:
-              DPRINT1("MapDefaultHandle() no handle creator\n");
+              DPRINT("MapDefaultHandle() no handle creator\n");
               Status = STATUS_INVALID_PARAMETER;
           }
-     }
-
+   }
    RtlLeaveCriticalSection(&HandleTableCS);
-
-DPRINT1("Status %x\n", Status);
-
-   if (NT_SUCCESS(Status))
-     {
-        *ParentKey = (HKEY)*Handle;
-     }
-
+   if (NT_SUCCESS(Status)) {
+        *RealKey = (HKEY)*Handle;
+   }
    return Status;
 }
 
 
-static VOID CloseDefaultKeys (VOID)
+static VOID
+CloseDefaultKeys(VOID)
 {
    ULONG i;
 
    RtlEnterCriticalSection(&HandleTableCS);
-
-   for (i = 0; i < MAX_DEFAULT_HANDLES; i++)
-     {
-        if (DefaultHandleTable[i] != NULL)
-          {
+   for (i = 0; i < MAX_DEFAULT_HANDLES; i++) {
+        if (DefaultHandleTable[i] != NULL) {
              NtClose (DefaultHandleTable[i]);
              DefaultHandleTable[i] = NULL;
-          }
-     }
-
+        }
+   }
    RtlLeaveCriticalSection(&HandleTableCS);
 }
 
 
 static NTSTATUS
-OpenLocalMachineKey (PHANDLE KeyHandle)
+OpenClassesRootKey(PHANDLE KeyHandle)
 {
-   OBJECT_ATTRIBUTES Attributes;
-   UNICODE_STRING KeyName;
+  OBJECT_ATTRIBUTES Attributes;
+  UNICODE_STRING KeyName = UNICODE_STRING_INITIALIZER(L"\\Registry\\Machine\\Software\\CLASSES");
+
+  DPRINT("OpenClassesRootKey()\n");
+
+  InitializeObjectAttributes(&Attributes,
+           &KeyName,
+           OBJ_CASE_INSENSITIVE,
+           NULL,
+           NULL);
+  return(NtOpenKey(KeyHandle,
+       KEY_ALL_ACCESS,
+       &Attributes));
+}
 
-   DPRINT1("OpenLocalMachineKey()\n");
 
-   RtlInitUnicodeString(&KeyName,
-                        L"\\Registry\\Machine");
+static NTSTATUS
+OpenLocalMachineKey(PHANDLE KeyHandle)
+{
+  OBJECT_ATTRIBUTES Attributes;
+  UNICODE_STRING KeyName = UNICODE_STRING_INITIALIZER(L"\\Registry\\Machine");
+
+  DPRINT("OpenLocalMachineKey()\n");
+
+  InitializeObjectAttributes(&Attributes,
+           &KeyName,
+           OBJ_CASE_INSENSITIVE,
+           NULL,
+           NULL);
+  return(NtOpenKey(KeyHandle,
+       KEY_ALL_ACCESS,
+       &Attributes));
+}
 
-   InitializeObjectAttributes(&Attributes,
-                              &KeyName,
-                              OBJ_CASE_INSENSITIVE,
-                              NULL,
-                              NULL);
 
-   return (NtOpenKey (KeyHandle,
-                      KEY_ALL_ACCESS,
-                      &Attributes));
+static NTSTATUS
+OpenUsersKey(PHANDLE KeyHandle)
+{
+  OBJECT_ATTRIBUTES Attributes;
+  UNICODE_STRING KeyName = UNICODE_STRING_INITIALIZER(L"\\Registry\\User");
+
+  DPRINT("OpenUsersKey()\n");
+
+  InitializeObjectAttributes(&Attributes,
+           &KeyName,
+           OBJ_CASE_INSENSITIVE,
+           NULL,
+           NULL);
+  return(NtOpenKey(KeyHandle,
+       KEY_ALL_ACCESS,
+       &Attributes));
 }
 
 
+static NTSTATUS
+OpenCurrentConfigKey(PHANDLE KeyHandle)
+{
+  OBJECT_ATTRIBUTES Attributes;
+  UNICODE_STRING KeyName =
+  UNICODE_STRING_INITIALIZER(L"\\Registry\\Machine\\System\\CurrentControlSet\\Hardware Profiles\\Current");
+
+  DPRINT("OpenCurrentConfigKey()\n");
+
+  InitializeObjectAttributes(&Attributes,
+           &KeyName,
+           OBJ_CASE_INSENSITIVE,
+           NULL,
+           NULL);
+  return(NtOpenKey(KeyHandle,
+       KEY_ALL_ACCESS,
+       &Attributes));
+}
+
 /************************************************************************
- *     RegCloseKey
+ *  RegCloseKey
  */
-LONG
-STDCALL
-RegCloseKey(
-       HKEY    hKey
-       )
+LONG STDCALL
+RegCloseKey(HKEY hKey)
 {
-       NTSTATUS Status;
+  NTSTATUS Status;
+
+  /* don't close null handle or a pseudo handle */
+  if ((!hKey) || (((ULONG)hKey & 0xF0000000) == 0x80000000))
+    return ERROR_INVALID_HANDLE;
+  Status = NtClose (hKey);
+  if (!NT_SUCCESS(Status)) {
+      LONG ErrorCode = RtlNtStatusToDosError(Status);
+      SetLastError (ErrorCode);
+      return ErrorCode;
+  }
+  return ERROR_SUCCESS;
+}
 
-       /* don't close null handle or a pseudo handle */
-       if ((!hKey) || (((ULONG)hKey & 0xF0000000) == 0x80000000))
-               return ERROR_INVALID_HANDLE;
 
-       Status = NtClose (hKey);
-       if (!NT_SUCCESS(Status))
-       {
-               LONG ErrorCode = RtlNtStatusToDosError(Status);
+/************************************************************************
+ *  RegConnectRegistryA
+ */
+LONG STDCALL
+RegConnectRegistryA(LPCSTR lpMachineName,
+        HKEY hKey,
+        PHKEY phkResult)
+{
+  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+  return ERROR_CALL_NOT_IMPLEMENTED;
+}
 
-               SetLastError (ErrorCode);
-               return ErrorCode;
-       }
 
-       return ERROR_SUCCESS;
+/************************************************************************
+ *  RegConnectRegistryW
+ */
+LONG STDCALL
+RegConnectRegistryW(LPCWSTR lpMachineName,
+        HKEY hKey,
+        PHKEY phkResult)
+{
+  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+  return ERROR_CALL_NOT_IMPLEMENTED;
 }
 
 
 /************************************************************************
- *     RegConnectRegistryA
+ *  RegCreateKeyExA
  */
-LONG
-STDCALL
-RegConnectRegistryA(
-       LPSTR   lpMachineName,
-       HKEY    hKey,
-       PHKEY   phkResult
-       )
+LONG STDCALL
+RegCreateKeyExA(HKEY hKey,
+    LPCSTR lpSubKey,
+    DWORD Reserved,
+    LPSTR lpClass,
+    DWORD dwOptions,
+    REGSAM samDesired,
+    LPSECURITY_ATTRIBUTES lpSecurityAttributes,
+    PHKEY phkResult,
+    LPDWORD lpdwDisposition)
 {
-       SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-       return ERROR_CALL_NOT_IMPLEMENTED;
+  UNICODE_STRING SubKeyString;
+  UNICODE_STRING ClassString;
+  OBJECT_ATTRIBUTES Attributes;
+  NTSTATUS Status;
+  HKEY ParentKey;
+
+  DPRINT("RegCreateKeyExW() called\n");
+
+  /* get the real parent key */
+  Status = MapDefaultKey(&ParentKey, hKey);
+  if (!NT_SUCCESS(Status)) {
+      LONG ErrorCode = RtlNtStatusToDosError(Status);
+      SetLastError(ErrorCode);
+      return(ErrorCode);
+  }
+  DPRINT("ParentKey %x\n", (ULONG)ParentKey);
+
+  if (lpClass != NULL)
+    RtlCreateUnicodeStringFromAsciiz(&ClassString, lpClass);
+  RtlCreateUnicodeStringFromAsciiz(&SubKeyString, (LPSTR)lpSubKey);
+  InitializeObjectAttributes(&Attributes,
+           &SubKeyString,
+           OBJ_CASE_INSENSITIVE,
+           (HANDLE)ParentKey,
+           (PSECURITY_DESCRIPTOR)lpSecurityAttributes);
+  Status = NtCreateKey(phkResult,
+           samDesired,
+           &Attributes,
+           0,
+           (lpClass == NULL)? NULL : &ClassString,
+           dwOptions,
+           (PULONG)lpdwDisposition);
+  RtlFreeUnicodeString(&SubKeyString);
+  if (lpClass != NULL)
+    RtlFreeUnicodeString(&ClassString);
+  DPRINT("Status %x\n", Status);
+  if (!NT_SUCCESS(Status)) {
+      LONG ErrorCode = RtlNtStatusToDosError(Status);
+      SetLastError (ErrorCode);
+      return ErrorCode;
+  }
+  return(ERROR_SUCCESS);
 }
 
 
 /************************************************************************
- *     RegCreateKeyA
+ *  RegCreateKeyExW
  */
-LONG
-STDCALL
-RegCreateKeyA(
-       HKEY    hKey,
-       LPCSTR  lpSubKey,
-       PHKEY   phkResult
-       )
+LONG STDCALL
+RegCreateKeyExW(HKEY hKey,
+    LPCWSTR   lpSubKey,
+    DWORD     Reserved,
+    LPWSTR    lpClass,
+    DWORD     dwOptions,
+    REGSAM    samDesired,
+    LPSECURITY_ATTRIBUTES lpSecurityAttributes,
+    PHKEY     phkResult,
+    LPDWORD   lpdwDisposition)
 {
-       return RegCreateKeyExA(hKey,
-               lpSubKey,
-               0,
-               NULL,
-               0,
-               KEY_ALL_ACCESS,
-               NULL,
-               phkResult,
-               NULL);
+  UNICODE_STRING SubKeyString;
+  UNICODE_STRING ClassString;
+  OBJECT_ATTRIBUTES Attributes;
+  NTSTATUS Status;
+  HKEY ParentKey;
+
+  DPRINT("RegCreateKeyExW() called\n");
+
+  /* get the real parent key */
+  Status = MapDefaultKey (&ParentKey, hKey);
+  if (!NT_SUCCESS(Status)) {
+    LONG ErrorCode = RtlNtStatusToDosError(Status);
+    SetLastError (ErrorCode);
+    return ErrorCode;
+  }
+  DPRINT("ParentKey %x\n", (ULONG)ParentKey);
+  RtlInitUnicodeString (&ClassString, lpClass);
+  RtlInitUnicodeString (&SubKeyString, lpSubKey);
+  InitializeObjectAttributes (&Attributes,
+            &SubKeyString,
+            OBJ_CASE_INSENSITIVE,
+            (HANDLE)ParentKey,
+            (PSECURITY_DESCRIPTOR)lpSecurityAttributes);
+  Status = NtCreateKey (phkResult,
+            samDesired,
+            &Attributes,
+            0,
+            (lpClass == NULL)? NULL : &ClassString,
+            dwOptions,
+            (PULONG)lpdwDisposition);
+  DPRINT("Status %x\n", Status);
+  if (!NT_SUCCESS(Status)) {
+    LONG ErrorCode = RtlNtStatusToDosError(Status);
+    SetLastError (ErrorCode);
+    return ErrorCode;
+  }
+  return ERROR_SUCCESS;
 }
 
 
 /************************************************************************
- *     RegCreateKeyW
+ *  RegCreateKeyA
  */
-LONG
-STDCALL
-RegCreateKeyW(
-       HKEY    hKey,
-       LPCWSTR lpSubKey,
-       PHKEY   phkResult
-       )
+LONG STDCALL
+RegCreateKeyA(HKEY hKey,
+        LPCSTR lpSubKey,
+        PHKEY phkResult)
 {
-       return RegCreateKeyExW(hKey,
-               lpSubKey,
-               0,
-               NULL,
-               0,
-               KEY_ALL_ACCESS,
-               NULL,
-               phkResult,
-               NULL);
+  return(RegCreateKeyExA(hKey,
+       lpSubKey,
+       0,
+       NULL,
+       0,
+       KEY_ALL_ACCESS,
+       NULL,
+       phkResult,
+       NULL));
 }
 
 
 /************************************************************************
- *     RegCreateKeyExA
+ *  RegCreateKeyW
  */
-LONG
-STDCALL
-RegCreateKeyExA(
-       HKEY                    hKey,
-       LPCSTR                  lpSubKey,
-       DWORD                   Reserved,
-       LPSTR                   lpClass,
-       DWORD                   dwOptions,
-       REGSAM                  samDesired,
-       LPSECURITY_ATTRIBUTES   lpSecurityAttributes,
-       PHKEY                   phkResult,
-       LPDWORD                 lpdwDisposition
-       )
+LONG STDCALL
+RegCreateKeyW(HKEY hKey,
+        LPCWSTR lpSubKey,
+        PHKEY phkResult)
 {
-       SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-       return ERROR_CALL_NOT_IMPLEMENTED;
+  return(RegCreateKeyExW(hKey,
+       lpSubKey,
+       0,
+       NULL,
+       0,
+       KEY_ALL_ACCESS,
+       NULL,
+       phkResult,
+       NULL));
 }
 
 
 /************************************************************************
- *     RegCreateKeyExW
+ *  RegDeleteKeyA
  */
 LONG
 STDCALL
-RegCreateKeyExW(
-       HKEY                    hKey,
-       LPCWSTR                 lpSubKey,
-       DWORD                   Reserved,
-       LPWSTR                  lpClass,
-       DWORD                   dwOptions,
-       REGSAM                  samDesired,
-       LPSECURITY_ATTRIBUTES   lpSecurityAttributes,
-       PHKEY                   phkResult,
-       LPDWORD                 lpdwDisposition
-       )
+RegDeleteKeyA(
+  HKEY  hKey,
+  LPCSTR  lpSubKey)
 {
-       UNICODE_STRING SubKeyString;
-       UNICODE_STRING ClassString;
-       OBJECT_ATTRIBUTES Attributes;
-       NTSTATUS Status;
-       HKEY ParentKey;
-
-       DPRINT1("RegCreateKeyExW() called\n");
-
-       /* get the real parent key */
-       Status = MapDefaultKey (&ParentKey, hKey);
-       if (!NT_SUCCESS(Status))
-       {
-               LONG ErrorCode = RtlNtStatusToDosError(Status);
-
-               SetLastError (ErrorCode);
-               return ErrorCode;
-       }
-
-       DPRINT1("ParentKey %x\n", (ULONG)ParentKey);
-
-       RtlInitUnicodeString (&ClassString, lpClass);
-       RtlInitUnicodeString (&SubKeyString, lpSubKey);
+  OBJECT_ATTRIBUTES ObjectAttributes;
+  UNICODE_STRING SubKeyStringW;
+  ANSI_STRING SubKeyStringA;
+//  HANDLE ParentKey;
+  HKEY ParentKey;
+  HANDLE TargetKey;
+  NTSTATUS Status;
+  LONG ErrorCode;
+
+  Status = MapDefaultKey(&ParentKey, hKey);
+  if (!NT_SUCCESS(Status)) {
+    ErrorCode = RtlNtStatusToDosError(Status);
+    SetLastError (ErrorCode);
+    return ErrorCode;
+  }
+  RtlInitAnsiString(&SubKeyStringA, (LPSTR)lpSubKey);
+  RtlAnsiStringToUnicodeString(&SubKeyStringW, &SubKeyStringA, TRUE);
+  InitializeObjectAttributes (&ObjectAttributes,
+            &SubKeyStringW,
+            OBJ_CASE_INSENSITIVE,
+            (HANDLE)ParentKey,
+            NULL);
+  Status = NtOpenKey(&TargetKey, DELETE, &ObjectAttributes);
+  RtlFreeUnicodeString(&SubKeyStringW);
+  if (!NT_SUCCESS(Status)) {
+    ErrorCode = RtlNtStatusToDosError(Status);
+    SetLastError(ErrorCode);
+    return ErrorCode;
+  }
+  Status = NtDeleteKey(TargetKey);
+  NtClose(TargetKey);
+  if (!NT_SUCCESS(Status)) {
+    ErrorCode = RtlNtStatusToDosError(Status);
+    SetLastError(ErrorCode);
+    return ErrorCode;
+  }
+  return ERROR_SUCCESS;
+}
 
-       InitializeObjectAttributes (&Attributes,
-                                   &SubKeyString,
-                                   OBJ_CASE_INSENSITIVE,
-                                   (HANDLE)ParentKey,
-                                   (PSECURITY_DESCRIPTOR)lpSecurityAttributes);
 
-       Status = NtCreateKey (phkResult,
-                             samDesired,
-                             &Attributes,
-                             0,
-                             (lpClass == NULL)? NULL : &ClassString,
-                             dwOptions,
-                             (PULONG)lpdwDisposition);
-       DPRINT1("Status %x\n", Status);
-       if (!NT_SUCCESS(Status))
-       {
-               LONG ErrorCode = RtlNtStatusToDosError(Status);
+/************************************************************************
+ *  RegDeleteKeyW
+ */
+LONG
+STDCALL
+RegDeleteKeyW(
+  HKEY  hKey,
+  LPCWSTR lpSubKey)
+{
+  OBJECT_ATTRIBUTES ObjectAttributes;
+  UNICODE_STRING SubKeyString;
+  HKEY ParentKey;
+  HANDLE TargetKey;
+  NTSTATUS Status;
+  LONG ErrorCode;
+
+  Status = MapDefaultKey(&ParentKey, hKey);
+  if (!NT_SUCCESS(Status)) {
+    ErrorCode = RtlNtStatusToDosError(Status);
+    SetLastError (ErrorCode);
+    return ErrorCode;
+  }
+  RtlInitUnicodeString(&SubKeyString, (LPWSTR)lpSubKey);
+
+  InitializeObjectAttributes (&ObjectAttributes,
+            &SubKeyString,
+            OBJ_CASE_INSENSITIVE,
+            (HANDLE)ParentKey,
+            NULL);
+  Status = NtOpenKey(&TargetKey, DELETE, &ObjectAttributes);
+  if (!NT_SUCCESS(Status)) {
+    ErrorCode = RtlNtStatusToDosError(Status);
+    SetLastError (ErrorCode);
+    return ErrorCode;
+  }
+  Status = NtDeleteKey(TargetKey);
+  NtClose(TargetKey);
+  if (!NT_SUCCESS(Status)) {
+    ErrorCode = RtlNtStatusToDosError(Status);
+    SetLastError (ErrorCode);
+    return ErrorCode;
+  }
+  return ERROR_SUCCESS;
+}
 
-               SetLastError (ErrorCode);
-               return ErrorCode;
-       }
-       DPRINT1("Returned handle %x\n", (ULONG)*phkResult);
 
-       return ERROR_SUCCESS;
+/************************************************************************
+ *  RegDeleteValueA
+ */
+LONG
+STDCALL
+RegDeleteValueA(
+  HKEY  hKey,
+  LPCSTR  lpValueName)
+{
+  UNICODE_STRING ValueNameW;
+  ANSI_STRING ValueNameA;
+  NTSTATUS Status;
+  LONG ErrorCode;
+  HKEY KeyHandle;
+
+  Status = MapDefaultKey(&KeyHandle, hKey);
+  if (!NT_SUCCESS(Status)) {
+    ErrorCode = RtlNtStatusToDosError(Status);
+    SetLastError (ErrorCode);
+    return ErrorCode;
+  }
+  RtlInitAnsiString(&ValueNameA, (LPSTR)lpValueName);
+  RtlAnsiStringToUnicodeString(&ValueNameW, &ValueNameA, TRUE);
+  Status = NtDeleteValueKey(KeyHandle, &ValueNameW);
+  RtlFreeUnicodeString (&ValueNameW);
+  if (!NT_SUCCESS(Status)) {
+    ErrorCode = RtlNtStatusToDosError(Status);
+    SetLastError (ErrorCode);
+    return ErrorCode;
+  }
+  return ERROR_SUCCESS;
 }
 
 
 /************************************************************************
- *     RegDeleteKeyA
+ *  RegDeleteValueW
  */
 LONG
 STDCALL
-RegDeleteKeyA(
-       HKEY    hKey,
-       LPCSTR  lpSubKey
-       )
+RegDeleteValueW(
+  HKEY  hKey,
+  LPCWSTR lpValueName)
 {
-       SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-       return ERROR_CALL_NOT_IMPLEMENTED;
+  UNICODE_STRING ValueName;
+  NTSTATUS Status;
+  LONG ErrorCode;
+  HKEY KeyHandle;
+
+  Status = MapDefaultKey(&KeyHandle, hKey);
+  if (!NT_SUCCESS(Status))
+  {
+    ErrorCode = RtlNtStatusToDosError(Status);
+    SetLastError (ErrorCode);
+    return ErrorCode;
+  }
+  RtlInitUnicodeString(&ValueName, (LPWSTR)lpValueName);
+  Status = NtDeleteValueKey(KeyHandle, &ValueName);
+  if (!NT_SUCCESS(Status)) {
+    ErrorCode = RtlNtStatusToDosError(Status);
+    SetLastError (ErrorCode);
+    return ErrorCode;
+  }
+  return ERROR_SUCCESS;
 }
 
 
 /************************************************************************
- *     RegDeleteKeyW
+ *  RegEnumKeyExW
  */
 LONG
 STDCALL
-RegDeleteKeyW(
-       HKEY    hKey,
-       LPCWSTR lpSubKey
-       )
+RegEnumKeyExW(
+  HKEY    hKey,
+  DWORD   dwIndex,
+  LPWSTR    lpName,
+  LPDWORD   lpcbName,
+  LPDWORD   lpReserved,
+  LPWSTR    lpClass,
+  LPDWORD   lpcbClass,
+  PFILETIME lpftLastWriteTime)
 {
-       SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-       return ERROR_CALL_NOT_IMPLEMENTED;
+    PKEY_NODE_INFORMATION KeyInfo;
+  NTSTATUS Status;
+  DWORD dwError = ERROR_SUCCESS;
+  ULONG BufferSize;
+  ULONG ResultSize;
+  HKEY KeyHandle;
+
+  Status = MapDefaultKey(&KeyHandle, hKey);
+  if (!NT_SUCCESS(Status)) {
+    dwError = RtlNtStatusToDosError(Status);
+    SetLastError (dwError);
+    return dwError;
+  }
+
+  BufferSize = sizeof (KEY_NODE_INFORMATION) + *lpcbName * sizeof(WCHAR);
+  if (lpClass)
+    BufferSize += *lpcbClass;
+
+    //
+    // I think this is a memory leak, always allocated again below ???
+    //
+    // KeyInfo = RtlAllocateHeap(RtlGetProcessHeap(), 0, BufferSize);
+    //
+
+  /* We don't know the exact size of the data returned, so call
+     NtEnumerateKey() with a buffer size determined from parameters
+     to this function. If that call fails with a status code of
+     STATUS_BUFFER_OVERFLOW, allocate a new buffer and try again */
+  while (TRUE) {
+    KeyInfo = RtlAllocateHeap(RtlGetProcessHeap(), 0, BufferSize);
+    if (KeyInfo == NULL) {
+      SetLastError(ERROR_OUTOFMEMORY);
+      return ERROR_OUTOFMEMORY;
+    }
+    Status = NtEnumerateKey(
+      KeyHandle,
+      (ULONG)dwIndex,
+      KeyNodeInformation,
+      KeyInfo,
+      BufferSize,
+      &ResultSize);
+
+    DPRINT("NtEnumerateKey() returned status 0x%X\n", Status);
+
+    if (Status == STATUS_BUFFER_OVERFLOW) {
+      RtlFreeHeap(RtlGetProcessHeap(), 0, KeyInfo);
+      BufferSize = ResultSize;
+      continue;
+    }
+    if (!NT_SUCCESS(Status)) {
+      dwError = RtlNtStatusToDosError(Status);
+      SetLastError(dwError);
+      break;
+    } else {
+      if ((lpClass) && (*lpcbClass != 0) && (KeyInfo->ClassLength > *lpcbClass)) {
+        dwError = ERROR_MORE_DATA;
+        SetLastError(dwError);
+        break;
+      }
+      RtlMoveMemory(lpName, KeyInfo->Name, KeyInfo->NameLength);
+      *lpcbName = (DWORD)(KeyInfo->NameLength / sizeof(WCHAR));
+      RegiTerminateWideString(lpName, *lpcbName);
+      if (lpClass) {
+        RtlMoveMemory(lpClass,
+          (PVOID)((ULONG_PTR)KeyInfo->Name + KeyInfo->ClassOffset),
+          KeyInfo->ClassLength);
+        *lpcbClass = (DWORD)(KeyInfo->ClassLength / sizeof(WCHAR));
+      }
+      if (lpftLastWriteTime) {
+        /* FIXME: Fill lpftLastWriteTime */
+      }
+      break;
+    }
+  }
+  RtlFreeHeap (RtlGetProcessHeap(), 0, KeyInfo);
+  return dwError;
 }
 
 
 /************************************************************************
- *     RegDeleteValueA
+ *  RegEnumKeyW
  */
 LONG
 STDCALL
-RegDeleteValueA(
-       HKEY    hKey,
-       LPCSTR  lpValueName
-       )
+RegEnumKeyW(
+  HKEY  hKey,
+  DWORD dwIndex,
+  LPWSTR  lpName,
+  DWORD cbName)
 {
-       SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-       return ERROR_CALL_NOT_IMPLEMENTED;
+  DWORD dwLength = cbName;
+
+  return RegEnumKeyExW(hKey,
+           dwIndex,
+           lpName,
+           &dwLength,
+           NULL,
+           NULL,
+           NULL,
+           NULL);
 }
 
 
 /************************************************************************
- *     RegDeleteValueW
+ *  RegEnumKeyExA
  */
 LONG
 STDCALL
-RegDeleteValueW(
-       HKEY    hKey,
-       LPCWSTR lpValueName
-       )
+RegEnumKeyExA(
+  HKEY    hKey,
+  DWORD   dwIndex,
+  LPSTR   lpName,
+  LPDWORD   lpcbName,
+  LPDWORD   lpReserved,
+  LPSTR   lpClass,
+  LPDWORD   lpcbClass,
+  PFILETIME lpftLastWriteTime)
 {
-       SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-       return ERROR_CALL_NOT_IMPLEMENTED;
+  WCHAR Name[MAX_PATH+1];
+  UNICODE_STRING UnicodeStringName;
+  WCHAR Class[MAX_PATH+1];
+  UNICODE_STRING UnicodeStringClass;
+  ANSI_STRING AnsiString;
+  LONG ErrorCode;
+  DWORD NameLength;
+  DWORD ClassLength;
+
+  DPRINT("hKey 0x%x  dwIndex %d  lpName 0x%x  *lpcbName %d  lpClass 0x%x  lpcbClass %d\n",
+    hKey, dwIndex, lpName, *lpcbName, lpClass, lpcbClass);
+
+  if ((lpClass) && (!lpcbClass)) {
+    SetLastError(ERROR_INVALID_PARAMETER);
+    return ERROR_INVALID_PARAMETER;
+  }
+  RtlInitUnicodeString(&UnicodeStringName, NULL);
+  UnicodeStringName.Buffer = &Name[0];
+  UnicodeStringName.MaximumLength = sizeof(Name);
+  RtlInitUnicodeString(&UnicodeStringClass, NULL);
+  if (lpClass) {
+    UnicodeStringClass.Buffer = &Class[0];
+    UnicodeStringClass.MaximumLength = sizeof(Class);
+    ClassLength = *lpcbClass;
+  } else {
+    ClassLength = 0;
+  }
+  NameLength = *lpcbName;
+  ErrorCode = RegEnumKeyExW(
+    hKey,
+    dwIndex,
+    UnicodeStringName.Buffer,
+    &NameLength,
+    lpReserved,
+    UnicodeStringClass.Buffer,
+    &ClassLength,
+    lpftLastWriteTime);
+
+  if (ErrorCode != ERROR_SUCCESS)
+    return ErrorCode;
+
+  UnicodeStringName.Length = NameLength * sizeof(WCHAR);
+  UnicodeStringClass.Length = ClassLength * sizeof(WCHAR);
+  RtlInitAnsiString(&AnsiString, NULL);
+  AnsiString.Buffer = lpName;
+  AnsiString.MaximumLength = *lpcbName;
+  RtlUnicodeStringToAnsiString(&AnsiString, &UnicodeStringName, FALSE);
+  *lpcbName = AnsiString.Length;
+
+  DPRINT("Key Namea0 Length %d\n", UnicodeStringName.Length);
+  DPRINT("Key Namea1 Length %d\n", NameLength);
+  DPRINT("Key Namea Length %d\n", *lpcbName);
+  DPRINT("Key Namea %s\n", lpName);
+
+  if (lpClass) {
+    RtlInitAnsiString(&AnsiString, NULL);
+    AnsiString.Buffer = lpClass;
+    AnsiString.MaximumLength = *lpcbClass;
+    RtlUnicodeStringToAnsiString(&AnsiString, &UnicodeStringClass, FALSE);
+    *lpcbClass = AnsiString.Length;
+  }
+  return ERROR_SUCCESS;
 }
 
 
 /************************************************************************
- *     RegEnumKeyA
+ *  RegEnumKeyA
  */
 LONG
 STDCALL
 RegEnumKeyA(
-       HKEY    hKey,
-       DWORD   dwIndex,
-       LPSTR   lpName,
-       DWORD   cbName
-       )
+  HKEY  hKey,
+  DWORD dwIndex,
+  LPSTR lpName,
+  DWORD cbName)
 {
-       SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-       return ERROR_CALL_NOT_IMPLEMENTED;
+  DWORD dwLength = cbName;
+
+  return RegEnumKeyExA(hKey,
+           dwIndex,
+           lpName,
+           &dwLength,
+           NULL,
+           NULL,
+           NULL,
+           NULL);
 }
 
 
 /************************************************************************
- *     RegEnumKeyExA
+ *  RegEnumValueW
  */
 LONG
 STDCALL
-RegEnumKeyExA(
-       HKEY            hKey,
-       DWORD           dwIndex,
-       LPSTR           lpName,
-       LPDWORD         lpcbName,
-       LPDWORD         lpReserved,
-       LPSTR           lpClass,
-       LPDWORD         lpcbClass,
-       PFILETIME       lpftLastWriteTime
-       )
+RegEnumValueW(
+  HKEY  hKey,
+  DWORD dwIndex,
+  LPWSTR  lpValueName,
+  LPDWORD lpcbValueName,
+  LPDWORD lpReserved,
+  LPDWORD lpType,
+  LPBYTE  lpData,
+  LPDWORD lpcbData)
 {
-       SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-       return ERROR_CALL_NOT_IMPLEMENTED;
+  PKEY_VALUE_FULL_INFORMATION ValueInfo;
+  NTSTATUS Status;
+  DWORD dwError = ERROR_SUCCESS;
+  ULONG BufferSize;
+  ULONG ResultSize;
+  HKEY KeyHandle;
+
+  Status = MapDefaultKey(&KeyHandle, hKey);
+  if (!NT_SUCCESS(Status)) {
+      dwError = RtlNtStatusToDosError(Status);
+      SetLastError(dwError);
+      return(dwError);
+  }
+  BufferSize = sizeof (KEY_VALUE_FULL_INFORMATION) + *lpcbValueName * sizeof(WCHAR);
+  if (lpcbData)
+    BufferSize += *lpcbData;
+
+  /* We don't know the exact size of the data returned, so call
+     NtEnumerateValueKey() with a buffer size determined from parameters
+     to this function. If that call fails with a status code of
+     STATUS_BUFFER_OVERFLOW, allocate a new buffer and try again */
+  while (TRUE) {
+    ValueInfo = RtlAllocateHeap(RtlGetProcessHeap(), 0, BufferSize);
+    if (ValueInfo == NULL) {
+      SetLastError(ERROR_OUTOFMEMORY);
+      return ERROR_OUTOFMEMORY;
+    }
+    Status = NtEnumerateValueKey(
+    KeyHandle,
+      (ULONG)dwIndex,
+      KeyValueFullInformation,
+      ValueInfo,
+      BufferSize,
+      &ResultSize);
+
+    DPRINT("NtEnumerateValueKey() returned status 0x%X\n", Status);
+
+    if (Status == STATUS_BUFFER_OVERFLOW) {
+      RtlFreeHeap(RtlGetProcessHeap(), 0, ValueInfo);
+      BufferSize = ResultSize;
+      continue;
+    }
+    if (!NT_SUCCESS(Status)) {
+      dwError = RtlNtStatusToDosError(Status);
+      SetLastError(dwError);
+      break;
+    } else {
+      if ((lpData) && (*lpcbData != 0) && (ValueInfo->DataLength > *lpcbData)) {
+        dwError = ERROR_MORE_DATA;
+        SetLastError(dwError);
+        break;
+      }
+      memcpy(lpValueName, ValueInfo->Name, ValueInfo->NameLength);
+      *lpcbValueName = (DWORD)(ValueInfo->NameLength / sizeof(WCHAR));
+      RegiTerminateWideString(lpValueName, *lpcbValueName);
+      if (lpType)
+        *lpType = ValueInfo->Type;
+      if (lpData) {
+        memcpy(lpData,
+          //(PVOID)((ULONG_PTR)ValueInfo->Name + ValueInfo->DataOffset),
+          (PVOID)((ULONG_PTR)ValueInfo + ValueInfo->DataOffset),
+          ValueInfo->DataLength);
+        *lpcbData = (DWORD)ValueInfo->DataLength;
+/*
+                  RtlCopyMemory((PCHAR) ValueFullInformation + ValueFullInformation->DataOffset,
+                    DataCell->Data,
+                    ValueCell->DataSize & LONG_MAX);
+ */
+        }
+      break;
+    }
+  }
+  RtlFreeHeap (RtlGetProcessHeap(), 0, ValueInfo);
+  return dwError;
 }
 
 
 /************************************************************************
- *     RegEnumValueA
+ *  RegEnumValueA
  */
 LONG
 STDCALL
 RegEnumValueA(
-       HKEY    hKey,
-       DWORD   dwIndex,
-       LPSTR   lpValueName,
-       LPDWORD lpcbValueName,
-       LPDWORD lpReserved,
-       LPDWORD lpType,
-       LPBYTE  lpData,
-       LPDWORD lpcbData
-       )
+  HKEY  hKey,
+  DWORD dwIndex,
+  LPSTR lpValueName,
+  LPDWORD lpcbValueName,
+  LPDWORD lpReserved,
+  LPDWORD lpType,
+  LPBYTE  lpData,
+  LPDWORD lpcbData)
 {
-       SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-       return ERROR_CALL_NOT_IMPLEMENTED;
+  WCHAR ValueName[MAX_PATH+1];
+  UNICODE_STRING UnicodeString;
+  ANSI_STRING AnsiString;
+  LONG ErrorCode;
+  DWORD ValueNameLength;
+  BYTE* lpDataBuffer = NULL;
+  DWORD cbData = 0;
+  DWORD Type;
+  ANSI_STRING AnsiDataString;
+  UNICODE_STRING UnicodeDataString;
+
+  if (lpData != NULL /*&& lpcbData != NULL*/) {
+    cbData = *lpcbData; // this should always be valid if lpData is valid
+    lpDataBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, (*lpcbData) * sizeof(WCHAR));
+    if (lpDataBuffer == NULL) {
+      SetLastError(ERROR_OUTOFMEMORY);
+      return ERROR_OUTOFMEMORY;
+    }
+  }
+  RtlInitUnicodeString(&UnicodeString, NULL);
+  UnicodeString.Buffer = &ValueName[0];
+  UnicodeString.MaximumLength = sizeof(ValueName);
+  ValueNameLength = *lpcbValueName;
+  ErrorCode = RegEnumValueW(
+    hKey,
+    dwIndex,
+    UnicodeString.Buffer,
+    &ValueNameLength,
+    lpReserved,
+    &Type,
+    lpDataBuffer,
+    &cbData);
+  if (ErrorCode != ERROR_SUCCESS)
+    return ErrorCode;
+  UnicodeString.Length = ValueNameLength * sizeof(WCHAR);
+  RtlInitAnsiString(&AnsiString, NULL);
+  AnsiString.Buffer = lpValueName;
+  AnsiString.MaximumLength = *lpcbValueName;
+  RtlUnicodeStringToAnsiString(&AnsiString, &UnicodeString, FALSE);
+  *lpcbValueName = AnsiString.Length;
+//  if (lpData != lpDataBuffer) { // did we use a temp buffer
+  if (lpDataBuffer) { // did we use a temp buffer
+      if ((Type == REG_SZ) || (Type == REG_MULTI_SZ) || (Type == REG_EXPAND_SZ)) {
+          RtlInitUnicodeString(&UnicodeDataString, NULL);
+          UnicodeDataString.Buffer = (WCHAR*)lpDataBuffer;
+          UnicodeDataString.MaximumLength = (*lpcbData) * sizeof(WCHAR);
+          UnicodeDataString.Length = cbData /* * sizeof(WCHAR)*/;
+          RtlInitAnsiString(&AnsiDataString, NULL);
+          AnsiDataString.Buffer = lpData;
+          AnsiDataString.MaximumLength = *lpcbData;
+          RtlUnicodeStringToAnsiString(&AnsiDataString, &UnicodeDataString, FALSE);
+          *lpcbData = AnsiDataString.Length;
+//      else if (Type == REG_EXPAND_SZ) {
+      } else {
+          memcpy(lpData, lpDataBuffer, min(*lpcbData, cbData));
+          *lpcbData = cbData;
+      }
+      RtlFreeHeap(RtlGetProcessHeap(), 0, lpDataBuffer);
+  }
+  if (lpType != NULL) {
+    *lpType = Type;
+  }
+  return ERROR_SUCCESS;
 }
 
 
 /************************************************************************
- *     RegFlushKey
+ *  RegFlushKey
  */
-LONG
-STDCALL
-RegFlushKey(
-       HKEY    hKey
-       )
+LONG STDCALL
+RegFlushKey(HKEY hKey)
 {
-       SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-       return ERROR_CALL_NOT_IMPLEMENTED;
+  HKEY KeyHandle;
+  NTSTATUS Status;
+  LONG ErrorCode;
+  
+  if (hKey == HKEY_PERFORMANCE_DATA)
+    return(ERROR_SUCCESS);
+  Status = MapDefaultKey(&KeyHandle, hKey);
+  if (!NT_SUCCESS(Status)) {
+      ErrorCode = RtlNtStatusToDosError(Status);
+      SetLastError(ErrorCode);
+      return(ErrorCode);
+  }
+  Status = NtFlushKey(KeyHandle);
+  if (!NT_SUCCESS(Status)) {
+      ErrorCode = RtlNtStatusToDosError(Status);
+      SetLastError(ErrorCode);
+      return(ErrorCode);
+  }
+  return(ERROR_SUCCESS);
 }
 
 
 /************************************************************************
- *     RegGetKeySecurity
+ *  RegGetKeySecurity
  */
-#if 0
 LONG
 STDCALL
-RegGetKeySecurity (
-       HKEY                    hKey,
-       SECURITY_INFORMATION    SecurityInformation,    /* FIXME: ULONG ? */
-       PSECURITY_DESCRIPTOR    pSecurityDescriptor,
-       LPDWORD                 lpcbSecurityDescriptor
-       )
+RegGetKeySecurity(
+  HKEY      hKey,
+  SECURITY_INFORMATION  SecurityInformation,
+  PSECURITY_DESCRIPTOR  pSecurityDescriptor,
+  LPDWORD     lpcbSecurityDescriptor)
 {
-       SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-       return ERROR_CALL_NOT_IMPLEMENTED;
+  UNIMPLEMENTED;
+  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+  return ERROR_CALL_NOT_IMPLEMENTED;
 }
-#endif
 
 
 /************************************************************************
- *     RegLoadKeyA
+ *  RegLoadKeyA
  */
 LONG
 STDCALL
-RegLoadKey(
-       HKEY    hKey,
-       LPCSTR  lpSubKey,
-       LPCSTR  lpFile
-       )
+RegLoadKeyA(
+  HKEY  hKey,
+  LPCSTR  lpSubKey,
+  LPCSTR  lpFile)
 {
-       SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-       return ERROR_CALL_NOT_IMPLEMENTED;
+  UNIMPLEMENTED;
+  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+  return ERROR_CALL_NOT_IMPLEMENTED;
 }
 
 
 /************************************************************************
- *     RegLoadKeyW
+ *  RegLoadKeyW
  */
 LONG
 STDCALL
 RegLoadKeyW(
-       HKEY    hKey,
-       LPCWSTR lpSubKey,
-       LPCWSTR lpFile
-       )
+  HKEY  hKey,
+  LPCWSTR lpSubKey,
+  LPCWSTR lpFile)
 {
-       SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-       return ERROR_CALL_NOT_IMPLEMENTED;
+  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+  return ERROR_CALL_NOT_IMPLEMENTED;
 }
 
 
 /************************************************************************
- *     RegNotifyChangeKeyValue
+ *  RegNotifyChangeKeyValue
  */
 LONG
 STDCALL
 RegNotifyChangeKeyValue(
-       HKEY    hKey,
-       BOOL    bWatchSubtree,
-       DWORD   dwNotifyFilter,
-       HANDLE  hEvent,
-       BOOL    fAsynchronous
-       )
+  HKEY  hKey,
+  BOOL  bWatchSubtree,
+  DWORD dwNotifyFilter,
+  HANDLE  hEvent,
+  BOOL  fAsynchronous)
 {
-       SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-       return ERROR_CALL_NOT_IMPLEMENTED;
+  UNIMPLEMENTED;
+  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+  return ERROR_CALL_NOT_IMPLEMENTED;
 }
 
 
 
 /************************************************************************
- *     RegOpenKeyA
+ *  RegOpenKeyA
  */
-LONG
-STDCALL
-RegOpenKeyA(
-       HKEY    hKey,
-       LPCSTR  lpSubKey,
-       PHKEY   phkResult
-       )
+LONG STDCALL
+RegOpenKeyA(HKEY hKey,
+      LPCSTR lpSubKey,
+      PHKEY phkResult)
 {
-       SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-       return ERROR_CALL_NOT_IMPLEMENTED;
+  OBJECT_ATTRIBUTES ObjectAttributes;
+  UNICODE_STRING SubKeyString;
+  HKEY KeyHandle;
+  LONG ErrorCode;
+  NTSTATUS Status;
+
+  Status = MapDefaultKey(&KeyHandle, hKey);
+  if (!NT_SUCCESS(Status)) {
+      ErrorCode = RtlNtStatusToDosError(Status);
+      SetLastError(ErrorCode);
+      return(ErrorCode);
+  }
+  RtlCreateUnicodeStringFromAsciiz(&SubKeyString, (LPSTR)lpSubKey);
+  InitializeObjectAttributes(&ObjectAttributes,
+           &SubKeyString,
+           OBJ_CASE_INSENSITIVE,
+           KeyHandle,
+           NULL);
+  Status = NtOpenKey(phkResult, KEY_ALL_ACCESS, &ObjectAttributes);
+  RtlFreeUnicodeString(&SubKeyString);
+  if (!NT_SUCCESS(Status)) {
+      ErrorCode = RtlNtStatusToDosError(Status);
+      SetLastError(ErrorCode);
+      return(ErrorCode);
+  }
+  return(ERROR_SUCCESS);
 }
 
 
 /************************************************************************
- *     RegOpenKeyW
+ *  RegOpenKeyW
  *
- *     19981101 Ariadne
- *     19990525 EA
+ *  19981101 Ariadne
+ *  19990525 EA
  */
 LONG
 STDCALL
-RegOpenKeyW (
-       HKEY    hKey,
-       LPCWSTR lpSubKey,
-       PHKEY   phkResult
-       )
+RegOpenKeyW(
+  HKEY  hKey,
+  LPCWSTR lpSubKey,
+  PHKEY phkResult)
 {
-       NTSTATUS                errCode;
-       UNICODE_STRING          SubKeyString;
-       OBJECT_ATTRIBUTES       ObjectAttributes;
+  NTSTATUS    errCode;
+  UNICODE_STRING    SubKeyString;
+  OBJECT_ATTRIBUTES ObjectAttributes;
+  HKEY      KeyHandle;
+  LONG      ErrorCode;
+
+  errCode = MapDefaultKey(&KeyHandle, hKey);
+  if (!NT_SUCCESS(errCode)) {
+    ErrorCode = RtlNtStatusToDosError(errCode);
+    SetLastError (ErrorCode);
+    return ErrorCode;
+  }
+  RtlInitUnicodeString(&SubKeyString, (LPWSTR)lpSubKey);
+  InitializeObjectAttributes(&ObjectAttributes,
+           &SubKeyString,
+           OBJ_CASE_INSENSITIVE,
+           KeyHandle,
+           NULL);
+  errCode = NtOpenKey(phkResult, KEY_ALL_ACCESS, &ObjectAttributes);
+  if (!NT_SUCCESS(errCode)) {
+    ErrorCode = RtlNtStatusToDosError(errCode);
+    SetLastError(ErrorCode);
+    return ErrorCode;
+  }
+  return ERROR_SUCCESS;
+}
 
-       SubKeyString.Buffer = (LPWSTR)lpSubKey;
-       SubKeyString.Length = wcslen(SubKeyString.Buffer);
-       SubKeyString.MaximumLength = SubKeyString.Length;
 
-       ObjectAttributes.RootDirectory =  hKey;
-       ObjectAttributes.ObjectName = & SubKeyString;
-       ObjectAttributes.Attributes = OBJ_CASE_INSENSITIVE; 
-       errCode = NtOpenKey(
-                       phkResult,
-                       GENERIC_ALL,
-                       & ObjectAttributes
-                       );
-       if ( !NT_SUCCESS(errCode) )
-       {
-               LONG LastError = RtlNtStatusToDosError(errCode);
-               
-               SetLastError(LastError);
-               return LastError;
-       }
-       return ERROR_SUCCESS;
+/************************************************************************
+ *  RegOpenKeyExA
+ */
+LONG STDCALL
+RegOpenKeyExA(HKEY hKey,
+        LPCSTR lpSubKey,
+        DWORD ulOptions,
+        REGSAM samDesired,
+        PHKEY phkResult)
+{
+  OBJECT_ATTRIBUTES ObjectAttributes;
+  UNICODE_STRING SubKeyString;
+  HKEY KeyHandle;
+  LONG ErrorCode;
+  NTSTATUS Status;
+
+  Status = MapDefaultKey(&KeyHandle, hKey);
+  if (!NT_SUCCESS(Status)) {
+      ErrorCode = RtlNtStatusToDosError(Status);
+      SetLastError(ErrorCode);
+      return(ErrorCode);
+  }
+  RtlCreateUnicodeStringFromAsciiz(&SubKeyString, (LPSTR)lpSubKey);
+  InitializeObjectAttributes(&ObjectAttributes,
+           &SubKeyString,
+           OBJ_CASE_INSENSITIVE,
+           KeyHandle,
+           NULL);
+  Status = NtOpenKey(phkResult, samDesired, &ObjectAttributes);
+  RtlFreeUnicodeString(&SubKeyString);
+  if (!NT_SUCCESS(Status)) {
+      ErrorCode = RtlNtStatusToDosError(Status);
+      SetLastError(ErrorCode);
+      return(ErrorCode);
+  }
+  return(ERROR_SUCCESS);
 }
 
 
 /************************************************************************
- *     RegOpenKeyExA
+ *  RegOpenKeyExW
  */
-LONG
-STDCALL
-RegOpenKeyExA(
-       HKEY    hKey,
-       LPCSTR  lpSubKey,
-       DWORD   ulOptions,
-       REGSAM  samDesired,
-       PHKEY   phkResult
-       )
+LONG STDCALL
+RegOpenKeyExW(HKEY hKey,
+        LPCWSTR lpSubKey,
+        DWORD ulOptions,
+        REGSAM samDesired,
+        PHKEY phkResult)
 {
-       SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-       return ERROR_CALL_NOT_IMPLEMENTED;
+  OBJECT_ATTRIBUTES ObjectAttributes;
+  UNICODE_STRING SubKeyString;
+  HKEY KeyHandle;
+  LONG ErrorCode;
+  NTSTATUS Status;
+
+  Status = MapDefaultKey(&KeyHandle, hKey);
+  if (!NT_SUCCESS(Status)) {
+      ErrorCode = RtlNtStatusToDosError(Status);
+      SetLastError (ErrorCode);
+      return(ErrorCode);
+  }
+  if (lpSubKey != NULL) {
+      RtlInitUnicodeString(&SubKeyString, (LPWSTR)lpSubKey);
+  } else {
+      RtlInitUnicodeString(&SubKeyString, (LPWSTR)L"");
+  }
+  InitializeObjectAttributes(&ObjectAttributes,
+           &SubKeyString,
+           OBJ_CASE_INSENSITIVE,
+           KeyHandle,
+           NULL);
+  Status = NtOpenKey(phkResult, samDesired, &ObjectAttributes);
+  if (!NT_SUCCESS(Status)) {
+      ErrorCode = RtlNtStatusToDosError(Status);
+      SetLastError(ErrorCode);
+      return(ErrorCode);
+  }
+  return(ERROR_SUCCESS);
 }
 
 
 /************************************************************************
- *     RegOpenKeyExW
+ *  RegQueryInfoKeyW
  */
 LONG
 STDCALL
-RegOpenKeyExW(
-       HKEY    hKey,
-       LPCWSTR lpSubKey,
-       DWORD   ulOptions,
-       REGSAM  samDesired,
-       PHKEY   phkResult
-       )
+RegQueryInfoKeyW(
+  HKEY    hKey,
+  LPWSTR    lpClass,
+  LPDWORD   lpcbClass,
+  LPDWORD   lpReserved,
+  LPDWORD   lpcSubKeys,
+  LPDWORD   lpcbMaxSubKeyLen,
+  LPDWORD   lpcbMaxClassLen,
+  LPDWORD   lpcValues,
+  LPDWORD   lpcbMaxValueNameLen,
+  LPDWORD   lpcbMaxValueLen,
+  LPDWORD   lpcbSecurityDescriptor,
+  PFILETIME lpftLastWriteTime)
 {
-       SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-       return ERROR_CALL_NOT_IMPLEMENTED;
+  KEY_FULL_INFORMATION FullInfoBuffer;
+  PKEY_FULL_INFORMATION FullInfo;
+  ULONG FullInfoSize;
+  HKEY KeyHandle;
+  NTSTATUS Status;
+  LONG ErrorCode;
+  ULONG Length;
+
+  if ((lpClass) && (!lpcbClass)) {
+    SetLastError(ERROR_INVALID_PARAMETER);
+    return ERROR_INVALID_PARAMETER;
+  }
+
+  Status = MapDefaultKey(&KeyHandle, hKey);
+  CHECK_STATUS;
+
+  if (lpClass) {
+    FullInfoSize = sizeof(KEY_FULL_INFORMATION) + *lpcbClass;
+    FullInfo = RtlAllocateHeap(RtlGetProcessHeap(), 0, FullInfoSize);
+    if (!FullInfo) {
+      SetLastError(ERROR_OUTOFMEMORY);
+      return ERROR_OUTOFMEMORY;
+    }
+    FullInfo->ClassLength = *lpcbClass;
+  } else {
+    FullInfoSize = sizeof(KEY_FULL_INFORMATION);
+    FullInfo = &FullInfoBuffer;
+    FullInfo->ClassLength = 1;
+  }
+  FullInfo->ClassOffset = FIELD_OFFSET(KEY_FULL_INFORMATION, Class);
+  Status = NtQueryKey(
+    KeyHandle,
+    KeyFullInformation,
+    FullInfo,
+    FullInfoSize,
+    &Length);
+  if (!NT_SUCCESS(Status)) {
+    if (lpClass) {
+      RtlFreeHeap(RtlGetProcessHeap(), 0, FullInfo);
+    }
+    ErrorCode = RtlNtStatusToDosError(Status);
+    SetLastError(ErrorCode);
+    return ErrorCode;
+  }
+  if (lpcSubKeys) {
+    *lpcSubKeys = FullInfo->SubKeys;
+  }
+  if (lpcbMaxSubKeyLen) {
+    *lpcbMaxSubKeyLen = FullInfo->MaxNameLen;
+  }
+  if (lpcbMaxClassLen) {
+    *lpcbMaxClassLen = FullInfo->MaxClassLen;
+  }
+  if (lpcValues) {
+    *lpcValues = FullInfo->Values;
+  }
+  if (lpcbMaxValueNameLen) {
+    *lpcbMaxValueNameLen = FullInfo->MaxValueNameLen;
+  }
+  if (lpcbMaxValueLen) {
+    *lpcbMaxValueLen = FullInfo->MaxValueDataLen;
+  }
+  if (lpcbSecurityDescriptor) {
+    *lpcbSecurityDescriptor = 0;
+    /* FIXME */
+  }
+  if (lpftLastWriteTime != NULL) {
+    lpftLastWriteTime->dwLowDateTime = FullInfo->LastWriteTime.u.LowPart;
+    lpftLastWriteTime->dwHighDateTime = FullInfo->LastWriteTime.u.HighPart;
+  }
+  if (lpClass) {
+    wcsncpy(lpClass, FullInfo->Class, *lpcbClass);
+    RtlFreeHeap(RtlGetProcessHeap(), 0, FullInfo);
+  }
+  SetLastError(ERROR_SUCCESS);
+  return ERROR_SUCCESS;
 }
 
 
 /************************************************************************
- *     RegQueryInfoKeyA
+ *  RegQueryInfoKeyA
  */
 LONG
 STDCALL
 RegQueryInfoKeyA(
-       HKEY            hKey,
-       LPSTR           lpClass,
-       LPDWORD         lpcbClass,
-       LPDWORD         lpReserved,
-       LPDWORD         lpcSubKeys,
-       LPDWORD         lpcbMaxSubKeyLen,
-       LPDWORD         lpcbMaxClassLen,
-       LPDWORD         lpcValues,
-       LPDWORD         lpcbMaxValueNameLen,
-       LPDWORD         lpcbMaxValueLen,
-       LPDWORD         lpcbSecurityDescriptor,
-       PFILETIME       lpftLastWriteTime
-       )
+  HKEY    hKey,
+  LPSTR   lpClass,
+  LPDWORD   lpcbClass,
+  LPDWORD   lpReserved,
+  LPDWORD   lpcSubKeys,
+  LPDWORD   lpcbMaxSubKeyLen,
+  LPDWORD   lpcbMaxClassLen,
+  LPDWORD   lpcValues,
+  LPDWORD   lpcbMaxValueNameLen,
+  LPDWORD   lpcbMaxValueLen,
+  LPDWORD   lpcbSecurityDescriptor,
+  PFILETIME lpftLastWriteTime)
 {
-       SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-       return ERROR_CALL_NOT_IMPLEMENTED;
+  WCHAR ClassName[MAX_PATH];
+  UNICODE_STRING UnicodeString;
+  ANSI_STRING AnsiString;
+  LONG ErrorCode;
+
+  RtlInitUnicodeString(&UnicodeString, NULL);
+  if (lpClass) {
+    UnicodeString.Buffer = &ClassName[0];
+    UnicodeString.MaximumLength = sizeof(ClassName);
+  }
+  ErrorCode = RegQueryInfoKeyW(
+    hKey,
+    UnicodeString.Buffer,
+    lpcbClass,
+    lpReserved,
+    lpcSubKeys,
+    lpcbMaxSubKeyLen,
+    lpcbMaxClassLen,
+    lpcValues,
+    lpcbMaxValueNameLen,
+    lpcbMaxValueLen,
+    lpcbSecurityDescriptor,
+    lpftLastWriteTime);
+
+  if ((ErrorCode == ERROR_SUCCESS) && (lpClass)) {
+    RtlInitAnsiString(&AnsiString, NULL);
+    AnsiString.Buffer = lpClass;
+    AnsiString.MaximumLength = *lpcbClass;
+    RtlUnicodeStringToAnsiString(&AnsiString, &UnicodeString, FALSE);
+    *lpcbClass = AnsiString.Length;
+  }
+  return ErrorCode;
 }
 
 
 /************************************************************************
- *     RegQueryInfoKeyW
+ *  RegQueryMultipleValuesA
  */
 LONG
 STDCALL
-RegQueryInfoKeyW(
-       HKEY            hKey,
-       LPWSTR          lpClass,
-       LPDWORD         lpcbClass,
-       LPDWORD         lpReserved,
-       LPDWORD         lpcSubKeys,
-       LPDWORD         lpcbMaxSubKeyLen,
-       LPDWORD         lpcbMaxClassLen,
-       LPDWORD         lpcValues,
-       LPDWORD         lpcbMaxValueNameLen,
-       LPDWORD         lpcbMaxValueLen,
-       LPDWORD         lpcbSecurityDescriptor,
-       PFILETIME       lpftLastWriteTime
-       )
+RegQueryMultipleValuesA(
+  HKEY   hKey,
+  PVALENTA val_list,
+  DWORD  num_vals,
+  LPSTR  lpValueBuf,
+  LPDWORD  ldwTotsize)
 {
-       SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-       return ERROR_CALL_NOT_IMPLEMENTED;
+  UNIMPLEMENTED;
+  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+  return ERROR_CALL_NOT_IMPLEMENTED;
 }
 
 
 /************************************************************************
- *     RegQueryMultipleValuesA
+ *  RegQueryMultipleValuesW
  */
 LONG
 STDCALL
-RegQueryMultipleValuesA(
-       HKEY    hKey,
-       PVALENT val_list,
-       DWORD   num_vals,
-       LPSTR   lpValueBuf,
-       LPDWORD ldwTotsize
-       )
+RegQueryMultipleValuesW(
+  HKEY   hKey,
+  PVALENTW val_list,
+  DWORD  num_vals,
+  LPWSTR   lpValueBuf,
+  LPDWORD  ldwTotsize)
 {
-       SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-       return ERROR_CALL_NOT_IMPLEMENTED;
+  UNIMPLEMENTED;
+  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+  return ERROR_CALL_NOT_IMPLEMENTED;
 }
 
 
 /************************************************************************
- *     RegQueryValueA
+ *  RegQueryValueExW
  */
 LONG
 STDCALL
-RegQueryValueA(
-       HKEY    hKey,
-       LPCSTR  lpSubKey,
-       LPSTR   lpValue,
-       PLONG   lpcbValue
-       )
+RegQueryValueExW(
+  HKEY  hKey,
+  LPCWSTR lpValueName,
+  LPDWORD lpReserved,
+  LPDWORD lpType,
+  LPBYTE  lpData,
+  LPDWORD lpcbData)
 {
-       SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-       return ERROR_CALL_NOT_IMPLEMENTED;
+  PKEY_VALUE_PARTIAL_INFORMATION ValueInfo;
+  UNICODE_STRING ValueName;
+  NTSTATUS Status;
+  DWORD dwError = ERROR_SUCCESS;
+  ULONG BufferSize;
+  ULONG ResultSize;
+  HKEY KeyHandle;
+
+  DPRINT("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)) {
+      dwError = RtlNtStatusToDosError(Status);
+      SetLastError(dwError);
+      return(dwError);
+  }
+  if ((lpData) && (!lpcbData)) {
+    SetLastError(ERROR_INVALID_PARAMETER);
+    return ERROR_INVALID_PARAMETER;
+  }
+  RtlInitUnicodeString (&ValueName, lpValueName);
+  BufferSize = sizeof (KEY_VALUE_PARTIAL_INFORMATION) + *lpcbData;
+  ValueInfo = RtlAllocateHeap (RtlGetProcessHeap(),
+             0,
+             BufferSize);
+  if (ValueInfo == NULL) {
+    SetLastError(ERROR_OUTOFMEMORY);
+    return ERROR_OUTOFMEMORY;
+  }
+  Status = NtQueryValueKey (hKey,
+          &ValueName,
+          KeyValuePartialInformation,
+          ValueInfo,
+          BufferSize,
+          &ResultSize);
+  DPRINT("Status 0x%X\n", Status);
+  if (Status == STATUS_BUFFER_TOO_SMALL) {
+    /* Return ERROR_SUCCESS and the buffer space needed for a successful call */
+    dwError = ERROR_SUCCESS;
+  }
+  else if (!NT_SUCCESS(Status)) {
+    dwError = RtlNtStatusToDosError(Status);
+    SetLastError(dwError);
+  }
+  else {
+    if (lpType) {
+      *lpType = ValueInfo->Type;
+    }
+    RtlMoveMemory(lpData, ValueInfo->Data, ValueInfo->DataLength);
+    if ((ValueInfo->Type == REG_SZ) ||
+        (ValueInfo->Type == REG_MULTI_SZ) ||
+        (ValueInfo->Type == REG_EXPAND_SZ)) {
+      ((PWSTR)lpData)[ValueInfo->DataLength / sizeof(WCHAR)] = 0;
+    }
+  }
+  DPRINT("Type %d  ResultSize %d\n", ValueInfo->Type, ResultSize);
+  *lpcbData = (DWORD)ResultSize;
+  RtlFreeHeap(RtlGetProcessHeap(), 0, ValueInfo);
+  return dwError;
 }
 
 
 /************************************************************************
- *     RegQueryValueExA
+ *  RegQueryValueExA
  */
 LONG
 STDCALL
 RegQueryValueExA(
-       HKEY    hKey,
-       LPSTR   lpValueName,
-       LPDWORD lpReserved,
-       LPDWORD lpType,
-       LPBYTE  lpData,
-       LPDWORD lpcbData
-       )
+  HKEY  hKey,
+  LPCSTR  lpValueName,
+  LPDWORD lpReserved,
+  LPDWORD lpType,
+  LPBYTE  lpData,
+  LPDWORD lpcbData)
 {
-       SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-       return ERROR_CALL_NOT_IMPLEMENTED;
+  WCHAR ValueNameBuffer[MAX_PATH+1];
+  UNICODE_STRING ValueName;
+  UNICODE_STRING ValueData;
+  ANSI_STRING AnsiString;
+  LONG ErrorCode;
+  DWORD ResultSize;
+  DWORD Type;
+
+  /* FIXME: HKEY_PERFORMANCE_DATA is special, see MS SDK */
+
+  if ((lpData) && (!lpcbData)) {
+    SetLastError(ERROR_INVALID_PARAMETER);
+    return ERROR_INVALID_PARAMETER;
+  }
+  RtlInitUnicodeString(&ValueData, NULL);
+  if (lpData) {
+    ValueData.MaximumLength = *lpcbData * sizeof(WCHAR);
+    ValueData.Buffer = RtlAllocateHeap(
+      RtlGetProcessHeap(),
+      0,
+      ValueData.MaximumLength);
+    if (!ValueData.Buffer) {
+      SetLastError(ERROR_OUTOFMEMORY);
+      return ERROR_OUTOFMEMORY;
+    }
+  }
+  RtlInitAnsiString(&AnsiString, (LPSTR)lpValueName);
+  RtlInitUnicodeString(&ValueName, NULL);
+  ValueName.Buffer = &ValueNameBuffer[0];
+  ValueName.MaximumLength = sizeof(ValueNameBuffer);
+  RtlAnsiStringToUnicodeString(&ValueName, &AnsiString, FALSE);
+  if (lpcbData) {
+    ResultSize = *lpcbData;
+  } else {
+    ResultSize = 0;
+  }
+  ErrorCode = RegQueryValueExW(
+    hKey,
+    ValueName.Buffer,
+    lpReserved,
+    &Type,
+    (LPBYTE)ValueData.Buffer,
+    &ResultSize);
+  if ((ErrorCode == ERROR_SUCCESS) && (ValueData.Buffer != NULL)) {
+    if (lpType) {
+      *lpType = Type;
+    }
+    if ((Type == REG_SZ) || (Type == REG_MULTI_SZ) || (Type == REG_EXPAND_SZ)) {
+      ValueData.Length = ResultSize;
+      RtlInitAnsiString(&AnsiString, NULL);
+      AnsiString.Buffer = lpData;
+      AnsiString.MaximumLength = *lpcbData;
+      RtlUnicodeStringToAnsiString(&AnsiString, &ValueData, FALSE);
+    } else {
+      RtlMoveMemory(lpData, ValueData.Buffer, ResultSize);
+    }
+  }
+  if (lpcbData) {
+    *lpcbData = ResultSize;
+  }
+  if (ValueData.Buffer) {
+    RtlFreeHeap(RtlGetProcessHeap(), 0, ValueData.Buffer);
+  }
+  return ErrorCode;
 }
 
 
 /************************************************************************
- *     RegQueryValueExW
+ *  RegQueryValueW
  */
 LONG
 STDCALL
-RegQueryValueExW(
-       HKEY    hKey,
-       LPWSTR  lpValueName,
-       LPDWORD lpReserved,
-       LPDWORD lpType,
-       LPBYTE  lpData,
-       LPDWORD lpcbData
-       )
+RegQueryValueW(
+  HKEY  hKey,
+  LPCWSTR lpSubKey,
+  LPWSTR  lpValue,
+  PLONG lpcbValue)
 {
-       SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-       return ERROR_CALL_NOT_IMPLEMENTED;
+  NTSTATUS    errCode;
+  UNICODE_STRING    SubKeyString;
+  OBJECT_ATTRIBUTES ObjectAttributes;
+  HKEY      KeyHandle;
+  HANDLE      RealKey;
+  LONG        ErrorCode;
+  BOOL        CloseRealKey;
+
+  errCode = MapDefaultKey(&KeyHandle, hKey);
+  if (!NT_SUCCESS(errCode)) {
+    ErrorCode = RtlNtStatusToDosError(errCode);
+    SetLastError (ErrorCode);
+    return ErrorCode;
+  }
+  if ((lpSubKey) && (wcslen(lpSubKey) != 0)) {
+    RtlInitUnicodeString(&SubKeyString, (LPWSTR)lpSubKey);
+    InitializeObjectAttributes(&ObjectAttributes,
+             &SubKeyString,
+             OBJ_CASE_INSENSITIVE,
+             KeyHandle,
+             NULL);
+    errCode = NtOpenKey(
+        &RealKey,
+        KEY_ALL_ACCESS,
+        & ObjectAttributes);
+    if (!NT_SUCCESS(errCode)) {
+      ErrorCode = RtlNtStatusToDosError(errCode);
+      SetLastError(ErrorCode);
+      return ErrorCode;
+    }
+    CloseRealKey = TRUE;
+  } else {
+    RealKey = hKey;
+    CloseRealKey = FALSE;
+  }
+  ErrorCode = RegQueryValueExW(
+    RealKey,
+    NULL,
+    NULL,
+    NULL,
+    (LPBYTE)lpValue,
+    (LPDWORD)lpcbValue);
+  if (CloseRealKey) {
+    NtClose(RealKey);
+  }
+  return ErrorCode;
 }
 
 
 /************************************************************************
- *     RegReplaceKeyA
+ *  RegQueryValueA
  */
 LONG
 STDCALL
-RegReplaceKeyA(
-       HKEY    hKey,
-       LPCSTR  lpSubKey,
-       LPCSTR  lpNewFile,
-       LPCSTR  lpOldFile
-       )
+RegQueryValueA(
+  HKEY  hKey,
+  LPCSTR  lpSubKey,
+  LPSTR lpValue,
+  PLONG lpcbValue)
 {
-       SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-       return ERROR_CALL_NOT_IMPLEMENTED;
+  WCHAR SubKeyNameBuffer[MAX_PATH+1];
+  UNICODE_STRING SubKeyName;
+  UNICODE_STRING Value;
+  ANSI_STRING AnsiString;
+  LONG ValueSize;
+  LONG ErrorCode;
+
+  if ((lpValue) && (!lpcbValue)) {
+    SetLastError(ERROR_INVALID_PARAMETER);
+    return ERROR_INVALID_PARAMETER;
+  }
+  RtlInitUnicodeString(&SubKeyName, NULL);
+  RtlInitUnicodeString(&Value, NULL);
+  if ((lpSubKey) && (strlen(lpSubKey) != 0)) {
+    RtlInitAnsiString(&AnsiString, (LPSTR)lpSubKey);
+    SubKeyName.Buffer = &SubKeyNameBuffer[0];
+    SubKeyName.MaximumLength = sizeof(SubKeyNameBuffer);
+    RtlAnsiStringToUnicodeString(&SubKeyName, &AnsiString, FALSE);
+  }
+  if (lpValue) {
+    ValueSize = *lpcbValue * sizeof(WCHAR);
+    Value.MaximumLength = ValueSize;
+    Value.Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, ValueSize);
+    if (!Value.Buffer) {
+      SetLastError(ERROR_OUTOFMEMORY);
+      return ERROR_OUTOFMEMORY;
+    }
+  } else {
+    ValueSize = 0;
+  }
+  ErrorCode = RegQueryValueW(
+    hKey,
+    (LPCWSTR)SubKeyName.Buffer,
+    Value.Buffer,
+    &ValueSize);
+  if (ErrorCode == ERROR_SUCCESS) {
+    Value.Length = ValueSize;
+    RtlInitAnsiString(&AnsiString, NULL);
+    AnsiString.Buffer = lpValue;
+    AnsiString.MaximumLength = *lpcbValue;
+    RtlUnicodeStringToAnsiString(&AnsiString, &Value, FALSE);
+  }
+  *lpcbValue = ValueSize; 
+  if (Value.Buffer) {
+    RtlFreeHeap(RtlGetProcessHeap(), 0, Value.Buffer);
+  }
+  return ErrorCode;
 }
 
 
 /************************************************************************
- *     RegRestoreKeyA
+ *  RegReplaceKeyA
  */
 LONG
 STDCALL
-RegRestoreKeyA(
-       HKEY    hKey,
-       LPCSTR  lpFile,
-       DWORD   dwFlags
-       )
+RegReplaceKeyA(
+  HKEY  hKey,
+  LPCSTR  lpSubKey,
+  LPCSTR  lpNewFile,
+  LPCSTR  lpOldFile)
 {
-       SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-       return ERROR_CALL_NOT_IMPLEMENTED;
+  UNIMPLEMENTED;
+  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+  return ERROR_CALL_NOT_IMPLEMENTED;
 }
 
 
 /************************************************************************
- *     RegSaveKeyA
+ *  RegReplaceKeyW
  */
 LONG
 STDCALL
-RegSaveKeyA(
-       HKEY                    hKey,
-       LPCSTR                  lpFile,
-       LPSECURITY_ATTRIBUTES   lpSecurityAttributes 
-       )
+RegReplaceKeyW(
+  HKEY  hKey,
+  LPCWSTR lpSubKey,
+  LPCWSTR lpNewFile,
+  LPCWSTR lpOldFile)
 {
-       SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-       return ERROR_CALL_NOT_IMPLEMENTED;
+  UNIMPLEMENTED;
+  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+  return ERROR_CALL_NOT_IMPLEMENTED;
 }
 
 
 /************************************************************************
- *     RegSetKeySecurity
+ *  RegRestoreKeyA
  */
-#if 0
 LONG
 STDCALL
-RegSetKeySecurity(
-       HKEY                    hKey,
-       SECURITY_INFORMATION    SecurityInformation,    /* FIXME: ULONG? */
-       PSECURITY_DESCRIPTOR    pSecurityDescriptor
-       )
+RegRestoreKeyA(
+  HKEY  hKey,
+  LPCSTR  lpFile,
+  DWORD dwFlags)
 {
-       SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-       return ERROR_CALL_NOT_IMPLEMENTED;
+  UNIMPLEMENTED;
+  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+  return ERROR_CALL_NOT_IMPLEMENTED;
 }
-#endif
+
 
 /************************************************************************
- *     RegSetValueA
+ *  RegRestoreKeyW
  */
 LONG
 STDCALL
-RegSetValueA(
-       HKEY    hKey,
-       LPCSTR  lpSubKey,
-       DWORD   dwType,
-       LPCSTR  lpData,
-       DWORD   cbData
-       )
+RegRestoreKeyW(
+  HKEY  hKey,
+  LPCWSTR lpFile,
+  DWORD dwFlags)
 {
-       SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-       return ERROR_CALL_NOT_IMPLEMENTED;
+  UNIMPLEMENTED;
+  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+  return ERROR_CALL_NOT_IMPLEMENTED;
 }
 
 
 /************************************************************************
- *     RegSetValueExA
+ *  RegSaveKeyW
+ */
+LONG STDCALL
+RegSaveKeyW(HKEY hKey,
+      LPCWSTR lpFile,
+      LPSECURITY_ATTRIBUTES lpSecurityAttributes)
+{
+  PSECURITY_DESCRIPTOR SecurityDescriptor = NULL;
+  OBJECT_ATTRIBUTES ObjectAttributes;
+  UNICODE_STRING NtName;
+  IO_STATUS_BLOCK IoStatusBlock;
+  HANDLE FileHandle;
+  HKEY KeyHandle;
+  NTSTATUS Status;
+  LONG ErrorCode;
+
+  Status = MapDefaultKey(&KeyHandle, hKey);
+  if (!NT_SUCCESS(Status)) {
+      ErrorCode = RtlNtStatusToDosError(Status);
+      SetLastError(ErrorCode);
+      return(ErrorCode);
+  }
+  if (!RtlDosPathNameToNtPathName_U((LPWSTR)lpFile,
+                   &NtName, NULL, NULL)) {
+      SetLastError(ERROR_INVALID_PARAMETER);
+      return(ERROR_INVALID_PARAMETER);
+  }
+  if (lpSecurityAttributes != NULL)
+      SecurityDescriptor = lpSecurityAttributes->lpSecurityDescriptor;
+  InitializeObjectAttributes(&ObjectAttributes,
+           &NtName,
+           OBJ_CASE_INSENSITIVE,
+           NULL,
+           SecurityDescriptor);
+  Status = NtCreateFile(&FileHandle,
+      GENERIC_WRITE | SYNCHRONIZE,
+      &ObjectAttributes,
+      &IoStatusBlock,
+      NULL,
+      FILE_ATTRIBUTE_NORMAL,
+      FILE_SHARE_READ,
+      FILE_CREATE,
+      FILE_OPEN_FOR_BACKUP_INTENT | FILE_SYNCHRONOUS_IO_NONALERT,
+      NULL,
+      0);
+  RtlFreeUnicodeString(&NtName);
+  if (!NT_SUCCESS(Status)) {
+      ErrorCode = RtlNtStatusToDosError(Status);
+      SetLastError(ErrorCode);
+      return(ErrorCode);
+  }
+  Status = NtSaveKey(KeyHandle, FileHandle);
+  NtClose(FileHandle);
+  if (!NT_SUCCESS(Status)) {
+      ErrorCode = RtlNtStatusToDosError(Status);
+      SetLastError(ErrorCode);
+      return(ErrorCode);
+  }
+  return(ERROR_SUCCESS);
+}
+
+
+/************************************************************************
+ *  RegSaveKeyA
+ */
+LONG STDCALL
+RegSaveKeyA(HKEY hKey,
+      LPCSTR lpFile,
+      LPSECURITY_ATTRIBUTES lpSecurityAttributes)
+{
+  UNICODE_STRING FileName;
+  LONG ErrorCode;
+
+  RtlCreateUnicodeStringFromAsciiz(&FileName, (LPSTR)lpFile);
+  ErrorCode = RegSaveKeyW(hKey, FileName.Buffer, lpSecurityAttributes);
+  RtlFreeUnicodeString(&FileName);
+  return(ErrorCode);
+}
+
+
+/************************************************************************
+ *  RegSetKeySecurity
  */
 LONG
 STDCALL
-RegSetValueExA(
-       HKEY            hKey,
-       LPCSTR          lpValueName,
-       DWORD           Reserved,
-       DWORD           dwType,
-       CONST BYTE      *lpData,
-       DWORD           cbData
-       )
+RegSetKeySecurity(
+  HKEY      hKey,
+  SECURITY_INFORMATION  SecurityInformation,  /* FIXME: ULONG? */
+  PSECURITY_DESCRIPTOR  pSecurityDescriptor
+  )
 {
-       SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-       return ERROR_CALL_NOT_IMPLEMENTED;
+  UNIMPLEMENTED;
+  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+  return ERROR_CALL_NOT_IMPLEMENTED;
 }
 
 
 /************************************************************************
- *     RegSetValueExW
+ *  RegSetValueExW
  */
 LONG
 STDCALL
 RegSetValueExW(
-       HKEY            hKey,
-       LPCWSTR         lpValueName,
-       DWORD           Reserved,
-       DWORD           dwType,
-       CONST BYTE      *lpData,
-       DWORD           cbData
-       )
+  HKEY    hKey,
+  LPCWSTR lpValueName,
+  DWORD   Reserved,
+  DWORD   dwType,
+  CONST BYTE* lpData,
+  DWORD   cbData)
 {
-       UNICODE_STRING ValueName;
-       NTSTATUS Status;
+  UNICODE_STRING ValueName;
+  PUNICODE_STRING pValueName;
+  HKEY KeyHandle;
+  NTSTATUS Status;
+  LONG ErrorCode;
+
+  Status = MapDefaultKey(&KeyHandle, hKey);
+  if (!NT_SUCCESS(Status)) {
+    ErrorCode = RtlNtStatusToDosError(Status);
+    SetLastError(ErrorCode);
+    return ErrorCode;
+  }
+  if (lpValueName) {
+    RtlInitUnicodeString(&ValueName, lpValueName);
+    pValueName = &ValueName;
+  } else {
+    pValueName = NULL;
+  }
+  Status = NtSetValueKey(
+    KeyHandle,
+    pValueName,
+    0,
+    dwType,
+    (PVOID)lpData,
+    (ULONG)cbData);
+  if (!NT_SUCCESS(Status)) {
+    LONG ErrorCode = RtlNtStatusToDosError(Status);
+    SetLastError (ErrorCode);
+    return ErrorCode;
+  }
+  return ERROR_SUCCESS;
+}
 
-       RtlInitUnicodeString (&ValueName,
-                             lpValueName);
 
-       Status = NtSetValueKey (hKey,
-                               &ValueName,
-                               0,
-                               dwType,
-                               (PVOID)lpData,
-                               (ULONG)cbData);
-       if (!NT_SUCCESS(Status))
-       {
-               LONG ErrorCode = RtlNtStatusToDosError(Status);
+/************************************************************************
+ *  RegSetValueExA
+ */
+LONG
+STDCALL
+RegSetValueExA(
+  HKEY    hKey,
+  LPCSTR  lpValueName,
+  DWORD   Reserved,
+  DWORD   dwType,
+  CONST BYTE* lpData,
+  DWORD   cbData)
+{
+  UNICODE_STRING ValueName;
+  LPWSTR pValueName;
+  ANSI_STRING AnsiString;
+  UNICODE_STRING Data;
+  LONG ErrorCode;
+  LPBYTE pData;
+  DWORD DataSize;
+
+  if (!lpData) {
+    SetLastError(ERROR_INVALID_PARAMETER);
+    return ERROR_INVALID_PARAMETER;
+  }
+  if ((lpValueName) && (strlen(lpValueName) != 0)) {
+    RtlCreateUnicodeStringFromAsciiz(&ValueName, (LPSTR)lpValueName);
+    pValueName = (LPWSTR)ValueName.Buffer;
+  } else {
+    pValueName = NULL;
+  }
+  if ((dwType == REG_SZ) || (dwType == REG_MULTI_SZ) || (dwType == REG_EXPAND_SZ)) {
+    RtlInitAnsiString(&AnsiString, NULL);
+    AnsiString.Buffer = (LPSTR)lpData;
+    AnsiString.Length = cbData;
+    AnsiString.MaximumLength = cbData;
+    RtlAnsiStringToUnicodeString(&Data, &AnsiString, TRUE);
+    pData = (LPBYTE)Data.Buffer;
+    DataSize = cbData * sizeof(WCHAR);
+  } else {
+    RtlInitUnicodeString(&Data, NULL);
+    pData = (LPBYTE)lpData;
+    DataSize = cbData;
+  }
+  ErrorCode = RegSetValueExW(
+    hKey,
+    pValueName,
+    Reserved,
+    dwType,
+    pData,
+    DataSize);
+  if (pValueName) {
+    RtlFreeHeap(RtlGetProcessHeap(), 0, ValueName.Buffer);
+  }
+  if (Data.Buffer) {
+    RtlFreeHeap(RtlGetProcessHeap(), 0, Data.Buffer);
+  }
+  return ErrorCode;
+}
 
-               SetLastError (ErrorCode);
-               return ErrorCode;
-       }
 
-       return ERROR_SUCCESS;
+/************************************************************************
+ *  RegSetValueW
+ */
+LONG
+STDCALL
+RegSetValueW(
+  HKEY  hKey,
+  LPCWSTR lpSubKey,
+  DWORD dwType,
+  LPCWSTR lpData,
+  DWORD cbData)
+{
+  NTSTATUS    errCode;
+  UNICODE_STRING    SubKeyString;
+  OBJECT_ATTRIBUTES ObjectAttributes;
+  HKEY        KeyHandle;
+  HANDLE      RealKey;
+  LONG        ErrorCode;
+  BOOL        CloseRealKey;
+
+  errCode = MapDefaultKey(&KeyHandle, hKey);
+  if (!NT_SUCCESS(errCode)) {
+    ErrorCode = RtlNtStatusToDosError(errCode);
+    SetLastError (ErrorCode);
+    return ErrorCode;
+  }
+  if ((lpSubKey) && (wcslen(lpSubKey) != 0)) {
+    RtlInitUnicodeString(&SubKeyString, (LPWSTR)lpSubKey);
+    InitializeObjectAttributes(&ObjectAttributes,
+             &SubKeyString,
+             OBJ_CASE_INSENSITIVE,
+             KeyHandle,
+             NULL);
+    errCode = NtOpenKey(&RealKey, KEY_ALL_ACCESS, &ObjectAttributes);
+    if (!NT_SUCCESS(errCode)) {
+      ErrorCode = RtlNtStatusToDosError(errCode);
+      SetLastError(ErrorCode);
+      return ErrorCode;
+    }
+    CloseRealKey = TRUE;
+  } else {
+    RealKey = hKey;
+    CloseRealKey = FALSE;
+  }
+  ErrorCode = RegSetValueExW(
+    RealKey,
+    NULL,
+    0,
+    dwType,
+    (LPBYTE)lpData,
+    cbData);
+  if (CloseRealKey) {
+    NtClose(RealKey);
+  }
+  return ErrorCode;
 }
 
 
 /************************************************************************
- *     RegSetValueW
+ *  RegSetValueA
  */
 LONG
 STDCALL
-RegSetValueW(
-       HKEY    hKey,
-       LPCWSTR lpSubKey,
-       DWORD   dwType,
-       LPCWSTR lpData,
-       DWORD   cbData
-       )
+RegSetValueA(
+  HKEY  hKey,
+  LPCSTR  lpSubKey,
+  DWORD dwType,
+  LPCSTR  lpData,
+  DWORD cbData)
 {
-       SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-       return ERROR_CALL_NOT_IMPLEMENTED;
+  WCHAR SubKeyNameBuffer[MAX_PATH+1];
+  UNICODE_STRING SubKeyName;
+  UNICODE_STRING Data;
+  ANSI_STRING AnsiString;
+  LONG DataSize;
+  LONG ErrorCode;
+
+  if (!lpData) {
+    SetLastError(ERROR_INVALID_PARAMETER);
+    return ERROR_INVALID_PARAMETER;
+  }
+  RtlInitUnicodeString(&SubKeyName, NULL);
+  RtlInitUnicodeString(&Data, NULL);
+  if ((lpSubKey) && (strlen(lpSubKey) != 0)) {
+    RtlInitAnsiString(&AnsiString, (LPSTR)lpSubKey);
+    SubKeyName.Buffer = &SubKeyNameBuffer[0];
+    SubKeyName.MaximumLength = sizeof(SubKeyNameBuffer);
+    RtlAnsiStringToUnicodeString(&SubKeyName, &AnsiString, FALSE);
+  }
+  DataSize = cbData * sizeof(WCHAR);
+  Data.MaximumLength = DataSize;
+  Data.Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, DataSize);
+  if (!Data.Buffer) {
+    SetLastError(ERROR_OUTOFMEMORY);
+    return ERROR_OUTOFMEMORY;
+  }
+  ErrorCode = RegSetValueW(
+    hKey,
+    (LPCWSTR)SubKeyName.Buffer,
+    dwType,
+    Data.Buffer,
+    DataSize);
+  RtlFreeHeap(RtlGetProcessHeap(), 0, Data.Buffer);
+  return ErrorCode;
 }
 
 
 /************************************************************************
- *     RegUnLoadKeyA
+ *  RegUnLoadKeyA
  */
 LONG
 STDCALL
 RegUnLoadKeyA(
-       HKEY    hKey,
-       LPCSTR  lpSubKey
-       )
+  HKEY  hKey,
+  LPCSTR  lpSubKey)
+{
+  UNIMPLEMENTED;
+  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+  return ERROR_CALL_NOT_IMPLEMENTED;
+}
+
+
+/************************************************************************
+ *  RegUnLoadKeyW
+ */
+LONG
+STDCALL
+RegUnLoadKeyW(
+  HKEY  hKey,
+  LPCWSTR lpSubKey)
 {
-       SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-       return ERROR_CALL_NOT_IMPLEMENTED;
+  UNIMPLEMENTED;
+  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+  return ERROR_CALL_NOT_IMPLEMENTED;
 }
 
 /* EOF */