Implement RegQueryMultipleValuesA().
[reactos.git] / reactos / lib / advapi32 / reg / reg.c
index 843e941..4e8e98c 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: reg.c,v 1.46 2004/04/03 13:12:43 gvg Exp $
+/* $Id: reg.c,v 1.61 2004/10/10 10:43:23 ekohl Exp $
  *
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS system libraries
 
 /* INCLUDES *****************************************************************/
 
-#define NTOS_MODE_USER
-#include <ntos.h>
-#include <ddk/ntddk.h>
-#include <rosrtl/string.h>
-#include <ntdll/rtl.h>
-#include <windows.h>
-#include <wchar.h>
-
+#include "advapi32.h"
 #define NDEBUG
 #include <debug.h>
 
@@ -27,7 +20,7 @@
 
 #define MAX_DEFAULT_HANDLES   6
 #define REG_MAX_NAME_SIZE     256
-#define REG_MAX_DATA_SIZE     2048     
+#define REG_MAX_DATA_SIZE     2048
 
 /* GLOBALS ******************************************************************/
 
@@ -37,7 +30,7 @@ static HANDLE ProcessHeap;
 
 /* PROTOTYPES ***************************************************************/
 
-static NTSTATUS MapDefaultKey (PHKEY ParentKey, HKEY Key);
+static NTSTATUS MapDefaultKey (PHANDLE ParentKey, HKEY Key);
 static VOID CloseDefaultKeys(VOID);
 
 static NTSTATUS OpenClassesRootKey(PHANDLE KeyHandle);
@@ -81,7 +74,7 @@ RegCleanup (VOID)
 
 
 static NTSTATUS
