added a whole bunch of hacks #ifdef'd into the header section to support private...
[reactos.git] / reactos / lib / advapi32 / reg / reg.c
index 135ad01..5b2c685 100644 (file)
@@ -1,4 +1,5 @@
-/*
+/* $Id: reg.c,v 1.19 2002/11/10 13:44:48 robd Exp $
+ *
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS system libraries
  * FILE:            lib/advapi32/reg/reg.c
  *                  Created 01/11/98
  *                  19990309 EA Stubs
  */
-#include <windows.h>
+
+#ifdef 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
+#else
 #include <ddk/ntddk.h>
+#include <ntdll/rtl.h>
+#include <windows.h>
 #include <wchar.h>
 
+#define NDEBUG
+#include <debug.h>
+#endif
+
+#define CHECK_STATUS \
+{ \
+       if (!NT_SUCCESS(Status)) \
+       { \
+               LONG _ErrorCode = RtlNtStatusToDosError(Status); \
+               SetLastError(_ErrorCode); \
+               return _ErrorCode; \
+       } \
+}
+
+/* GLOBALS *******************************************************************/
+
+#define MAX_DEFAULT_HANDLES   6
+
+static CRITICAL_SECTION HandleTableCS;
+static HANDLE DefaultHandleTable[MAX_DEFAULT_HANDLES];
+
+
+/* PROTOTYPES ****************************************************************/
+
+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
+ */
+
+BOOL
+RegInitialize (VOID)
+{
+   DPRINT("RegInitialize()\n");
+
+   RtlZeroMemory (DefaultHandleTable,
+                 MAX_DEFAULT_HANDLES * sizeof(HANDLE));
+
+   RtlInitializeCriticalSection(&HandleTableCS);
+   return TRUE;
+}
+
+
+/************************************************************************
+ *     RegInit
+ */
+BOOL
+RegCleanup(VOID)
+{
+   DPRINT("RegCleanup()\n");
+
+   CloseDefaultKeys();
+   RtlDeleteCriticalSection(&HandleTableCS);
+   return TRUE;
+}
+
+
+static NTSTATUS
+MapDefaultKey(PHKEY RealKey,
+             HKEY Key)
+{
+   PHANDLE Handle;
+   ULONG Index;
+   NTSTATUS Status = STATUS_SUCCESS;
+
+   DPRINT("MapDefaultKey (Key %x)\n", Key);
+
+   if (((ULONG)Key & 0xF0000000) != 0x80000000)
+     {
+        *RealKey = Key;
+        return STATUS_SUCCESS;
+     }
+
+   /* Handle special cases here */
+   Index = (ULONG)Key & 0x0FFFFFFF;
+
+   if (Index >= MAX_DEFAULT_HANDLES)
+     return STATUS_INVALID_PARAMETER;
+
+   RtlEnterCriticalSection(&HandleTableCS);
+
+   Handle = &DefaultHandleTable[Index];
+   if (*Handle == NULL)
+     {
+        /* create/open the default handle */
+        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:
+              DPRINT("MapDefaultHandle() no handle creator\n");
+              Status = STATUS_INVALID_PARAMETER;
+          }
+     }
+
+   RtlLeaveCriticalSection(&HandleTableCS);
+
+   if (NT_SUCCESS(Status))
+     {
+        *RealKey = (HKEY)*Handle;
+     }
+
+   return Status;
+}
+
+
+static VOID
+CloseDefaultKeys(VOID)
+{
+   ULONG i;
+
+   RtlEnterCriticalSection(&HandleTableCS);
+
+   for (i = 0; i < MAX_DEFAULT_HANDLES; i++)
+     {
+        if (DefaultHandleTable[i] != NULL)
+          {
+             NtClose (DefaultHandleTable[i]);
+             DefaultHandleTable[i] = NULL;
+          }
+     }
+
+   RtlLeaveCriticalSection(&HandleTableCS);
+}
+
+
+static NTSTATUS
+OpenClassesRootKey(PHANDLE KeyHandle)
+{
+  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));
+}
+
+
+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));
+}
+
+
+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
  */
