Simplified key deletion.

Added workaround to prevent BSOD on missing hives.

svn path=/trunk/; revision=4129
This commit is contained in:
Eric Kohl 2003-02-09 19:55:40 +00:00
parent cc025a380a
commit 8ce89c167c
4 changed files with 122 additions and 57 deletions

View file

@ -437,6 +437,11 @@ CmiAddSubKey(IN PREGISTRY_HIVE RegistryHive,
IN PUNICODE_STRING Class, IN PUNICODE_STRING Class,
IN ULONG CreateOptions); IN ULONG CreateOptions);
NTSTATUS
CmiRemoveSubKey(IN PREGISTRY_HIVE RegistryHive,
IN PKEY_OBJECT Parent,
IN PKEY_OBJECT SubKey);
NTSTATUS NTSTATUS
CmiScanKeyForValue(IN PREGISTRY_HIVE RegistryHive, CmiScanKeyForValue(IN PREGISTRY_HIVE RegistryHive,
IN PKEY_CELL KeyCell, IN PKEY_CELL KeyCell,

View file

@ -976,11 +976,11 @@ NtOpenKey(OUT PHANDLE KeyHandle,
NTSTATUS STDCALL NTSTATUS STDCALL
NtQueryKey(IN HANDLE KeyHandle, NtQueryKey(IN HANDLE KeyHandle,
IN KEY_INFORMATION_CLASS KeyInformationClass, IN KEY_INFORMATION_CLASS KeyInformationClass,
OUT PVOID KeyInformation, OUT PVOID KeyInformation,
IN ULONG Length, IN ULONG Length,
OUT PULONG ResultLength) OUT PULONG ResultLength)
{ {
PKEY_BASIC_INFORMATION BasicInformation; PKEY_BASIC_INFORMATION BasicInformation;
PKEY_NODE_INFORMATION NodeInformation; PKEY_NODE_INFORMATION NodeInformation;
@ -1007,22 +1007,26 @@ NtQueryKey(IN HANDLE KeyHandle,
NULL); NULL);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
CHECKPOINT1;
return Status; return Status;
} }
CHECKPOINT1;
/* Acquire hive lock */ /* Acquire hive lock */
ExAcquireResourceSharedLite(&KeyObject->RegistryHive->HiveResource, TRUE); ExAcquireResourceSharedLite(&KeyObject->RegistryHive->HiveResource, TRUE);
CHECKPOINT1;
VERIFY_KEY_OBJECT(KeyObject); VERIFY_KEY_OBJECT(KeyObject);
/* Get pointer to KeyCell */ /* Get pointer to KeyCell */
KeyCell = KeyObject->KeyCell; KeyCell = KeyObject->KeyCell;
RegistryHive = KeyObject->RegistryHive; RegistryHive = KeyObject->RegistryHive;
Status = STATUS_SUCCESS; Status = STATUS_SUCCESS;
switch (KeyInformationClass) switch (KeyInformationClass)
{ {
case KeyBasicInformation: case KeyBasicInformation:
CHECKPOINT1;
/* Check size of buffer */ /* Check size of buffer */
if (Length < sizeof(KEY_BASIC_INFORMATION) + if (Length < sizeof(KEY_BASIC_INFORMATION) +
KeyObject->NameSize * sizeof(WCHAR)) KeyObject->NameSize * sizeof(WCHAR))
@ -1043,8 +1047,9 @@ NtQueryKey(IN HANDLE KeyHandle,
*ResultLength = sizeof(KEY_BASIC_INFORMATION) + *ResultLength = sizeof(KEY_BASIC_INFORMATION) +
KeyObject->NameSize * sizeof(WCHAR); KeyObject->NameSize * sizeof(WCHAR);
} }
CHECKPOINT1;
break; break;
case KeyNodeInformation: case KeyNodeInformation:
/* Check size of buffer */ /* Check size of buffer */
if (Length < sizeof(KEY_NODE_INFORMATION) if (Length < sizeof(KEY_NODE_INFORMATION)
@ -1124,10 +1129,13 @@ NtQueryKey(IN HANDLE KeyHandle,
break; break;
} }
CHECKPOINT1;
ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource); ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
CHECKPOINT1;
ObDereferenceObject(KeyObject); ObDereferenceObject(KeyObject);
CHECKPOINT1;
return Status; return(Status);
} }

View file

@ -508,10 +508,20 @@ CmiInitPermanentRegistryHive(PREGISTRY_HIVE RegistryHive,
NULL, NULL,
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) if (CreateNew == TRUE)
CreateDisposition = FILE_OPEN_IF; CreateDisposition = FILE_OPEN_IF;
else else
CreateDisposition = FILE_OPEN; CreateDisposition = FILE_OPEN;
#endif
CreateDisposition = FILE_OPEN_IF;
Status = NtCreateFile(&FileHandle, Status = NtCreateFile(&FileHandle,
FILE_ALL_ACCESS, FILE_ALL_ACCESS,
@ -531,7 +541,11 @@ CmiInitPermanentRegistryHive(PREGISTRY_HIVE RegistryHive,
return(Status); return(Status);
} }
/* Note: Another workaround! See the note above! */
#if 0
if ((CreateNew) && (IoSB.Information == FILE_CREATED)) if ((CreateNew) && (IoSB.Information == FILE_CREATED))
#endif
if (IoSB.Information != FILE_OPENED)
{ {
Status = CmiCreateNewRegFile(FileHandle); Status = CmiCreateNewRegFile(FileHandle);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
@ -1219,13 +1233,13 @@ CmiScanForSubKey(IN PREGISTRY_HIVE RegistryHive,
NTSTATUS NTSTATUS
CmiAddSubKey(PREGISTRY_HIVE RegistryHive, CmiAddSubKey(PREGISTRY_HIVE RegistryHive,
PKEY_OBJECT Parent, PKEY_OBJECT Parent,
PKEY_OBJECT SubKey, PKEY_OBJECT SubKey,
PWSTR NewSubKeyName, PWSTR NewSubKeyName,
USHORT NewSubKeyNameSize, USHORT NewSubKeyNameSize,
ULONG TitleIndex, ULONG TitleIndex,
PUNICODE_STRING Class, PUNICODE_STRING Class,
ULONG CreateOptions) ULONG CreateOptions)
{ {
PHASH_TABLE_CELL NewHashBlock; PHASH_TABLE_CELL NewHashBlock;
PHASH_TABLE_CELL HashBlock; 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 */ /* Don't modify hash table if key is volatile and parent is not */
if (IsVolatileHive(RegistryHive) && (!IsVolatileHive(Parent->RegistryHive))) if (IsVolatileHive(RegistryHive) && (!IsVolatileHive(Parent->RegistryHive)))
{ {
return Status; return(Status);
} }
if (KeyCell->HashTableOffset == (ULONG_PTR) -1) if (KeyCell->HashTableOffset == (ULONG_PTR) -1)
@ -1313,15 +1327,15 @@ CmiAddSubKey(PREGISTRY_HIVE RegistryHive,
&KeyCell->HashTableOffset, &KeyCell->HashTableOffset,
REG_INIT_HASH_TABLE_SIZE); REG_INIT_HASH_TABLE_SIZE);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
return Status; return(Status);
} }
} }
else else
{ {
HashBlock = CmiGetBlock(RegistryHive, KeyCell->HashTableOffset, NULL); HashBlock = CmiGetBlock(RegistryHive, KeyCell->HashTableOffset, NULL);
if (((KeyCell->NumberOfSubKeys + 1) >= HashBlock->HashTableSize)) if (((KeyCell->NumberOfSubKeys + 1) >= HashBlock->HashTableSize))
{ {
BLOCK_OFFSET HTOffset; BLOCK_OFFSET HTOffset;
/* Reallocate the hash table block */ /* Reallocate the hash table block */
@ -1335,24 +1349,84 @@ CmiAddSubKey(PREGISTRY_HIVE RegistryHive,
return Status; return Status;
} }
RtlZeroMemory(&NewHashBlock->Table[0], RtlZeroMemory(&NewHashBlock->Table[0],
sizeof(NewHashBlock->Table[0]) * NewHashBlock->HashTableSize); sizeof(NewHashBlock->Table[0]) * NewHashBlock->HashTableSize);
RtlCopyMemory(&NewHashBlock->Table[0], RtlCopyMemory(&NewHashBlock->Table[0],
&HashBlock->Table[0], &HashBlock->Table[0],
sizeof(NewHashBlock->Table[0]) * HashBlock->HashTableSize); sizeof(NewHashBlock->Table[0]) * HashBlock->HashTableSize);
CmiDestroyBlock(RegistryHive, HashBlock, KeyCell->HashTableOffset); CmiDestroyBlock(RegistryHive,
KeyCell->HashTableOffset = HTOffset; HashBlock,
HashBlock = NewHashBlock; KeyCell->HashTableOffset);
} KeyCell->HashTableOffset = HTOffset;
HashBlock = NewHashBlock;
}
} }
Status = CmiAddKeyToHashTable(RegistryHive, HashBlock, NewKeyCell, NKBOffset); Status = CmiAddKeyToHashTable(RegistryHive,
HashBlock,
NewKeyCell,
NKBOffset);
if (NT_SUCCESS(Status)) if (NT_SUCCESS(Status))
{ {
KeyCell->NumberOfSubKeys++; 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);
} }

View file

@ -277,34 +277,12 @@ CmiObjectDelete(PVOID DeletedObject)
if (KeyObject->Flags & KO_MARKED_FOR_DELETE) if (KeyObject->Flags & KO_MARKED_FOR_DELETE)
{ {
PHASH_TABLE_CELL HashBlock;
DPRINT("delete really key\n"); 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)) if (IsPermanentHive(KeyObject->RegistryHive))
CmiSyncHives(); CmiSyncHives();
} }