-MapDefaultKey (PHKEY RealKey,
+MapDefaultKey (PHANDLE RealKey,
               HKEY Key)
 {
   PHANDLE Handle;
@@ -92,7 +85,7 @@ MapDefaultKey (PHKEY RealKey,
 
   if (((ULONG)Key & 0xF0000000) != 0x80000000)
     {
-      *RealKey = Key;
+      *RealKey = (HANDLE)Key;
       return STATUS_SUCCESS;
     }
 
@@ -148,7 +141,7 @@ MapDefaultKey (PHKEY RealKey,
 
   if (NT_SUCCESS(Status))
     {
-      *RealKey = (HKEY)*Handle;
+      *RealKey = *Handle;
     }
 
    return Status;
@@ -313,6 +306,115 @@ RegConnectRegistryW (LPCWSTR lpMachineName,
 }
 
 
+/************************************************************************
+ *  CreateNestedKey
+ *
+ *  Create key and all necessary intermediate keys
+ */
+static NTSTATUS
+CreateNestedKey(PHKEY KeyHandle,
+               POBJECT_ATTRIBUTES ObjectAttributes,
+                PUNICODE_STRING ClassString,
+                DWORD dwOptions,
+                REGSAM samDesired,
+                DWORD *lpdwDisposition)
+{
+  OBJECT_ATTRIBUTES LocalObjectAttributes;
+  UNICODE_STRING LocalKeyName;
+  ULONG Disposition;
+  NTSTATUS Status;
+  ULONG FullNameLength;
+  ULONG Length;
+  PWCHAR Ptr;
+  HANDLE LocalKeyHandle;
+
+  Status = NtCreateKey((PHANDLE) KeyHandle,
+                       samDesired,
+                       ObjectAttributes,
+                       0,
+                       ClassString,
+                       dwOptions,
+                       (PULONG)lpdwDisposition);
+  DPRINT("NtCreateKey(%wZ) called (Status %lx)\n", ObjectAttributes->ObjectName, Status);
+  if (Status != STATUS_OBJECT_NAME_NOT_FOUND)
+    return Status;
+
+  /* Copy object attributes */
+  RtlCopyMemory (&LocalObjectAttributes,
+                ObjectAttributes,
+                sizeof(OBJECT_ATTRIBUTES));
+  RtlCreateUnicodeString (&LocalKeyName,
+                         ObjectAttributes->ObjectName->Buffer);
+  LocalObjectAttributes.ObjectName = &LocalKeyName;
+  FullNameLength = LocalKeyName.Length / sizeof(WCHAR);
+
+  /* Remove the last part of the key name and try to create the key again. */
+  while (Status == STATUS_OBJECT_NAME_NOT_FOUND)
+    {
+      Ptr = wcsrchr (LocalKeyName.Buffer, '\\');
+      if (Ptr == NULL || Ptr == LocalKeyName.Buffer)
+       {
+         Status = STATUS_UNSUCCESSFUL;
+         break;
+       }
+      *Ptr = (WCHAR)0;
+      LocalKeyName.Length = wcslen (LocalKeyName.Buffer) * sizeof(WCHAR);
+
+      Status = NtCreateKey (&LocalKeyHandle,
+                           KEY_ALL_ACCESS,
+                           &LocalObjectAttributes,
+                           0,
+                           NULL,
+                           0,
+                           &Disposition);
+      DPRINT("NtCreateKey(%wZ) called (Status %lx)\n", &LocalKeyName, Status);
+    }
+
+  if (!NT_SUCCESS(Status))
+    {
+      RtlFreeUnicodeString (&LocalKeyName);
+      return Status;
+    }
+
+  /* Add removed parts of the key name and create them too. */
+  Length = wcslen (LocalKeyName.Buffer);
+  while (TRUE)
+    {
+      NtClose (LocalKeyHandle);
+
+      LocalKeyName.Buffer[Length] = L'\\';
+      Length = wcslen (LocalKeyName.Buffer);
+      LocalKeyName.Length = Length * sizeof(WCHAR);
+
+      if (Length == FullNameLength)
+        {
+          Status = NtCreateKey((PHANDLE) KeyHandle,
+                               samDesired,
+                               ObjectAttributes,
+                               0,
+                               ClassString,
+                               dwOptions,
+                               (PULONG)lpdwDisposition);
+          break;
+        }
+      Status = NtCreateKey (&LocalKeyHandle,
+                           KEY_ALL_ACCESS,
+                           &LocalObjectAttributes,
+                           0,
+                           NULL,
+                           0,
+                           &Disposition);
+      DPRINT("NtCreateKey(%wZ) called (Status %lx)\n", &LocalKeyName, Status);
+      if (!NT_SUCCESS(Status))
+       break;
+    }
+
+  RtlFreeUnicodeString (&LocalKeyName);
+
+  return Status;
+}
+
+
 /************************************************************************
  *  RegCreateKeyExA
  *
@@ -332,7 +434,7 @@ RegCreateKeyExA (HKEY hKey,
   UNICODE_STRING SubKeyString;
   UNICODE_STRING ClassString;
   OBJECT_ATTRIBUTES Attributes;
-  HKEY ParentKey;
+  HANDLE ParentKey;
   LONG ErrorCode;
   NTSTATUS Status;
 
@@ -354,25 +456,26 @@ RegCreateKeyExA (HKEY hKey,
       RtlCreateUnicodeStringFromAsciiz (&ClassString,
                                        lpClass);
     }
-  RtlCreateUnicodeStringFromAsciiz (&SubKeyString,
-                                   (LPSTR)lpSubKey);
+
+  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);
+  Status = CreateNestedKey(phkResult,
+                          &Attributes,
+                          (lpClass == NULL)? NULL : &ClassString,
+                          dwOptions,
+                          samDesired,
+                          lpdwDisposition);
   RtlFreeUnicodeString (&SubKeyString);
   if (lpClass != NULL)
     {
       RtlFreeUnicodeString (&ClassString);
     }
+
   DPRINT("Status %x\n", Status);
   if (!NT_SUCCESS(Status))
     {
@@ -404,7 +507,7 @@ RegCreateKeyExW (HKEY hKey,
   UNICODE_STRING SubKeyString;
   UNICODE_STRING ClassString;
   OBJECT_ATTRIBUTES Attributes;
-  HKEY ParentKey;
+  HANDLE ParentKey;
   LONG ErrorCode;
   NTSTATUS Status;
 
@@ -430,13 +533,12 @@ RegCreateKeyExW (HKEY hKey,
                              OBJ_CASE_INSENSITIVE,
                              (HANDLE)ParentKey,
                              (PSECURITY_DESCRIPTOR)lpSecurityAttributes);
-  Status = NtCreateKey (phkResult,
-                       samDesired,
-                       &Attributes,
-                       0,
-                       (lpClass == NULL)? NULL : &ClassString,
-                       dwOptions,
-                       (PULONG)lpdwDisposition);
+  Status = CreateNestedKey(phkResult,
+                          &Attributes,
+                           (lpClass == NULL)? NULL : &ClassString,
+                           dwOptions,
+                           samDesired,
+                           lpdwDisposition);
   DPRINT("Status %x\n", Status);
   if (!NT_SUCCESS(Status))
     {
@@ -504,7 +606,7 @@ RegDeleteKeyA (HKEY hKey,
 {
   OBJECT_ATTRIBUTES ObjectAttributes;
   UNICODE_STRING SubKeyName;
-  HKEY ParentKey;
+  HANDLE ParentKey;
   HANDLE TargetKey;
   NTSTATUS Status;
   LONG ErrorCode;
@@ -561,7 +663,7 @@ RegDeleteKeyW (HKEY hKey,
 {
   OBJECT_ATTRIBUTES ObjectAttributes;
   UNICODE_STRING SubKeyName;
-  HKEY ParentKey;
+  HANDLE ParentKey;
   HANDLE TargetKey;
   NTSTATUS Status;
   LONG ErrorCode;
@@ -615,7 +717,7 @@ RegDeleteValueA (HKEY hKey,
                 LPCSTR lpValueName)
 {
   UNICODE_STRING ValueName;
-  HKEY KeyHandle;
+  HANDLE KeyHandle;
   LONG ErrorCode;
   NTSTATUS Status;
 
@@ -656,7 +758,7 @@ RegDeleteValueW (HKEY hKey,
   UNICODE_STRING ValueName;
   NTSTATUS Status;
   LONG ErrorCode;
-  HKEY KeyHandle;
+  HANDLE KeyHandle;
 
   Status = MapDefaultKey (&KeyHandle,
                          hKey);
@@ -758,10 +860,10 @@ RegEnumKeyExA (HKEY hKey,
   ANSI_STRING StringA;
   LONG ErrorCode = ERROR_SUCCESS;
   DWORD NameLength;
-  DWORD ClassLength;
+  DWORD ClassLength = 0;
   DWORD BufferSize;
   DWORD ResultSize;
-  HKEY KeyHandle;
+  HANDLE KeyHandle;
   NTSTATUS Status;
 
   DPRINT("RegEnumKeyExA(hKey 0x%x, dwIndex %d, lpName 0x%x, *lpcbName %d, lpClass 0x%x, lpcbClass %d)\n",
@@ -935,8 +1037,8 @@ RegEnumKeyExW (HKEY hKey,
   ULONG BufferSize;
   ULONG ResultSize;
   ULONG NameLength;
-  ULONG ClassLength;
-  HKEY KeyHandle;
+  ULONG ClassLength = 0;
+  HANDLE KeyHandle;
   LONG ErrorCode = ERROR_SUCCESS;
   NTSTATUS Status;
 
@@ -1086,9 +1188,9 @@ RegEnumValueA (HKEY hKey,
 
   ULONG NameLength;
   ULONG BufferSize;
-  ULONG DataLength;
+  ULONG DataLength = 0;
   ULONG ResultSize;
-  HKEY KeyHandle;
+  HANDLE KeyHandle;
   LONG ErrorCode;
   NTSTATUS Status;
   UNICODE_STRING StringU;
@@ -1253,9 +1355,9 @@ RegEnumValueW (HKEY hKey,
 
   ULONG NameLength;
   ULONG BufferSize;
-  ULONG DataLength;
+  ULONG DataLength = 0;
   ULONG ResultSize;
-  HKEY KeyHandle;
+  HANDLE KeyHandle;
   LONG ErrorCode;
   NTSTATUS Status;
 
@@ -1344,6 +1446,10 @@ RegEnumValueW (HKEY hKey,
              *lpcbValueName = (DWORD)(ValueInfo->Basic.NameLength / sizeof(WCHAR));
              lpValueName[*lpcbValueName] = 0;
            }
+         if (NULL != lpcbData)
+           {
+             *lpcbData = (DWORD)ValueInfo->Full.DataLength;
+           }
        }
 
       if (ErrorCode == ERROR_SUCCESS && lpType != NULL)
@@ -1373,7 +1479,7 @@ RegEnumValueW (HKEY hKey,
 LONG STDCALL
 RegFlushKey(HKEY hKey)
 {
-  HKEY KeyHandle;
+  HANDLE KeyHandle;
   LONG ErrorCode;
   NTSTATUS Status;
 
@@ -1406,47 +1512,48 @@ RegFlushKey(HKEY hKey)
 /************************************************************************
  *  RegGetKeySecurity
  *
- * @unimplemented
+ * @implemented
  */
 LONG STDCALL
-RegGetKeySecurity (HKEY hKey,
-                  SECURITY_INFORMATION SecurityInformation,
-                  PSECURITY_DESCRIPTOR pSecurityDescriptor,
-                  LPDWORD lpcbSecurityDescriptor)
+RegGetKeySecurity(HKEY hKey,
+                 SECURITY_INFORMATION SecurityInformation,
+                 PSECURITY_DESCRIPTOR pSecurityDescriptor,
+                 LPDWORD lpcbSecurityDescriptor)
 {
-#if 0
-  HKEY KeyHandle;
+  HANDLE KeyHandle;
   LONG ErrorCode;
   NTSTATUS Status;
 
-  if (hKey = HKEY_PERFORMANCE_DATA)
+  if (hKey == HKEY_PERFORMANCE_DATA)
     {
+      SetLastError(ERROR_INVALID_HANDLE);
       return ERROR_INVALID_HANDLE;
     }
 
-  Status = MapDefaultKey (&KeyHandle,
-                         hKey);
+  Status = MapDefaultKey(&KeyHandle,
+                        hKey);
   if (!NT_SUCCESS(Status))
     {
-      ErrorCode = RtlNtStatusToDosError (Status);
-      SetLastError (ErrorCode);
+      DPRINT("MapDefaultKey() failed (Status %lx)\n", Status);
+      ErrorCode = RtlNtStatusToDosError(Status);
+      SetLastError(ErrorCode);
       return ErrorCode;
     }
 
-  Status = NtQuerySecurityObject ()
+  Status = NtQuerySecurityObject(KeyHandle,
+                                SecurityInformation,
+                                pSecurityDescriptor,
+                                *lpcbSecurityDescriptor,
+                                lpcbSecurityDescriptor);
   if (!NT_SUCCESS(Status))
     {
-      ErrorCode = RtlNtStatusToDosError (Status);
-      SetLastError (ErrorCode);
+      DPRINT("NtQuerySecurityObject() failed (Status %lx)\n", Status);
+      ErrorCode = RtlNtStatusToDosError(Status);
+      SetLastError(ErrorCode);
       return ErrorCode;
     }
 
   return ERROR_SUCCESS;
-#endif
-
-  UNIMPLEMENTED;
-  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-  return ERROR_CALL_NOT_IMPLEMENTED;
 }
 
 
@@ -1500,6 +1607,7 @@ RegLoadKeyW (HKEY hKey,
 
   if (hKey == HKEY_PERFORMANCE_DATA)
     {
+      SetLastError(ERROR_INVALID_HANDLE);
       return ERROR_INVALID_HANDLE;
     }
 
@@ -1618,7 +1726,7 @@ RegOpenKeyA (HKEY hKey,
 {
   OBJECT_ATTRIBUTES ObjectAttributes;
   UNICODE_STRING SubKeyString;
-  HKEY KeyHandle;
+  HANDLE KeyHandle;
   LONG ErrorCode;
   NTSTATUS Status;
 
@@ -1638,7 +1746,7 @@ RegOpenKeyA (HKEY hKey,
                              OBJ_CASE_INSENSITIVE,
                              KeyHandle,
                              NULL);
-  Status = NtOpenKey (phkResult,
+  Status = NtOpenKey ((PHANDLE)phkResult,
                      MAXIMUM_ALLOWED,
                      &ObjectAttributes);
   RtlFreeUnicodeString (&SubKeyString);
@@ -1668,7 +1776,7 @@ RegOpenKeyW (HKEY hKey,
 {
   OBJECT_ATTRIBUTES ObjectAttributes;
   UNICODE_STRING SubKeyString;
-  HKEY KeyHandle;
+  HANDLE KeyHandle;
   LONG ErrorCode;
   NTSTATUS Status;
 
@@ -1688,7 +1796,7 @@ RegOpenKeyW (HKEY hKey,
                              OBJ_CASE_INSENSITIVE,
                              KeyHandle,
                              NULL);
-  Status = NtOpenKey (phkResult,
+  Status = NtOpenKey ((PHANDLE)phkResult,
                      MAXIMUM_ALLOWED,
                      &ObjectAttributes);
   if (!NT_SUCCESS(Status))
@@ -1716,7 +1824,7 @@ RegOpenKeyExA (HKEY hKey,
 {
   OBJECT_ATTRIBUTES ObjectAttributes;
   UNICODE_STRING SubKeyString;
-  HKEY KeyHandle;
+  HANDLE KeyHandle;
   LONG ErrorCode;
   NTSTATUS Status;
 
@@ -1736,7 +1844,7 @@ RegOpenKeyExA (HKEY hKey,
                              OBJ_CASE_INSENSITIVE,
                              KeyHandle,
                              NULL);
-  Status = NtOpenKey (phkResult,
+  Status = NtOpenKey ((PHANDLE)phkResult,
                      samDesired,
                      &ObjectAttributes);
   RtlFreeUnicodeString (&SubKeyString);
@@ -1765,7 +1873,7 @@ RegOpenKeyExW (HKEY hKey,
 {
   OBJECT_ATTRIBUTES ObjectAttributes;
   UNICODE_STRING SubKeyString;
-  HKEY KeyHandle;
+  HANDLE KeyHandle;
   LONG ErrorCode;
   NTSTATUS Status;
 
@@ -1793,7 +1901,7 @@ RegOpenKeyExW (HKEY hKey,
                              OBJ_CASE_INSENSITIVE,
                              KeyHandle,
                              NULL);
-  Status = NtOpenKey (phkResult,
+  Status = NtOpenKey ((PHANDLE)phkResult,
                      samDesired,
                      &ObjectAttributes);
   if (!NT_SUCCESS(Status))
@@ -1890,8 +1998,8 @@ RegQueryInfoKeyW (HKEY hKey,
   KEY_FULL_INFORMATION FullInfoBuffer;
   PKEY_FULL_INFORMATION FullInfo;
   ULONG FullInfoSize;
-  ULONG ClassLength;
-  HKEY KeyHandle;
+  ULONG ClassLength = 0;
+  HANDLE KeyHandle;
   NTSTATUS Status;
   LONG ErrorCode = ERROR_SUCCESS;
   ULONG Length;
@@ -2000,8 +2108,26 @@ RegQueryInfoKeyW (HKEY hKey,
 
   if (lpcbSecurityDescriptor != NULL)
     {
-      /* FIXME */
-      *lpcbSecurityDescriptor = 0;
+      Status = NtQuerySecurityObject(KeyHandle,
+                                    OWNER_SECURITY_INFORMATION |
+                                    GROUP_SECURITY_INFORMATION |
+                                    DACL_SECURITY_INFORMATION,
+                                    NULL,
+                                    0,
+                                    lpcbSecurityDescriptor);
+      if (!NT_SUCCESS(Status))
+       {
+         if (lpClass != NULL)
+           {
+             RtlFreeHeap(ProcessHeap,
+                         0,
+                         FullInfo);
+           }
+
+         ErrorCode = RtlNtStatusToDosError(Status);
+         SetLastError(ErrorCode);
+         return ErrorCode;
+       }
     }
 
   if (lpftLastWriteTime != NULL)
@@ -2042,7 +2168,7 @@ RegQueryInfoKeyW (HKEY hKey,
 /************************************************************************
  *  RegQueryMultipleValuesA
  *
- * @unimplemented
+ * @implemented
  */
 LONG STDCALL
 RegQueryMultipleValuesA (HKEY hKey,
@@ -2051,9 +2177,55 @@ RegQueryMultipleValuesA (HKEY hKey,
                         LPSTR lpValueBuf,
                         LPDWORD ldwTotsize)
 {
-  UNIMPLEMENTED;
-  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-  return ERROR_CALL_NOT_IMPLEMENTED;
+  ULONG i;
+  DWORD maxBytes = *ldwTotsize;
+  LPSTR bufptr = (LPSTR)lpValueBuf;
+  LONG ErrorCode;
+
+  if (maxBytes >= (1024*1024))
+    return ERROR_TRANSFER_TOO_LONG;
+
+  *ldwTotsize = 0;
+
+  DPRINT ("RegQueryMultipleValuesA(%p,%p,%ld,%p,%p=%ld)\n",
+         hKey, val_list, num_vals, lpValueBuf, ldwTotsize, *ldwTotsize);
+
+  for (i = 0; i < num_vals; i++)
+    {
+      val_list[i].ve_valuelen = 0;
+      ErrorCode = RegQueryValueExA (hKey,
+                                   val_list[i].ve_valuename,
+                                   NULL,
+                                   NULL,
+                                   NULL,
+                                   &val_list[i].ve_valuelen);
+      if (ErrorCode != ERROR_SUCCESS)
+       {
+         return ErrorCode;
+       }
+
+      if (lpValueBuf != NULL && *ldwTotsize + val_list[i].ve_valuelen <= maxBytes)
+       {
+         ErrorCode = RegQueryValueExA (hKey,
+                                       val_list[i].ve_valuename,
+                                       NULL,
+                                       &val_list[i].ve_type,
+                                       bufptr,
+                                       &val_list[i].ve_valuelen);
+         if (ErrorCode != ERROR_SUCCESS)
+           {
+             return ErrorCode;
+           }
+
+         val_list[i].ve_valueptr = (DWORD_PTR)bufptr;
+
+         bufptr += val_list[i].ve_valuelen;
+       }
+
+      *ldwTotsize += val_list[i].ve_valuelen;
+    }
+
+  return (lpValueBuf != NULL && *ldwTotsize <= maxBytes) ? ERROR_SUCCESS : ERROR_MORE_DATA;
 }
 
 
@@ -2082,7 +2254,7 @@ RegQueryMultipleValuesW (HKEY hKey,
   DPRINT ("RegQueryMultipleValuesW(%p,%p,%ld,%p,%p=%ld)\n",
          hKey, val_list, num_vals, lpValueBuf, ldwTotsize, *ldwTotsize);
 
-  for (i = 0; i < num_vals; ++i)
+  for (i = 0; i < num_vals; i++)
     {
       val_list[i].ve_valuelen = 0;
       ErrorCode = RegQueryValueExW (hKey,
@@ -2091,12 +2263,12 @@ RegQueryMultipleValuesW (HKEY hKey,
                                    NULL,
                                    NULL,
                                    &val_list[i].ve_valuelen);
-      if(ErrorCode != ERROR_SUCCESS)
+      if (ErrorCode != ERROR_SUCCESS)
        {
          return ErrorCode;
        }
 
-      if(lpValueBuf != NULL && *ldwTotsize + val_list[i].ve_valuelen <= maxBytes)
+      if (lpValueBuf != NULL && *ldwTotsize + val_list[i].ve_valuelen <= maxBytes)
        {
          ErrorCode = RegQueryValueExW (hKey,
                                        val_list[i].ve_valuename,
@@ -2140,8 +2312,8 @@ RegQueryValueExW (HKEY hKey,
   LONG ErrorCode = ERROR_SUCCESS;
   ULONG BufferSize;
   ULONG ResultSize;
-  HKEY KeyHandle;
-  ULONG MaxCopy = lpcbData ? *lpcbData : 0;
+  HANDLE KeyHandle;
+  ULONG MaxCopy = lpcbData != NULL && lpData != NULL ? *lpcbData : 0;
 
   DPRINT("hKey 0x%X  lpValueName %S  lpData 0x%X  lpcbData %d\n",
         hKey, lpValueName, lpData, lpcbData ? *lpcbData : 0);
@@ -2163,7 +2335,7 @@ RegQueryValueExW (HKEY hKey,
 
   RtlInitUnicodeString (&ValueName,
                        lpValueName);
-  BufferSize = sizeof (KEY_VALUE_PARTIAL_INFORMATION) + MaxCopy;
+  BufferSize = FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[0]) + MaxCopy;
   ValueInfo = RtlAllocateHeap (ProcessHeap,
                               0,
                               BufferSize);
@@ -2180,7 +2352,7 @@ RegQueryValueExW (HKEY hKey,
                            BufferSize,
                            &ResultSize);
   DPRINT("Status 0x%X\n", Status);
-  if (Status == STATUS_BUFFER_TOO_SMALL)
+  if (Status == STATUS_BUFFER_OVERFLOW)
     {
       /* Return ERROR_SUCCESS and the buffer space needed for a successful call */
       MaxCopy = 0;
@@ -2193,7 +2365,7 @@ RegQueryValueExW (HKEY hKey,
       MaxCopy = 0;
       if (lpcbData != NULL)
        {
-         ResultSize = sizeof(*ValueInfo) + *lpcbData;
+         ResultSize = FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[0]) + *lpcbData;
        }
     }
 
@@ -2220,7 +2392,7 @@ RegQueryValueExW (HKEY hKey,
 
       if (lpcbData != NULL)
        {
-         *lpcbData = (ResultSize - sizeof(*ValueInfo));
+         *lpcbData = (ResultSize - FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[0]));
          DPRINT("(string) Returning Size: %lu\n", *lpcbData);
        }
     }
@@ -2228,7 +2400,7 @@ RegQueryValueExW (HKEY hKey,
     {
       if (lpcbData != NULL)
        {
-         *lpcbData = ResultSize - sizeof(*ValueInfo);
+         *lpcbData = ResultSize - FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[0]);
          DPRINT("(other) Returning Size: %lu\n", *lpcbData);
        }
     }
@@ -2449,7 +2621,7 @@ RegQueryValueW (HKEY hKey,
 {
   OBJECT_ATTRIBUTES ObjectAttributes;
   UNICODE_STRING SubKeyString;
-  HKEY KeyHandle;
+  HANDLE KeyHandle;
   HANDLE RealKey;
   LONG ErrorCode;
   BOOL CloseRealKey;
@@ -2811,7 +2983,7 @@ RegSaveKeyW (HKEY hKey,
   UNICODE_STRING FileName;
   IO_STATUS_BLOCK IoStatusBlock;
   HANDLE FileHandle;
-  HKEY KeyHandle;
+  HANDLE KeyHandle;
   NTSTATUS Status;
   LONG ErrorCode;
 
@@ -2886,12 +3058,13 @@ RegSetKeySecurity (HKEY hKey,
                   SECURITY_INFORMATION SecurityInformation,
                   PSECURITY_DESCRIPTOR pSecurityDescriptor)
 {
-  HKEY KeyHandle;
+  HANDLE KeyHandle;
   LONG ErrorCode;
   NTSTATUS Status;
 
   if (hKey == HKEY_PERFORMANCE_DATA)
     {
+      SetLastError(ERROR_INVALID_HANDLE);
       return ERROR_INVALID_HANDLE;
     }
 
@@ -3019,7 +3192,7 @@ RegSetValueExW (HKEY hKey,
 {
   UNICODE_STRING ValueName;
   PUNICODE_STRING pValueName;
-  HKEY KeyHandle;
+  HANDLE KeyHandle;
   NTSTATUS Status;
   LONG ErrorCode;
 
@@ -3134,7 +3307,7 @@ RegSetValueW (HKEY hKey,
 {
   OBJECT_ATTRIBUTES ObjectAttributes;
   UNICODE_STRING SubKeyString;
-  HKEY KeyHandle;
+  HANDLE KeyHandle;
   HANDLE RealKey;
   LONG ErrorCode;
   BOOL CloseRealKey;
@@ -3230,7 +3403,10 @@ RegUnLoadKeyW (HKEY hKey,
   NTSTATUS Status;
 
   if (hKey == HKEY_PERFORMANCE_DATA)
-    return ERROR_INVALID_HANDLE;
+    {
+      SetLastError(ERROR_INVALID_HANDLE);
+      return ERROR_INVALID_HANDLE;
+    }
 
   Status = MapDefaultKey (&KeyHandle, hKey);
   if (!NT_SUCCESS(Status))