From 3507ef2ac6b7532369d53ef279dda6b75ea45fbf Mon Sep 17 00:00:00 2001 From: Eric Kohl Date: Sat, 27 Jun 2015 19:26:12 +0000 Subject: [PATCH] [NTOSKRNL] Implement NtUnloadKey2. TODO: Destroy the unlinked hive. CORE-3094 svn path=/trunk/; revision=68295 --- reactos/ntoskrnl/config/cmapi.c | 114 ++++++++++++++++++++++++- reactos/ntoskrnl/config/cminit.c | 16 ++++ reactos/ntoskrnl/config/cmsysini.c | 10 +-- reactos/ntoskrnl/config/ntapi.c | 12 +-- reactos/ntoskrnl/include/internal/cm.h | 6 ++ 5 files changed, 139 insertions(+), 19 deletions(-) diff --git a/reactos/ntoskrnl/config/cmapi.c b/reactos/ntoskrnl/config/cmapi.c index 40a1e58cc49..31e8949e903 100644 --- a/reactos/ntoskrnl/config/cmapi.c +++ b/reactos/ntoskrnl/config/cmapi.c @@ -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 diff --git a/reactos/ntoskrnl/config/cminit.c b/reactos/ntoskrnl/config/cminit.c index 84749d3b555..bf23d20750a 100644 --- a/reactos/ntoskrnl/config/cminit.c +++ b/reactos/ntoskrnl/config/cminit.c @@ -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; + } + } +} diff --git a/reactos/ntoskrnl/config/cmsysini.c b/reactos/ntoskrnl/config/cmsysini.c index 006e4effc78..90df1b81d8b 100644 --- a/reactos/ntoskrnl/config/cmsysini.c +++ b/reactos/ntoskrnl/config/cmsysini.c @@ -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; } diff --git a/reactos/ntoskrnl/config/ntapi.c b/reactos/ntoskrnl/config/ntapi.c index 14f705a098b..a5290d5bb7e 100644 --- a/reactos/ntoskrnl/config/ntapi.c +++ b/reactos/ntoskrnl/config/ntapi.c @@ -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 diff --git a/reactos/ntoskrnl/include/internal/cm.h b/reactos/ntoskrnl/include/internal/cm.h index 1881476ec0f..d991869bdb7 100644 --- a/reactos/ntoskrnl/include/internal/cm.h +++ b/reactos/ntoskrnl/include/internal/cm.h @@ -828,6 +828,12 @@ CmpOpenHiveFiles( OUT PULONG ClusterSize OPTIONAL ); +VOID +NTAPI +CmpCloseHiveFiles( + IN PCMHIVE Hive +); + NTSTATUS NTAPI CmpInitHiveFromFile(