-LONG
-STDCALL
-RegCloseKey(
-       HKEY    hKey
-       )
+LONG STDCALL
+RegCloseKey(HKEY hKey)
 {
-       if (!hKey)
-               return ERROR_INVALID_HANDLE;
+  NTSTATUS Status;
 
-       SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-       return ERROR_CALL_NOT_IMPLEMENTED;
+  /* 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;
 }
 
 
 /************************************************************************
  *     RegConnectRegistryA
  */
-LONG
-STDCALL
-RegConnectRegistryA(
-       LPSTR   lpMachineName,
-       HKEY    hKey,
-       PHKEY   phkResult
-       )
+LONG STDCALL
+RegConnectRegistryA(LPCSTR lpMachineName,
+                   HKEY hKey,
+                   PHKEY phkResult)
 {
-       SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-       return ERROR_CALL_NOT_IMPLEMENTED;
+  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+  return ERROR_CALL_NOT_IMPLEMENTED;
+}
+
+
+/************************************************************************
+ *     RegConnectRegistryW
+ */
+LONG STDCALL
+RegConnectRegistryW(LPCWSTR lpMachineName,
+                   HKEY hKey,
+                   PHKEY phkResult)
+{
+  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+  return ERROR_CALL_NOT_IMPLEMENTED;
+}
+
+
+/************************************************************************
+ *     RegCreateKeyExA
+ */
+LONG STDCALL
+RegCreateKeyExA(HKEY hKey,
+               LPCSTR lpSubKey,
+               DWORD Reserved,
+               LPSTR lpClass,
+               DWORD dwOptions,
+               REGSAM samDesired,
+               LPSECURITY_ATTRIBUTES lpSecurityAttributes,
+               PHKEY phkResult,
+               LPDWORD lpdwDisposition)
+{
+  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);
+}
+
+
+/************************************************************************
+ *     RegCreateKeyExW
+ */
+LONG STDCALL
+RegCreateKeyExW(HKEY                   hKey,
+               LPCWSTR                 lpSubKey,
+               DWORD                   Reserved,
+               LPWSTR                  lpClass,
+               DWORD                   dwOptions,
+               REGSAM                  samDesired,
+               LPSECURITY_ATTRIBUTES   lpSecurityAttributes,
+               PHKEY                   phkResult,
+               LPDWORD                 lpdwDisposition)
+{
+       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;
 }
 
 
 /************************************************************************
  *     RegCreateKeyA
  */
+LONG STDCALL
+RegCreateKeyA(HKEY hKey,
+             LPCSTR lpSubKey,
+             PHKEY phkResult)
+{
+  return(RegCreateKeyExA(hKey,
+                        lpSubKey,
+                        0,
+                        NULL,
+                        0,
+                        KEY_ALL_ACCESS,
+                        NULL,
+                        phkResult,
+                        NULL));
+}
+
+
+/************************************************************************
+ *     RegCreateKeyW
+ */
+LONG STDCALL
+RegCreateKeyW(HKEY hKey,
+             LPCWSTR lpSubKey,
+             PHKEY phkResult)
+{
+  return(RegCreateKeyExW(hKey,
+                        lpSubKey,
+                        0,
+                        NULL,
+                        0,
+                        KEY_ALL_ACCESS,
+                        NULL,
+                        phkResult,
+                        NULL));
+}
+
+
+/************************************************************************
+ *     RegDeleteKeyA
+ */
 LONG
 STDCALL
