[NTOSKRNL]
authorEric Kohl <eric.kohl@reactos.org>
Sat, 27 Jun 2015 19:26:12 +0000 (19:26 +0000)
committerEric Kohl <eric.kohl@reactos.org>
Sat, 27 Jun 2015 19:26:12 +0000 (19:26 +0000)
Implement NtUnloadKey2. TODO: Destroy the unlinked hive.
CORE-3094

svn path=/trunk/; revision=68295

reactos/ntoskrnl/config/cmapi.c
reactos/ntoskrnl/config/cminit.c
reactos/ntoskrnl/config/cmsysini.c
reactos/ntoskrnl/config/ntapi.c
reactos/ntoskrnl/include/internal/cm.h

index 40a1e58..31e8949 100644 (file)
@@ -2127,13 +2127,123 @@ CmLoadKey(IN POBJECT_ATTRIBUTES TargetKey,
     return Status;
 }
 
+static
+BOOLEAN
+NTAPI
+CmpUnlinkHiveFromMaster(IN PHHIVE Hive,
+                        IN HCELL_INDEX Cell)
+{
+    PCELL_DATA CellData;
+    HCELL_INDEX LinkCell;
+    NTSTATUS Status;
+
+    DPRINT("CmpUnlinkHiveFromMaster()\n");
+
+    /* Get the cell data */
+    CellData = HvGetCell(Hive, Cell);
+    if (CellData == NULL)
+        return FALSE;
+
+    /* Get the link cell and release the current cell */
+    LinkCell = CellData->u.KeyNode.Parent;
+    HvReleaseCell(Hive, Cell);
+
+    /* Remove the link cell from the master hive */
+    CmpLockHiveFlusherExclusive(CmiVolatileHive);
+    Status = CmpFreeKeyByCell((PHHIVE)CmiVolatileHive,
+                              LinkCell,
+                              TRUE);
+    CmpUnlockHiveFlusher(CmiVolatileHive);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("CmpFreeKeyByCell() failed (Status 0x%08lx)\n", Status);
+        return FALSE;
+    }
+
+    /* Lock the hive list */
+    ExAcquirePushLockExclusive(&CmpHiveListHeadLock);
+
+    /* Remove this hive */
+    RemoveEntryList(&((PCMHIVE)Hive)->HiveList);
+
+    /* Release the lock */
+    ExReleasePushLock(&CmpHiveListHeadLock);
+
+    return TRUE;
+}
+
 NTSTATUS
 NTAPI
 CmUnloadKey(IN PCM_KEY_CONTROL_BLOCK Kcb,
             IN ULONG Flags)
 {
-    UNIMPLEMENTED;
-    return STATUS_NOT_IMPLEMENTED;
+    PHHIVE Hive;
+    PCMHIVE CmHive;
+    HCELL_INDEX Cell;
+
+    DPRINT("CmUnloadKey(%p, %lx)\n", Kcb, Flags);
+
+    /* Get the hive */
+    Hive = Kcb->KeyHive;
+    Cell = Kcb->KeyCell;
+    CmHive = (PCMHIVE)Hive;
+
+    /* Fail if the key is no a hive root key */
+    if (Cell != Hive->BaseBlock->RootCell)
+    {
+        DPRINT1("Key is not a hive root key!\n");
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    /* Fail if we try to unload the master hive */
+    if (CmHive == CmiVolatileHive)
+    {
+        DPRINT1("Do not try to unload the master hive!\n");
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    /* Flush the hive */
+    CmFlushKey(Kcb, TRUE);
+
+    /* Unlink the hive from the master hive */
+    if (!CmpUnlinkHiveFromMaster(Hive, Cell))
+    {
+        DPRINT("CmpUnlinkHiveFromMaster() failed!\n");
+
+        /* Remove the unloading flag */
+        Hive->HiveFlags &= ~HIVE_IS_UNLOADING;
+
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+
+    /* Clean up information we have on the subkey */
+    CmpCleanUpSubKeyInfo(Kcb->ParentKcb);
+
+    /* Set the KCB in delete mode and remove it */
+    Kcb->Delete = TRUE;
+    CmpRemoveKeyControlBlock(Kcb);
+
+    if (Flags != REG_FORCE_UNLOAD)
+    {
+        /* Release the KCB locks */
+        CmpReleaseTwoKcbLockByKey(Kcb->ConvKey, Kcb->ParentKcb->ConvKey);
+
+        /* Release the hive loading lock */
+        ExReleasePushLockExclusive(&CmpLoadHiveLock);
+    }
+
+    /* Release hive lock */
+    CmpUnlockRegistry();
+
+    /* Close file handles */
+    CmpCloseHiveFiles(CmHive);
+
+    /* Remove the hive from the hive file list */
+    CmpRemoveFromHiveFileList(CmHive);
+
+    /* FIXME: Destroy the hive */
+
+    return STATUS_SUCCESS;
 }
 
 ULONG
index 84749d3..bf23d20 100644 (file)
@@ -626,3 +626,19 @@ CmpOpenHiveFiles(IN PCUNICODE_STRING BaseName,
     ZwClose(EventHandle);
     return STATUS_SUCCESS;
 }
+
+VOID
+NTAPI
+CmpCloseHiveFiles(IN PCMHIVE Hive)
+{
+    ULONG i;
+
+    for (i = 0; i < HFILE_TYPE_MAX; i++)
+    {
+        if (Hive->FileHandles[i] != NULL)
+        {
+            ZwClose(Hive->FileHandles[i]);
+            Hive->FileHandles[i] = NULL;
+        }
+    }
+}
index 006e4ef..90df1b8 100644 (file)
@@ -2138,7 +2138,6 @@ CmShutdownSystem(VOID)
 {
     PLIST_ENTRY ListEntry;
     PCMHIVE Hive;
-    ULONG i;
 
     /* Kill the workers */
     if (!CmFirstTime) CmpShutdownWorkers();
@@ -2153,14 +2152,7 @@ CmShutdownSystem(VOID)
     {
         Hive = CONTAINING_RECORD(ListEntry, CMHIVE, HiveList);
 
-        for (i = 0; i < HFILE_TYPE_MAX; i++)
-        {
-            if (Hive->FileHandles[i] != NULL)
-            {
-                ZwClose(Hive->FileHandles[i]);
-                Hive->FileHandles[i] = NULL;
-            }
-        }
+        CmpCloseHiveFiles(Hive);
 
         ListEntry = ListEntry->Flink;
     }
index 14f705a..a5290d5 100644 (file)
@@ -1372,7 +1372,6 @@ NTAPI
 NtUnloadKey2(IN POBJECT_ATTRIBUTES TargetKey,
              IN ULONG Flags)
 {
-#if 0
     NTSTATUS Status;
     OBJECT_ATTRIBUTES ObjectAttributes;
     UNICODE_STRING ObjectName;
@@ -1381,6 +1380,7 @@ NtUnloadKey2(IN POBJECT_ATTRIBUTES TargetKey,
     PCM_KEY_BODY KeyBody = NULL;
     ULONG ParentConv = 0, ChildConv = 0;
     HANDLE Handle;
+
     PAGED_CODE();
 
     /* Validate privilege */
@@ -1515,11 +1515,11 @@ NtUnloadKey2(IN POBJECT_ATTRIBUTES TargetKey,
     {
         if (Flags != REG_FORCE_UNLOAD)
         {
-            /* Release the hive loading lock */
-            ExReleasePushLockExclusive(&CmpLoadHiveLock);
-
             /* Release two KCBs lock */
             CmpReleaseTwoKcbLockByKey(ChildConv, ParentConv);
+
+            /* Release the hive loading lock */
+            ExReleasePushLockExclusive(&CmpLoadHiveLock);
         }
 
         /* Unlock the registry */
@@ -1532,10 +1532,6 @@ Quickie:
 
     /* Return status */
     return Status;
-#else
-    UNIMPLEMENTED;
-    return STATUS_NOT_IMPLEMENTED;
-#endif
 }
 
 NTSTATUS
index 1881476..d991869 100644 (file)
@@ -828,6 +828,12 @@ CmpOpenHiveFiles(
     OUT PULONG ClusterSize OPTIONAL
 );
 
+VOID
+NTAPI
+CmpCloseHiveFiles(
+    IN PCMHIVE Hive
+);
+
 NTSTATUS
 NTAPI
 CmpInitHiveFromFile(