101 lines
3.3 KiB
C
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;
|
|
} |