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=2…
==============================================================================
--- 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=2…
==============================================================================
--- 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=…
==============================================================================
--- 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=2…
==============================================================================
--- 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=2…
==============================================================================
--- 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?re…
==============================================================================
--- 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?…
==============================================================================
--- 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(a)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?r…
==============================================================================
--- 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>