mirror of
https://github.com/reactos/reactos.git
synced 2025-02-24 01:15:09 +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;
|
||||
}
|
||||
|
||||
ASSERT(FALSE);
|
||||
//ASSERT(FALSE);
|
||||
}
|
||||
|
||||
static HCELL_INDEX CMAPI
|
||||
|
|
|
@ -167,9 +167,6 @@ VOID
|
|||
CmiAddKeyToList(IN PKEY_OBJECT ParentKey,
|
||||
IN PKEY_OBJECT NewKey);
|
||||
|
||||
NTSTATUS
|
||||
CmiRemoveKeyFromList(IN PKEY_OBJECT NewKey);
|
||||
|
||||
NTSTATUS
|
||||
CmiScanKeyList(IN PKEY_OBJECT Parent,
|
||||
IN PUNICODE_STRING KeyName,
|
||||
|
@ -184,9 +181,6 @@ CmiLoadHive(POBJECT_ATTRIBUTES KeyObjectAttributes,
|
|||
NTSTATUS
|
||||
CmiFlushRegistryHive(PEREGISTRY_HIVE RegistryHive);
|
||||
|
||||
ULONG
|
||||
CmiGetNumberOfSubKeys(PKEY_OBJECT KeyObject);
|
||||
|
||||
ULONG
|
||||
CmiGetMaxNameLength(IN PHHIVE RegistryHive, IN PCM_KEY_NODE KeyCell);
|
||||
|
||||
|
@ -219,11 +213,6 @@ CmiAddSubKey(IN PEREGISTRY_HIVE RegistryHive,
|
|||
IN PUNICODE_STRING Class,
|
||||
IN ULONG CreateOptions);
|
||||
|
||||
NTSTATUS
|
||||
CmiRemoveSubKey(IN PEREGISTRY_HIVE RegistryHive,
|
||||
IN PKEY_OBJECT Parent,
|
||||
IN PKEY_OBJECT SubKey);
|
||||
|
||||
NTSTATUS
|
||||
CmiScanKeyForValue(IN PEREGISTRY_HIVE RegistryHive,
|
||||
IN PCM_KEY_NODE KeyCell,
|
||||
|
@ -279,6 +268,10 @@ CmEnumerateKey(IN PKEY_OBJECT KeyObject,
|
|||
IN ULONG Length,
|
||||
IN PULONG ResultLength);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CmDeleteKey(IN PKEY_OBJECT KeyObject);
|
||||
|
||||
NTSTATUS
|
||||
CmiAllocateHashTableCell(IN PEREGISTRY_HIVE RegistryHive,
|
||||
OUT PHASH_TABLE_CELL *HashBlock,
|
||||
|
@ -294,16 +287,6 @@ CmiAddKeyToHashTable(PEREGISTRY_HIVE RegistryHive,
|
|||
PCM_KEY_NODE NewKeyCell,
|
||||
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
|
||||
CmiConnectHive(POBJECT_ATTRIBUTES KeyObjectAttributes,
|
||||
PEREGISTRY_HIVE RegistryHive);
|
||||
|
@ -330,10 +313,6 @@ CmpFindSubKeyByName(
|
|||
VOID
|
||||
CmiSyncHives(VOID);
|
||||
|
||||
NTSTATUS
|
||||
CmiSaveTempHive (PEREGISTRY_HIVE Hive,
|
||||
HANDLE FileHandle);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CmFindObject(
|
||||
|
|
|
@ -435,115 +435,6 @@ Cleanup:
|
|||
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
|
||||
NtFlushKey(IN HANDLE KeyHandle)
|
||||
{
|
||||
|
@ -812,6 +703,52 @@ NtInitializeRegistry (IN BOOLEAN SetUpBoot)
|
|||
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
|
||||
NTAPI
|
||||
NtEnumerateKey(IN HANDLE KeyHandle,
|
||||
|
|
|
@ -66,7 +66,6 @@ CmCloseHiveFiles(PEREGISTRY_HIVE RegistryHive)
|
|||
ZwClose(RegistryHive->LogHandle);
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS
|
||||
CmiFlushRegistryHive(PEREGISTRY_HIVE RegistryHive)
|
||||
{
|
||||
|
@ -103,26 +102,6 @@ CmiFlushRegistryHive(PEREGISTRY_HIVE RegistryHive)
|
|||
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
|
||||
CmiGetMaxNameLength(PHHIVE Hive,
|
||||
PCM_KEY_NODE KeyCell)
|
||||
|
@ -160,7 +139,6 @@ CmiGetMaxNameLength(PHHIVE Hive,
|
|||
return MaxName;
|
||||
}
|
||||
|
||||
|
||||
ULONG
|
||||
CmiGetMaxClassLength(PHHIVE Hive,
|
||||
PCM_KEY_NODE KeyCell)
|
||||
|
@ -196,7 +174,6 @@ CmiGetMaxClassLength(PHHIVE Hive,
|
|||
return MaxClass;
|
||||
}
|
||||
|
||||
|
||||
ULONG
|
||||
CmiGetMaxValueNameLength(PHHIVE Hive,
|
||||
PCM_KEY_NODE KeyCell)
|
||||
|
@ -244,7 +221,6 @@ CmiGetMaxValueNameLength(PHHIVE Hive,
|
|||
return MaxValueName;
|
||||
}
|
||||
|
||||
|
||||
ULONG
|
||||
CmiGetMaxValueDataLength(PHHIVE Hive,
|
||||
PCM_KEY_NODE KeyCell)
|
||||
|
@ -517,109 +493,6 @@ CmiAddSubKey(PEREGISTRY_HIVE RegistryHive,
|
|||
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
|
||||
CmiAllocateHashTableCell (IN PEREGISTRY_HIVE RegistryHive,
|
||||
OUT PHASH_TABLE_CELL *HashBlock,
|
||||
|
@ -675,34 +548,4 @@ CmiAddKeyToHashTable(PEREGISTRY_HIVE RegistryHive,
|
|||
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 */
|
||||
|
|
|
@ -633,21 +633,10 @@ CmpDeleteKeyObject(PVOID DeletedObject)
|
|||
RemoveEntryList(&KeyObject->ListEntry);
|
||||
RtlFreeUnicodeString(&KeyObject->Name);
|
||||
|
||||
if (!NT_SUCCESS(CmiRemoveKeyFromList(KeyObject)))
|
||||
{
|
||||
DPRINT1("Key not found in parent list ???\n");
|
||||
}
|
||||
|
||||
|
||||
ASSERT((KeyObject->Flags & KO_MARKED_FOR_DELETE) == FALSE);
|
||||
ASSERT((KeyObject->Flags & KO_MARKED_FOR_DELETE) == FALSE);
|
||||
|
||||
ObDereferenceObject (ParentKeyObject);
|
||||
|
||||
if (KeyObject->SubKeyCounts)
|
||||
{
|
||||
KEBUGCHECK(REGISTRY_ERROR);
|
||||
}
|
||||
|
||||
if (KeyObject->SizeOfSubKeys)
|
||||
{
|
||||
ExFreePool(KeyObject->SubKeys);
|
||||
|
@ -768,36 +757,6 @@ CmiAddKeyToList(PKEY_OBJECT 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
|
||||
CmiScanKeyList(PKEY_OBJECT Parent,
|
||||
PUNICODE_STRING KeyName,
|
||||
|
|
|
@ -693,6 +693,7 @@ typedef struct _KEY_INFORMATION
|
|||
#define SYSTEM_LOG_FILE L"\\SystemRoot\\System32\\Config\\SYSTEM.log"
|
||||
#define REG_SYSTEM_KEY_NAME L"\\Registry\\Machine\\SYSTEM"
|
||||
#define REG_HARDWARE_KEY_NAME L"\\Registry\\Machine\\HARDWARE"
|
||||
#define IsNoFileHive(Hive) ((Hive)->Flags & HIVE_NO_FILE)
|
||||
typedef struct _EREGISTRY_HIVE
|
||||
{
|
||||
HHIVE Hive;
|
||||
|
@ -1032,6 +1033,14 @@ EnlistKeyBodyWithKCB(
|
|||
IN ULONG Flags
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CmpFreeKeyByCell(
|
||||
IN PHHIVE Hive,
|
||||
IN HCELL_INDEX Cell,
|
||||
IN BOOLEAN Unlink
|
||||
);
|
||||
|
||||
//
|
||||
// Name Functions
|
||||
//
|
||||
|
@ -1131,6 +1140,22 @@ CmpComputeHashKey(
|
|||
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
|
||||
//
|
||||
|
|
|
@ -983,3 +983,87 @@ Quickie:
|
|||
KeLeaveCriticalRegion();
|
||||
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 */
|
||||
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;
|
||||
|
||||
/* Get the cell we'll need to release */
|
||||
|
@ -777,3 +771,343 @@ CmpFindSubKeyByName(IN PHHIVE Hive,
|
|||
/* If we got here, then we failed */
|
||||
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>cmhook.c</file>
|
||||
<file>cmkcbncb.c</file>
|
||||
<file>cmkeydel.c</file>
|
||||
<file>cmmapvw.c</file>
|
||||
<file>cmname.c</file>
|
||||
<file>cmparse.c</file>
|
||||
|
|
Loading…
Reference in a new issue