X-Git-Url: https://git.reactos.org/?p=reactos.git;a=blobdiff_plain;f=reactos%2Flib%2Fadvapi32%2Freg%2Freg.c;h=671221408836cf1885a651692995c0ad9f5c181e;hp=1664b1fcb7de057834d71bb3340bd549fa48d835;hb=f34a907c7abfee58303bd726baab0d4d5fcec486;hpb=3889a8a8dd4069f8c489f50ef138cb08e1ebf3bb diff --git a/reactos/lib/advapi32/reg/reg.c b/reactos/lib/advapi32/reg/reg.c index 1664b1fcb7d..67122140883 100644 --- a/reactos/lib/advapi32/reg/reg.c +++ b/reactos/lib/advapi32/reg/reg.c @@ -1,4 +1,4 @@ -/* $Id: reg.c,v 1.31 2003/10/14 18:18:27 navaraf Exp $ +/* $Id: reg.c,v 1.56 2004/09/13 11:41:26 ekohl Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS system libraries @@ -12,21 +12,15 @@ /* INCLUDES *****************************************************************/ -#define NTOS_MODE_USER -#include -#include -#include -#include -#include - -//#define NDEBUG +#include "advapi32.h" +#define NDEBUG #include /* DEFINES ******************************************************************/ #define MAX_DEFAULT_HANDLES 6 #define REG_MAX_NAME_SIZE 256 -#define REG_MAX_DATA_SIZE 2048 +#define REG_MAX_DATA_SIZE 2048 /* GLOBALS ******************************************************************/ @@ -36,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); @@ -80,7 +74,7 @@ RegCleanup (VOID) static NTSTATUS -MapDefaultKey (PHKEY RealKey, +MapDefaultKey (PHANDLE RealKey, HKEY Key) { PHANDLE Handle; @@ -91,7 +85,7 @@ MapDefaultKey (PHKEY RealKey, if (((ULONG)Key & 0xF0000000) != 0x80000000) { - *RealKey = Key; + *RealKey = (HANDLE)Key; return STATUS_SUCCESS; } @@ -147,7 +141,7 @@ MapDefaultKey (PHKEY RealKey, if (NT_SUCCESS(Status)) { - *RealKey = (HKEY)*Handle; + *RealKey = *Handle; } return Status; @@ -176,7 +170,7 @@ static NTSTATUS OpenClassesRootKey (PHANDLE KeyHandle) { OBJECT_ATTRIBUTES Attributes; - UNICODE_STRING KeyName = UNICODE_STRING_INITIALIZER(L"\\Registry\\Machine\\Software\\CLASSES"); + UNICODE_STRING KeyName = ROS_STRING_INITIALIZER(L"\\Registry\\Machine\\Software\\CLASSES"); DPRINT("OpenClassesRootKey()\n"); @@ -195,7 +189,8 @@ static NTSTATUS OpenLocalMachineKey (PHANDLE KeyHandle) { OBJECT_ATTRIBUTES Attributes; - UNICODE_STRING KeyName = UNICODE_STRING_INITIALIZER(L"\\Registry\\Machine"); + UNICODE_STRING KeyName = ROS_STRING_INITIALIZER(L"\\Registry\\Machine"); + NTSTATUS Status; DPRINT("OpenLocalMachineKey()\n"); @@ -204,9 +199,12 @@ OpenLocalMachineKey (PHANDLE KeyHandle) OBJ_CASE_INSENSITIVE, NULL, NULL); - return NtOpenKey (KeyHandle, - MAXIMUM_ALLOWED, - &Attributes); + Status = NtOpenKey (KeyHandle, + MAXIMUM_ALLOWED, + &Attributes); + + DPRINT("NtOpenKey(%wZ) => %08x\n", &KeyName, Status); + return Status; } @@ -214,7 +212,7 @@ static NTSTATUS OpenUsersKey (PHANDLE KeyHandle) { OBJECT_ATTRIBUTES Attributes; - UNICODE_STRING KeyName = UNICODE_STRING_INITIALIZER(L"\\Registry\\User"); + UNICODE_STRING KeyName = ROS_STRING_INITIALIZER(L"\\Registry\\User"); DPRINT("OpenUsersKey()\n"); @@ -234,7 +232,7 @@ OpenCurrentConfigKey (PHANDLE KeyHandle) { OBJECT_ATTRIBUTES Attributes; UNICODE_STRING KeyName = - UNICODE_STRING_INITIALIZER(L"\\Registry\\Machine\\System\\CurrentControlSet\\Hardware Profiles\\Current"); + ROS_STRING_INITIALIZER(L"\\Registry\\Machine\\System\\CurrentControlSet\\Hardware Profiles\\Current"); DPRINT("OpenCurrentConfigKey()\n"); @@ -308,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 * @@ -327,7 +434,7 @@ RegCreateKeyExA (HKEY hKey, UNICODE_STRING SubKeyString; UNICODE_STRING ClassString; OBJECT_ATTRIBUTES Attributes; - HKEY ParentKey; + HANDLE ParentKey; LONG ErrorCode; NTSTATUS Status; @@ -356,13 +463,12 @@ RegCreateKeyExA (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); RtlFreeUnicodeString (&SubKeyString); if (lpClass != NULL) { @@ -386,20 +492,20 @@ RegCreateKeyExA (HKEY hKey, * @implemented */ LONG STDCALL -RegCreateKeyExW(HKEY hKey, - LPCWSTR lpSubKey, - DWORD Reserved, - LPWSTR lpClass, - DWORD dwOptions, - REGSAM samDesired, - LPSECURITY_ATTRIBUTES lpSecurityAttributes, - PHKEY phkResult, - LPDWORD lpdwDisposition) +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; - HKEY ParentKey; + HANDLE ParentKey; LONG ErrorCode; NTSTATUS Status; @@ -425,13 +531,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)) { @@ -499,7 +604,7 @@ RegDeleteKeyA (HKEY hKey, { OBJECT_ATTRIBUTES ObjectAttributes; UNICODE_STRING SubKeyName; - HKEY ParentKey; + HANDLE ParentKey; HANDLE TargetKey; NTSTATUS Status; LONG ErrorCode; @@ -556,7 +661,7 @@ RegDeleteKeyW (HKEY hKey, { OBJECT_ATTRIBUTES ObjectAttributes; UNICODE_STRING SubKeyName; - HKEY ParentKey; + HANDLE ParentKey; HANDLE TargetKey; NTSTATUS Status; LONG ErrorCode; @@ -610,7 +715,7 @@ RegDeleteValueA (HKEY hKey, LPCSTR lpValueName) { UNICODE_STRING ValueName; - HKEY KeyHandle; + HANDLE KeyHandle; LONG ErrorCode; NTSTATUS Status; @@ -651,7 +756,7 @@ RegDeleteValueW (HKEY hKey, UNICODE_STRING ValueName; NTSTATUS Status; LONG ErrorCode; - HKEY KeyHandle; + HANDLE KeyHandle; Status = MapDefaultKey (&KeyHandle, hKey); @@ -753,10 +858,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", @@ -767,6 +872,7 @@ RegEnumKeyExA (HKEY hKey, SetLastError (ERROR_INVALID_PARAMETER); return ERROR_INVALID_PARAMETER; } + Status = MapDefaultKey(&KeyHandle, hKey); if (!NT_SUCCESS(Status)) @@ -784,16 +890,18 @@ RegEnumKeyExA (HKEY hKey, { NameLength = 0; } + if (lpClass) { if (*lpcbClass > 0) - { - ClassLength = min (*lpcbClass -1, REG_MAX_NAME_SIZE) * sizeof(WCHAR); + { + ClassLength = min (*lpcbClass -1, REG_MAX_NAME_SIZE) * sizeof(WCHAR); } else - { + { ClassLength = 0; } + /* The class name should start at a dword boundary */ BufferSize = ((sizeof(KEY_NODE_INFORMATION) + NameLength + 3) & ~3) + ClassLength; } @@ -801,11 +909,10 @@ RegEnumKeyExA (HKEY hKey, { BufferSize = sizeof(KEY_BASIC_INFORMATION) + NameLength; } - + KeyInfo = RtlAllocateHeap (ProcessHeap, 0, BufferSize); - if (KeyInfo == NULL) { SetLastError (ERROR_OUTOFMEMORY); @@ -826,7 +933,7 @@ RegEnumKeyExA (HKEY hKey, else { if (lpClass == NULL) - { + { if (KeyInfo->Basic.NameLength > NameLength) { ErrorCode = ERROR_BUFFER_OVERFLOW; @@ -839,7 +946,7 @@ RegEnumKeyExA (HKEY hKey, } } else - { + { if (KeyInfo->Node.NameLength > NameLength || KeyInfo->Node.ClassLength > ClassLength) { @@ -847,13 +954,13 @@ RegEnumKeyExA (HKEY hKey, } else { - StringA.Buffer = lpClass; + StringA.Buffer = lpClass; StringA.Length = 0; StringA.MaximumLength = *lpcbClass; StringU.Buffer = (PWCHAR)((ULONG_PTR)KeyInfo->Node.Name + KeyInfo->Node.ClassOffset); StringU.Length = KeyInfo->Node.ClassLength; StringU.MaximumLength = KeyInfo->Node.ClassLength; - RtlUnicodeStringToAnsiString (&StringA, &StringU, FALSE); + RtlUnicodeStringToAnsiString (&StringA, &StringU, FALSE); lpClass[StringA.Length] = 0; *lpcbClass = StringA.Length; StringU.Buffer = KeyInfo->Node.Name; @@ -861,26 +968,27 @@ RegEnumKeyExA (HKEY hKey, StringU.MaximumLength = KeyInfo->Node.NameLength; } } + if (ErrorCode == ERROR_SUCCESS) - { - StringA.Buffer = lpName; + { + StringA.Buffer = lpName; StringA.Length = 0; StringA.MaximumLength = *lpcbName; - RtlUnicodeStringToAnsiString (&StringA, &StringU, FALSE); + RtlUnicodeStringToAnsiString (&StringA, &StringU, FALSE); lpName[StringA.Length] = 0; *lpcbName = StringA.Length; if (lpftLastWriteTime != NULL) { if (lpClass == NULL) - { - lpftLastWriteTime->dwLowDateTime = KeyInfo->Basic.LastWriteTime.u.LowPart; - lpftLastWriteTime->dwHighDateTime = KeyInfo->Basic.LastWriteTime.u.HighPart; - } + { + lpftLastWriteTime->dwLowDateTime = KeyInfo->Basic.LastWriteTime.u.LowPart; + lpftLastWriteTime->dwHighDateTime = KeyInfo->Basic.LastWriteTime.u.HighPart; + } else - { - lpftLastWriteTime->dwLowDateTime = KeyInfo->Node.LastWriteTime.u.LowPart; - lpftLastWriteTime->dwHighDateTime = KeyInfo->Node.LastWriteTime.u.HighPart; - } + { + lpftLastWriteTime->dwLowDateTime = KeyInfo->Node.LastWriteTime.u.LowPart; + lpftLastWriteTime->dwHighDateTime = KeyInfo->Node.LastWriteTime.u.HighPart; + } } } } @@ -927,8 +1035,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; @@ -940,6 +1048,7 @@ RegEnumKeyExW (HKEY hKey, SetLastError (ErrorCode); return ErrorCode; } + if (*lpcbName > 0) { NameLength = min (*lpcbName - 1, REG_MAX_NAME_SIZE) * sizeof (WCHAR); @@ -948,22 +1057,25 @@ RegEnumKeyExW (HKEY hKey, { NameLength = 0; } + if (lpClass) { if (*lpcbClass > 0) - { - ClassLength = min (*lpcbClass - 1, REG_MAX_NAME_SIZE) * sizeof(WCHAR); + { + ClassLength = min (*lpcbClass - 1, REG_MAX_NAME_SIZE) * sizeof(WCHAR); } else - { + { ClassLength = 0; } + BufferSize = ((sizeof(KEY_NODE_INFORMATION) + NameLength + 3) & ~3) + ClassLength; } else { BufferSize = sizeof(KEY_BASIC_INFORMATION) + NameLength; } + KeyInfo = RtlAllocateHeap (ProcessHeap, 0, BufferSize); @@ -987,7 +1099,7 @@ RegEnumKeyExW (HKEY hKey, else { if (lpClass == NULL) - { + { if (KeyInfo->Basic.NameLength > NameLength) { ErrorCode = ERROR_BUFFER_OVERFLOW; @@ -1002,7 +1114,7 @@ RegEnumKeyExW (HKEY hKey, } } else - { + { if (KeyInfo->Node.NameLength > NameLength || KeyInfo->Node.ClassLength > ClassLength) { @@ -1011,7 +1123,7 @@ RegEnumKeyExW (HKEY hKey, else { RtlCopyMemory (lpName, - KeyInfo->Node.Name, + KeyInfo->Node.Name, KeyInfo->Node.NameLength); *lpcbName = KeyInfo->Node.NameLength / sizeof(WCHAR); lpName[*lpcbName] = 0; @@ -1022,6 +1134,7 @@ RegEnumKeyExW (HKEY hKey, lpClass[*lpcbClass] = 0; } } + if (ErrorCode == ERROR_SUCCESS && lpftLastWriteTime != NULL) { if (lpClass == NULL) @@ -1045,6 +1158,7 @@ RegEnumKeyExW (HKEY hKey, { SetLastError(ErrorCode); } + return ErrorCode; } @@ -1072,9 +1186,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; @@ -1100,6 +1214,7 @@ RegEnumValueA (HKEY hKey, { NameLength = 0; } + if (lpData) { DataLength = min (*lpcbData * sizeof(WCHAR), REG_MAX_DATA_SIZE); @@ -1111,7 +1226,7 @@ RegEnumValueA (HKEY hKey, } ValueInfo = RtlAllocateHeap (ProcessHeap, - 0, + 0, BufferSize); if (ValueInfo == NULL) { @@ -1135,8 +1250,8 @@ RegEnumValueA (HKEY hKey, { if (lpData) { - IsStringType = (ValueInfo->Full.Type == REG_SZ) || - (ValueInfo->Full.Type == REG_MULTI_SZ) || + IsStringType = (ValueInfo->Full.Type == REG_SZ) || + (ValueInfo->Full.Type == REG_MULTI_SZ) || (ValueInfo->Full.Type == REG_EXPAND_SZ); if (ValueInfo->Full.NameLength > NameLength || (!IsStringType && ValueInfo->Full.DataLength > *lpcbData) || @@ -1154,45 +1269,47 @@ RegEnumValueA (HKEY hKey, StringA.Buffer = (PCHAR)lpData; StringA.Length = 0; StringA.MaximumLength = *lpcbData; - RtlUnicodeStringToAnsiString (&StringA, - &StringU, - FALSE); - *lpcbData = StringA.Length; + RtlUnicodeStringToAnsiString (&StringA, + &StringU, + FALSE); + *lpcbData = StringA.Length; } else - { - RtlCopyMemory(lpData, - (PVOID)((ULONG_PTR)ValueInfo + ValueInfo->Full.DataOffset), - ValueInfo->Full.DataLength); + { + RtlCopyMemory (lpData, + (PVOID)((ULONG_PTR)ValueInfo + ValueInfo->Full.DataOffset), + ValueInfo->Full.DataLength); *lpcbData = ValueInfo->Full.DataLength; } - StringU.Buffer = ValueInfo->Full.Name; + + StringU.Buffer = ValueInfo->Full.Name; StringU.Length = ValueInfo->Full.NameLength; StringU.MaximumLength = NameLength; } } else - { + { if (ValueInfo->Basic.NameLength > NameLength) { ErrorCode = ERROR_BUFFER_OVERFLOW; } else { - StringU.Buffer = ValueInfo->Basic.Name; + StringU.Buffer = ValueInfo->Basic.Name; StringU.Length = ValueInfo->Basic.NameLength; StringU.MaximumLength = NameLength; } } + if (ErrorCode == ERROR_SUCCESS) { StringA.Buffer = (PCHAR)lpValueName; StringA.Length = 0; StringA.MaximumLength = *lpcbValueName; RtlUnicodeStringToAnsiString (&StringA, - &StringU, + &StringU, FALSE); - StringA.Buffer[StringA.Length] = 0; + StringA.Buffer[StringA.Length] = 0; *lpcbValueName = StringA.Length; if (lpType) { @@ -1200,13 +1317,15 @@ RegEnumValueA (HKEY hKey, } } } + RtlFreeHeap (ProcessHeap, - 0, + 0, ValueInfo); if (ErrorCode != ERROR_SUCCESS) { SetLastError(ErrorCode); } + return ErrorCode; } @@ -1234,12 +1353,12 @@ RegEnumValueW (HKEY hKey, ULONG NameLength; ULONG BufferSize; - ULONG DataLength; + ULONG DataLength = 0; ULONG ResultSize; - HKEY KeyHandle; + HANDLE KeyHandle; LONG ErrorCode; NTSTATUS Status; - + ErrorCode = ERROR_SUCCESS; Status = MapDefaultKey (&KeyHandle, @@ -1250,7 +1369,7 @@ RegEnumValueW (HKEY hKey, SetLastError (ErrorCode); return ErrorCode; } - + if (*lpcbValueName > 0) { NameLength = min (*lpcbValueName - 1, REG_MAX_NAME_SIZE) * sizeof(WCHAR); @@ -1259,6 +1378,7 @@ RegEnumValueW (HKEY hKey, { NameLength = 0; } + if (lpData) { DataLength = min(*lpcbData, REG_MAX_DATA_SIZE); @@ -1291,13 +1411,13 @@ RegEnumValueW (HKEY hKey, else { if (lpData) - { - if (ValueInfo->Full.DataLength > DataLength || + { + if (ValueInfo->Full.DataLength > DataLength || ValueInfo->Full.NameLength > NameLength) - { + { ErrorCode = ERROR_BUFFER_OVERFLOW; } - else + else { RtlCopyMemory (lpValueName, ValueInfo->Full.Name, @@ -1311,7 +1431,7 @@ RegEnumValueW (HKEY hKey, } } else - { + { if (ValueInfo->Basic.NameLength > NameLength) { ErrorCode = ERROR_BUFFER_OVERFLOW; @@ -1324,19 +1444,24 @@ RegEnumValueW (HKEY hKey, *lpcbValueName = (DWORD)(ValueInfo->Basic.NameLength / sizeof(WCHAR)); lpValueName[*lpcbValueName] = 0; } + *lpcbData = (DWORD)ValueInfo->Full.DataLength; } + if (ErrorCode == ERROR_SUCCESS && lpType != NULL) { *lpType = lpData ? ValueInfo->Full.Type : ValueInfo->Basic.Type; } } + RtlFreeHeap (ProcessHeap, 0, ValueInfo); + if (ErrorCode != ERROR_SUCCESS) { - SetLastError(ErrorCode); + SetLastError (ErrorCode); } + return ErrorCode; } @@ -1349,7 +1474,7 @@ RegEnumValueW (HKEY hKey, LONG STDCALL RegFlushKey(HKEY hKey) { - HKEY KeyHandle; + HANDLE KeyHandle; LONG ErrorCode; NTSTATUS Status; @@ -1382,47 +1507,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; } @@ -1438,7 +1564,7 @@ RegLoadKeyA (HKEY hKey, { UNICODE_STRING FileName; UNICODE_STRING KeyName; - DWORD ErrorCode; + LONG ErrorCode; RtlCreateUnicodeStringFromAsciiz (&KeyName, (LPSTR)lpSubKey); @@ -1471,11 +1597,12 @@ RegLoadKeyW (HKEY hKey, UNICODE_STRING FileName; UNICODE_STRING KeyName; HANDLE KeyHandle; - DWORD ErrorCode; + LONG ErrorCode; NTSTATUS Status; if (hKey == HKEY_PERFORMANCE_DATA) { + SetLastError(ERROR_INVALID_HANDLE); return ERROR_INVALID_HANDLE; } @@ -1582,7 +1709,6 @@ RegNotifyChangeKeyValue (HKEY hKey, } - /************************************************************************ * RegOpenKeyA * @@ -1595,7 +1721,7 @@ RegOpenKeyA (HKEY hKey, { OBJECT_ATTRIBUTES ObjectAttributes; UNICODE_STRING SubKeyString; - HKEY KeyHandle; + HANDLE KeyHandle; LONG ErrorCode; NTSTATUS Status; @@ -1615,7 +1741,7 @@ RegOpenKeyA (HKEY hKey, OBJ_CASE_INSENSITIVE, KeyHandle, NULL); - Status = NtOpenKey (phkResult, + Status = NtOpenKey ((PHANDLE)phkResult, MAXIMUM_ALLOWED, &ObjectAttributes); RtlFreeUnicodeString (&SubKeyString); @@ -1645,7 +1771,7 @@ RegOpenKeyW (HKEY hKey, { OBJECT_ATTRIBUTES ObjectAttributes; UNICODE_STRING SubKeyString; - HKEY KeyHandle; + HANDLE KeyHandle; LONG ErrorCode; NTSTATUS Status; @@ -1665,7 +1791,7 @@ RegOpenKeyW (HKEY hKey, OBJ_CASE_INSENSITIVE, KeyHandle, NULL); - Status = NtOpenKey (phkResult, + Status = NtOpenKey ((PHANDLE)phkResult, MAXIMUM_ALLOWED, &ObjectAttributes); if (!NT_SUCCESS(Status)) @@ -1693,7 +1819,7 @@ RegOpenKeyExA (HKEY hKey, { OBJECT_ATTRIBUTES ObjectAttributes; UNICODE_STRING SubKeyString; - HKEY KeyHandle; + HANDLE KeyHandle; LONG ErrorCode; NTSTATUS Status; @@ -1713,7 +1839,7 @@ RegOpenKeyExA (HKEY hKey, OBJ_CASE_INSENSITIVE, KeyHandle, NULL); - Status = NtOpenKey (phkResult, + Status = NtOpenKey ((PHANDLE)phkResult, samDesired, &ObjectAttributes); RtlFreeUnicodeString (&SubKeyString); @@ -1742,7 +1868,7 @@ RegOpenKeyExW (HKEY hKey, { OBJECT_ATTRIBUTES ObjectAttributes; UNICODE_STRING SubKeyString; - HKEY KeyHandle; + HANDLE KeyHandle; LONG ErrorCode; NTSTATUS Status; @@ -1770,7 +1896,7 @@ RegOpenKeyExW (HKEY hKey, OBJ_CASE_INSENSITIVE, KeyHandle, NULL); - Status = NtOpenKey (phkResult, + Status = NtOpenKey ((PHANDLE)phkResult, samDesired, &ObjectAttributes); if (!NT_SUCCESS(Status)) @@ -1867,8 +1993,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; @@ -1891,13 +2017,14 @@ RegQueryInfoKeyW (HKEY hKey, if (lpClass != NULL) { if (*lpcbClass > 0) - { - ClassLength = min(*lpcbClass - 1, REG_MAX_NAME_SIZE) * sizeof(WCHAR); + { + ClassLength = min(*lpcbClass - 1, REG_MAX_NAME_SIZE) * sizeof(WCHAR); } else - { + { ClassLength = 0; } + FullInfoSize = sizeof(KEY_FULL_INFORMATION) + ((ClassLength + 3) & ~3); FullInfo = RtlAllocateHeap (ProcessHeap, 0, @@ -1907,6 +2034,7 @@ RegQueryInfoKeyW (HKEY hKey, SetLastError (ERROR_OUTOFMEMORY); return ERROR_OUTOFMEMORY; } + FullInfo->ClassLength = ClassLength; } else @@ -1925,83 +2053,89 @@ RegQueryInfoKeyW (HKEY hKey, DPRINT("NtQueryKey() returned status 0x%X\n", Status); if (!NT_SUCCESS(Status)) { + if (lpClass != NULL) + { + RtlFreeHeap (ProcessHeap, + 0, + FullInfo); + } + ErrorCode = RtlNtStatusToDosError (Status); + SetLastError (ErrorCode); + return ErrorCode; } - else - { - DPRINT("SubKeys %d\n", FullInfo->SubKeys); - if (lpcSubKeys != NULL) - { - *lpcSubKeys = FullInfo->SubKeys; - } - DPRINT("MaxNameLen %lu\n", FullInfo->MaxNameLen); - if (lpcbMaxSubKeyLen != NULL) - { - *lpcbMaxSubKeyLen = FullInfo->MaxNameLen / sizeof(WCHAR) + 1; - } + DPRINT("SubKeys %d\n", FullInfo->SubKeys); + if (lpcSubKeys != NULL) + { + *lpcSubKeys = FullInfo->SubKeys; + } - DPRINT("MaxClassLen %lu\n", FullInfo->MaxClassLen); - if (lpcbMaxClassLen != NULL) - { - *lpcbMaxClassLen = FullInfo->MaxClassLen / sizeof(WCHAR) + 1; - } + DPRINT("MaxNameLen %lu\n", FullInfo->MaxNameLen); + if (lpcbMaxSubKeyLen != NULL) + { + *lpcbMaxSubKeyLen = FullInfo->MaxNameLen / sizeof(WCHAR) + 1; + } - DPRINT("Values %lu\n", FullInfo->Values); - if (lpcValues) - { - *lpcValues = FullInfo->Values; - } + DPRINT("MaxClassLen %lu\n", FullInfo->MaxClassLen); + if (lpcbMaxClassLen != NULL) + { + *lpcbMaxClassLen = FullInfo->MaxClassLen / sizeof(WCHAR) + 1; + } - DPRINT("MaxValueNameLen %lu\n", FullInfo->MaxValueNameLen); - if (lpcbMaxValueNameLen) - { - *lpcbMaxValueNameLen = FullInfo->MaxValueNameLen / sizeof(WCHAR) + 1; - } + DPRINT("Values %lu\n", FullInfo->Values); + if (lpcValues != NULL) + { + *lpcValues = FullInfo->Values; + } - DPRINT("MaxValueDataLen %lu\n", FullInfo->MaxValueDataLen); - if (lpcbMaxValueLen) - { - *lpcbMaxValueLen = FullInfo->MaxValueDataLen; - } + DPRINT("MaxValueNameLen %lu\n", FullInfo->MaxValueNameLen); + if (lpcbMaxValueNameLen != NULL) + { + *lpcbMaxValueNameLen = FullInfo->MaxValueNameLen / sizeof(WCHAR) + 1; + } - if (lpcbSecurityDescriptor) - { - *lpcbSecurityDescriptor = 0; - /* FIXME */ - } + DPRINT("MaxValueDataLen %lu\n", FullInfo->MaxValueDataLen); + if (lpcbMaxValueLen != NULL) + { + *lpcbMaxValueLen = FullInfo->MaxValueDataLen; + } - if (lpftLastWriteTime != NULL) - { - lpftLastWriteTime->dwLowDateTime = FullInfo->LastWriteTime.u.LowPart; - lpftLastWriteTime->dwHighDateTime = FullInfo->LastWriteTime.u.HighPart; - } + if (lpcbSecurityDescriptor != NULL) + { + /* FIXME */ + *lpcbSecurityDescriptor = 0; + } - if (lpClass != NULL) - { - if (FullInfo->ClassLength > ClassLength) - { - ErrorCode = ERROR_BUFFER_OVERFLOW; - } - else - { - RtlCopyMemory (lpClass, - FullInfo->Class, - FullInfo->ClassLength); - *lpcbClass = FullInfo->ClassLength / sizeof(WCHAR); - lpClass[*lpcbClass] = 0; - } - } + if (lpftLastWriteTime != NULL) + { + lpftLastWriteTime->dwLowDateTime = FullInfo->LastWriteTime.u.LowPart; + lpftLastWriteTime->dwHighDateTime = FullInfo->LastWriteTime.u.HighPart; } + if (lpClass != NULL) { + if (FullInfo->ClassLength > ClassLength) + { + ErrorCode = ERROR_BUFFER_OVERFLOW; + } + else + { + RtlCopyMemory (lpClass, + FullInfo->Class, + FullInfo->ClassLength); + *lpcbClass = FullInfo->ClassLength / sizeof(WCHAR); + lpClass[*lpcbClass] = 0; + } + RtlFreeHeap (ProcessHeap, - 0, + 0, FullInfo); } + if (ErrorCode != ERROR_SUCCESS) { - SetLastError(ErrorCode); + SetLastError (ErrorCode); } return ErrorCode; @@ -2040,32 +2174,42 @@ RegQueryMultipleValuesW (HKEY hKey, { ULONG i; DWORD maxBytes = *ldwTotsize; - HRESULT status; LPSTR bufptr = (LPSTR)lpValueBuf; + LONG ErrorCode; - if ( maxBytes >= (1024*1024) ) + if (maxBytes >= (1024*1024)) return ERROR_TRANSFER_TOO_LONG; *ldwTotsize = 0; - //TRACE("(%p,%p,%ld,%p,%p=%ld)\n", hKey, val_list, num_vals, lpValueBuf, ldwTotsize, *ldwTotsize); + 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; - status = RegQueryValueExW(hKey, val_list[i].ve_valuename, NULL, NULL, NULL, &val_list[i].ve_valuelen); - if(status != ERROR_SUCCESS) + val_list[i].ve_valuelen = 0; + ErrorCode = RegQueryValueExW (hKey, + val_list[i].ve_valuename, + NULL, + NULL, + NULL, + &val_list[i].ve_valuelen); + if (ErrorCode != ERROR_SUCCESS) { - return status; + return ErrorCode; } - if(lpValueBuf != NULL && *ldwTotsize + val_list[i].ve_valuelen <= maxBytes) + if (lpValueBuf != NULL && *ldwTotsize + val_list[i].ve_valuelen <= maxBytes) { - status = RegQueryValueExW(hKey, val_list[i].ve_valuename, NULL, &val_list[i].ve_type, - bufptr, &val_list[i].ve_valuelen); - if(status != ERROR_SUCCESS) + ErrorCode = RegQueryValueExW (hKey, + val_list[i].ve_valuename, + NULL, + &val_list[i].ve_type, + bufptr, + &val_list[i].ve_valuelen); + if (ErrorCode != ERROR_SUCCESS) { - return status; + return ErrorCode; } val_list[i].ve_valueptr = (DWORD_PTR)bufptr; @@ -2075,7 +2219,8 @@ RegQueryMultipleValuesW (HKEY hKey, *ldwTotsize += val_list[i].ve_valuelen; } - return lpValueBuf != NULL && *ldwTotsize <= maxBytes ? ERROR_SUCCESS : ERROR_MORE_DATA; + + return (lpValueBuf != NULL && *ldwTotsize <= maxBytes) ? ERROR_SUCCESS : ERROR_MORE_DATA; } @@ -2098,7 +2243,8 @@ RegQueryValueExW (HKEY hKey, LONG ErrorCode = ERROR_SUCCESS; ULONG BufferSize; ULONG ResultSize; - HKEY KeyHandle; + 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); @@ -2120,7 +2266,7 @@ RegQueryValueExW (HKEY hKey, RtlInitUnicodeString (&ValueName, lpValueName); - BufferSize = sizeof (KEY_VALUE_PARTIAL_INFORMATION) + *lpcbData; + BufferSize = sizeof (KEY_VALUE_PARTIAL_INFORMATION) + MaxCopy; ValueInfo = RtlAllocateHeap (ProcessHeap, 0, BufferSize); @@ -2140,35 +2286,58 @@ RegQueryValueExW (HKEY hKey, if (Status == STATUS_BUFFER_TOO_SMALL) { /* Return ERROR_SUCCESS and the buffer space needed for a successful call */ - ErrorCode = ERROR_SUCCESS; + MaxCopy = 0; + ErrorCode = lpData ? ERROR_MORE_DATA : ERROR_SUCCESS; } else if (!NT_SUCCESS(Status)) { ErrorCode = RtlNtStatusToDosError (Status); SetLastError (ErrorCode); - } - else - { - if (lpType != NULL) + MaxCopy = 0; + if (lpcbData != NULL) { - *lpType = ValueInfo->Type; + ResultSize = sizeof(*ValueInfo) + *lpcbData; } + } + + if (lpType != NULL) + { + *lpType = ValueInfo->Type; + } + + if (NT_SUCCESS(Status) && lpData != NULL) + { RtlMoveMemory (lpData, ValueInfo->Data, - ValueInfo->DataLength); - if ((ValueInfo->Type == REG_SZ) || - (ValueInfo->Type == REG_MULTI_SZ) || - (ValueInfo->Type == REG_EXPAND_SZ)) + min(ValueInfo->DataLength, MaxCopy)); + } + + if ((ValueInfo->Type == REG_SZ) || + (ValueInfo->Type == REG_MULTI_SZ) || + (ValueInfo->Type == REG_EXPAND_SZ)) + { + if (lpData != NULL && MaxCopy > ValueInfo->DataLength) { ((PWSTR)lpData)[ValueInfo->DataLength / sizeof(WCHAR)] = 0; } - } - DPRINT("Type %d Size %d\n", ValueInfo->Type, ValueInfo->DataLength); - if (NULL != lpcbData) + if (lpcbData != NULL) + { + *lpcbData = (ResultSize - sizeof(*ValueInfo)); + DPRINT("(string) Returning Size: %lu\n", *lpcbData); + } + } + else { - *lpcbData = (DWORD)ValueInfo->DataLength; + if (lpcbData != NULL) + { + *lpcbData = ResultSize - sizeof(*ValueInfo); + DPRINT("(other) Returning Size: %lu\n", *lpcbData); + } } + + DPRINT("Type %d Size %d\n", ValueInfo->Type, ValueInfo->DataLength); + RtlFreeHeap (ProcessHeap, 0, ValueInfo); @@ -2182,22 +2351,22 @@ RegQueryValueExW (HKEY hKey, * * @implemented */ -LONG -STDCALL -RegQueryValueExA( - HKEY hKey, - LPCSTR lpValueName, - LPDWORD lpReserved, - LPDWORD lpType, - LPBYTE lpData, - LPDWORD lpcbData) +LONG STDCALL +RegQueryValueExA (HKEY hKey, + LPCSTR lpValueName, + LPDWORD lpReserved, + LPDWORD lpType, + LPBYTE lpData, + LPDWORD lpcbData) { UNICODE_STRING ValueName; UNICODE_STRING ValueData; ANSI_STRING AnsiString; LONG ErrorCode; + DWORD Length; + DWORD Type; - if ((lpData) && (!lpcbData)) + if (lpData != NULL && lpcbData == NULL) { SetLastError(ERROR_INVALID_PARAMETER); return ERROR_INVALID_PARAMETER; @@ -2205,48 +2374,76 @@ RegQueryValueExA( if (lpData) { - ValueData.Length = ValueData.MaximumLength = *lpcbData * sizeof(WCHAR); - ValueData.Buffer = RtlAllocateHeap( - ProcessHeap, - 0, - ValueData.Length); + ValueData.Length = *lpcbData * sizeof(WCHAR); + ValueData.MaximumLength = ValueData.Length + sizeof(WCHAR); + ValueData.Buffer = RtlAllocateHeap (ProcessHeap, + 0, + ValueData.MaximumLength); if (!ValueData.Buffer) - { - SetLastError(ERROR_OUTOFMEMORY); - return ERROR_OUTOFMEMORY; - } + { + SetLastError(ERROR_OUTOFMEMORY); + return ERROR_OUTOFMEMORY; + } } else { ValueData.Buffer = NULL; + ValueData.Length = 0; + ValueData.MaximumLength = 0; } - RtlCreateUnicodeStringFromAsciiz(&ValueName, (LPSTR)lpValueName); + RtlCreateUnicodeStringFromAsciiz (&ValueName, + (LPSTR)lpValueName); - ErrorCode = RegQueryValueExW( - hKey, - ValueName.Buffer, - lpReserved, - lpType, - (LPBYTE)ValueData.Buffer, - (LPDWORD)&ValueData.Length); + if (NULL != lpcbData) + { + Length = *lpcbData * sizeof(WCHAR); + } + ErrorCode = RegQueryValueExW (hKey, + ValueName.Buffer, + lpReserved, + &Type, + (LPBYTE)ValueData.Buffer, + NULL == lpcbData ? NULL : &Length); + DPRINT("ErrorCode %lu\n", ErrorCode); - if ((ErrorCode == ERROR_SUCCESS) && (ValueData.Buffer != NULL)) + if (ErrorCode == ERROR_SUCCESS || + ErrorCode == ERROR_MORE_DATA) { - if (lpType && ((*lpType == REG_SZ) || (*lpType == REG_MULTI_SZ) || (*lpType == REG_EXPAND_SZ))) - { - RtlInitAnsiString(&AnsiString, NULL); - AnsiString.Buffer = lpData; - AnsiString.MaximumLength = *lpcbData; - RtlUnicodeStringToAnsiString(&AnsiString, &ValueData, FALSE); - *lpcbData = ValueData.Length / sizeof(WCHAR); - } else { - RtlMoveMemory(lpData, ValueData.Buffer, *lpcbData); - *lpcbData = ValueData.Length; - } - } + if (lpType != NULL) + { + *lpType = Type; + } + + if ((Type == REG_SZ) || (Type == REG_MULTI_SZ) || (Type == REG_EXPAND_SZ)) + { + if (ErrorCode == ERROR_SUCCESS && ValueData.Buffer != NULL) + { + RtlInitAnsiString(&AnsiString, NULL); + AnsiString.Buffer = lpData; + AnsiString.MaximumLength = *lpcbData; + ValueData.Length = Length; + ValueData.MaximumLength = ValueData.Length + sizeof(WCHAR); + RtlUnicodeStringToAnsiString(&AnsiString, &ValueData, FALSE); + } + Length = Length / sizeof(WCHAR); + } + else if (lpcbData != NULL) + { + Length = min(*lpcbData, Length); + if (ErrorCode == ERROR_SUCCESS && ValueData.Buffer != NULL) + { + RtlMoveMemory(lpData, ValueData.Buffer, Length); + } + } - if (ValueData.Buffer) + if (lpcbData != NULL) + { + *lpcbData = Length; + } + } + + if (ValueData.Buffer != NULL) { RtlFreeHeap(ProcessHeap, 0, ValueData.Buffer); } @@ -2355,7 +2552,7 @@ RegQueryValueW (HKEY hKey, { OBJECT_ATTRIBUTES ObjectAttributes; UNICODE_STRING SubKeyString; - HKEY KeyHandle; + HANDLE KeyHandle; HANDLE RealKey; LONG ErrorCode; BOOL CloseRealKey; @@ -2423,19 +2620,28 @@ RegReplaceKeyA (HKEY hKey, LPCSTR lpNewFile, LPCSTR lpOldFile) { - UNICODE_STRING lpSubKeyW; - UNICODE_STRING lpNewFileW; - UNICODE_STRING lpOldFileW; - LONG ret; - - RtlCreateUnicodeStringFromAsciiz( &lpSubKeyW, (PCSZ)lpSubKey ); - RtlCreateUnicodeStringFromAsciiz( &lpOldFileW, (PCSZ)lpOldFile ); - RtlCreateUnicodeStringFromAsciiz( &lpNewFileW, (PCSZ)lpNewFile ); - ret = RegReplaceKeyW( hKey, lpSubKeyW.Buffer, lpNewFileW.Buffer, lpOldFileW.Buffer ); - RtlFreeUnicodeString( &lpOldFileW ); - RtlFreeUnicodeString( &lpNewFileW ); - RtlFreeUnicodeString( &lpSubKeyW ); - return ret; + UNICODE_STRING SubKey; + UNICODE_STRING NewFile; + UNICODE_STRING OldFile; + LONG ErrorCode; + + RtlCreateUnicodeStringFromAsciiz (&SubKey, + (PCSZ)lpSubKey); + RtlCreateUnicodeStringFromAsciiz (&OldFile, + (PCSZ)lpOldFile); + RtlCreateUnicodeStringFromAsciiz (&NewFile, + (PCSZ)lpNewFile); + + ErrorCode = RegReplaceKeyW (hKey, + SubKey.Buffer, + NewFile.Buffer, + OldFile.Buffer); + + RtlFreeUnicodeString (&OldFile); + RtlFreeUnicodeString (&NewFile); + RtlFreeUnicodeString (&SubKey); + + return ErrorCode; } @@ -2450,9 +2656,120 @@ RegReplaceKeyW (HKEY hKey, LPCWSTR lpNewFile, LPCWSTR lpOldFile) { - UNIMPLEMENTED; - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return ERROR_CALL_NOT_IMPLEMENTED; + OBJECT_ATTRIBUTES KeyObjectAttributes; + OBJECT_ATTRIBUTES NewObjectAttributes; + OBJECT_ATTRIBUTES OldObjectAttributes; + UNICODE_STRING SubKeyName; + UNICODE_STRING NewFileName; + UNICODE_STRING OldFileName; + BOOLEAN CloseRealKey; + HANDLE RealKeyHandle; + HANDLE KeyHandle; + LONG ErrorCode; + NTSTATUS Status; + + if (hKey == HKEY_PERFORMANCE_DATA) + { + return ERROR_INVALID_HANDLE; + } + + Status = MapDefaultKey (&KeyHandle, + hKey); + if (!NT_SUCCESS(Status)) + { + ErrorCode = RtlNtStatusToDosError (Status); + SetLastError (ErrorCode); + return ErrorCode; + } + + /* Open the real key */ + if (lpSubKey != NULL && *lpSubKey != (WCHAR)0) + { + RtlInitUnicodeString (&SubKeyName, + (PWSTR)lpSubKey); + InitializeObjectAttributes (&KeyObjectAttributes, + &SubKeyName, + OBJ_CASE_INSENSITIVE, + KeyHandle, + NULL); + Status = NtOpenKey (&RealKeyHandle, + KEY_ALL_ACCESS, + &KeyObjectAttributes); + if (!NT_SUCCESS(Status)) + { + ErrorCode = RtlNtStatusToDosError (Status); + SetLastError (ErrorCode); + return ErrorCode; + } + CloseRealKey = TRUE; + } + else + { + RealKeyHandle = KeyHandle; + CloseRealKey = FALSE; + } + + /* Convert new file name */ + if (!RtlDosPathNameToNtPathName_U ((LPWSTR)lpNewFile, + &NewFileName, + NULL, + NULL)) + { + if (CloseRealKey) + { + NtClose (RealKeyHandle); + } + SetLastError (ERROR_INVALID_PARAMETER); + return ERROR_INVALID_PARAMETER; + } + + InitializeObjectAttributes (&NewObjectAttributes, + &NewFileName, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); + + /* Convert old file name */ + if (!RtlDosPathNameToNtPathName_U ((LPWSTR)lpOldFile, + &OldFileName, + NULL, + NULL)) + { + RtlFreeUnicodeString (&NewFileName); + if (CloseRealKey) + { + NtClose (RealKeyHandle); + } + SetLastError (ERROR_INVALID_PARAMETER); + return ERROR_INVALID_PARAMETER; + } + + InitializeObjectAttributes (&OldObjectAttributes, + &OldFileName, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); + + Status = NtReplaceKey (&NewObjectAttributes, + RealKeyHandle, + &OldObjectAttributes); + + RtlFreeUnicodeString (&OldFileName); + RtlFreeUnicodeString (&NewFileName); + + if (CloseRealKey) + { + NtClose (RealKeyHandle); + } + + if (!NT_SUCCESS(Status)) + { + ErrorCode = RtlNtStatusToDosError (Status); + SetLastError (ErrorCode); + return ErrorCode; + } + + return ERROR_SUCCESS; } @@ -2466,29 +2783,95 @@ RegRestoreKeyA (HKEY hKey, LPCSTR lpFile, DWORD dwFlags) { - UNICODE_STRING lpFileW; - LONG ret; + UNICODE_STRING FileName; + LONG ErrorCode; + + RtlCreateUnicodeStringFromAsciiz (&FileName, + (PCSZ)lpFile); + + ErrorCode = RegRestoreKeyW (hKey, + FileName.Buffer, + dwFlags); - RtlCreateUnicodeStringFromAsciiz( &lpFileW, (PCSZ)lpFile ); - ret = RegRestoreKeyW( hKey, lpFileW.Buffer, dwFlags ); - RtlFreeUnicodeString( &lpFileW ); - return ret; + RtlFreeUnicodeString (&FileName); + + return ErrorCode; } /************************************************************************ * RegRestoreKeyW * - * @unimplemented + * @implemented */ LONG STDCALL RegRestoreKeyW (HKEY hKey, LPCWSTR lpFile, DWORD dwFlags) { - UNIMPLEMENTED; - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return ERROR_CALL_NOT_IMPLEMENTED; + OBJECT_ATTRIBUTES ObjectAttributes; + IO_STATUS_BLOCK IoStatusBlock; + UNICODE_STRING FileName; + HANDLE FileHandle; + HANDLE KeyHandle; + LONG ErrorCode; + NTSTATUS Status; + + if (hKey == HKEY_PERFORMANCE_DATA) + { + return ERROR_INVALID_HANDLE; + } + + Status = MapDefaultKey (&KeyHandle, + hKey); + if (!NT_SUCCESS(Status)) + { + ErrorCode = RtlNtStatusToDosError (Status); + SetLastError (ErrorCode); + return ErrorCode; + } + + if (!RtlDosPathNameToNtPathName_U ((LPWSTR)lpFile, + &FileName, + NULL, + NULL)) + { + SetLastError (ERROR_INVALID_PARAMETER); + return ERROR_INVALID_PARAMETER; + } + + InitializeObjectAttributes (&ObjectAttributes, + &FileName, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); + + Status = NtOpenFile (&FileHandle, + FILE_GENERIC_READ, + &ObjectAttributes, + &IoStatusBlock, + FILE_SHARE_READ, + FILE_SYNCHRONOUS_IO_NONALERT); + RtlFreeUnicodeString (&FileName); + if (!NT_SUCCESS(Status)) + { + ErrorCode = RtlNtStatusToDosError (Status); + SetLastError (ErrorCode); + return ErrorCode; + } + + Status = NtRestoreKey (KeyHandle, + FileHandle, + (ULONG)dwFlags); + NtClose (FileHandle); + if (!NT_SUCCESS(Status)) + { + ErrorCode = RtlNtStatusToDosError (Status); + SetLastError (ErrorCode); + return ErrorCode; + } + + return ERROR_SUCCESS; } @@ -2498,9 +2881,9 @@ RegRestoreKeyW (HKEY hKey, * @implemented */ LONG STDCALL -RegSaveKeyA(HKEY hKey, - LPCSTR lpFile, - LPSECURITY_ATTRIBUTES lpSecurityAttributes) +RegSaveKeyA (HKEY hKey, + LPCSTR lpFile, + LPSECURITY_ATTRIBUTES lpSecurityAttributes) { UNICODE_STRING FileName; LONG ErrorCode; @@ -2528,10 +2911,10 @@ RegSaveKeyW (HKEY hKey, { PSECURITY_DESCRIPTOR SecurityDescriptor = NULL; OBJECT_ATTRIBUTES ObjectAttributes; - UNICODE_STRING NtName; + UNICODE_STRING FileName; IO_STATUS_BLOCK IoStatusBlock; HANDLE FileHandle; - HKEY KeyHandle; + HANDLE KeyHandle; NTSTATUS Status; LONG ErrorCode; @@ -2544,8 +2927,8 @@ RegSaveKeyW (HKEY hKey, return ErrorCode; } - if (!RtlDosPathNameToNtPathName_U ((LPWSTR)lpFile, - &NtName, + if (!RtlDosPathNameToNtPathName_U ((PWSTR)lpFile, + &FileName, NULL, NULL)) { @@ -2559,7 +2942,7 @@ RegSaveKeyW (HKEY hKey, } InitializeObjectAttributes (&ObjectAttributes, - &NtName, + &FileName, OBJ_CASE_INSENSITIVE, NULL, SecurityDescriptor); @@ -2574,7 +2957,7 @@ RegSaveKeyW (HKEY hKey, FILE_OPEN_FOR_BACKUP_INTENT | FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0); - RtlFreeUnicodeString (&NtName); + RtlFreeUnicodeString (&FileName); if (!NT_SUCCESS(Status)) { ErrorCode = RtlNtStatusToDosError (Status); @@ -2606,12 +2989,15 @@ RegSetKeySecurity (HKEY hKey, SECURITY_INFORMATION SecurityInformation, PSECURITY_DESCRIPTOR pSecurityDescriptor) { - HKEY KeyHandle; - NTSTATUS Status; + HANDLE KeyHandle; LONG ErrorCode; + NTSTATUS Status; if (hKey == HKEY_PERFORMANCE_DATA) - return ERROR_INVALID_HANDLE; + { + SetLastError(ERROR_INVALID_HANDLE); + return ERROR_INVALID_HANDLE; + } Status = MapDefaultKey (&KeyHandle, hKey); @@ -2667,7 +3053,7 @@ RegSetValueExA (HKEY hKey, strlen(lpValueName) != 0) { RtlCreateUnicodeStringFromAsciiz (&ValueName, - (LPSTR)lpValueName); + (PSTR)lpValueName); pValueName = (LPWSTR)ValueName.Buffer; } else @@ -2681,7 +3067,7 @@ RegSetValueExA (HKEY hKey, { RtlInitAnsiString (&AnsiString, NULL); - AnsiString.Buffer = (LPSTR)lpData; + AnsiString.Buffer = (PSTR)lpData; AnsiString.Length = cbData; AnsiString.MaximumLength = cbData; RtlAnsiStringToUnicodeString (&Data, @@ -2737,7 +3123,7 @@ RegSetValueExW (HKEY hKey, { UNICODE_STRING ValueName; PUNICODE_STRING pValueName; - HKEY KeyHandle; + HANDLE KeyHandle; NTSTATUS Status; LONG ErrorCode; @@ -2754,12 +3140,12 @@ RegSetValueExW (HKEY hKey, { RtlInitUnicodeString (&ValueName, lpValueName); - pValueName = &ValueName; } else { - pValueName = NULL; + RtlInitUnicodeString (&ValueName, L""); } + pValueName = &ValueName; Status = NtSetValueKey (KeyHandle, pValueName, @@ -2829,6 +3215,7 @@ RegSetValueA (HKEY hKey, dwType, Data.Buffer, DataSize); + RtlFreeHeap (ProcessHeap, 0, Data.Buffer); @@ -2851,7 +3238,7 @@ RegSetValueW (HKEY hKey, { OBJECT_ATTRIBUTES ObjectAttributes; UNICODE_STRING SubKeyString; - HKEY KeyHandle; + HANDLE KeyHandle; HANDLE RealKey; LONG ErrorCode; BOOL CloseRealKey; @@ -2937,7 +3324,7 @@ RegUnLoadKeyA (HKEY hKey, * @implemented */ LONG STDCALL -RegUnLoadKeyW (HKEY hKey, +RegUnLoadKeyW (HKEY hKey, LPCWSTR lpSubKey) { OBJECT_ATTRIBUTES ObjectAttributes; @@ -2947,7 +3334,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))