Windows2000/private/ntos/config/cmapi2.c
2020-09-30 17:12:32 +02:00

101 lines
3.3 KiB
C

/*++
Copyright (c) 1991 Microsoft Corporation
Module Name:
cmapi2.c
Abstract:
This module contains CM level entry points for the registry, particularly those which we don't want to link into tools, setup, the boot loader, etc.
Author:
Bryan M. Willman (bryanwi) 26-Jan-1993
--*/
#include "cmp.h"
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE,CmDeleteKey)
#endif
NTSTATUS CmDeleteKey(IN PCM_KEY_BODY KeyBody)
/*++
Routine Description:
Delete a registry key, clean up Notify block.
Arguments:
KeyBody - pointer to key handle object
Return Value:
NTSTATUS
--*/
{
NTSTATUS status;
PCM_KEY_NODE ptarget;
PHHIVE Hive;
HCELL_INDEX Cell;
PCM_KEY_CONTROL_BLOCK KeyControlBlock;
CMLOG(CML_WORKER, CMS_CM) KdPrint(("CmDeleteKey\n"));
CmpLockRegistryExclusive();
// If already marked for deletion, storage is gone, so do nothing and return success.
KeyControlBlock = KeyBody->KeyControlBlock;
if (KeyControlBlock->Delete == TRUE) {
status = STATUS_SUCCESS;
goto Exit;
}
// Mark the hive as read only
CmpMarkAllBinsReadOnly(KeyControlBlock->KeyHive);
ptarget = KeyControlBlock->KeyNode;
if ( ((ptarget->SubKeyCounts[Stable] + ptarget->SubKeyCounts[Volatile]) == 0) && ((ptarget->Flags & KEY_NO_DELETE) == 0))
{
// Cell is NOT marked NO_DELETE and does NOT have children
// Send Notification while key still present, if delete fails, we'll have sent a spurious notify, that doesn't matter
// Delete the actual storage
Hive = KeyControlBlock->KeyHive;
Cell = KeyControlBlock->KeyCell;
CmpReportNotify(KeyControlBlock, Hive, Cell, REG_NOTIFY_CHANGE_NAME);
status = CmpFreeKeyByCell(Hive, Cell, TRUE);
if (NT_SUCCESS(status)) {
// post any waiting notifies
#ifdef KCB_TO_KEYBODY_LINK
CmpFlushNotifiesOnKeyBodyList(KeyControlBlock);
#else
CmpFlushNotify(KeyBody);
#endif
// Remove kcb out of cache, but do NOT free its storage, CmDelete will do that when the RefCount becomes zero.
// There are two things that can hold the RefCount non-zero.
// 1. open handles for this key
// 2. Fake subKeys that are still in DelayClose.
// At this point, we have no way of deleting the fake subkeys from cache unless we do a search for the whole cache, which is too expensive.
// Thus, we decide to either let the fake keys age out of cache or when someone is doing the lookup for the fake key, then we delete it at that point.
// See routine CmpCacheLookup in cmparse.c for more details.
// If the parent has the subkey info or hint cached, free it.
// Again, registry is locked exclusively, no need to lock KCB.
ASSERT_CM_LOCK_OWNED_EXCLUSIVE();
CmpCleanUpSubKeyInfo(KeyControlBlock->ParentKcb);
KeyControlBlock->Delete = TRUE;
CmpRemoveKeyControlBlock(KeyControlBlock);
KeyControlBlock->KeyCell = HCELL_NIL;
KeyControlBlock->KeyNode = NULL;
}
} else {
status = STATUS_CANNOT_DELETE;
}
Exit:
CmpUnlockRegistry();
CmpMarkAllBinsReadOnly(KeyControlBlock->KeyHive);// Mark the hive as read only
return status;
}