Author: ion Date: Thu May 17 04:27:14 2007 New Revision: 26817
URL: http://svn.reactos.org/svn/reactos?rev=26817&view=rev Log: - 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.
Added: trunk/reactos/ntoskrnl/config/cmkeydel.c Modified: trunk/reactos/lib/cmlib/hivecell.c trunk/reactos/ntoskrnl/cm/cm.h trunk/reactos/ntoskrnl/cm/ntfunc.c trunk/reactos/ntoskrnl/cm/regfile.c trunk/reactos/ntoskrnl/cm/regobj.c trunk/reactos/ntoskrnl/config/cm.h trunk/reactos/ntoskrnl/config/cmapi.c trunk/reactos/ntoskrnl/config/cmindex.c trunk/reactos/ntoskrnl/ntoskrnl.rbuild
Modified: trunk/reactos/lib/cmlib/hivecell.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/lib/cmlib/hivecell.c?rev=26... ============================================================================== --- trunk/reactos/lib/cmlib/hivecell.c (original) +++ trunk/reactos/lib/cmlib/hivecell.c Thu May 17 04:27:14 2007 @@ -221,7 +221,7 @@ pFreeCellOffset = FreeCellData; }
- ASSERT(FALSE); + //ASSERT(FALSE); }
static HCELL_INDEX CMAPI
Modified: trunk/reactos/ntoskrnl/cm/cm.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/cm/cm.h?rev=26817&... ============================================================================== --- trunk/reactos/ntoskrnl/cm/cm.h (original) +++ trunk/reactos/ntoskrnl/cm/cm.h Thu May 17 04:27:14 2007 @@ -168,9 +168,6 @@ IN PKEY_OBJECT NewKey);
NTSTATUS -CmiRemoveKeyFromList(IN PKEY_OBJECT NewKey); - -NTSTATUS CmiScanKeyList(IN PKEY_OBJECT Parent, IN PUNICODE_STRING KeyName, IN ULONG Attributes, @@ -183,9 +180,6 @@
NTSTATUS CmiFlushRegistryHive(PEREGISTRY_HIVE RegistryHive); - -ULONG -CmiGetNumberOfSubKeys(PKEY_OBJECT KeyObject);
ULONG CmiGetMaxNameLength(IN PHHIVE RegistryHive, IN PCM_KEY_NODE KeyCell); @@ -220,11 +214,6 @@ 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, IN PUNICODE_STRING ValueName, @@ -280,6 +269,10 @@ IN PULONG ResultLength);
NTSTATUS +NTAPI +CmDeleteKey(IN PKEY_OBJECT KeyObject); + +NTSTATUS CmiAllocateHashTableCell(IN PEREGISTRY_HIVE RegistryHive, OUT PHASH_TABLE_CELL *HashBlock, OUT HCELL_INDEX *HBOffset, @@ -295,16 +288,6 @@ 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);
@@ -329,10 +312,6 @@
VOID CmiSyncHives(VOID); - -NTSTATUS -CmiSaveTempHive (PEREGISTRY_HIVE Hive, - HANDLE FileHandle);
NTSTATUS NTAPI
Modified: trunk/reactos/ntoskrnl/cm/ntfunc.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/cm/ntfunc.c?rev=26... ============================================================================== --- trunk/reactos/ntoskrnl/cm/ntfunc.c (original) +++ trunk/reactos/ntoskrnl/cm/ntfunc.c Thu May 17 04:27:14 2007 @@ -435,115 +435,6 @@ 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) { @@ -810,6 +701,52 @@ CmiRegistryInitialized = TRUE;
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
Modified: trunk/reactos/ntoskrnl/cm/regfile.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/cm/regfile.c?rev=2... ============================================================================== --- trunk/reactos/ntoskrnl/cm/regfile.c (original) +++ trunk/reactos/ntoskrnl/cm/regfile.c Thu May 17 04:27:14 2007 @@ -66,7 +66,6 @@ ZwClose(RegistryHive->LogHandle); }
- NTSTATUS CmiFlushRegistryHive(PEREGISTRY_HIVE RegistryHive) { @@ -103,26 +102,6 @@ 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 @@ return MaxName; }
- ULONG CmiGetMaxClassLength(PHHIVE Hive, PCM_KEY_NODE KeyCell) @@ -195,7 +173,6 @@
return MaxClass; } -
ULONG CmiGetMaxValueNameLength(PHHIVE Hive, @@ -243,7 +220,6 @@
return MaxValueName; } -
ULONG CmiGetMaxValueDataLength(PHHIVE Hive, @@ -518,109 +494,6 @@ }
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, OUT HCELL_INDEX *HBOffset, @@ -675,34 +548,4 @@ 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 */
Modified: trunk/reactos/ntoskrnl/cm/regobj.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/cm/regobj.c?rev=26... ============================================================================== --- trunk/reactos/ntoskrnl/cm/regobj.c (original) +++ trunk/reactos/ntoskrnl/cm/regobj.c Thu May 17 04:27:14 2007 @@ -633,20 +633,9 @@ 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) { @@ -767,36 +756,6 @@ KernelMode); 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,
Modified: trunk/reactos/ntoskrnl/config/cm.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/config/cm.h?rev=26... ============================================================================== --- trunk/reactos/ntoskrnl/config/cm.h (original) +++ trunk/reactos/ntoskrnl/config/cm.h Thu May 17 04:27:14 2007 @@ -693,6 +693,7 @@ #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 @@ IN ULONG Flags );
+NTSTATUS +NTAPI +CmpFreeKeyByCell( + IN PHHIVE Hive, + IN HCELL_INDEX Cell, + IN BOOLEAN Unlink +); + // // Name Functions // @@ -1129,6 +1138,22 @@ IN ULONG Hash, IN PUNICODE_STRING Name, 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 );
//
Modified: trunk/reactos/ntoskrnl/config/cmapi.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/config/cmapi.c?rev... ============================================================================== --- trunk/reactos/ntoskrnl/config/cmapi.c (original) +++ trunk/reactos/ntoskrnl/config/cmapi.c Thu May 17 04:27:14 2007 @@ -983,3 +983,87 @@ 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; +}
Modified: trunk/reactos/ntoskrnl/config/cmindex.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/config/cmindex.c?r... ============================================================================== --- trunk/reactos/ntoskrnl/config/cmindex.c (original) +++ trunk/reactos/ntoskrnl/config/cmindex.c Thu May 17 04:27:14 2007 @@ -703,12 +703,6 @@ { /* 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 @@ /* 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; +}
Added: trunk/reactos/ntoskrnl/config/cmkeydel.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/config/cmkeydel.c?... ============================================================================== --- trunk/reactos/ntoskrnl/config/cmkeydel.c (added) +++ trunk/reactos/ntoskrnl/config/cmkeydel.c Thu May 17 04:27:14 2007 @@ -1,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; +}
Modified: trunk/reactos/ntoskrnl/ntoskrnl.rbuild URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ntoskrnl.rbuild?re... ============================================================================== --- trunk/reactos/ntoskrnl/ntoskrnl.rbuild (original) +++ trunk/reactos/ntoskrnl/ntoskrnl.rbuild Thu May 17 04:27:14 2007 @@ -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>