-RegCreateKeyA(
+RegDeleteKeyA(
        HKEY    hKey,
-       LPCSTR  lpSubKey,
-       PHKEY   phkResult
+       LPCSTR  lpSubKey
        )
 {
-       return RegCreateKeyExA(hKey,
-               lpSubKey,
-               0,
-               NULL,
-               0,
-               MAXIMUM_ALLOWED,
-               NULL,
-               phkResult,
-               NULL);
+       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;
 }
 
 
 /************************************************************************
- *     RegCreateKeyW
+ *     RegDeleteKeyW
  */
 LONG
 STDCALL
-RegCreateKeyW(
+RegDeleteKeyW(
        HKEY    hKey,
-       LPCWSTR lpSubKey,
-       PHKEY   phkResult
+       LPCWSTR lpSubKey
        )
 {
-       return RegCreateKeyExW(hKey,
-               lpSubKey,
-               0,
-               NULL,
-               0,
-               MAXIMUM_ALLOWED,
-               NULL,
-               phkResult,
-               NULL);
+       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;
 }
 
 
 /************************************************************************
- *     RegCreateKeyExA
+ *     RegDeleteValueA
  */
 LONG
 STDCALL
-RegCreateKeyExA(
-       HKEY                    hKey,
-       LPCSTR                  lpSubKey,
-       DWORD                   Reserved,
-       LPSTR                   lpClass,
-       DWORD                   dwOptions,
-       REGSAM                  samDesired,
-       LPSECURITY_ATTRIBUTES   lpSecurityAttributes,
-       PHKEY                   phkResult,
-       LPDWORD                 lpdwDisposition
+RegDeleteValueA(
+       HKEY    hKey,
+       LPCSTR  lpValueName
        )
 {
-       SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-       return ERROR_CALL_NOT_IMPLEMENTED;
+       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;
 }
 
 
 /************************************************************************
- *     RegCreateKeyExW
+ *     RegDeleteValueW
  */
 LONG
 STDCALL
-RegCreateKeyExW(
-       HKEY                    hKey,
-       LPCWSTR                 lpSubKey,
-       DWORD                   Reserved,
-       LPWSTR                  lpClass,
-       DWORD                   dwOptions,
-       REGSAM                  samDesired,
-       LPSECURITY_ATTRIBUTES   lpSecurityAttributes,
-       PHKEY                   phkResult,
-       LPDWORD                 lpdwDisposition
+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;
 }
 
 
 /************************************************************************
- *     RegDeleteKeyA
+ *     RegEnumKeyExW
  */
 LONG
 STDCALL
-RegDeleteKeyA(
-       HKEY    hKey,
-       LPCSTR  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;
 }
 
 
 /************************************************************************
- *     RegDeleteKeyW
+ *     RegEnumKeyW
  */
 LONG
 STDCALL
-RegDeleteKeyW(
+RegEnumKeyW(
        HKEY    hKey,
-       LPCWSTR lpSubKey
+       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);
 }
 
 
 /************************************************************************
- *     RegDeleteValueA
+ *     RegEnumKeyExA
  */
 LONG
 STDCALL
-RegDeleteValueA(
-       HKEY    hKey,
-       LPCSTR  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;
 }
 
 
@@ -192,29 +1026,130 @@ RegEnumKeyA(
        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;
 }
 
 
@@ -234,42 +1169,131 @@ RegEnumValueA(
        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 = 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
  */
-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
  */
-#if 0
 LONG
 STDCALL
 RegGetKeySecurity (
        HKEY                    hKey,
-       SECURITY_INFORMATION    SecurityInformation,    /* FIXME: ULONG ? */
+       SECURITY_INFORMATION    SecurityInformation,
        PSECURITY_DESCRIPTOR    pSecurityDescriptor,
        LPDWORD                 lpcbSecurityDescriptor
        )
 {
+  UNIMPLEMENTED;
        SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
        return ERROR_CALL_NOT_IMPLEMENTED;
 }
-#endif
 
 
 /************************************************************************
@@ -277,12 +1301,13 @@ RegGetKeySecurity (
  */
 LONG
 STDCALL
-RegLoadKey(
+RegLoadKeyA(
        HKEY    hKey,
        LPCSTR  lpSubKey,
        LPCSTR  lpFile
        )
 {
+  UNIMPLEMENTED;
        SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
        return ERROR_CALL_NOT_IMPLEMENTED;
 }
@@ -317,6 +1342,7 @@ RegNotifyChangeKeyValue(
        BOOL    fAsynchronous
        )
 {
+  UNIMPLEMENTED;
        SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
        return ERROR_CALL_NOT_IMPLEMENTED;
 }
@@ -326,16 +1352,50 @@ RegNotifyChangeKeyValue(
 /************************************************************************
  *     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);
 }
 
 
@@ -356,25 +1416,39 @@ RegOpenKeyW (
        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);
 
-       SubKeyString.Buffer = (LPWSTR)lpSubKey;
-       SubKeyString.Length = wcslen(lpSubKey);
-       SubKeyString.MaximumLength = SubKeyString.Length;
+       InitializeObjectAttributes(&ObjectAttributes,
+                                  &SubKeyString,
+                                  OBJ_CASE_INSENSITIVE,
+                                  KeyHandle,
+                                  NULL);
 
-       ObjectAttributes.RootDirectory =  hKey;
-       ObjectAttributes.ObjectName = & SubKeyString;
-       ObjectAttributes.Attributes = OBJ_CASE_INSENSITIVE; 
        errCode = NtOpenKey(
                        phkResult,
-                       GENERIC_ALL,
+                       KEY_ALL_ACCESS,
                        & ObjectAttributes
                        );
        if ( !NT_SUCCESS(errCode) )
        {
-               LONG LastError = RtlNtStatusToDosError(errCode);
+               ErrorCode = RtlNtStatusToDosError(errCode);
                
-               SetLastError(LastError);
-               return LastError;
+               SetLastError(ErrorCode);
+               return ErrorCode;
        }
        return ERROR_SUCCESS;
 }
@@ -383,47 +1457,118 @@ RegOpenKeyW (
 /************************************************************************
  *     RegOpenKeyExA
  */
-LONG
-STDCALL
-RegOpenKeyExA(
-       HKEY    hKey,
-       LPCSTR  lpSubKey,
-       DWORD   ulOptions,
-       REGSAM  samDesired,
-       PHKEY   phkResult
-       )
+LONG STDCALL
+RegOpenKeyExA(HKEY hKey,
+             LPCSTR 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);
+    }
+
+  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);
 }
 
 
 /************************************************************************
  *     RegOpenKeyExW
  */
-LONG
-STDCALL
-RegOpenKeyExW(
-       HKEY    hKey,
-       LPCWSTR 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);
 }
 
 
 /************************************************************************
- *     RegQueryInfoKeyA
+ *     RegQueryInfoKeyW
  */
 LONG
 STDCALL
-RegQueryInfoKeyA(
+RegQueryInfoKeyW(
        HKEY            hKey,
-       LPSTR           lpClass,
+       LPWSTR          lpClass,
        LPDWORD         lpcbClass,
        LPDWORD         lpReserved,
        LPDWORD         lpcSubKeys,
@@ -436,19 +1581,124 @@ RegQueryInfoKeyA(
        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;
 }
 
 
 /************************************************************************
- *     RegQueryInfoKeyW
+ *     RegQueryInfoKeyA
  */
 LONG
 STDCALL
-RegQueryInfoKeyW(
+RegQueryInfoKeyA(
        HKEY            hKey,
-       LPWSTR          lpClass,
+       LPSTR           lpClass,
        LPDWORD         lpcbClass,
        LPDWORD         lpReserved,
        LPDWORD         lpcSubKeys,
@@ -461,8 +1711,43 @@ RegQueryInfoKeyW(
        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;
 }
 
 
@@ -472,70 +1757,390 @@ RegQueryInfoKeyW(
 LONG
 STDCALL
 RegQueryMultipleValuesA(
-       HKEY    hKey,
-       PVALENT val_list,
-       DWORD   num_vals,
-       LPSTR   lpValueBuf,
-       LPDWORD ldwTotsize
+       HKEY     hKey,
+       PVALENTA val_list,
+       DWORD    num_vals,
+       LPSTR    lpValueBuf,
+       LPDWORD  ldwTotsize
        )
 {
+  UNIMPLEMENTED;
        SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
        return ERROR_CALL_NOT_IMPLEMENTED;
 }
 
 
 /************************************************************************
- *     RegQueryValueA
+ *     RegQueryMultipleValuesW
  */
 LONG
 STDCALL
-RegQueryValueA(
-       HKEY    hKey,
-       LPCSTR  lpSubKey,
-       LPSTR   lpValue,
-       PLONG   lpcbValue
+RegQueryMultipleValuesW(
+       HKEY     hKey,
+       PVALENTW val_list,
+       DWORD    num_vals,
+       LPWSTR   lpValueBuf,
+       LPDWORD  ldwTotsize
        )
 {
+  UNIMPLEMENTED;
        SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
        return ERROR_CALL_NOT_IMPLEMENTED;
 }
 
 
 /************************************************************************
- *     RegQueryValueExA
+ *     RegQueryValueExW
  */
 LONG
 STDCALL
-RegQueryValueExA(
+RegQueryValueExW(
        HKEY    hKey,
-       LPSTR   lpValueName,
+       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;
 }
 
 
 /************************************************************************
- *     RegQueryValueExW
+ *     RegQueryValueExA
  */
 LONG
 STDCALL
-RegQueryValueExW(
+RegQueryValueExA(
        HKEY    hKey,
-       LPWSTR  lpValueName,
+       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;
+}
+
+
+/************************************************************************
+ *     RegQueryValueW
+ */
+LONG
+STDCALL
+RegQueryValueW(
+       HKEY    hKey,
+       LPCWSTR lpSubKey,
+       LPWSTR  lpValue,
+       PLONG   lpcbValue
+       )
+{
+       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;
+}
+
+
+/************************************************************************
+ *     RegQueryValueA
+ */
+LONG
+STDCALL
+RegQueryValueA(
+       HKEY    hKey,
+       LPCSTR  lpSubKey,
+       LPSTR   lpValue,
+       PLONG   lpcbValue
+       )
+{
+  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;
 }
 
 
@@ -551,6 +2156,25 @@ RegReplaceKeyA(
        LPCSTR  lpOldFile
        )
 {
+  UNIMPLEMENTED;
+       SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+       return ERROR_CALL_NOT_IMPLEMENTED;
+}
+
+
+/************************************************************************
+ *     RegReplaceKeyW
+ */
+LONG
+STDCALL
+RegReplaceKeyW(
+       HKEY    hKey,
+       LPCWSTR lpSubKey,
+       LPCWSTR lpNewFile,
+       LPCWSTR lpOldFile
+       )
+{
+  UNIMPLEMENTED;
        SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
        return ERROR_CALL_NOT_IMPLEMENTED;
 }
@@ -567,31 +2191,131 @@ RegRestoreKeyA(
        DWORD   dwFlags
        )
 {
+  UNIMPLEMENTED;
        SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
        return ERROR_CALL_NOT_IMPLEMENTED;
 }
 
 
 /************************************************************************
- *     RegSaveKeyA
+ *     RegRestoreKeyW
  */
 LONG
 STDCALL
-RegSaveKeyA(
-       HKEY                    hKey,
-       LPCSTR                  lpFile,
-       LPSECURITY_ATTRIBUTES   lpSecurityAttributes 
+RegRestoreKeyW(
+       HKEY    hKey,
+       LPCWSTR lpFile,
+       DWORD   dwFlags
        )
 {
+  UNIMPLEMENTED;
        SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
        return ERROR_CALL_NOT_IMPLEMENTED;
 }
 
 
+/************************************************************************
+ *     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
  */
-#if 0
 LONG
 STDCALL
 RegSetKeySecurity(
@@ -600,26 +2324,65 @@ RegSetKeySecurity(
        PSECURITY_DESCRIPTOR    pSecurityDescriptor
        )
 {
+  UNIMPLEMENTED;
        SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
        return ERROR_CALL_NOT_IMPLEMENTED;
 }
-#endif
+
 
 /************************************************************************
- *     RegSetValueA
+ *     RegSetValueExW
  */
 LONG
 STDCALL
-RegSetValueA(
-       HKEY    hKey,
-       LPCSTR  lpSubKey,
-       DWORD   dwType,
-       LPCSTR  lpData,
-       DWORD   cbData
+RegSetValueExW(
+       HKEY            hKey,
+       LPCWSTR         lpValueName,
+       DWORD           Reserved,
+       DWORD           dwType,
+       CONST BYTE      *lpData,
+       DWORD           cbData
        )
 {
-       SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-       return ERROR_CALL_NOT_IMPLEMENTED;
+       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;
 }
 
 
@@ -637,8 +2400,202 @@ RegSetValueExA(
        DWORD           cbData
        )
 {
-       SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-       return ERROR_CALL_NOT_IMPLEMENTED;
+  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;
+}
+
+
+/************************************************************************
+ *     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;
+}
+
+
+/************************************************************************
+ *     RegSetValueA
+ */
+LONG
+STDCALL
+RegSetValueA(
+       HKEY    hKey,
+       LPCSTR  lpSubKey,
+       DWORD   dwType,
+       LPCSTR  lpData,
+       DWORD   cbData
+       )
+{
+  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;
 }
 
 
@@ -652,9 +2609,25 @@ RegUnLoadKeyA(
        LPCSTR  lpSubKey
        )
 {
+  UNIMPLEMENTED;
        SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
        return ERROR_CALL_NOT_IMPLEMENTED;
 }
 
 
+/************************************************************************
+ *     RegUnLoadKeyW
+ */
+LONG
+STDCALL
+RegUnLoadKeyW(
+       HKEY    hKey,
+       LPCWSTR lpSubKey
+       )
+{
+  UNIMPLEMENTED;
+       SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+       return ERROR_CALL_NOT_IMPLEMENTED;
+}
+
 /* EOF */