From 4b34e5c2de7af93dce4bed40174261d10485fdeb Mon Sep 17 00:00:00 2001 From: Eric Kohl Date: Fri, 8 Sep 2000 22:55:14 +0000 Subject: [PATCH] Implemented basic registry functions svn path=/trunk/; revision=1346 --- reactos/lib/advapi32/reg/reg.c | 506 ++++++++++++++++++++++++++++++--- reactos/ntoskrnl/cm/registry.c | 372 +++++++++++++++++------- 2 files changed, 735 insertions(+), 143 deletions(-) diff --git a/reactos/lib/advapi32/reg/reg.c b/reactos/lib/advapi32/reg/reg.c index f9f16c6a4e0..c2d59dc951d 100644 --- a/reactos/lib/advapi32/reg/reg.c +++ b/reactos/lib/advapi32/reg/reg.c @@ -1,4 +1,4 @@ -/* $Id: reg.c,v 1.9 2000/09/06 19:58:47 ekohl Exp $ +/* $Id: reg.c,v 1.10 2000/09/08 22:54:13 ekohl Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS system libraries @@ -42,7 +42,7 @@ static NTSTATUS OpenLocalMachineKey (PHANDLE KeyHandle); BOOL RegInitialize (VOID) { - DPRINT1("RegInitialize()\n"); + DPRINT("RegInitialize()\n"); RtlZeroMemory (DefaultHandleTable, MAX_DEFAULT_HANDLES * sizeof(HANDLE)); @@ -58,7 +58,7 @@ RegInitialize (VOID) BOOL RegCleanup(VOID) { - DPRINT1("RegCleanup()\n"); + DPRINT("RegCleanup()\n"); CloseDefaultKeys(); RtlDeleteCriticalSection(&HandleTableCS); @@ -67,24 +67,23 @@ RegCleanup(VOID) static NTSTATUS -MapDefaultKey (PHKEY ParentKey, +MapDefaultKey (PHKEY RealKey, HKEY Key) { PHANDLE Handle; ULONG Index; NTSTATUS Status = STATUS_SUCCESS; - DPRINT1("MapDefaultKey (Key %x)\n", Key); + DPRINT("MapDefaultKey (Key %x)\n", Key); if (((ULONG)Key & 0xF0000000) != 0x80000000) { - *ParentKey = Key; + *RealKey = Key; return STATUS_SUCCESS; } /* Handle special cases here */ Index = (ULONG)Key & 0x0FFFFFFF; -DPRINT1("Index %x\n", Index); if (Index >= MAX_DEFAULT_HANDLES) return STATUS_INVALID_PARAMETER; @@ -102,18 +101,16 @@ DPRINT1("Index %x\n", Index); break; default: - DPRINT1("MapDefaultHandle() no handle creator\n"); + DPRINT("MapDefaultHandle() no handle creator\n"); Status = STATUS_INVALID_PARAMETER; } } RtlLeaveCriticalSection(&HandleTableCS); -DPRINT1("Status %x\n", Status); - if (NT_SUCCESS(Status)) { - *ParentKey = (HKEY)*Handle; + *RealKey = (HKEY)*Handle; } return Status; @@ -145,7 +142,7 @@ OpenLocalMachineKey (PHANDLE KeyHandle) OBJECT_ATTRIBUTES Attributes; UNICODE_STRING KeyName; - DPRINT1("OpenLocalMachineKey()\n"); + DPRINT("OpenLocalMachineKey()\n"); RtlInitUnicodeString(&KeyName, L"\\Registry\\Machine"); @@ -206,6 +203,22 @@ RegConnectRegistryA( } +/************************************************************************ + * RegConnectRegistryW + */ +LONG +STDCALL +RegConnectRegistryW( + LPWSTR lpMachineName, + HKEY hKey, + PHKEY phkResult + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return ERROR_CALL_NOT_IMPLEMENTED; +} + + /************************************************************************ * RegCreateKeyA */ @@ -297,7 +310,7 @@ RegCreateKeyExW( NTSTATUS Status; HKEY ParentKey; - DPRINT1("RegCreateKeyExW() called\n"); + DPRINT("RegCreateKeyExW() called\n"); /* get the real parent key */ Status = MapDefaultKey (&ParentKey, hKey); @@ -309,7 +322,7 @@ RegCreateKeyExW( return ErrorCode; } - DPRINT1("ParentKey %x\n", (ULONG)ParentKey); + DPRINT("ParentKey %x\n", (ULONG)ParentKey); RtlInitUnicodeString (&ClassString, lpClass); RtlInitUnicodeString (&SubKeyString, lpSubKey); @@ -327,7 +340,7 @@ RegCreateKeyExW( (lpClass == NULL)? NULL : &ClassString, dwOptions, (PULONG)lpdwDisposition); - DPRINT1("Status %x\n", Status); + DPRINT("Status %x\n", Status); if (!NT_SUCCESS(Status)) { LONG ErrorCode = RtlNtStatusToDosError(Status); @@ -335,7 +348,6 @@ RegCreateKeyExW( SetLastError (ErrorCode); return ErrorCode; } - DPRINT1("Returned handle %x\n", (ULONG)*phkResult); return ERROR_SUCCESS; } @@ -366,8 +378,56 @@ RegDeleteKeyW( LPCWSTR lpSubKey ) { - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return ERROR_CALL_NOT_IMPLEMENTED; + OBJECT_ATTRIBUTES ObjectAttributes; + UNICODE_STRING SubKeyString; + HANDLE ParentKey; + HANDLE TargetKey; + NTSTATUS Status; + LONG ErrorCode; + + Status = MapDefaultKey(&ParentKey, + hKey); + if (!NT_SUCCESS(Status)) + { + ErrorCode = RtlNtStatusToDosError(Status); + + SetLastError (ErrorCode); + return ErrorCode; + } + + RtlInitUnicodeString(&SubKeyString, + (LPWSTR)lpSubKey); + + InitializeObjectAttributes (&ObjectAttributes, + &SubKeyString, + OBJ_CASE_INSENSITIVE, + (HANDLE)ParentKey, + NULL); + + + Status = NtOpenKey (&TargetKey, + DELETE, + &ObjectAttributes); + if (!NT_SUCCESS(Status)) + { + ErrorCode = RtlNtStatusToDosError(Status); + + SetLastError (ErrorCode); + return ErrorCode; + } + + Status = NtDeleteKey(TargetKey); + + NtClose(TargetKey); + + if (!NT_SUCCESS(Status)) + { + ErrorCode = RtlNtStatusToDosError(Status); + + SetLastError (ErrorCode); + return ErrorCode; + } + return ERROR_SUCCESS; } @@ -396,8 +456,35 @@ RegDeleteValueW( LPCWSTR lpValueName ) { - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return ERROR_CALL_NOT_IMPLEMENTED; + UNICODE_STRING ValueName; + NTSTATUS Status; + LONG ErrorCode; + HANDLE KeyHandle; + + Status = MapDefaultKey(&KeyHandle, + hKey); + if (!NT_SUCCESS(Status)) + { + ErrorCode = RtlNtStatusToDosError(Status); + + SetLastError (ErrorCode); + return ErrorCode; + } + + RtlInitUnicodeString(&ValueName, + lpValueName); + + Status = NtDeleteValueKey(KeyHandle, + &ValueName); + if (!NT_SUCCESS(Status)) + { + ErrorCode = RtlNtStatusToDosError(Status); + + SetLastError (ErrorCode); + return ErrorCode; + } + + return ERROR_SUCCESS; } @@ -439,6 +526,111 @@ RegEnumKeyExA( } +/************************************************************************ + * RegEnumKeyExW + */ +LONG +STDCALL +RegEnumKeyExW( + HKEY hKey, + DWORD dwIndex, + LPWSTR lpName, + LPDWORD lpcbName, + LPDWORD lpReserved, + LPWSTR lpClass, + LPDWORD lpcbClass, + PFILETIME lpftLastWriteTime + ) +{ + PKEY_NODE_INFORMATION KeyInfo; + NTSTATUS Status; + DWORD dwError = ERROR_SUCCESS; + ULONG BufferSize; + ULONG ResultSize; + HANDLE KeyHandle; + + Status = MapDefaultKey(&KeyHandle, + hKey); + if (!NT_SUCCESS(Status)) + { + dwError = RtlNtStatusToDosError(Status); + + SetLastError (dwError); + return dwError; + } + + BufferSize = sizeof (KEY_NODE_INFORMATION) + + *lpcbName * sizeof(WCHAR); + if (lpClass) + BufferSize += *lpcbClass; + KeyInfo = RtlAllocateHeap (RtlGetProcessHeap(), + 0, + BufferSize); + if (KeyInfo == NULL) + return ERROR_OUTOFMEMORY; + + Status = NtEnumerateKey (KeyHandle, + (ULONG)dwIndex, + KeyNodeInformation, + KeyInfo, + BufferSize, + &ResultSize); + if (!NT_SUCCESS(Status)) + { + dwError = RtlNtStatusToDosError(Status); + + SetLastError(dwError); + } + else + { + memcpy (lpName, KeyInfo->Name, KeyInfo->NameLength); + *lpcbName = (DWORD)(KeyInfo->NameLength / sizeof(WCHAR)) - 1; + + if (lpClass) + { + memcpy (lpClass, + KeyInfo->Name + KeyInfo->ClassOffset, + KeyInfo->ClassLength); + *lpcbClass = (DWORD)(KeyInfo->ClassLength / sizeof(WCHAR)) - 1; + } + + if (lpftLastWriteTime) + { + + } + } + + RtlFreeHeap (RtlGetProcessHeap(), 0, KeyInfo); + + return dwError; +} + + +/************************************************************************ + * RegEnumKeyW + */ +LONG +STDCALL +RegEnumKeyW( + HKEY hKey, + DWORD dwIndex, + LPWSTR lpName, + DWORD cbName + ) +{ + DWORD dwLength = cbName; + + return RegEnumKeyExW(hKey, + dwIndex, + lpName, + &dwLength, + NULL, + NULL, + NULL, + NULL); +} + + /************************************************************************ * RegEnumValueA */ @@ -460,6 +652,73 @@ RegEnumValueA( } +/************************************************************************ + * RegEnumValueW + */ +LONG +STDCALL +RegEnumValueW( + HKEY hKey, + DWORD dwIndex, + LPWSTR lpValueName, + LPDWORD lpcbValueName, + LPDWORD lpReserved, + LPDWORD lpType, + LPBYTE lpData, + LPDWORD lpcbData + ) +{ + PKEY_VALUE_FULL_INFORMATION ValueInfo; + NTSTATUS Status; + DWORD dwError = ERROR_SUCCESS; + ULONG BufferSize; + ULONG ResultSize; + + BufferSize = sizeof (KEY_VALUE_FULL_INFORMATION) + + *lpcbValueName * sizeof(WCHAR); + if (lpcbData) + BufferSize += *lpcbData; + ValueInfo = RtlAllocateHeap (RtlGetProcessHeap(), + 0, + BufferSize); + if (ValueInfo == NULL) + return ERROR_OUTOFMEMORY; + + Status = NtEnumerateValueKey (hKey, + (ULONG)dwIndex, + KeyValueFullInformation, + ValueInfo, + BufferSize, + &ResultSize); + if (!NT_SUCCESS(Status)) + { + dwError = RtlNtStatusToDosError(Status); + + SetLastError(dwError); + } + else + { + memcpy (lpValueName, ValueInfo->Name, ValueInfo->NameLength); + *lpcbValueName = (DWORD)(ValueInfo->NameLength / sizeof(WCHAR)) - 1; + + if (lpType) + *lpType = ValueInfo->Type; + + if (lpData) + { + memcpy (lpData, + ValueInfo->Name + ValueInfo->DataOffset, + ValueInfo->DataLength); + *lpcbValueName = (DWORD)ValueInfo->DataLength; + } + } + + RtlFreeHeap (RtlGetProcessHeap(), 0, ValueInfo); + + return dwError; +} + + /************************************************************************ * RegFlushKey */ @@ -477,7 +736,6 @@ RegFlushKey( /************************************************************************ * RegGetKeySecurity */ -#if 0 LONG STDCALL RegGetKeySecurity ( @@ -490,7 +748,6 @@ RegGetKeySecurity ( SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return ERROR_CALL_NOT_IMPLEMENTED; } -#endif /************************************************************************ @@ -577,25 +834,39 @@ RegOpenKeyW ( NTSTATUS errCode; UNICODE_STRING SubKeyString; OBJECT_ATTRIBUTES ObjectAttributes; + HANDLE KeyHandle; + LONG ErrorCode; - SubKeyString.Buffer = (LPWSTR)lpSubKey; - SubKeyString.Length = wcslen(SubKeyString.Buffer); - SubKeyString.MaximumLength = SubKeyString.Length; + errCode = MapDefaultKey(&KeyHandle, + hKey); + if (!NT_SUCCESS(errCode)) + { + ErrorCode = RtlNtStatusToDosError(errCode); + + SetLastError (ErrorCode); + return ErrorCode; + } + + RtlInitUnicodeString(&SubKeyString, + (LPWSTR)lpSubKey); + + InitializeObjectAttributes(&ObjectAttributes, + &SubKeyString, + OBJ_CASE_INSENSITIVE, + KeyHandle, + NULL); - ObjectAttributes.RootDirectory = hKey; - ObjectAttributes.ObjectName = & SubKeyString; - ObjectAttributes.Attributes = OBJ_CASE_INSENSITIVE; errCode = NtOpenKey( phkResult, - GENERIC_ALL, + KEY_ALL_ACCESS, & ObjectAttributes ); if ( !NT_SUCCESS(errCode) ) { - LONG LastError = RtlNtStatusToDosError(errCode); + ErrorCode = RtlNtStatusToDosError(errCode); - SetLastError(LastError); - return LastError; + SetLastError(ErrorCode); + return ErrorCode; } return ERROR_SUCCESS; } @@ -632,8 +903,32 @@ RegOpenKeyExW( PHKEY phkResult ) { - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return ERROR_CALL_NOT_IMPLEMENTED; + NTSTATUS errCode; + UNICODE_STRING SubKeyString; + OBJECT_ATTRIBUTES ObjectAttributes; + + RtlInitUnicodeString(&SubKeyString, + (LPWSTR)lpSubKey); + + InitializeObjectAttributes(&ObjectAttributes, + &SubKeyString, + OBJ_CASE_INSENSITIVE, + (HANDLE)hKey, + NULL); + + errCode = NtOpenKey( + phkResult, + samDesired, + & ObjectAttributes + ); + if ( !NT_SUCCESS(errCode) ) + { + LONG LastError = RtlNtStatusToDosError(errCode); + + SetLastError(LastError); + return LastError; + } + return ERROR_SUCCESS; } @@ -705,6 +1000,24 @@ RegQueryMultipleValuesA( } +/************************************************************************ + * RegQueryMultipleValuesW + */ +LONG +STDCALL +RegQueryMultipleValuesW( + HKEY hKey, + PVALENT val_list, + DWORD num_vals, + LPWSTR lpValueBuf, + LPDWORD ldwTotsize + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return ERROR_CALL_NOT_IMPLEMENTED; +} + + /************************************************************************ * RegQueryValueA */ @@ -754,6 +1067,62 @@ RegQueryValueExW( LPBYTE lpData, LPDWORD lpcbData ) +{ + PKEY_VALUE_PARTIAL_INFORMATION ValueInfo; + UNICODE_STRING ValueName; + NTSTATUS Status; + DWORD dwError = ERROR_SUCCESS; + ULONG BufferSize; + ULONG ResultSize; + + RtlInitUnicodeString (&ValueName, + lpValueName); + + BufferSize = sizeof (KEY_VALUE_PARTIAL_INFORMATION) + *lpcbData; + ValueInfo = RtlAllocateHeap (RtlGetProcessHeap(), + 0, + BufferSize); + if (ValueInfo == NULL) + return ERROR_OUTOFMEMORY; + + Status = NtQueryValueKey (hKey, + &ValueName, + KeyValuePartialInformation, + ValueInfo, + BufferSize, + &ResultSize); + if (!NT_SUCCESS(Status)) + { + dwError = RtlNtStatusToDosError(Status); + + SetLastError(dwError); + } + else + { + *lpType = ValueInfo->Type; + memcpy (lpData, ValueInfo->Data, ValueInfo->DataLength); + if (ValueInfo->Type == REG_SZ) + ((PWSTR)lpData)[ValueInfo->DataLength / sizeof(WCHAR)] = 0; + } + *lpcbData = (DWORD)ResultSize; + + RtlFreeHeap (RtlGetProcessHeap(), 0, ValueInfo); + + return dwError; +} + + +/************************************************************************ + * RegQueryValueW + */ +LONG +STDCALL +RegQueryValueW( + HKEY hKey, + LPCWSTR lpSubKey, + LPWSTR lpValue, + PLONG lpcbValue + ) { SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return ERROR_CALL_NOT_IMPLEMENTED; @@ -777,6 +1146,23 @@ RegReplaceKeyA( } +/************************************************************************ + * RegReplaceKeyW + */ +LONG +STDCALL +RegReplaceKeyW( + HKEY hKey, + LPCWSTR lpSubKey, + LPCWSTR lpNewFile, + LPCWSTR lpOldFile + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return ERROR_CALL_NOT_IMPLEMENTED; +} + + /************************************************************************ * RegRestoreKeyA */ @@ -793,6 +1179,22 @@ RegRestoreKeyA( } +/************************************************************************ + * RegRestoreKeyW + */ +LONG +STDCALL +RegRestoreKeyW( + HKEY hKey, + LPCWSTR lpFile, + DWORD dwFlags + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return ERROR_CALL_NOT_IMPLEMENTED; +} + + /************************************************************************ * RegSaveKeyA */ @@ -801,7 +1203,23 @@ STDCALL RegSaveKeyA( HKEY hKey, LPCSTR lpFile, - LPSECURITY_ATTRIBUTES lpSecurityAttributes + LPSECURITY_ATTRIBUTES lpSecurityAttributes + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return ERROR_CALL_NOT_IMPLEMENTED; +} + + +/************************************************************************ + * RegSaveKeyW + */ +LONG +STDCALL +RegSaveKeyW( + HKEY hKey, + LPCWSTR lpFile, + LPSECURITY_ATTRIBUTES lpSecurityAttributes ) { SetLastError(ERROR_CALL_NOT_IMPLEMENTED); @@ -812,7 +1230,6 @@ RegSaveKeyA( /************************************************************************ * RegSetKeySecurity */ -#if 0 LONG STDCALL RegSetKeySecurity( @@ -824,7 +1241,7 @@ RegSetKeySecurity( SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return ERROR_CALL_NOT_IMPLEMENTED; } -#endif + /************************************************************************ * RegSetValueA @@ -933,4 +1350,19 @@ RegUnLoadKeyA( return ERROR_CALL_NOT_IMPLEMENTED; } + +/************************************************************************ + * RegUnLoadKeyW + */ +LONG +STDCALL +RegUnLoadKeyW( + HKEY hKey, + LPCWSTR lpSubKey + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return ERROR_CALL_NOT_IMPLEMENTED; +} + /* EOF */ diff --git a/reactos/ntoskrnl/cm/registry.c b/reactos/ntoskrnl/cm/registry.c index 3ac66f679bf..ef10346143a 100644 --- a/reactos/ntoskrnl/cm/registry.c +++ b/reactos/ntoskrnl/cm/registry.c @@ -1,4 +1,4 @@ -/* $Id: registry.c,v 1.28 2000/09/06 19:59:54 ekohl Exp $ +/* $Id: registry.c,v 1.29 2000/09/08 22:55:14 ekohl Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -16,7 +16,7 @@ #include #include -//#define NDEBUG +#define NDEBUG #include #define PROTO_REG 1 /* Comment out to disable */ @@ -227,6 +227,10 @@ static NTSTATUS CmiScanKeyForValue(IN PREGISTRY_FILE RegistryFile, IN PKEY_BLOCK KeyBlock, IN PWSTR ValueName, OUT PVALUE_BLOCK *ValueBlock); +static NTSTATUS CmiGetValueFromKeyByIndex(IN PREGISTRY_FILE RegistryFile, + IN PKEY_BLOCK KeyBlock, + IN ULONG Index, + OUT PVALUE_BLOCK *ValueBlock); static NTSTATUS CmiAddValueToKey(IN PREGISTRY_FILE RegistryFile, IN PKEY_BLOCK KeyBlock, IN PWSTR ValueNameBuf, @@ -364,7 +368,6 @@ CmInitializeRegistry(VOID) { return; } -CHECKPOINT; CmiReleaseBlock(CmiVolatileFile, KeyBlock); /* FIXME: create remaining structure needed for default handles */ @@ -373,6 +376,7 @@ CHECKPOINT; #endif } + VOID CmImportHive(PCHAR Chunk) { @@ -380,7 +384,8 @@ CmImportHive(PCHAR Chunk) return; } -NTSTATUS + +NTSTATUS STDCALL NtCreateKey ( OUT PHANDLE KeyHandle, @@ -432,7 +437,6 @@ NtCreateKey ( { *Disposition = REG_OPENED_EXISTING_KEY; } -DPRINT1("KeyHandle (opened) %x\n", *KeyHandle); return Status; } @@ -472,7 +476,6 @@ DPRINT1("KeyHandle (opened) %x\n", *KeyHandle); FALSE, KeyHandle); -DPRINT1("Status %x KeyHandle (created) %x\n", Status, *KeyHandle); if (NT_SUCCESS(Status)) { *Disposition = REG_CREATED_NEW_KEY; @@ -522,7 +525,48 @@ NtDeleteKey ( } -NTSTATUS +NTSTATUS +STDCALL +NtDeleteValueKey ( + IN HANDLE KeyHandle, + IN PUNICODE_STRING ValueName + ) +{ +#ifdef PROTO_REG + NTSTATUS Status; + PKEY_OBJECT KeyObject; + PREGISTRY_FILE RegistryFile; + PKEY_BLOCK KeyBlock; + + /* Verify that the handle is valid and is a registry key */ + Status = ObReferenceObjectByHandle(KeyHandle, + KEY_QUERY_VALUE, + CmiKeyType, + UserMode, + (PVOID *)&KeyObject, + NULL); + if (!NT_SUCCESS(Status)) + { + return Status; + } + + /* Get pointer to KeyBlock */ + KeyBlock = KeyObject->KeyBlock; + RegistryFile = KeyObject->RegistryFile; + Status = CmiDeleteValueFromKey(RegistryFile, + KeyBlock, + ValueName->Buffer); + + ObDereferenceObject(KeyObject); + + return Status; +#else + UNIMPLEMENTED; +#endif +} + + +NTSTATUS STDCALL NtEnumerateKey ( IN HANDLE KeyHandle, @@ -542,7 +586,7 @@ NtEnumerateKey ( PKEY_BASIC_INFORMATION BasicInformation; PKEY_NODE_INFORMATION NodeInformation; PKEY_FULL_INFORMATION FullInformation; - + /* Verify that the handle is valid and is a registry key */ Status = ObReferenceObjectByHandle(KeyHandle, KEY_ENUMERATE_SUB_KEYS, @@ -558,11 +602,11 @@ NtEnumerateKey ( /* Get pointer to KeyBlock */ KeyBlock = KeyObject->KeyBlock; RegistryFile = KeyObject->RegistryFile; - + /* Get pointer to SubKey */ HashTableBlock = CmiGetHashTableBlock(RegistryFile, KeyBlock->HashTableOffset); - SubKeyBlock = CmiGetKeyFromHashByIndex(RegistryFile, - HashTableBlock, + SubKeyBlock = CmiGetKeyFromHashByIndex(RegistryFile, + HashTableBlock, Index); if (SubKeyBlock == NULL) { @@ -575,7 +619,7 @@ NtEnumerateKey ( case KeyBasicInformation: /* Check size of buffer */ if (Length < sizeof(KEY_BASIC_INFORMATION) + - SubKeyBlock->NameSize * sizeof(WCHAR)) + (SubKeyBlock->NameSize + 1) * sizeof(WCHAR)) { Status = STATUS_BUFFER_OVERFLOW; } @@ -585,7 +629,7 @@ NtEnumerateKey ( BasicInformation = (PKEY_BASIC_INFORMATION) KeyInformation; BasicInformation->LastWriteTime = SubKeyBlock->LastWriteTime; BasicInformation->TitleIndex = Index; - BasicInformation->NameLength = SubKeyBlock->NameSize; + BasicInformation->NameLength = (SubKeyBlock->NameSize + 1) * sizeof(WCHAR); wcsncpy(BasicInformation->Name, SubKeyBlock->Name, SubKeyBlock->NameSize); @@ -598,7 +642,7 @@ NtEnumerateKey ( case KeyNodeInformation: /* Check size of buffer */ if (Length < sizeof(KEY_NODE_INFORMATION) + - SubKeyBlock->NameSize * sizeof(WCHAR) + + (SubKeyBlock->NameSize + 1) * sizeof(WCHAR) + (SubKeyBlock->ClassSize + 1) * sizeof(WCHAR)) { Status = STATUS_BUFFER_OVERFLOW; @@ -612,7 +656,7 @@ NtEnumerateKey ( NodeInformation->ClassOffset = sizeof(KEY_NODE_INFORMATION) + SubKeyBlock->NameSize * sizeof(WCHAR); NodeInformation->ClassLength = SubKeyBlock->ClassSize; - NodeInformation->NameLength = SubKeyBlock->NameSize; + NodeInformation->NameLength = (SubKeyBlock->NameSize + 1) * sizeof(WCHAR); wcsncpy(NodeInformation->Name, SubKeyBlock->Name, SubKeyBlock->NameSize); @@ -667,6 +711,7 @@ NtEnumerateKey ( break; } CmiReleaseBlock(RegistryFile, SubKeyBlock); + ObDereferenceObject (KeyObject); return Status; #else @@ -675,26 +720,141 @@ NtEnumerateKey ( } -NTSTATUS +NTSTATUS STDCALL NtEnumerateValueKey ( IN HANDLE KeyHandle, IN ULONG Index, - IN KEY_VALUE_INFORMATION_CLASS KeyInformationClass, - OUT PVOID KeyInformation, + IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass, + OUT PVOID KeyValueInformation, IN ULONG Length, OUT PULONG ResultLength ) { #ifdef PROTO_REG - UNIMPLEMENTED; + NTSTATUS Status; + PKEY_OBJECT KeyObject; + PREGISTRY_FILE RegistryFile; + PKEY_BLOCK KeyBlock; + PVALUE_BLOCK ValueBlock; + PVOID DataBlock; + PKEY_VALUE_BASIC_INFORMATION ValueBasicInformation; + PKEY_VALUE_PARTIAL_INFORMATION ValuePartialInformation; + PKEY_VALUE_FULL_INFORMATION ValueFullInformation; + + /* Verify that the handle is valid and is a registry key */ + Status = ObReferenceObjectByHandle(KeyHandle, + KEY_QUERY_VALUE, + CmiKeyType, + UserMode, + (PVOID *)&KeyObject, + NULL); + if (!NT_SUCCESS(Status)) + { + return Status; + } + + /* Get pointer to KeyBlock */ + KeyBlock = KeyObject->KeyBlock; + RegistryFile = KeyObject->RegistryFile; + + /* Get Value block of interest */ + Status = CmiGetValueFromKeyByIndex(RegistryFile, + KeyBlock, + Index, + &ValueBlock); + if (!NT_SUCCESS(Status)) + { + return Status; + } + else if (ValueBlock != NULL) + { + switch (KeyValueInformationClass) + { + case KeyValueBasicInformation: + *ResultLength = sizeof(KEY_VALUE_BASIC_INFORMATION) + + (ValueBlock->NameSize + 1) * sizeof(WCHAR); + if (Length < *ResultLength) + { + Status = STATUS_BUFFER_OVERFLOW; + } + else + { + ValueBasicInformation = (PKEY_VALUE_BASIC_INFORMATION) + KeyValueInformation; + ValueBasicInformation->TitleIndex = 0; + ValueBasicInformation->Type = ValueBlock->DataType; + ValueBasicInformation->NameLength = + (ValueBlock->NameSize + 1) * sizeof(WCHAR); + wcscpy(ValueBasicInformation->Name, ValueBlock->Name); + } + break; + + case KeyValuePartialInformation: + *ResultLength = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + + ValueBlock->DataSize; + if (Length < *ResultLength) + { + Status = STATUS_BUFFER_OVERFLOW; + } + else + { + ValuePartialInformation = (PKEY_VALUE_PARTIAL_INFORMATION) + KeyValueInformation; + ValuePartialInformation->TitleIndex = 0; + ValuePartialInformation->Type = ValueBlock->DataType; + ValuePartialInformation->DataLength = ValueBlock->DataSize; + DataBlock = CmiGetBlock(RegistryFile, ValueBlock->DataOffset); + RtlCopyMemory(ValuePartialInformation->Data, + DataBlock, + ValueBlock->DataSize); + CmiReleaseBlock(RegistryFile, DataBlock); + } + break; + + case KeyValueFullInformation: + *ResultLength = sizeof(KEY_VALUE_FULL_INFORMATION) + + (ValueBlock->NameSize + 1) * sizeof(WCHAR) + ValueBlock->DataSize; + if (Length < *ResultLength) + { + Status = STATUS_BUFFER_OVERFLOW; + } + else + { + ValueFullInformation = (PKEY_VALUE_FULL_INFORMATION) + KeyValueInformation; + ValueFullInformation->TitleIndex = 0; + ValueFullInformation->Type = ValueBlock->DataType; + ValueFullInformation->DataOffset = + sizeof(KEY_VALUE_FULL_INFORMATION) + + ValueBlock->NameSize * sizeof(WCHAR); + ValueFullInformation->DataLength = ValueBlock->DataSize; + ValueFullInformation->NameLength = + (ValueBlock->NameSize + 1) * sizeof(WCHAR); + wcscpy(ValueFullInformation->Name, ValueBlock->Name); + DataBlock = CmiGetBlock(RegistryFile, ValueBlock->DataOffset); + RtlCopyMemory(&ValueFullInformation->Name[ValueBlock->NameSize + 1], + DataBlock, + ValueBlock->DataSize); + CmiReleaseBlock(RegistryFile, DataBlock); + } + break; + } + } + else + { + Status = STATUS_UNSUCCESSFUL; + } + ObDereferenceObject(KeyObject); + + return Status; #else UNIMPLEMENTED; #endif } -NTSTATUS +NTSTATUS STDCALL NtFlushKey ( IN HANDLE KeyHandle @@ -750,8 +910,6 @@ NtOpenKey ( KeyHandle); ExFreePool(KeyNameBuf); -DPRINT1("Status %x KeyHandle (opened) %x\n", Status, *KeyHandle); - return Status; } @@ -794,7 +952,6 @@ DPRINT1("Status %x KeyHandle (opened) %x\n", Status, *KeyHandle); NewKey->RegistryFile = FileToUse; NewKey->KeyBlock = KeyBlock; CmiAddKeyToList(NewKey); -DPRINT1("KeyHandle (created) %x\n", *KeyHandle); Status = ObCreateHandle(PsGetCurrentProcess(), NewKey, @@ -802,7 +959,6 @@ DPRINT1("KeyHandle (created) %x\n", *KeyHandle); FALSE, KeyHandle); -DPRINT1("Status %x KeyHandle (created) %x\n", Status, *KeyHandle); return Status; #else UNIMPLEMENTED; @@ -828,7 +984,7 @@ NtQueryKey ( PKEY_BASIC_INFORMATION BasicInformation; PKEY_NODE_INFORMATION NodeInformation; PKEY_FULL_INFORMATION FullInformation; - + /* Verify that the handle is valid and is a registry key */ Status = ObReferenceObjectByHandle(KeyHandle, KEY_READ, @@ -844,13 +1000,13 @@ NtQueryKey ( /* Get pointer to KeyBlock */ KeyBlock = KeyObject->KeyBlock; RegistryFile = KeyObject->RegistryFile; - + Status = STATUS_SUCCESS; switch (KeyInformationClass) { case KeyBasicInformation: /* Check size of buffer */ - if (Length < sizeof(KEY_BASIC_INFORMATION) + + if (Length < sizeof(KEY_BASIC_INFORMATION) + KeyBlock->NameSize * sizeof(WCHAR)) { Status = STATUS_BUFFER_OVERFLOW; @@ -862,11 +1018,11 @@ NtQueryKey ( BasicInformation->LastWriteTime = KeyBlock->LastWriteTime; BasicInformation->TitleIndex = 0; BasicInformation->NameLength = KeyBlock->NameSize; - wcsncpy(BasicInformation->Name, - KeyBlock->Name, + wcsncpy(BasicInformation->Name, + KeyBlock->Name, KeyBlock->NameSize); BasicInformation->Name[KeyBlock->NameSize] = 0; - *ResultLength = sizeof(KEY_BASIC_INFORMATION) + + *ResultLength = sizeof(KEY_BASIC_INFORMATION) + KeyBlock->NameSize * sizeof(WCHAR); } break; @@ -885,12 +1041,12 @@ NtQueryKey ( NodeInformation = (PKEY_NODE_INFORMATION) KeyInformation; NodeInformation->LastWriteTime = KeyBlock->LastWriteTime; NodeInformation->TitleIndex = 0; - NodeInformation->ClassOffset = sizeof(KEY_NODE_INFORMATION) + + NodeInformation->ClassOffset = sizeof(KEY_NODE_INFORMATION) + KeyBlock->NameSize * sizeof(WCHAR); NodeInformation->ClassLength = KeyBlock->ClassSize; NodeInformation->NameLength = KeyBlock->NameSize; - wcsncpy(NodeInformation->Name, - KeyBlock->Name, + wcsncpy(NodeInformation->Name, + KeyBlock->Name, KeyBlock->NameSize); NodeInformation->Name[KeyBlock->NameSize] = 0; if (KeyBlock->ClassSize != 0) @@ -920,7 +1076,7 @@ NtQueryKey ( FullInformation = (PKEY_FULL_INFORMATION) KeyInformation; FullInformation->LastWriteTime = KeyBlock->LastWriteTime; FullInformation->TitleIndex = 0; - FullInformation->ClassOffset = sizeof(KEY_FULL_INFORMATION) - + FullInformation->ClassOffset = sizeof(KEY_FULL_INFORMATION) - sizeof(WCHAR); FullInformation->ClassLength = KeyBlock->ClassSize; FullInformation->SubKeys = KeyBlock->NumberOfSubKeys; @@ -942,6 +1098,7 @@ NtQueryKey ( } break; } + ObDereferenceObject (KeyObject); return Status; #else @@ -950,7 +1107,7 @@ NtQueryKey ( } -NTSTATUS +NTSTATUS STDCALL NtQueryValueKey ( IN HANDLE KeyHandle, @@ -1073,7 +1230,8 @@ NtQueryValueKey ( { Status = STATUS_UNSUCCESSFUL; } - + ObDereferenceObject(KeyObject); + return Status; #else UNIMPLEMENTED; @@ -1147,58 +1305,27 @@ NtSetValueKey ( #endif } + NTSTATUS STDCALL -NtDeleteValueKey ( - IN HANDLE KeyHandle, - IN PUNICODE_STRING ValueName - ) -{ -#ifdef PROTO_REG - NTSTATUS Status; - PKEY_OBJECT KeyObject; - PREGISTRY_FILE RegistryFile; - PKEY_BLOCK KeyBlock; - - /* Verify that the handle is valid and is a registry key */ - Status = ObReferenceObjectByHandle(KeyHandle, - KEY_QUERY_VALUE, - CmiKeyType, - UserMode, - (PVOID *)&KeyObject, - NULL); - if (!NT_SUCCESS(Status)) - { - return Status; - } - - /* Get pointer to KeyBlock */ - KeyBlock = KeyObject->KeyBlock; - RegistryFile = KeyObject->RegistryFile; - Status = CmiDeleteValueFromKey(RegistryFile, - KeyBlock, - ValueName->Buffer); - - return Status; -#else - UNIMPLEMENTED; -#endif -} - -NTSTATUS -STDCALL NtLoadKey ( PHANDLE KeyHandle, OBJECT_ATTRIBUTES ObjectAttributes ) { - UNIMPLEMENTED; + return NtLoadKey2(KeyHandle, + ObjectAttributes, + 0); } NTSTATUS STDCALL -NtLoadKey2(VOID) +NtLoadKey2 ( + PHANDLE KeyHandle, + OBJECT_ATTRIBUTES ObjectAttributes, + ULONG Unknown3 + ) { UNIMPLEMENTED; } @@ -1209,11 +1336,11 @@ STDCALL NtNotifyChangeKey ( IN HANDLE KeyHandle, IN HANDLE Event, - IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, - IN PVOID ApcContext OPTIONAL, + IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, + IN PVOID ApcContext OPTIONAL, OUT PIO_STATUS_BLOCK IoStatusBlock, IN ULONG CompletionFilter, - IN BOOLEAN Asynchroneous, + IN BOOLEAN Asynchroneous, OUT PVOID ChangeBuffer, IN ULONG Length, IN BOOLEAN WatchSubtree @@ -1287,7 +1414,7 @@ NtSetInformationKey ( NTSTATUS -STDCALL +STDCALL NtUnloadKey ( HANDLE KeyHandle ) @@ -1297,7 +1424,7 @@ NtUnloadKey ( NTSTATUS -STDCALL +STDCALL NtInitializeRegistry ( BOOLEAN SetUpBoot ) @@ -1408,7 +1535,7 @@ static NTSTATUS CmiObjectParse(PVOID ParsedObject, return Status; } - CurKeyBlock = CmiGetKeyBlock(RegistryFile, + CurKeyBlock = CmiGetKeyBlock(RegistryFile, RegistryFile->HeaderBlock->RootKeyBlock); /* Loop through each key level and find the needed subkey */ @@ -1429,8 +1556,8 @@ static NTSTATUS CmiObjectParse(PVOID ParsedObject, } /* Verify existance of CurKeyName */ - Status = CmiScanForSubKey(RegistryFile, - CurKeyBlock, + Status = CmiScanForSubKey(RegistryFile, + CurKeyBlock, &SubKeyBlock, CurKeyName, STANDARD_RIGHTS_REQUIRED); @@ -1514,8 +1641,6 @@ CmiBuildKeyPath(PWSTR *KeyPath, POBJECT_ATTRIBUTES ObjectAttributes) ObjectHeader = 0; if (ObjectAttributes->RootDirectory != NULL) { -DbgPrint ("RootDirectory %x\n", ObjectAttributes->RootDirectory); -DbgPrint ("KeyName %wZ\n", ObjectAttributes->ObjectName); /* FIXME: determine type of object for RootDirectory */ Status = ObReferenceObjectByHandle(ObjectAttributes->RootDirectory, KEY_READ, @@ -1525,7 +1650,6 @@ DbgPrint ("KeyName %wZ\n", ObjectAttributes->ObjectName); NULL); if (!NT_SUCCESS(Status)) { -CHECKPOINT1; return Status; } ObjectHeader = BODY_TO_HEADER(ObjectBody); @@ -1650,7 +1774,7 @@ CmiAddKeyToList(PKEY_OBJECT NewKey) KeReleaseSpinLock(&CmiKeyListLock, OldIrql); } -static VOID +static VOID CmiRemoveKeyFromList(PKEY_OBJECT KeyToRemove) { KIRQL OldIrql; @@ -2104,12 +2228,12 @@ CmiScanForSubKey(IN PREGISTRY_FILE RegistryFile, } static NTSTATUS -CmiAddSubKey(PREGISTRY_FILE RegistryFile, +CmiAddSubKey(PREGISTRY_FILE RegistryFile, PKEY_BLOCK KeyBlock, PKEY_BLOCK *SubKeyBlock, PWSTR NewSubKeyName, ULONG TitleIndex, - PWSTR Class, + PWSTR Class, ULONG CreateOptions) { NTSTATUS Status; @@ -2128,7 +2252,7 @@ CmiAddSubKey(PREGISTRY_FILE RegistryFile, } if (KeyBlock->HashTableOffset == 0) { - Status = CmiAllocateHashTableBlock(RegistryFile, + Status = CmiAllocateHashTableBlock(RegistryFile, &HashBlock, REG_INIT_HASH_TABLE_SIZE); if (!NT_SUCCESS(Status)) @@ -2175,7 +2299,7 @@ CmiAddSubKey(PREGISTRY_FILE RegistryFile, return Status; } -static NTSTATUS +static NTSTATUS CmiScanKeyForValue(IN PREGISTRY_FILE RegistryFile, IN PKEY_BLOCK KeyBlock, IN PWSTR ValueName, @@ -2185,10 +2309,10 @@ CmiScanKeyForValue(IN PREGISTRY_FILE RegistryFile, PVALUE_LIST_BLOCK ValueListBlock; PVALUE_BLOCK CurValueBlock; - ValueListBlock = CmiGetBlock(RegistryFile, + ValueListBlock = CmiGetBlock(RegistryFile, KeyBlock->ValuesOffset); *ValueBlock = NULL; - if (ValueListBlock == 0) + if (ValueListBlock == NULL) { return STATUS_SUCCESS; } @@ -2210,6 +2334,40 @@ CmiScanKeyForValue(IN PREGISTRY_FILE RegistryFile, return STATUS_SUCCESS; } + +static NTSTATUS +CmiGetValueFromKeyByIndex(IN PREGISTRY_FILE RegistryFile, + IN PKEY_BLOCK KeyBlock, + IN ULONG Index, + OUT PVALUE_BLOCK *ValueBlock) +{ + PVALUE_LIST_BLOCK ValueListBlock; + PVALUE_BLOCK CurValueBlock; + + ValueListBlock = CmiGetBlock(RegistryFile, + KeyBlock->ValuesOffset); + *ValueBlock = NULL; + if (ValueListBlock == NULL) + { + return STATUS_NO_MORE_ENTRIES; + } + if (Index >= KeyBlock->NumberOfValues) + { + return STATUS_NO_MORE_ENTRIES; + } + CurValueBlock = CmiGetBlock(RegistryFile, + ValueListBlock->Values[Index]); + if (CurValueBlock != NULL) + { + *ValueBlock = CurValueBlock; + } + CmiReleaseBlock(RegistryFile, CurValueBlock); + CmiReleaseBlock(RegistryFile, ValueListBlock); + + return STATUS_SUCCESS; +} + + static NTSTATUS CmiAddValueToKey(IN PREGISTRY_FILE RegistryFile, IN PKEY_BLOCK KeyBlock, @@ -2246,6 +2404,8 @@ CmiAddValueToKey(IN PREGISTRY_FILE RegistryFile, ValueBlock); return Status; } + KeyBlock->ValuesOffset = CmiGetBlockOffset(RegistryFile, + ValueListBlock); } else if (KeyBlock->NumberOfValues % REG_VALUE_LIST_BLOCK_MULTIPLE) { @@ -2268,6 +2428,7 @@ CmiAddValueToKey(IN PREGISTRY_FILE RegistryFile, CmiDestroyBlock(RegistryFile, ValueListBlock); ValueListBlock = NewValueListBlock; } + ValueListBlock->Values[KeyBlock->NumberOfValues] = CmiGetBlockOffset(RegistryFile, ValueBlock); KeyBlock->NumberOfValues++; @@ -2347,7 +2508,7 @@ CmiAllocateKeyBlock(IN PREGISTRY_FILE RegistryFile, NewKeySize = sizeof(KEY_BLOCK) + (wcslen(KeyName) + 1) * sizeof(WCHAR) + (Class != NULL ? (wcslen(Class) + 1) * sizeof(WCHAR) : 0); -DPRINT ("NewKeySize: %lu\n", NewKeySize); + DPRINT ("NewKeySize: %lu\n", NewKeySize); //CHECKPOINT; NewKeyBlock = ExAllocatePool(NonPagedPool, NewKeySize); //CHECKPOINT; @@ -2421,7 +2582,7 @@ CmiDestroyKeyBlock(PREGISTRY_FILE RegistryFile, ExFreePool(KeyBlock); } else - { + { UNIMPLEMENTED; } @@ -2466,7 +2627,7 @@ CmiAllocateHashTableBlock(IN PREGISTRY_FILE RegistryFile, return Status; } -static PHASH_TABLE_BLOCK +static PHASH_TABLE_BLOCK CmiGetHashTableBlock(PREGISTRY_FILE RegistryFile, BLOCK_OFFSET HashBlockOffset) { @@ -2486,7 +2647,7 @@ CmiGetHashTableBlock(PREGISTRY_FILE RegistryFile, return HashBlock; } -static PKEY_BLOCK +static PKEY_BLOCK CmiGetKeyFromHashByIndex(PREGISTRY_FILE RegistryFile, PHASH_TABLE_BLOCK HashBlock, ULONG Index) @@ -2506,7 +2667,7 @@ CmiGetKeyFromHashByIndex(PREGISTRY_FILE RegistryFile, return KeyBlock; } -static NTSTATUS +static NTSTATUS CmiAddKeyToHashTable(PREGISTRY_FILE RegistryFile, PHASH_TABLE_BLOCK HashBlock, PKEY_BLOCK NewKeyBlock) @@ -2553,7 +2714,7 @@ static NTSTATUS CmiAllocateValueBlock(PREGISTRY_FILE RegistryFile, PVALUE_BLOCK *ValueBlock, IN PWSTR ValueNameBuf, - IN ULONG Type, + IN ULONG Type, IN PVOID Data, IN ULONG DataSize) { @@ -2610,7 +2771,7 @@ CmiAllocateValueBlock(PREGISTRY_FILE RegistryFile, static NTSTATUS CmiReplaceValueData(IN PREGISTRY_FILE RegistryFile, IN PVALUE_BLOCK ValueBlock, - IN ULONG Type, + IN ULONG Type, IN PVOID Data, IN ULONG DataSize) { @@ -2652,8 +2813,7 @@ CmiDestroyValueBlock(PREGISTRY_FILE RegistryFile, { NTSTATUS Status; -CHECKPOINT1; - Status = CmiDestroyBlock(RegistryFile, + Status = CmiDestroyBlock(RegistryFile, CmiGetBlock(RegistryFile, ValueBlock->DataOffset)); if (!NT_SUCCESS(Status)) @@ -2710,7 +2870,7 @@ CmiDestroyBlock(PREGISTRY_FILE RegistryFile, ExFreePool(Block); } else - { + { Status = STATUS_NOT_IMPLEMENTED; } @@ -2756,7 +2916,7 @@ CmiGetBlockOffset(PREGISTRY_FILE RegistryFile, return BlockOffset; } -static VOID +static VOID CmiLockBlock(PREGISTRY_FILE RegistryFile, PVOID Block) { @@ -2766,7 +2926,7 @@ CmiLockBlock(PREGISTRY_FILE RegistryFile, } } -static VOID +static VOID CmiReleaseBlock(PREGISTRY_FILE RegistryFile, PVOID Block) {