Implement RegQueryMultipleValuesA().
[reactos.git] / reactos / lib / advapi32 / reg / reg.c
index d216e0a..4e8e98c 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: reg.c,v 1.55 2004/09/13 08:51:40 ekohl 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
@@ -456,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))
     {
@@ -1444,7 +1446,10 @@ RegEnumValueW (HKEY hKey,
              *lpcbValueName = (DWORD)(ValueInfo->Basic.NameLength / sizeof(WCHAR));
              lpValueName[*lpcbValueName] = 0;
            }
-          *lpcbData = (DWORD)ValueInfo->Full.DataLength;
+         if (NULL != lpcbData)
+           {
+             *lpcbData = (DWORD)ValueInfo->Full.DataLength;
+           }
        }
 
       if (ErrorCode == ERROR_SUCCESS && lpType != NULL)
@@ -1521,6 +1526,7 @@ RegGetKeySecurity(HKEY hKey,
 
   if (hKey == HKEY_PERFORMANCE_DATA)
     {
+      SetLastError(ERROR_INVALID_HANDLE);
       return ERROR_INVALID_HANDLE;
     }
 
@@ -1528,18 +1534,20 @@ RegGetKeySecurity(HKEY hKey,
                         hKey);
   if (!NT_SUCCESS(Status))
     {
+      DPRINT("MapDefaultKey() failed (Status %lx)\n", Status);
       ErrorCode = RtlNtStatusToDosError(Status);
       SetLastError(ErrorCode);
       return ErrorCode;
     }
 
-  Status = NtQuerySecurityObject(hKey,
+  Status = NtQuerySecurityObject(KeyHandle,
                                 SecurityInformation,
                                 pSecurityDescriptor,
                                 *lpcbSecurityDescriptor,
                                 lpcbSecurityDescriptor);
   if (!NT_SUCCESS(Status))
     {
+      DPRINT("NtQuerySecurityObject() failed (Status %lx)\n", Status);
       ErrorCode = RtlNtStatusToDosError(Status);
       SetLastError(ErrorCode);
       return ErrorCode;
@@ -1599,6 +1607,7 @@ RegLoadKeyW (HKEY hKey,
 
   if (hKey == HKEY_PERFORMANCE_DATA)
     {
+      SetLastError(ERROR_INVALID_HANDLE);
       return ERROR_INVALID_HANDLE;
     }
 
@@ -2099,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)
@@ -2141,7 +2168,7 @@ RegQueryInfoKeyW (HKEY hKey,
 /************************************************************************
  *  RegQueryMultipleValuesA
  *
- * @unimplemented
+ * @implemented
  */
 LONG STDCALL
 RegQueryMultipleValuesA (HKEY hKey,
@@ -2150,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;
 }
 
 
@@ -2181,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,
@@ -2262,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);
@@ -2279,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;
@@ -2292,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;
        }
     }
 
@@ -2319,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);
        }
     }
@@ -2327,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);
        }
     }
@@ -2991,6 +3064,7 @@ RegSetKeySecurity (HKEY hKey,
 
   if (hKey == HKEY_PERFORMANCE_DATA)
     {
+      SetLastError(ERROR_INVALID_HANDLE);
       return ERROR_INVALID_HANDLE;
     }
 
@@ -3329,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))