- 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:
Alex Ionescu 2007-05-17 00:27:14 +00:00
parent b527796afa
commit 70e2b462a5
10 changed files with 723 additions and 340 deletions

View file

@ -221,7 +221,7 @@ HvpRemoveFree(
pFreeCellOffset = FreeCellData;
}
ASSERT(FALSE);
//ASSERT(FALSE);
}
static HCELL_INDEX CMAPI

View file

@ -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(

View file

@ -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,

View file

@ -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 */

View file

@ -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);
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,

View file

@ -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
//

View file

@ -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;
}

View file

@ -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;
}

View 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;
}

View file

@ -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>