From 8ce89c167c14dee99a61a7fb63648e686bfcebc6 Mon Sep 17 00:00:00 2001 From: Eric Kohl Date: Sun, 9 Feb 2003 19:55:40 +0000 Subject: [PATCH] Simplified key deletion. Added workaround to prevent BSOD on missing hives. svn path=/trunk/; revision=4129 --- reactos/ntoskrnl/cm/cm.h | 5 ++ reactos/ntoskrnl/cm/ntfunc.c | 24 ++++--- reactos/ntoskrnl/cm/regfile.c | 122 +++++++++++++++++++++++++++------- reactos/ntoskrnl/cm/regobj.c | 28 +------- 4 files changed, 122 insertions(+), 57 deletions(-) diff --git a/reactos/ntoskrnl/cm/cm.h b/reactos/ntoskrnl/cm/cm.h index 07cb91933d3..1ca939f97aa 100644 --- a/reactos/ntoskrnl/cm/cm.h +++ b/reactos/ntoskrnl/cm/cm.h @@ -437,6 +437,11 @@ CmiAddSubKey(IN PREGISTRY_HIVE RegistryHive, IN PUNICODE_STRING Class, IN ULONG CreateOptions); +NTSTATUS +CmiRemoveSubKey(IN PREGISTRY_HIVE RegistryHive, + IN PKEY_OBJECT Parent, + IN PKEY_OBJECT SubKey); + NTSTATUS CmiScanKeyForValue(IN PREGISTRY_HIVE RegistryHive, IN PKEY_CELL KeyCell, diff --git a/reactos/ntoskrnl/cm/ntfunc.c b/reactos/ntoskrnl/cm/ntfunc.c index 253e11b03c6..6b16e610e3b 100644 --- a/reactos/ntoskrnl/cm/ntfunc.c +++ b/reactos/ntoskrnl/cm/ntfunc.c @@ -976,11 +976,11 @@ NtOpenKey(OUT PHANDLE KeyHandle, NTSTATUS STDCALL -NtQueryKey(IN HANDLE KeyHandle, - IN KEY_INFORMATION_CLASS KeyInformationClass, - OUT PVOID KeyInformation, - IN ULONG Length, - OUT PULONG ResultLength) +NtQueryKey(IN HANDLE KeyHandle, + IN KEY_INFORMATION_CLASS KeyInformationClass, + OUT PVOID KeyInformation, + IN ULONG Length, + OUT PULONG ResultLength) { PKEY_BASIC_INFORMATION BasicInformation; PKEY_NODE_INFORMATION NodeInformation; @@ -1007,22 +1007,26 @@ NtQueryKey(IN HANDLE KeyHandle, NULL); if (!NT_SUCCESS(Status)) { +CHECKPOINT1; return Status; } +CHECKPOINT1; /* Acquire hive lock */ ExAcquireResourceSharedLite(&KeyObject->RegistryHive->HiveResource, TRUE); +CHECKPOINT1; VERIFY_KEY_OBJECT(KeyObject); /* Get pointer to KeyCell */ KeyCell = KeyObject->KeyCell; RegistryHive = KeyObject->RegistryHive; - + Status = STATUS_SUCCESS; switch (KeyInformationClass) { case KeyBasicInformation: +CHECKPOINT1; /* Check size of buffer */ if (Length < sizeof(KEY_BASIC_INFORMATION) + KeyObject->NameSize * sizeof(WCHAR)) @@ -1043,8 +1047,9 @@ NtQueryKey(IN HANDLE KeyHandle, *ResultLength = sizeof(KEY_BASIC_INFORMATION) + KeyObject->NameSize * sizeof(WCHAR); } +CHECKPOINT1; break; - + case KeyNodeInformation: /* Check size of buffer */ if (Length < sizeof(KEY_NODE_INFORMATION) @@ -1124,10 +1129,13 @@ NtQueryKey(IN HANDLE KeyHandle, break; } +CHECKPOINT1; ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource); +CHECKPOINT1; ObDereferenceObject(KeyObject); +CHECKPOINT1; - return Status; + return(Status); } diff --git a/reactos/ntoskrnl/cm/regfile.c b/reactos/ntoskrnl/cm/regfile.c index a3f58982b27..d2cef807883 100644 --- a/reactos/ntoskrnl/cm/regfile.c +++ b/reactos/ntoskrnl/cm/regfile.c @@ -508,10 +508,20 @@ CmiInitPermanentRegistryHive(PREGISTRY_HIVE RegistryHive, NULL, NULL); + /* + * Note: + * This is a workaround to prevent a BSOD because of missing registry hives. + * The workaround is only useful for developers. An implementation for the + * ordinary user must bail out on missing registry hives because they are + * essential to booting and configuring the OS. + */ +#if 0 if (CreateNew == TRUE) CreateDisposition = FILE_OPEN_IF; else CreateDisposition = FILE_OPEN; +#endif + CreateDisposition = FILE_OPEN_IF; Status = NtCreateFile(&FileHandle, FILE_ALL_ACCESS, @@ -531,7 +541,11 @@ CmiInitPermanentRegistryHive(PREGISTRY_HIVE RegistryHive, return(Status); } + /* Note: Another workaround! See the note above! */ +#if 0 if ((CreateNew) && (IoSB.Information == FILE_CREATED)) +#endif + if (IoSB.Information != FILE_OPENED) { Status = CmiCreateNewRegFile(FileHandle); if (!NT_SUCCESS(Status)) @@ -1219,13 +1233,13 @@ CmiScanForSubKey(IN PREGISTRY_HIVE RegistryHive, NTSTATUS CmiAddSubKey(PREGISTRY_HIVE RegistryHive, - PKEY_OBJECT Parent, - PKEY_OBJECT SubKey, - PWSTR NewSubKeyName, - USHORT NewSubKeyNameSize, - ULONG TitleIndex, - PUNICODE_STRING Class, - ULONG CreateOptions) + PKEY_OBJECT Parent, + PKEY_OBJECT SubKey, + PWSTR NewSubKeyName, + USHORT NewSubKeyNameSize, + ULONG TitleIndex, + PUNICODE_STRING Class, + ULONG CreateOptions) { PHASH_TABLE_CELL NewHashBlock; PHASH_TABLE_CELL HashBlock; @@ -1303,7 +1317,7 @@ CmiAddSubKey(PREGISTRY_HIVE RegistryHive, /* Don't modify hash table if key is volatile and parent is not */ if (IsVolatileHive(RegistryHive) && (!IsVolatileHive(Parent->RegistryHive))) { - return Status; + return(Status); } if (KeyCell->HashTableOffset == (ULONG_PTR) -1) @@ -1313,15 +1327,15 @@ CmiAddSubKey(PREGISTRY_HIVE RegistryHive, &KeyCell->HashTableOffset, REG_INIT_HASH_TABLE_SIZE); if (!NT_SUCCESS(Status)) - { - return Status; - } + { + return(Status); + } } else { HashBlock = CmiGetBlock(RegistryHive, KeyCell->HashTableOffset, NULL); if (((KeyCell->NumberOfSubKeys + 1) >= HashBlock->HashTableSize)) - { + { BLOCK_OFFSET HTOffset; /* Reallocate the hash table block */ @@ -1335,24 +1349,84 @@ CmiAddSubKey(PREGISTRY_HIVE RegistryHive, return Status; } - RtlZeroMemory(&NewHashBlock->Table[0], - sizeof(NewHashBlock->Table[0]) * NewHashBlock->HashTableSize); - RtlCopyMemory(&NewHashBlock->Table[0], - &HashBlock->Table[0], - sizeof(NewHashBlock->Table[0]) * HashBlock->HashTableSize); - CmiDestroyBlock(RegistryHive, HashBlock, KeyCell->HashTableOffset); - KeyCell->HashTableOffset = HTOffset; - HashBlock = NewHashBlock; - } + RtlZeroMemory(&NewHashBlock->Table[0], + sizeof(NewHashBlock->Table[0]) * NewHashBlock->HashTableSize); + RtlCopyMemory(&NewHashBlock->Table[0], + &HashBlock->Table[0], + sizeof(NewHashBlock->Table[0]) * HashBlock->HashTableSize); + CmiDestroyBlock(RegistryHive, + HashBlock, + KeyCell->HashTableOffset); + KeyCell->HashTableOffset = HTOffset; + HashBlock = NewHashBlock; + } } - Status = CmiAddKeyToHashTable(RegistryHive, HashBlock, NewKeyCell, NKBOffset); + Status = CmiAddKeyToHashTable(RegistryHive, + HashBlock, + NewKeyCell, + NKBOffset); if (NT_SUCCESS(Status)) { KeyCell->NumberOfSubKeys++; } - - return Status; + + return(Status); +} + + +NTSTATUS +CmiRemoveSubKey(PREGISTRY_HIVE RegistryHive, + PKEY_OBJECT ParentKey, + PKEY_OBJECT SubKey) +{ + PHASH_TABLE_CELL HashBlock; + + DPRINT1("CmiRemoveSubKey() called\n"); + + /* Remove the key from the parent key's hash block */ + HashBlock = CmiGetBlock(RegistryHive, + ParentKey->KeyCell->HashTableOffset, + NULL); + if (HashBlock != NULL) + { + CmiRemoveKeyFromHashTable(RegistryHive, + HashBlock, + SubKey->BlockOffset); + CmiMarkBlockDirty(RegistryHive, + ParentKey->KeyCell->HashTableOffset); + } + + /* Remove the key's hash block */ + DPRINT1("HashTableOffset %lx\n", SubKey->KeyCell->HashTableOffset) + if (SubKey->KeyCell->HashTableOffset != 0) + { + HashBlock = CmiGetBlock(RegistryHive, + SubKey->KeyCell->HashTableOffset, + NULL); + DPRINT1("HashBlock %p\n", HashBlock) + if (HashBlock != NULL) + { + CmiDestroyBlock(RegistryHive, + HashBlock, + SubKey->KeyCell->HashTableOffset); + } + SubKey->KeyCell->HashTableOffset = 0; + } + +CHECKPOINT1; + /* Remove the key from the parent key's hash block */ + ParentKey->KeyCell->NumberOfSubKeys--; + CmiMarkBlockDirty(RegistryHive, + ParentKey->BlockOffset); + +CHECKPOINT1; + /* Destroy key cell */ + CmiDestroyBlock(RegistryHive, + SubKey->KeyCell, + SubKey->BlockOffset); + + return(STATUS_SUCCESS); } diff --git a/reactos/ntoskrnl/cm/regobj.c b/reactos/ntoskrnl/cm/regobj.c index ec704c516b0..e4570e460bc 100644 --- a/reactos/ntoskrnl/cm/regobj.c +++ b/reactos/ntoskrnl/cm/regobj.c @@ -277,34 +277,12 @@ CmiObjectDelete(PVOID DeletedObject) if (KeyObject->Flags & KO_MARKED_FOR_DELETE) { - PHASH_TABLE_CELL HashBlock; - DPRINT("delete really key\n"); - /* FIXME: Destroy the key's hash block */ + CmiRemoveSubKey(KeyObject->RegistryHive, + KeyObject->ParentKey, + KeyObject); - /* Remove the key from the parent key's hash block */ - HashBlock = CmiGetBlock(KeyObject->RegistryHive, - KeyObject->ParentKey->KeyCell->HashTableOffset, NULL); - DPRINT1("HashBlock %p\n", HashBlock); - if (HashBlock != NULL) - { - CmiRemoveKeyFromHashTable(KeyObject->RegistryHive, - HashBlock, - KeyObject->BlockOffset); - CmiMarkBlockDirty(KeyObject->RegistryHive, - KeyObject->ParentKey->KeyCell->HashTableOffset); - } - - /* Remove the key from the parent key's hash block */ - KeyObject->ParentKey->KeyCell->NumberOfSubKeys--; - CmiMarkBlockDirty(KeyObject->RegistryHive, - KeyObject->ParentKey->BlockOffset); - - /* Destroy key cell */ - CmiDestroyBlock(KeyObject->RegistryHive, - KeyObject->KeyCell, - KeyObject->BlockOffset); if (IsPermanentHive(KeyObject->RegistryHive)) CmiSyncHives(); }