Implement RegQueryMultipleValuesA().
[reactos.git] / reactos / lib / advapi32 / reg / reg.c
index d747d7d..4e8e98c 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: reg.c,v 1.50 2004/07/03 17:40:21 navaraf 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 ******************************************************************/
 
@@ -463,24 +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 = CreateNestedKey(phkResult,
-                          &Attributes,
-                           (lpClass == NULL)? NULL : &ClassString,
-                           dwOptions,
-                           samDesired,
-                           lpdwDisposition);
+                          &Attributes,
+                          (lpClass == NULL)? NULL : &ClassString,
+                          dwOptions,
+                          samDesired,
+                          lpdwDisposition);
   RtlFreeUnicodeString (&SubKeyString);
   if (lpClass != NULL)
     {
       RtlFreeUnicodeString (&ClassString);
     }
+
   DPRINT("Status %x\n", Status);
   if (!NT_SUCCESS(Status))
     {
@@ -1451,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)
@@ -1513,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;
 }
 
 
@@ -1607,6 +1607,7 @@ RegLoadKeyW (HKEY hKey,
 
   if (hKey == HKEY_PERFORMANCE_DATA)
     {
+      SetLastError(ERROR_INVALID_HANDLE);
       return ERROR_INVALID_HANDLE;
     }
 
@@ -2107,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)
@@ -2149,7 +2168,7 @@ RegQueryInfoKeyW (HKEY hKey,
 /************************************************************************
  *  RegQueryMultipleValuesA
  *
- * @unimplemented
+ * @implemented
  */
 LONG STDCALL
 RegQueryMultipleValuesA (HKEY hKey,
@@ -2158,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;
 }
 
 
@@ -2189,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,
@@ -2248,7 +2313,7 @@ RegQueryValueExW (HKEY hKey,
   ULONG BufferSize;
   ULONG ResultSize;
   HANDLE KeyHandle;
-  ULONG MaxCopy = lpcbData ? *lpcbData : 0;
+  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);
@@ -2270,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);
@@ -2287,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;
@@ -2300,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;
        }
     }
 
@@ -2327,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);
        }
     }
@@ -2335,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);
        }
     }
@@ -2999,6 +3064,7 @@ RegSetKeySecurity (HKEY hKey,
 
   if (hKey == HKEY_PERFORMANCE_DATA)
     {
+      SetLastError(ERROR_INVALID_HANDLE);
       return ERROR_INVALID_HANDLE;
     }
 
@@ -3337,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))