-/* $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>
#define MAX_DEFAULT_HANDLES 6
#define REG_MAX_NAME_SIZE 256
-#define REG_MAX_DATA_SIZE 2048
+#define REG_MAX_DATA_SIZE 2048
/* GLOBALS ******************************************************************/
/* PROTOTYPES ***************************************************************/
-static NTSTATUS MapDefaultKey (PHKEY ParentKey, HKEY Key);
+static NTSTATUS MapDefaultKey (PHANDLE ParentKey, HKEY Key);
static VOID CloseDefaultKeys(VOID);
static NTSTATUS OpenClassesRootKey(PHANDLE KeyHandle);
static NTSTATUS
-MapDefaultKey (PHKEY RealKey,
+MapDefaultKey (PHANDLE RealKey,
HKEY Key)
{
PHANDLE Handle;
if (((ULONG)Key & 0xF0000000) != 0x80000000)
{
- *RealKey = Key;
+ *RealKey = (HANDLE)Key;
return STATUS_SUCCESS;
}
if (NT_SUCCESS(Status))
{
- *RealKey = (HKEY)*Handle;
+ *RealKey = *Handle;
}
return Status;
}
+/************************************************************************
+ * 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
*
UNICODE_STRING SubKeyString;
UNICODE_STRING ClassString;
OBJECT_ATTRIBUTES Attributes;
- HKEY ParentKey;
+ HANDLE ParentKey;
LONG ErrorCode;
NTSTATUS Status;
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))
{
UNICODE_STRING SubKeyString;
UNICODE_STRING ClassString;
OBJECT_ATTRIBUTES Attributes;
- HKEY ParentKey;
+ HANDLE ParentKey;
LONG ErrorCode;
NTSTATUS Status;
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))
{
{
OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING SubKeyName;
- HKEY ParentKey;
+ HANDLE ParentKey;
HANDLE TargetKey;
NTSTATUS Status;
LONG ErrorCode;
{
OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING SubKeyName;
- HKEY ParentKey;
+ HANDLE ParentKey;
HANDLE TargetKey;
NTSTATUS Status;
LONG ErrorCode;
LPCSTR lpValueName)
{
UNICODE_STRING ValueName;
- HKEY KeyHandle;
+ HANDLE KeyHandle;
LONG ErrorCode;
NTSTATUS Status;
UNICODE_STRING ValueName;
NTSTATUS Status;
LONG ErrorCode;
- HKEY KeyHandle;
+ HANDLE KeyHandle;
Status = MapDefaultKey (&KeyHandle,
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",
ULONG BufferSize;
ULONG ResultSize;
ULONG NameLength;
- ULONG ClassLength;
- HKEY KeyHandle;
+ ULONG ClassLength = 0;
+ HANDLE KeyHandle;
LONG ErrorCode = ERROR_SUCCESS;
NTSTATUS Status;
ULONG NameLength;
ULONG BufferSize;
- ULONG DataLength;
+ ULONG DataLength = 0;
ULONG ResultSize;
- HKEY KeyHandle;
+ HANDLE KeyHandle;
LONG ErrorCode;
NTSTATUS Status;
UNICODE_STRING StringU;
ULONG NameLength;
ULONG BufferSize;
- ULONG DataLength;
+ ULONG DataLength = 0;
ULONG ResultSize;
- HKEY KeyHandle;
+ HANDLE KeyHandle;
LONG ErrorCode;
NTSTATUS Status;
*lpcbValueName = (DWORD)(ValueInfo->Basic.NameLength / sizeof(WCHAR));
lpValueName[*lpcbValueName] = 0;
}
+ if (NULL != lpcbData)
+ {
+ *lpcbData = (DWORD)ValueInfo->Full.DataLength;
+ }
}
if (ErrorCode == ERROR_SUCCESS && lpType != NULL)
LONG STDCALL
RegFlushKey(HKEY hKey)
{
- HKEY KeyHandle;
+ HANDLE KeyHandle;
LONG ErrorCode;
NTSTATUS Status;
/************************************************************************
* 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;
}
if (hKey == HKEY_PERFORMANCE_DATA)
{
+ SetLastError(ERROR_INVALID_HANDLE);
return ERROR_INVALID_HANDLE;
}
{
OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING SubKeyString;
- HKEY KeyHandle;
+ HANDLE KeyHandle;
LONG ErrorCode;
NTSTATUS Status;
OBJ_CASE_INSENSITIVE,
KeyHandle,
NULL);
- Status = NtOpenKey (phkResult,
+ Status = NtOpenKey ((PHANDLE)phkResult,
MAXIMUM_ALLOWED,
&ObjectAttributes);
RtlFreeUnicodeString (&SubKeyString);
{
OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING SubKeyString;
- HKEY KeyHandle;
+ HANDLE KeyHandle;
LONG ErrorCode;
NTSTATUS Status;
OBJ_CASE_INSENSITIVE,
KeyHandle,
NULL);
- Status = NtOpenKey (phkResult,
+ Status = NtOpenKey ((PHANDLE)phkResult,
MAXIMUM_ALLOWED,
&ObjectAttributes);
if (!NT_SUCCESS(Status))
{
OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING SubKeyString;
- HKEY KeyHandle;
+ HANDLE KeyHandle;
LONG ErrorCode;
NTSTATUS Status;
OBJ_CASE_INSENSITIVE,
KeyHandle,
NULL);
- Status = NtOpenKey (phkResult,
+ Status = NtOpenKey ((PHANDLE)phkResult,
samDesired,
&ObjectAttributes);
RtlFreeUnicodeString (&SubKeyString);
{
OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING SubKeyString;
- HKEY KeyHandle;
+ HANDLE KeyHandle;
LONG ErrorCode;
NTSTATUS Status;
OBJ_CASE_INSENSITIVE,
KeyHandle,
NULL);
- Status = NtOpenKey (phkResult,
+ Status = NtOpenKey ((PHANDLE)phkResult,
samDesired,
&ObjectAttributes);
if (!NT_SUCCESS(Status))
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;
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)
/************************************************************************
* RegQueryMultipleValuesA
*
- * @unimplemented
+ * @implemented
*/
LONG STDCALL
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;
}
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,
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,
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);
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);
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;
MaxCopy = 0;
if (lpcbData != NULL)
{
- ResultSize = sizeof(*ValueInfo) + *lpcbData;
+ ResultSize = FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[0]) + *lpcbData;
}
}
if (lpcbData != NULL)
{
- *lpcbData = (ResultSize - sizeof(*ValueInfo));
+ *lpcbData = (ResultSize - FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[0]));
DPRINT("(string) Returning Size: %lu\n", *lpcbData);
}
}
{
if (lpcbData != NULL)
{
- *lpcbData = ResultSize - sizeof(*ValueInfo);
+ *lpcbData = ResultSize - FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[0]);
DPRINT("(other) Returning Size: %lu\n", *lpcbData);
}
}
{
OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING SubKeyString;
- HKEY KeyHandle;
+ HANDLE KeyHandle;
HANDLE RealKey;
LONG ErrorCode;
BOOL CloseRealKey;
UNICODE_STRING FileName;
IO_STATUS_BLOCK IoStatusBlock;
HANDLE FileHandle;
- HKEY KeyHandle;
+ HANDLE KeyHandle;
NTSTATUS Status;
LONG ErrorCode;
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;
}
{
UNICODE_STRING ValueName;
PUNICODE_STRING pValueName;
- HKEY KeyHandle;
+ HANDLE KeyHandle;
NTSTATUS Status;
LONG ErrorCode;
{
OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING SubKeyString;
- HKEY KeyHandle;
+ HANDLE KeyHandle;
HANDLE RealKey;
LONG ErrorCode;
BOOL CloseRealKey;
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))