mirror of
https://github.com/reactos/reactos.git
synced 2025-07-02 05:21:22 +00:00
- Implement NtDeleteKey as a simpler wrapper around CmDeleteKey.
- Add cmkeydel.c to handle key deletion. Will proably move to cmkcbncb.c later. Implemented CmpMarkKeyDirty, CmpFreeKeyBody, CmpFreeKeyByCell. - Implement CmpMarkIndexDirty, CmpRemoveSubKey in cmindex.c. - Implement CmDeleteKey (which uses CmpFreeKeyByCell for all the work). - Remove CmiRemoveKeyFromList, CmiRemoveSubKey, CmiRemoveKeyFromHashTable, CmiSaveTempHive. svn path=/trunk/; revision=26817
This commit is contained in:
parent
b527796afa
commit
70e2b462a5
10 changed files with 723 additions and 340 deletions
|
@ -221,7 +221,7 @@ HvpRemoveFree(
|
||||||
pFreeCellOffset = FreeCellData;
|
pFreeCellOffset = FreeCellData;
|
||||||
}
|
}
|
||||||
|
|
||||||
ASSERT(FALSE);
|
//ASSERT(FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static HCELL_INDEX CMAPI
|
static HCELL_INDEX CMAPI
|
||||||
|
|
|
@ -167,9 +167,6 @@ VOID
|
||||||
CmiAddKeyToList(IN PKEY_OBJECT ParentKey,
|
CmiAddKeyToList(IN PKEY_OBJECT ParentKey,
|
||||||
IN PKEY_OBJECT NewKey);
|
IN PKEY_OBJECT NewKey);
|
||||||
|
|
||||||
NTSTATUS
|
|
||||||
CmiRemoveKeyFromList(IN PKEY_OBJECT NewKey);
|
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
CmiScanKeyList(IN PKEY_OBJECT Parent,
|
CmiScanKeyList(IN PKEY_OBJECT Parent,
|
||||||
IN PUNICODE_STRING KeyName,
|
IN PUNICODE_STRING KeyName,
|
||||||
|
@ -184,9 +181,6 @@ CmiLoadHive(POBJECT_ATTRIBUTES KeyObjectAttributes,
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
CmiFlushRegistryHive(PEREGISTRY_HIVE RegistryHive);
|
CmiFlushRegistryHive(PEREGISTRY_HIVE RegistryHive);
|
||||||
|
|
||||||
ULONG
|
|
||||||
CmiGetNumberOfSubKeys(PKEY_OBJECT KeyObject);
|
|
||||||
|
|
||||||
ULONG
|
ULONG
|
||||||
CmiGetMaxNameLength(IN PHHIVE RegistryHive, IN PCM_KEY_NODE KeyCell);
|
CmiGetMaxNameLength(IN PHHIVE RegistryHive, IN PCM_KEY_NODE KeyCell);
|
||||||
|
|
||||||
|
@ -219,11 +213,6 @@ CmiAddSubKey(IN PEREGISTRY_HIVE RegistryHive,
|
||||||
IN PUNICODE_STRING Class,
|
IN PUNICODE_STRING Class,
|
||||||
IN ULONG CreateOptions);
|
IN ULONG CreateOptions);
|
||||||
|
|
||||||
NTSTATUS
|
|
||||||
CmiRemoveSubKey(IN PEREGISTRY_HIVE RegistryHive,
|
|
||||||
IN PKEY_OBJECT Parent,
|
|
||||||
IN PKEY_OBJECT SubKey);
|
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
CmiScanKeyForValue(IN PEREGISTRY_HIVE RegistryHive,
|
CmiScanKeyForValue(IN PEREGISTRY_HIVE RegistryHive,
|
||||||
IN PCM_KEY_NODE KeyCell,
|
IN PCM_KEY_NODE KeyCell,
|
||||||
|
@ -279,6 +268,10 @@ CmEnumerateKey(IN PKEY_OBJECT KeyObject,
|
||||||
IN ULONG Length,
|
IN ULONG Length,
|
||||||
IN PULONG ResultLength);
|
IN PULONG ResultLength);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
CmDeleteKey(IN PKEY_OBJECT KeyObject);
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
CmiAllocateHashTableCell(IN PEREGISTRY_HIVE RegistryHive,
|
CmiAllocateHashTableCell(IN PEREGISTRY_HIVE RegistryHive,
|
||||||
OUT PHASH_TABLE_CELL *HashBlock,
|
OUT PHASH_TABLE_CELL *HashBlock,
|
||||||
|
@ -294,16 +287,6 @@ CmiAddKeyToHashTable(PEREGISTRY_HIVE RegistryHive,
|
||||||
PCM_KEY_NODE NewKeyCell,
|
PCM_KEY_NODE NewKeyCell,
|
||||||
HCELL_INDEX NKBOffset);
|
HCELL_INDEX NKBOffset);
|
||||||
|
|
||||||
NTSTATUS
|
|
||||||
CmiRemoveKeyFromHashTable(PEREGISTRY_HIVE RegistryHive,
|
|
||||||
PHASH_TABLE_CELL HashBlock,
|
|
||||||
HCELL_INDEX NKBOffset);
|
|
||||||
|
|
||||||
NTSTATUS
|
|
||||||
CmiDestroyValueCell(PEREGISTRY_HIVE RegistryHive,
|
|
||||||
PCM_KEY_VALUE ValueCell,
|
|
||||||
HCELL_INDEX VBOffset);
|
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
CmiConnectHive(POBJECT_ATTRIBUTES KeyObjectAttributes,
|
CmiConnectHive(POBJECT_ATTRIBUTES KeyObjectAttributes,
|
||||||
PEREGISTRY_HIVE RegistryHive);
|
PEREGISTRY_HIVE RegistryHive);
|
||||||
|
@ -330,10 +313,6 @@ CmpFindSubKeyByName(
|
||||||
VOID
|
VOID
|
||||||
CmiSyncHives(VOID);
|
CmiSyncHives(VOID);
|
||||||
|
|
||||||
NTSTATUS
|
|
||||||
CmiSaveTempHive (PEREGISTRY_HIVE Hive,
|
|
||||||
HANDLE FileHandle);
|
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
NTAPI
|
NTAPI
|
||||||
CmFindObject(
|
CmFindObject(
|
||||||
|
|
|
@ -435,115 +435,6 @@ Cleanup:
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
NTSTATUS STDCALL
|
|
||||||
NtDeleteKey(IN HANDLE KeyHandle)
|
|
||||||
{
|
|
||||||
KPROCESSOR_MODE PreviousMode;
|
|
||||||
PKEY_OBJECT KeyObject;
|
|
||||||
NTSTATUS Status;
|
|
||||||
REG_DELETE_KEY_INFORMATION DeleteKeyInfo;
|
|
||||||
REG_POST_OPERATION_INFORMATION PostOperationInfo;
|
|
||||||
|
|
||||||
PAGED_CODE();
|
|
||||||
|
|
||||||
DPRINT("NtDeleteKey(KeyHandle 0x%p) called\n", KeyHandle);
|
|
||||||
|
|
||||||
PreviousMode = ExGetPreviousMode();
|
|
||||||
|
|
||||||
/* Verify that the handle is valid and is a registry key */
|
|
||||||
Status = ObReferenceObjectByHandle(KeyHandle,
|
|
||||||
DELETE,
|
|
||||||
CmpKeyObjectType,
|
|
||||||
PreviousMode,
|
|
||||||
(PVOID *)&KeyObject,
|
|
||||||
NULL);
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
DPRINT1("ObReferenceObjectByHandle() failed (Status %lx)\n", Status);
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
PostOperationInfo.Object = (PVOID)KeyObject;
|
|
||||||
DeleteKeyInfo.Object = (PVOID)KeyObject;
|
|
||||||
Status = CmiCallRegisteredCallbacks(RegNtPreDeleteKey, &DeleteKeyInfo);
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
PostOperationInfo.Status = Status;
|
|
||||||
CmiCallRegisteredCallbacks(RegNtPostDeleteKey, &PostOperationInfo);
|
|
||||||
ObDereferenceObject(KeyObject);
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Acquire hive lock */
|
|
||||||
KeEnterCriticalRegion();
|
|
||||||
ExAcquireResourceExclusiveLite(&CmpRegistryLock, TRUE);
|
|
||||||
|
|
||||||
VERIFY_KEY_OBJECT(KeyObject);
|
|
||||||
|
|
||||||
/* Check for subkeys */
|
|
||||||
if (KeyObject->KeyCell->SubKeyCounts[HvStable] != 0 ||
|
|
||||||
KeyObject->KeyCell->SubKeyCounts[HvVolatile] != 0)
|
|
||||||
{
|
|
||||||
Status = STATUS_CANNOT_DELETE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
PKEY_OBJECT ParentKeyObject = KeyObject->ParentKey;
|
|
||||||
|
|
||||||
if (!NT_SUCCESS(CmiRemoveKeyFromList(KeyObject)))
|
|
||||||
{
|
|
||||||
DPRINT1("Key not found in parent list ???\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
CmiRemoveSubKey(KeyObject->RegistryHive,
|
|
||||||
ParentKeyObject,
|
|
||||||
KeyObject);
|
|
||||||
|
|
||||||
KeQuerySystemTime (&ParentKeyObject->KeyCell->LastWriteTime);
|
|
||||||
HvMarkCellDirty(&ParentKeyObject->RegistryHive->Hive,
|
|
||||||
ParentKeyObject->KeyCellOffset);
|
|
||||||
|
|
||||||
if (!IsNoFileHive (KeyObject->RegistryHive) ||
|
|
||||||
!IsNoFileHive (ParentKeyObject->RegistryHive))
|
|
||||||
{
|
|
||||||
CmiSyncHives ();
|
|
||||||
}
|
|
||||||
|
|
||||||
Status = STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Release hive lock */
|
|
||||||
ExReleaseResourceLite(&CmpRegistryLock);
|
|
||||||
KeLeaveCriticalRegion();
|
|
||||||
|
|
||||||
DPRINT("PointerCount %lu\n", ObGetObjectPointerCount((PVOID)KeyObject));
|
|
||||||
|
|
||||||
/* Remove the keep-alive reference */
|
|
||||||
ObDereferenceObject(KeyObject);
|
|
||||||
|
|
||||||
if (KeyObject->RegistryHive != KeyObject->ParentKey->RegistryHive)
|
|
||||||
ObDereferenceObject(KeyObject);
|
|
||||||
|
|
||||||
PostOperationInfo.Status = Status;
|
|
||||||
CmiCallRegisteredCallbacks(RegNtPostDeleteKey, &PostOperationInfo);
|
|
||||||
|
|
||||||
/* Dereference the object */
|
|
||||||
ObDereferenceObject(KeyObject);
|
|
||||||
|
|
||||||
DPRINT("PointerCount %lu\n", ObGetObjectPointerCount((PVOID)KeyObject));
|
|
||||||
DPRINT("HandleCount %lu\n", ObGetObjectHandleCount((PVOID)KeyObject));
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Note:
|
|
||||||
* Hive-Synchronization will not be triggered here. This is done in
|
|
||||||
* CmpDeleteKeyObject() (in regobj.c) after all key-related structures
|
|
||||||
* have been released.
|
|
||||||
*/
|
|
||||||
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
NTSTATUS STDCALL
|
NTSTATUS STDCALL
|
||||||
NtFlushKey(IN HANDLE KeyHandle)
|
NtFlushKey(IN HANDLE KeyHandle)
|
||||||
{
|
{
|
||||||
|
@ -812,6 +703,52 @@ NtInitializeRegistry (IN BOOLEAN SetUpBoot)
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
NtDeleteKey(IN HANDLE KeyHandle)
|
||||||
|
{
|
||||||
|
PKEY_OBJECT KeyObject;
|
||||||
|
NTSTATUS Status;
|
||||||
|
REG_DELETE_KEY_INFORMATION DeleteKeyInfo;
|
||||||
|
REG_POST_OPERATION_INFORMATION PostOperationInfo;
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
/* Verify that the handle is valid and is a registry key */
|
||||||
|
Status = ObReferenceObjectByHandle(KeyHandle,
|
||||||
|
DELETE,
|
||||||
|
CmpKeyObjectType,
|
||||||
|
ExGetPreviousMode(),
|
||||||
|
(PVOID *)&KeyObject,
|
||||||
|
NULL);
|
||||||
|
if (!NT_SUCCESS(Status)) return Status;
|
||||||
|
|
||||||
|
/* Setup the callback */
|
||||||
|
PostOperationInfo.Object = (PVOID)KeyObject;
|
||||||
|
DeleteKeyInfo.Object = (PVOID)KeyObject;
|
||||||
|
Status = CmiCallRegisteredCallbacks(RegNtPreDeleteKey, &DeleteKeyInfo);
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
/* Call the internal API */
|
||||||
|
Status = CmDeleteKey(KeyObject);
|
||||||
|
|
||||||
|
/* Remove the keep-alive reference */
|
||||||
|
ObDereferenceObject(KeyObject);
|
||||||
|
if (KeyObject->RegistryHive != KeyObject->ParentKey->RegistryHive)
|
||||||
|
{
|
||||||
|
/* Dereference again */
|
||||||
|
ObDereferenceObject(KeyObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Do post callback */
|
||||||
|
PostOperationInfo.Status = Status;
|
||||||
|
CmiCallRegisteredCallbacks(RegNtPostDeleteKey, &PostOperationInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Dereference the object */
|
||||||
|
ObDereferenceObject(KeyObject);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
NTAPI
|
NTAPI
|
||||||
NtEnumerateKey(IN HANDLE KeyHandle,
|
NtEnumerateKey(IN HANDLE KeyHandle,
|
||||||
|
|
|
@ -66,7 +66,6 @@ CmCloseHiveFiles(PEREGISTRY_HIVE RegistryHive)
|
||||||
ZwClose(RegistryHive->LogHandle);
|
ZwClose(RegistryHive->LogHandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
CmiFlushRegistryHive(PEREGISTRY_HIVE RegistryHive)
|
CmiFlushRegistryHive(PEREGISTRY_HIVE RegistryHive)
|
||||||
{
|
{
|
||||||
|
@ -103,26 +102,6 @@ CmiFlushRegistryHive(PEREGISTRY_HIVE RegistryHive)
|
||||||
return Success ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL;
|
return Success ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ULONG
|
|
||||||
CmiGetNumberOfSubKeys(PKEY_OBJECT KeyObject)
|
|
||||||
{
|
|
||||||
PCM_KEY_NODE KeyCell;
|
|
||||||
ULONG SubKeyCount;
|
|
||||||
|
|
||||||
VERIFY_KEY_OBJECT(KeyObject);
|
|
||||||
|
|
||||||
KeyCell = KeyObject->KeyCell;
|
|
||||||
VERIFY_KEY_CELL(KeyCell);
|
|
||||||
|
|
||||||
SubKeyCount = (KeyCell == NULL) ? 0 :
|
|
||||||
KeyCell->SubKeyCounts[HvStable] +
|
|
||||||
KeyCell->SubKeyCounts[HvVolatile];
|
|
||||||
|
|
||||||
return SubKeyCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
ULONG
|
ULONG
|
||||||
CmiGetMaxNameLength(PHHIVE Hive,
|
CmiGetMaxNameLength(PHHIVE Hive,
|
||||||
PCM_KEY_NODE KeyCell)
|
PCM_KEY_NODE KeyCell)
|
||||||
|
@ -160,7 +139,6 @@ CmiGetMaxNameLength(PHHIVE Hive,
|
||||||
return MaxName;
|
return MaxName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ULONG
|
ULONG
|
||||||
CmiGetMaxClassLength(PHHIVE Hive,
|
CmiGetMaxClassLength(PHHIVE Hive,
|
||||||
PCM_KEY_NODE KeyCell)
|
PCM_KEY_NODE KeyCell)
|
||||||
|
@ -196,7 +174,6 @@ CmiGetMaxClassLength(PHHIVE Hive,
|
||||||
return MaxClass;
|
return MaxClass;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ULONG
|
ULONG
|
||||||
CmiGetMaxValueNameLength(PHHIVE Hive,
|
CmiGetMaxValueNameLength(PHHIVE Hive,
|
||||||
PCM_KEY_NODE KeyCell)
|
PCM_KEY_NODE KeyCell)
|
||||||
|
@ -244,7 +221,6 @@ CmiGetMaxValueNameLength(PHHIVE Hive,
|
||||||
return MaxValueName;
|
return MaxValueName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ULONG
|
ULONG
|
||||||
CmiGetMaxValueDataLength(PHHIVE Hive,
|
CmiGetMaxValueDataLength(PHHIVE Hive,
|
||||||
PCM_KEY_NODE KeyCell)
|
PCM_KEY_NODE KeyCell)
|
||||||
|
@ -517,109 +493,6 @@ CmiAddSubKey(PEREGISTRY_HIVE RegistryHive,
|
||||||
return(Status);
|
return(Status);
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS
|
|
||||||
CmiRemoveSubKey(PEREGISTRY_HIVE RegistryHive,
|
|
||||||
PKEY_OBJECT ParentKey,
|
|
||||||
PKEY_OBJECT SubKey)
|
|
||||||
{
|
|
||||||
PHASH_TABLE_CELL HashBlock;
|
|
||||||
PVALUE_LIST_CELL ValueList;
|
|
||||||
PCM_KEY_VALUE ValueCell;
|
|
||||||
HV_STORAGE_TYPE Storage;
|
|
||||||
ULONG i;
|
|
||||||
|
|
||||||
DPRINT("CmiRemoveSubKey() called\n");
|
|
||||||
|
|
||||||
Storage = (SubKey->KeyCell->Flags & REG_KEY_VOLATILE_CELL) ? HvVolatile : HvStable;
|
|
||||||
|
|
||||||
/* Remove all values */
|
|
||||||
if (SubKey->KeyCell->ValueList.Count != 0)
|
|
||||||
{
|
|
||||||
/* Get pointer to the value list cell */
|
|
||||||
ValueList = HvGetCell (&RegistryHive->Hive, SubKey->KeyCell->ValueList.List);
|
|
||||||
|
|
||||||
/* Enumerate all values */
|
|
||||||
for (i = 0; i < SubKey->KeyCell->ValueList.Count; i++)
|
|
||||||
{
|
|
||||||
/* Get pointer to value cell */
|
|
||||||
ValueCell = HvGetCell(&RegistryHive->Hive,
|
|
||||||
ValueList->ValueOffset[i]);
|
|
||||||
|
|
||||||
if (!(ValueCell->DataSize & REG_DATA_IN_OFFSET)
|
|
||||||
&& ValueCell->DataSize > sizeof(HCELL_INDEX)
|
|
||||||
&& ValueCell->DataOffset != HCELL_NULL)
|
|
||||||
{
|
|
||||||
/* Destroy data cell */
|
|
||||||
HvFreeCell (&RegistryHive->Hive, ValueCell->DataOffset);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Destroy value cell */
|
|
||||||
HvFreeCell (&RegistryHive->Hive, ValueList->ValueOffset[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Destroy value list cell */
|
|
||||||
HvFreeCell (&RegistryHive->Hive, SubKey->KeyCell->ValueList.List);
|
|
||||||
|
|
||||||
SubKey->KeyCell->ValueList.Count = 0;
|
|
||||||
SubKey->KeyCell->ValueList.List = (HCELL_INDEX)-1;
|
|
||||||
|
|
||||||
HvMarkCellDirty(&RegistryHive->Hive, SubKey->KeyCellOffset);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Remove the key from the parent key's hash block */
|
|
||||||
if (ParentKey->KeyCell->SubKeyLists[Storage] != HCELL_NULL)
|
|
||||||
{
|
|
||||||
DPRINT("ParentKey SubKeyLists %lx\n", ParentKey->KeyCell->SubKeyLists[Storage]);
|
|
||||||
HashBlock = HvGetCell (&ParentKey->RegistryHive->Hive,
|
|
||||||
ParentKey->KeyCell->SubKeyLists[Storage]);
|
|
||||||
ASSERT(HashBlock->Id == REG_HASH_TABLE_CELL_ID);
|
|
||||||
DPRINT("ParentKey HashBlock %p\n", HashBlock);
|
|
||||||
CmiRemoveKeyFromHashTable(ParentKey->RegistryHive,
|
|
||||||
HashBlock,
|
|
||||||
SubKey->KeyCellOffset);
|
|
||||||
HvMarkCellDirty(&ParentKey->RegistryHive->Hive,
|
|
||||||
ParentKey->KeyCell->SubKeyLists[Storage]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Remove the key's hash block */
|
|
||||||
if (SubKey->KeyCell->SubKeyLists[Storage] != HCELL_NULL)
|
|
||||||
{
|
|
||||||
DPRINT("SubKey SubKeyLists %lx\n", SubKey->KeyCell->SubKeyLists[Storage]);
|
|
||||||
HvFreeCell (&RegistryHive->Hive, SubKey->KeyCell->SubKeyLists[Storage]);
|
|
||||||
SubKey->KeyCell->SubKeyLists[Storage] = HCELL_NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Decrement the number of the parent key's sub keys */
|
|
||||||
if (ParentKey != NULL)
|
|
||||||
{
|
|
||||||
DPRINT("ParentKey %p\n", ParentKey);
|
|
||||||
ParentKey->KeyCell->SubKeyCounts[Storage]--;
|
|
||||||
|
|
||||||
/* Remove the parent key's hash table */
|
|
||||||
if (ParentKey->KeyCell->SubKeyCounts[Storage] == 0 &&
|
|
||||||
ParentKey->KeyCell->SubKeyLists[Storage] != HCELL_NULL)
|
|
||||||
{
|
|
||||||
DPRINT("ParentKey SubKeyLists %lx\n", ParentKey->KeyCell->SubKeyLists);
|
|
||||||
HvFreeCell (&ParentKey->RegistryHive->Hive,
|
|
||||||
ParentKey->KeyCell->SubKeyLists[Storage]);
|
|
||||||
ParentKey->KeyCell->SubKeyLists[Storage] = HCELL_NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
KeQuerySystemTime(&ParentKey->KeyCell->LastWriteTime);
|
|
||||||
HvMarkCellDirty(&ParentKey->RegistryHive->Hive,
|
|
||||||
ParentKey->KeyCellOffset);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Destroy key cell */
|
|
||||||
HvFreeCell (&RegistryHive->Hive, SubKey->KeyCellOffset);
|
|
||||||
SubKey->KeyCell = NULL;
|
|
||||||
SubKey->KeyCellOffset = (HCELL_INDEX)-1;
|
|
||||||
|
|
||||||
DPRINT("CmiRemoveSubKey() done\n");
|
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
CmiAllocateHashTableCell (IN PEREGISTRY_HIVE RegistryHive,
|
CmiAllocateHashTableCell (IN PEREGISTRY_HIVE RegistryHive,
|
||||||
OUT PHASH_TABLE_CELL *HashBlock,
|
OUT PHASH_TABLE_CELL *HashBlock,
|
||||||
|
@ -675,34 +548,4 @@ CmiAddKeyToHashTable(PEREGISTRY_HIVE RegistryHive,
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS
|
|
||||||
CmiRemoveKeyFromHashTable(PEREGISTRY_HIVE RegistryHive,
|
|
||||||
PHASH_TABLE_CELL HashBlock,
|
|
||||||
HCELL_INDEX NKBOffset)
|
|
||||||
{
|
|
||||||
ULONG i;
|
|
||||||
|
|
||||||
for (i = 0; i < HashBlock->HashTableSize; i++)
|
|
||||||
{
|
|
||||||
if (HashBlock->Table[i].KeyOffset == NKBOffset)
|
|
||||||
{
|
|
||||||
RtlMoveMemory(HashBlock->Table + i,
|
|
||||||
HashBlock->Table + i + 1,
|
|
||||||
(HashBlock->HashTableSize - i - 1) *
|
|
||||||
sizeof(HashBlock->Table[0]));
|
|
||||||
return STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return STATUS_UNSUCCESSFUL;
|
|
||||||
}
|
|
||||||
|
|
||||||
NTSTATUS
|
|
||||||
CmiSaveTempHive (PEREGISTRY_HIVE Hive,
|
|
||||||
HANDLE FileHandle)
|
|
||||||
{
|
|
||||||
Hive->HiveHandle = FileHandle;
|
|
||||||
return HvWriteHive(&Hive->Hive) ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* EOF */
|
/* EOF */
|
||||||
|
|
|
@ -633,21 +633,10 @@ CmpDeleteKeyObject(PVOID DeletedObject)
|
||||||
RemoveEntryList(&KeyObject->ListEntry);
|
RemoveEntryList(&KeyObject->ListEntry);
|
||||||
RtlFreeUnicodeString(&KeyObject->Name);
|
RtlFreeUnicodeString(&KeyObject->Name);
|
||||||
|
|
||||||
if (!NT_SUCCESS(CmiRemoveKeyFromList(KeyObject)))
|
ASSERT((KeyObject->Flags & KO_MARKED_FOR_DELETE) == FALSE);
|
||||||
{
|
|
||||||
DPRINT1("Key not found in parent list ???\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
ASSERT((KeyObject->Flags & KO_MARKED_FOR_DELETE) == FALSE);
|
|
||||||
|
|
||||||
ObDereferenceObject (ParentKeyObject);
|
ObDereferenceObject (ParentKeyObject);
|
||||||
|
|
||||||
if (KeyObject->SubKeyCounts)
|
|
||||||
{
|
|
||||||
KEBUGCHECK(REGISTRY_ERROR);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (KeyObject->SizeOfSubKeys)
|
if (KeyObject->SizeOfSubKeys)
|
||||||
{
|
{
|
||||||
ExFreePool(KeyObject->SubKeys);
|
ExFreePool(KeyObject->SubKeys);
|
||||||
|
@ -768,36 +757,6 @@ CmiAddKeyToList(PKEY_OBJECT ParentKey,
|
||||||
NewKey->ParentKey = ParentKey;
|
NewKey->ParentKey = ParentKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
NTSTATUS
|
|
||||||
CmiRemoveKeyFromList(PKEY_OBJECT KeyToRemove)
|
|
||||||
{
|
|
||||||
PKEY_OBJECT ParentKey;
|
|
||||||
ULONG Index;
|
|
||||||
|
|
||||||
ParentKey = KeyToRemove->ParentKey;
|
|
||||||
/* FIXME: If list maintained in alphabetic order, use dichotomic search */
|
|
||||||
for (Index = 0; Index < ParentKey->SubKeyCounts; Index++)
|
|
||||||
{
|
|
||||||
if (ParentKey->SubKeys[Index] == KeyToRemove)
|
|
||||||
{
|
|
||||||
if (Index < ParentKey->SubKeyCounts-1)
|
|
||||||
RtlMoveMemory(&ParentKey->SubKeys[Index],
|
|
||||||
&ParentKey->SubKeys[Index + 1],
|
|
||||||
(ParentKey->SubKeyCounts - Index - 1) * sizeof(PKEY_OBJECT));
|
|
||||||
ParentKey->SubKeyCounts--;
|
|
||||||
|
|
||||||
DPRINT("Dereference parent key: 0x%x\n", ParentKey);
|
|
||||||
|
|
||||||
ObDereferenceObject(ParentKey);
|
|
||||||
return STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return STATUS_UNSUCCESSFUL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
CmiScanKeyList(PKEY_OBJECT Parent,
|
CmiScanKeyList(PKEY_OBJECT Parent,
|
||||||
PUNICODE_STRING KeyName,
|
PUNICODE_STRING KeyName,
|
||||||
|
|
|
@ -693,6 +693,7 @@ typedef struct _KEY_INFORMATION
|
||||||
#define SYSTEM_LOG_FILE L"\\SystemRoot\\System32\\Config\\SYSTEM.log"
|
#define SYSTEM_LOG_FILE L"\\SystemRoot\\System32\\Config\\SYSTEM.log"
|
||||||
#define REG_SYSTEM_KEY_NAME L"\\Registry\\Machine\\SYSTEM"
|
#define REG_SYSTEM_KEY_NAME L"\\Registry\\Machine\\SYSTEM"
|
||||||
#define REG_HARDWARE_KEY_NAME L"\\Registry\\Machine\\HARDWARE"
|
#define REG_HARDWARE_KEY_NAME L"\\Registry\\Machine\\HARDWARE"
|
||||||
|
#define IsNoFileHive(Hive) ((Hive)->Flags & HIVE_NO_FILE)
|
||||||
typedef struct _EREGISTRY_HIVE
|
typedef struct _EREGISTRY_HIVE
|
||||||
{
|
{
|
||||||
HHIVE Hive;
|
HHIVE Hive;
|
||||||
|
@ -1032,6 +1033,14 @@ EnlistKeyBodyWithKCB(
|
||||||
IN ULONG Flags
|
IN ULONG Flags
|
||||||
);
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
CmpFreeKeyByCell(
|
||||||
|
IN PHHIVE Hive,
|
||||||
|
IN HCELL_INDEX Cell,
|
||||||
|
IN BOOLEAN Unlink
|
||||||
|
);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Name Functions
|
// Name Functions
|
||||||
//
|
//
|
||||||
|
@ -1131,6 +1140,22 @@ CmpComputeHashKey(
|
||||||
IN BOOLEAN AllowSeparators
|
IN BOOLEAN AllowSeparators
|
||||||
);
|
);
|
||||||
|
|
||||||
|
BOOLEAN
|
||||||
|
NTAPI
|
||||||
|
CmpRemoveSubKey(
|
||||||
|
IN PHHIVE Hive,
|
||||||
|
IN HCELL_INDEX ParentKey,
|
||||||
|
IN HCELL_INDEX TargetKey
|
||||||
|
);
|
||||||
|
|
||||||
|
BOOLEAN
|
||||||
|
NTAPI
|
||||||
|
CmpMarkIndexDirty(
|
||||||
|
IN PHHIVE Hive,
|
||||||
|
HCELL_INDEX ParentKey,
|
||||||
|
HCELL_INDEX TargetKey
|
||||||
|
);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Cell Value Routines
|
// Cell Value Routines
|
||||||
//
|
//
|
||||||
|
|
|
@ -983,3 +983,87 @@ Quickie:
|
||||||
KeLeaveCriticalRegion();
|
KeLeaveCriticalRegion();
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
CmDeleteKey(IN PKEY_OBJECT KeyObject)
|
||||||
|
{
|
||||||
|
NTSTATUS Status;
|
||||||
|
PHHIVE Hive;
|
||||||
|
PCM_KEY_NODE Node, Parent;
|
||||||
|
HCELL_INDEX Cell, ParentCell;
|
||||||
|
|
||||||
|
/* Acquire hive lock */
|
||||||
|
KeEnterCriticalRegion();
|
||||||
|
ExAcquireResourceExclusiveLite(&CmpRegistryLock, TRUE);
|
||||||
|
|
||||||
|
/* Get the hive and node */
|
||||||
|
Hive = &KeyObject->RegistryHive->Hive;
|
||||||
|
Cell = KeyObject->KeyCellOffset;
|
||||||
|
|
||||||
|
/* Check if we have no parent */
|
||||||
|
if (!KeyObject->ParentKey)
|
||||||
|
{
|
||||||
|
/* This is an attempt to delete \Registry itself! */
|
||||||
|
Status = STATUS_CANNOT_DELETE;
|
||||||
|
goto Quickie;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the key node */
|
||||||
|
Node = (PCM_KEY_NODE)HvGetCell(Hive, Cell);
|
||||||
|
if (!Node)
|
||||||
|
{
|
||||||
|
/* Fail */
|
||||||
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
goto Quickie;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if we don't have any children */
|
||||||
|
if (!(Node->SubKeyCounts[HvStable] + Node->SubKeyCounts[HvVolatile]))
|
||||||
|
{
|
||||||
|
/* Get the parent and free the cell */
|
||||||
|
ParentCell = Node->Parent;
|
||||||
|
Status = CmpFreeKeyByCell(Hive, Cell, TRUE);
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
/* Get the parent node */
|
||||||
|
Parent = (PCM_KEY_NODE)HvGetCell(Hive, ParentCell);
|
||||||
|
if (Parent)
|
||||||
|
{
|
||||||
|
/* Make sure we're dirty */
|
||||||
|
ASSERT(HvIsCellDirty(Hive, ParentCell));
|
||||||
|
|
||||||
|
/* Update the write time */
|
||||||
|
KeQuerySystemTime(&Parent->LastWriteTime);
|
||||||
|
|
||||||
|
/* Release the cell */
|
||||||
|
HvReleaseCell(Hive, ParentCell);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Clear the cell */
|
||||||
|
KeyObject->KeyCellOffset = HCELL_NIL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Fail */
|
||||||
|
Status = STATUS_CANNOT_DELETE;
|
||||||
|
}
|
||||||
|
|
||||||
|
Quickie:
|
||||||
|
/* Release the cell */
|
||||||
|
HvReleaseCell(Hive, Cell);
|
||||||
|
|
||||||
|
/* Make sure we're file-backed */
|
||||||
|
if (!(IsNoFileHive(KeyObject->RegistryHive)) ||
|
||||||
|
!(IsNoFileHive(KeyObject->ParentKey->RegistryHive)))
|
||||||
|
{
|
||||||
|
/* Sync up the hives */
|
||||||
|
CmiSyncHives();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Release hive lock */
|
||||||
|
ExReleaseResourceLite(&CmpRegistryLock);
|
||||||
|
KeLeaveCriticalRegion();
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
|
@ -703,12 +703,6 @@ CmpFindSubKeyByName(IN PHHIVE Hive,
|
||||||
{
|
{
|
||||||
/* Get the Index */
|
/* Get the Index */
|
||||||
IndexRoot = (PCM_KEY_INDEX)HvGetCell(Hive, Parent->SubKeyLists[i]);
|
IndexRoot = (PCM_KEY_INDEX)HvGetCell(Hive, Parent->SubKeyLists[i]);
|
||||||
#if 0
|
|
||||||
/* Make sure we have one and that the cell is allocated */
|
|
||||||
ASSERT((IndexRoot == NULL) ||
|
|
||||||
HvIsCellAllocated(Hive, Parent->SubKeyLists[i]));
|
|
||||||
#endif
|
|
||||||
/* Fail if we don't actually have an index root */
|
|
||||||
if (!IndexRoot) return HCELL_NIL;
|
if (!IndexRoot) return HCELL_NIL;
|
||||||
|
|
||||||
/* Get the cell we'll need to release */
|
/* Get the cell we'll need to release */
|
||||||
|
@ -777,3 +771,343 @@ CmpFindSubKeyByName(IN PHHIVE Hive,
|
||||||
/* If we got here, then we failed */
|
/* If we got here, then we failed */
|
||||||
return HCELL_NIL;
|
return HCELL_NIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOLEAN
|
||||||
|
NTAPI
|
||||||
|
CmpMarkIndexDirty(IN PHHIVE Hive,
|
||||||
|
IN HCELL_INDEX ParentKey,
|
||||||
|
IN HCELL_INDEX TargetKey)
|
||||||
|
{
|
||||||
|
PCM_KEY_NODE Node;
|
||||||
|
UNICODE_STRING SearchName;
|
||||||
|
BOOLEAN IsCompressed;
|
||||||
|
ULONG i, Result;
|
||||||
|
PCM_KEY_INDEX Index;
|
||||||
|
HCELL_INDEX IndexCell, Child = HCELL_NIL, CellToRelease = HCELL_NIL;
|
||||||
|
|
||||||
|
/* Get the target key node */
|
||||||
|
Node = (PCM_KEY_NODE)HvGetCell(Hive, TargetKey);
|
||||||
|
if (!Node) return FALSE;
|
||||||
|
|
||||||
|
/* Check if it's compressed */
|
||||||
|
if (Node->Flags & KEY_COMP_NAME)
|
||||||
|
{
|
||||||
|
/* Remember this for later */
|
||||||
|
IsCompressed = TRUE;
|
||||||
|
|
||||||
|
/* Build the search name */
|
||||||
|
SearchName.Length = CmpCompressedNameSize(Node->Name,
|
||||||
|
Node->NameLength);
|
||||||
|
SearchName.MaximumLength = SearchName.Length;
|
||||||
|
SearchName.Buffer = ExAllocatePoolWithTag(PagedPool,
|
||||||
|
SearchName.Length,
|
||||||
|
TAG_CM);
|
||||||
|
if (!SearchName.Buffer)
|
||||||
|
{
|
||||||
|
/* Fail */
|
||||||
|
HvReleaseCell(Hive, TargetKey);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Copy it */
|
||||||
|
CmpCopyCompressedName(SearchName.Buffer,
|
||||||
|
SearchName.MaximumLength,
|
||||||
|
Node->Name,
|
||||||
|
Node->NameLength);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Name isn't compressed, build it directly from the node */
|
||||||
|
IsCompressed = FALSE;
|
||||||
|
SearchName.Length = Node->NameLength;
|
||||||
|
SearchName.MaximumLength = Node->NameLength;
|
||||||
|
SearchName.Buffer = Node->Name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We can release the target key now */
|
||||||
|
HvReleaseCell(Hive, TargetKey);
|
||||||
|
|
||||||
|
/* Now get the parent key node */
|
||||||
|
Node = (PCM_KEY_NODE)HvGetCell(Hive, ParentKey);
|
||||||
|
if (!Node) goto Quickie;
|
||||||
|
|
||||||
|
/* Loop all hive storage */
|
||||||
|
for (i = 0; i < Hive->StorageTypeCount; i++)
|
||||||
|
{
|
||||||
|
/* Check if any subkeys are in this index */
|
||||||
|
if (Node->SubKeyCounts[i])
|
||||||
|
{
|
||||||
|
/* Get the cell index */
|
||||||
|
//ASSERT(HvIsCellAllocated(Hive, Node->SubKeyLists[i]));
|
||||||
|
IndexCell = Node->SubKeyLists[i];
|
||||||
|
|
||||||
|
/* Check if we had anything to release from before */
|
||||||
|
if (CellToRelease != HCELL_NIL)
|
||||||
|
{
|
||||||
|
/* Release it now */
|
||||||
|
HvReleaseCell(Hive, CellToRelease);
|
||||||
|
CellToRelease = HCELL_NIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the key index for the cell */
|
||||||
|
Index = (PCM_KEY_INDEX)HvGetCell(Hive, IndexCell);
|
||||||
|
if (!Index) goto Quickie;
|
||||||
|
|
||||||
|
/* Release it at the next iteration or below */
|
||||||
|
CellToRelease = IndexCell;
|
||||||
|
|
||||||
|
/* Check if this is a root */
|
||||||
|
if (Index->Signature == CM_KEY_INDEX_ROOT)
|
||||||
|
{
|
||||||
|
/* Get the child inside the root */
|
||||||
|
Result = CmpFindSubKeyInRoot(Hive, Index, &SearchName, &Child);
|
||||||
|
if (Result & 0x80000000) goto Quickie;
|
||||||
|
if (Child == HCELL_NIL) continue;
|
||||||
|
|
||||||
|
/* We found it, mark the cell dirty */
|
||||||
|
HvMarkCellDirty(Hive, IndexCell);
|
||||||
|
|
||||||
|
/* Check if we had anything to release from before */
|
||||||
|
if (CellToRelease != HCELL_NIL)
|
||||||
|
{
|
||||||
|
/* Release it now */
|
||||||
|
HvReleaseCell(Hive, CellToRelease);
|
||||||
|
CellToRelease = HCELL_NIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now this child is the index, get the actual key index */
|
||||||
|
IndexCell = Child;
|
||||||
|
Index = (PCM_KEY_INDEX)HvGetCell(Hive, Child);
|
||||||
|
if (!Index) goto Quickie;
|
||||||
|
|
||||||
|
/* Release it later */
|
||||||
|
CellToRelease = Child;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make sure this is a valid index */
|
||||||
|
ASSERT((Index->Signature == CM_KEY_INDEX_LEAF) ||
|
||||||
|
(Index->Signature == CM_KEY_FAST_LEAF) ||
|
||||||
|
(Index->Signature == CM_KEY_HASH_LEAF));
|
||||||
|
|
||||||
|
/* Find the child in the leaf */
|
||||||
|
Result = CmpFindSubKeyInLeaf(Hive, Index, &SearchName, &Child);
|
||||||
|
if (Result & 0x80000000) goto Quickie;
|
||||||
|
if (Child != HCELL_NIL)
|
||||||
|
{
|
||||||
|
/* We found it, free the name now */
|
||||||
|
if (IsCompressed) ExFreePool(SearchName.Buffer);
|
||||||
|
|
||||||
|
/* Release the parent key */
|
||||||
|
HvReleaseCell(Hive, ParentKey);
|
||||||
|
|
||||||
|
/* Check if we had a left over cell to release */
|
||||||
|
if (CellToRelease != HCELL_NIL)
|
||||||
|
{
|
||||||
|
/* Release it */
|
||||||
|
HvReleaseCell(Hive, CellToRelease);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* And mark the index cell dirty */
|
||||||
|
HvMarkCellDirty(Hive, IndexCell);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Quickie:
|
||||||
|
/* Release any cells that we still hold */
|
||||||
|
if (Node) HvReleaseCell(Hive, ParentKey);
|
||||||
|
if (CellToRelease != HCELL_NIL) HvReleaseCell(Hive, CellToRelease);
|
||||||
|
|
||||||
|
/* Free the search name and return failure */
|
||||||
|
if (IsCompressed) ExFreePool(SearchName.Buffer);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOLEAN
|
||||||
|
NTAPI
|
||||||
|
CmpRemoveSubKey(IN PHHIVE Hive,
|
||||||
|
IN HCELL_INDEX ParentKey,
|
||||||
|
IN HCELL_INDEX TargetKey)
|
||||||
|
{
|
||||||
|
PCM_KEY_NODE Node;
|
||||||
|
UNICODE_STRING SearchName;
|
||||||
|
BOOLEAN IsCompressed;
|
||||||
|
WCHAR Buffer[50];
|
||||||
|
HCELL_INDEX RootCell = HCELL_NIL, LeafCell, ChildCell;
|
||||||
|
PCM_KEY_INDEX Root = NULL, Leaf;
|
||||||
|
PCM_KEY_FAST_INDEX Child;
|
||||||
|
ULONG Storage, RootIndex = 0x80000000, LeafIndex;
|
||||||
|
BOOLEAN Result = FALSE;
|
||||||
|
HCELL_INDEX CellToRelease1 = HCELL_NIL, CellToRelease2 = HCELL_NIL;
|
||||||
|
|
||||||
|
/* Get the target key node */
|
||||||
|
Node = (PCM_KEY_NODE)HvGetCell(Hive, TargetKey);
|
||||||
|
if (!Node) return FALSE;
|
||||||
|
|
||||||
|
/* Make sure it's dirty, then release it */
|
||||||
|
ASSERT(HvIsCellDirty(Hive, TargetKey));
|
||||||
|
HvReleaseCell(Hive, TargetKey);
|
||||||
|
|
||||||
|
/* Check if the name is compressed */
|
||||||
|
if (Node->Flags & KEY_COMP_NAME)
|
||||||
|
{
|
||||||
|
/* Remember for later */
|
||||||
|
IsCompressed = TRUE;
|
||||||
|
|
||||||
|
/* Build the search name */
|
||||||
|
SearchName.Length = CmpCompressedNameSize(Node->Name,
|
||||||
|
Node->NameLength);
|
||||||
|
SearchName.MaximumLength = SearchName.Length;
|
||||||
|
|
||||||
|
/* Do we need an extra bufer? */
|
||||||
|
if (SearchName.MaximumLength > sizeof(Buffer))
|
||||||
|
{
|
||||||
|
/* Allocate one */
|
||||||
|
SearchName.Buffer = ExAllocatePoolWithTag(PagedPool,
|
||||||
|
SearchName.Length,
|
||||||
|
TAG_CM);
|
||||||
|
if (!SearchName.Buffer) return FALSE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Otherwise, use our local stack buffer */
|
||||||
|
SearchName.Buffer = Buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Copy the compressed name */
|
||||||
|
CmpCopyCompressedName(SearchName.Buffer,
|
||||||
|
SearchName.MaximumLength,
|
||||||
|
Node->Name,
|
||||||
|
Node->NameLength);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* It's not compressed, build the name directly from the node */
|
||||||
|
IsCompressed = FALSE;
|
||||||
|
SearchName.Length = Node->NameLength;
|
||||||
|
SearchName.MaximumLength = Node->NameLength;
|
||||||
|
SearchName.Buffer = Node->Name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now get the parent node */
|
||||||
|
Node = (PCM_KEY_NODE)HvGetCell(Hive, ParentKey);
|
||||||
|
if (!Node) goto Exit;
|
||||||
|
|
||||||
|
/* Make sure it's dirty, then release it */
|
||||||
|
ASSERT(HvIsCellDirty(Hive, ParentKey));
|
||||||
|
HvReleaseCell(Hive, ParentKey);
|
||||||
|
|
||||||
|
/* Get the storage type and make sure it's not empty */
|
||||||
|
Storage = HvGetCellType(TargetKey);
|
||||||
|
ASSERT(Node->SubKeyCounts[Storage] != 0);
|
||||||
|
//ASSERT(HvIsCellAllocated(Hive, Node->SubKeyLists[Storage]));
|
||||||
|
|
||||||
|
/* Get the leaf cell now */
|
||||||
|
LeafCell = Node->SubKeyLists[Storage];
|
||||||
|
Leaf = (PCM_KEY_INDEX)HvGetCell(Hive, LeafCell);
|
||||||
|
if (!Leaf) goto Exit;
|
||||||
|
|
||||||
|
/* Remember to release it later */
|
||||||
|
CellToRelease1 = LeafCell;
|
||||||
|
|
||||||
|
/* Check if the leaf is a root */
|
||||||
|
if (Leaf->Signature == CM_KEY_INDEX_ROOT)
|
||||||
|
{
|
||||||
|
/* Find the child inside the root */
|
||||||
|
RootIndex = CmpFindSubKeyInRoot(Hive, Leaf, &SearchName, &ChildCell);
|
||||||
|
if (RootIndex & 0x80000000) goto Exit;
|
||||||
|
ASSERT(ChildCell != FALSE);
|
||||||
|
|
||||||
|
/* The root cell is now this leaf */
|
||||||
|
Root = Leaf;
|
||||||
|
RootCell = LeafCell;
|
||||||
|
|
||||||
|
/* And the new leaf is now this child */
|
||||||
|
LeafCell = ChildCell;
|
||||||
|
Leaf = (PCM_KEY_INDEX)HvGetCell(Hive, LeafCell);
|
||||||
|
if (!Leaf) goto Exit;
|
||||||
|
|
||||||
|
/* Remember to release it later */
|
||||||
|
CellToRelease2 = LeafCell;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make sure the leaf is valid */
|
||||||
|
ASSERT((Leaf->Signature == CM_KEY_INDEX_LEAF) ||
|
||||||
|
(Leaf->Signature == CM_KEY_FAST_LEAF) ||
|
||||||
|
(Leaf->Signature == CM_KEY_HASH_LEAF));
|
||||||
|
|
||||||
|
/* Now get the child in the leaf */
|
||||||
|
LeafIndex = CmpFindSubKeyInLeaf(Hive, Leaf, &SearchName, &ChildCell);
|
||||||
|
if (LeafIndex & 0x80000000) goto Exit;
|
||||||
|
ASSERT(ChildCell != HCELL_NIL);
|
||||||
|
|
||||||
|
/* Decrement key counts and check if this was the last leaf entry */
|
||||||
|
Node->SubKeyCounts[Storage]--;
|
||||||
|
if (!(--Leaf->Count))
|
||||||
|
{
|
||||||
|
/* Free the leaf */
|
||||||
|
HvFreeCell(Hive, LeafCell);
|
||||||
|
|
||||||
|
/* Check if we were inside a root */
|
||||||
|
if (Root)
|
||||||
|
{
|
||||||
|
/* Decrease the root count too, since the leaf is going away */
|
||||||
|
if (!(--Root->Count))
|
||||||
|
{
|
||||||
|
/* The root is gone too,n ow */
|
||||||
|
HvFreeCell(Hive, RootCell);
|
||||||
|
Node->SubKeyLists[Storage] = HCELL_NIL;
|
||||||
|
}
|
||||||
|
else if (RootIndex < Root->Count)
|
||||||
|
{
|
||||||
|
/* Bring everything up by one */
|
||||||
|
RtlMoveMemory(&Root->List[RootIndex],
|
||||||
|
&Root->List[RootIndex + 1],
|
||||||
|
(Root->Count - RootIndex) * sizeof(HCELL_INDEX));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Otherwise, just clear the cell */
|
||||||
|
Node->SubKeyLists[Storage] = HCELL_NIL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (LeafIndex < Leaf->Count)
|
||||||
|
{
|
||||||
|
/* Was the leaf a normal index? */
|
||||||
|
if (Leaf->Signature == CM_KEY_INDEX_LEAF)
|
||||||
|
{
|
||||||
|
/* Bring everything up by one */
|
||||||
|
RtlMoveMemory(&Leaf->List[LeafIndex],
|
||||||
|
&Leaf->List[LeafIndex + 1],
|
||||||
|
(Leaf->Count - LeafIndex) * sizeof(HCELL_INDEX));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* This is a fast index, bring everything up by one */
|
||||||
|
Child = (PCM_KEY_FAST_INDEX)Leaf;
|
||||||
|
RtlMoveMemory(&Child->List[LeafIndex],
|
||||||
|
&Child->List[LeafIndex+1],
|
||||||
|
(Child->Count - LeafIndex) * sizeof(CM_INDEX));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we got here, now we're done */
|
||||||
|
Result = TRUE;
|
||||||
|
|
||||||
|
Exit:
|
||||||
|
/* Release any cells we may have been holding */
|
||||||
|
if (CellToRelease1 != HCELL_NIL) HvReleaseCell(Hive, CellToRelease1);
|
||||||
|
if (CellToRelease2 != HCELL_NIL) HvReleaseCell(Hive, CellToRelease2);
|
||||||
|
|
||||||
|
/* Check if the name was compressed and not inside our local buffer */
|
||||||
|
if ((IsCompressed) && (SearchName.MaximumLength > sizeof(Buffer)))
|
||||||
|
{
|
||||||
|
/* Free the buffer we allocated */
|
||||||
|
ExFreePool(SearchName.Buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return the result */
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
221
reactos/ntoskrnl/config/cmkeydel.c
Normal file
221
reactos/ntoskrnl/config/cmkeydel.c
Normal file
|
@ -0,0 +1,221 @@
|
||||||
|
/*
|
||||||
|
* PROJECT: ReactOS Kernel
|
||||||
|
* LICENSE: GPL - See COPYING in the top level directory
|
||||||
|
* FILE: ntoskrnl/config/cmkeydel.c
|
||||||
|
* PURPOSE: Configuration Manager - Key Body Deletion
|
||||||
|
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* INCLUDES ******************************************************************/
|
||||||
|
|
||||||
|
#include "ntoskrnl.h"
|
||||||
|
#include "cm.h"
|
||||||
|
#define NDEBUG
|
||||||
|
#include "debug.h"
|
||||||
|
|
||||||
|
/* FUNCTIONS *****************************************************************/
|
||||||
|
|
||||||
|
BOOLEAN
|
||||||
|
NTAPI
|
||||||
|
CmpMarkKeyDirty(IN PHHIVE Hive,
|
||||||
|
IN HCELL_INDEX Cell,
|
||||||
|
IN BOOLEAN CheckNoSubkeys)
|
||||||
|
{
|
||||||
|
PCELL_DATA CellData, ListData, SecurityData, ValueData;
|
||||||
|
ULONG i;
|
||||||
|
|
||||||
|
/* Get the cell data for our target */
|
||||||
|
CellData = HvGetCell(Hive, Cell);
|
||||||
|
if (!CellData) return FALSE;
|
||||||
|
|
||||||
|
/* Check if sanity checks requested */
|
||||||
|
if (CheckNoSubkeys)
|
||||||
|
{
|
||||||
|
/* Do them */
|
||||||
|
ASSERT(CellData->u.KeyNode.SubKeyCounts[HvStable] == 0);
|
||||||
|
ASSERT(CellData->u.KeyNode.SubKeyCounts[HvVolatile] == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If this is an exit hive, there's nothing to do */
|
||||||
|
if (CellData->u.KeyNode.Flags & KEY_HIVE_EXIT)
|
||||||
|
{
|
||||||
|
/* Release the cell and get out */
|
||||||
|
HvReleaseCell(Hive, Cell);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Otherwise, mark it dirty and release it */
|
||||||
|
HvMarkCellDirty(Hive, Cell);
|
||||||
|
HvReleaseCell(Hive, Cell);
|
||||||
|
|
||||||
|
/* Check if we have a class */
|
||||||
|
if (CellData->u.KeyNode.Class != HCELL_NIL)
|
||||||
|
{
|
||||||
|
/* Mark it dirty */
|
||||||
|
HvMarkCellDirty(Hive, CellData->u.KeyNode.Class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if we have security */
|
||||||
|
if (CellData->u.KeyNode.Security != HCELL_NIL)
|
||||||
|
{
|
||||||
|
/* Mark it dirty */
|
||||||
|
HvMarkCellDirty(Hive, CellData->u.KeyNode.Security);
|
||||||
|
|
||||||
|
/* Get the security data and release it */
|
||||||
|
SecurityData = HvGetCell(Hive, CellData->u.KeyNode.Security);
|
||||||
|
if (!SecurityData) ASSERT(FALSE);
|
||||||
|
HvReleaseCell(Hive, CellData->u.KeyNode.Security);
|
||||||
|
|
||||||
|
/* Mark the security links dirty too */
|
||||||
|
HvMarkCellDirty(Hive, SecurityData->u.KeySecurity.Flink);
|
||||||
|
HvMarkCellDirty(Hive, SecurityData->u.KeySecurity.Blink);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if we have any values */
|
||||||
|
if (CellData->u.KeyNode.ValueList.Count > 0)
|
||||||
|
{
|
||||||
|
/* Dirty the value list */
|
||||||
|
HvMarkCellDirty(Hive, CellData->u.KeyNode.ValueList.List);
|
||||||
|
|
||||||
|
/* Get the list data itself, and release it */
|
||||||
|
ListData = HvGetCell(Hive, CellData->u.KeyNode.ValueList.List);
|
||||||
|
if (!ListData) ASSERT(FALSE);
|
||||||
|
HvReleaseCell(Hive, CellData->u.KeyNode.ValueList.List);
|
||||||
|
|
||||||
|
/* Loop all values */
|
||||||
|
for (i = 0; i < CellData->u.KeyNode.ValueList.Count; i++)
|
||||||
|
{
|
||||||
|
/* Dirty each value */
|
||||||
|
HvMarkCellDirty(Hive, ListData->u.KeyList[i]);
|
||||||
|
|
||||||
|
/* Get the value data and release it */
|
||||||
|
ValueData = HvGetCell(Hive, ListData->u.KeyList[i]);
|
||||||
|
if (ValueData) ASSERT(FALSE);
|
||||||
|
HvReleaseCell(Hive,ListData->u.KeyList[i]);
|
||||||
|
|
||||||
|
/* Mark the value data dirty too */
|
||||||
|
if (!CmpMarkValueDataDirty(Hive, &ValueData->u.KeyValue))
|
||||||
|
{
|
||||||
|
/* Failure */
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If this is an entry hive, we're done */
|
||||||
|
if (CellData->u.KeyNode.Flags & KEY_HIVE_ENTRY) return TRUE;
|
||||||
|
|
||||||
|
/* Otherwise mark the index dirty too */
|
||||||
|
if (!CmpMarkIndexDirty(Hive, CellData->u.KeyNode.Parent, Cell))
|
||||||
|
{
|
||||||
|
/* Failure */
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Finally, mark the parent dirty */
|
||||||
|
HvMarkCellDirty(Hive, CellData->u.KeyNode.Parent);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOLEAN
|
||||||
|
NTAPI
|
||||||
|
CmpFreeKeyBody(IN PHHIVE Hive,
|
||||||
|
IN HCELL_INDEX Cell)
|
||||||
|
{
|
||||||
|
PCELL_DATA CellData;
|
||||||
|
|
||||||
|
/* Get the key node */
|
||||||
|
CellData = HvGetCell(Hive, Cell);
|
||||||
|
if (!CellData) ASSERT(FALSE);
|
||||||
|
|
||||||
|
/* Check if we can delete the child cells */
|
||||||
|
if (!(CellData->u.KeyNode.Flags & KEY_HIVE_EXIT))
|
||||||
|
{
|
||||||
|
/* Check if we have a security cell */
|
||||||
|
if (CellData->u.KeyNode.Security != HCELL_NIL)
|
||||||
|
{
|
||||||
|
/* Free the security cell */
|
||||||
|
HvFreeCell(Hive, CellData->u.KeyNode.Security);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if we have a class */
|
||||||
|
if (CellData->u.KeyNode.ClassLength > 0)
|
||||||
|
{
|
||||||
|
/* Free it */
|
||||||
|
HvFreeCell(Hive, CellData->u.KeyNode.Class);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Release and free the cell */
|
||||||
|
HvReleaseCell(Hive, Cell);
|
||||||
|
HvFreeCell(Hive, Cell);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
CmpFreeKeyByCell(IN PHHIVE Hive,
|
||||||
|
IN HCELL_INDEX Cell,
|
||||||
|
IN BOOLEAN Unlink)
|
||||||
|
{
|
||||||
|
PCELL_DATA CellData, ParentData, ListData;
|
||||||
|
ULONG i;
|
||||||
|
BOOLEAN Result;
|
||||||
|
|
||||||
|
/* Mark the entire key dirty */
|
||||||
|
CmpMarkKeyDirty(Hive, Cell ,TRUE);
|
||||||
|
|
||||||
|
/* Get the target node and release it */
|
||||||
|
CellData = HvGetCell(Hive, Cell);
|
||||||
|
if (!CellData) ASSERT(FALSE);
|
||||||
|
HvReleaseCell(Hive, Cell);
|
||||||
|
|
||||||
|
/* Make sure we don't have subkeys */
|
||||||
|
ASSERT((CellData->u.KeyNode.SubKeyCounts[HvStable] +
|
||||||
|
CellData->u.KeyNode.SubKeyCounts[HvVolatile]) == 0);
|
||||||
|
|
||||||
|
/* Check if we have to unlink */
|
||||||
|
if (Unlink)
|
||||||
|
{
|
||||||
|
/* Remove the subkey */
|
||||||
|
Result = CmpRemoveSubKey(Hive, CellData->u.KeyNode.Parent, Cell);
|
||||||
|
if (!Result) return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
|
||||||
|
/* Get the parent node and release it */
|
||||||
|
ParentData = HvGetCell(Hive, CellData->u.KeyNode.Parent);
|
||||||
|
if (!ParentData) ASSERT(FALSE);
|
||||||
|
HvReleaseCell(Hive, CellData->u.KeyNode.Parent);
|
||||||
|
|
||||||
|
/* Check if the parent node has no more subkeys */
|
||||||
|
if (!(ParentData->u.KeyNode.SubKeyCounts[HvStable] +
|
||||||
|
ParentData->u.KeyNode.SubKeyCounts[HvVolatile]))
|
||||||
|
{
|
||||||
|
/* Then free the cached name/class lengths */
|
||||||
|
ParentData->u.KeyNode.MaxNameLen = 0;
|
||||||
|
ParentData->u.KeyNode.MaxClassLen = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if we have any values */
|
||||||
|
if (CellData->u.KeyNode.ValueList.Count > 0)
|
||||||
|
{
|
||||||
|
/* Get the value list and release it */
|
||||||
|
ListData = HvGetCell(Hive, CellData->u.KeyNode.ValueList.List);
|
||||||
|
if (!ListData) ASSERT(FALSE);
|
||||||
|
HvReleaseCell(Hive, CellData->u.KeyNode.ValueList.List);
|
||||||
|
|
||||||
|
/* Loop every value */
|
||||||
|
for (i = 0; i < CellData->u.KeyNode.ValueList.Count; i++)
|
||||||
|
{
|
||||||
|
/* Free it */
|
||||||
|
if (!CmpFreeValue(Hive, ListData->u.KeyList[i])) ASSERT(FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Free the value list */
|
||||||
|
HvFreeCell(Hive, CellData->u.KeyNode.ValueList.List);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Free the key body itself, and then return our status */
|
||||||
|
if (!CmpFreeKeyBody(Hive, Cell)) return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
|
@ -99,6 +99,7 @@
|
||||||
<file>cminit.c</file>
|
<file>cminit.c</file>
|
||||||
<file>cmhook.c</file>
|
<file>cmhook.c</file>
|
||||||
<file>cmkcbncb.c</file>
|
<file>cmkcbncb.c</file>
|
||||||
|
<file>cmkeydel.c</file>
|
||||||
<file>cmmapvw.c</file>
|
<file>cmmapvw.c</file>
|
||||||
<file>cmname.c</file>
|
<file>cmname.c</file>
|
||||||
<file>cmparse.c</file>
|
<file>cmparse.c</file>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue