[ros-diffs] [ion] 26817: - 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.

ion at svn.reactos.org ion at svn.reactos.org
Thu May 17 02:27:15 CEST 2007


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=26817&r1=26816&r2=26817&view=diff
==============================================================================
--- 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&r1=26816&r2=26817&view=diff
==============================================================================
--- 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=26817&r1=26816&r2=26817&view=diff
==============================================================================
--- 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=26817&r1=26816&r2=26817&view=diff
==============================================================================
--- 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=26817&r1=26816&r2=26817&view=diff
==============================================================================
--- 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=26817&r1=26816&r2=26817&view=diff
==============================================================================
--- 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=26817&r1=26816&r2=26817&view=diff
==============================================================================
--- 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?rev=26817&r1=26816&r2=26817&view=diff
==============================================================================
--- 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?rev=26817&view=auto
==============================================================================
--- 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 at 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?rev=26817&r1=26816&r2=26817&view=diff
==============================================================================
--- 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>




More information about the Ros-diffs mailing list