NT4/private/ntos/config/cmtredel.c
2020-09-30 17:12:29 +02:00

378 lines
8.5 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
Copyright (c) 1992 Microsoft Corporation
Module Name:
cmtredel.c
Abstract:
This file contains code for CmpDeleteTree, and support.
Author:
Bryan M. Willman (bryanwi) 24-Jan-92
Revision History:
--*/
#include "cmp.h"
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE,CmpDeleteTree)
#pragma alloc_text(PAGE,CmpFreeKeyByCell)
#pragma alloc_text(PAGE,CmpMarkKeyDirty)
#endif
//
// Routine to actually call to do a tree delete
//
VOID
CmpDeleteTree(
PHHIVE Hive,
HCELL_INDEX Cell
)
/*++
Routine Description:
Delete all child subkeys, recursively, of Hive.Cell. Delete all
value entries of Hive.Cell. Do NOT delete Hive.Cell itself.
NOTE: If this call fails part way through, it will NOT undo
any successfully completed deletes.
NOTE: This algorithm can deal with a hive of any depth, at the
cost of some "redundent" scaning and mapping.
Arguments:
Hive - pointer to hive control structure for hive to delete from
Cell - index of cell at root of tree to delete
Return Value:
BOOLEAN - Result code from call, among the following:
TRUE - it worked
FALSE - the tree delete was not completed (though more than 0
keys may have been deleted)
--*/
{
ULONG count;
HCELL_INDEX ptr1;
HCELL_INDEX ptr2;
HCELL_INDEX parent;
PCM_KEY_NODE Node;
CMLOG(CML_MAJOR, CMS_SAVRES) {
KdPrint(("CmpDeleteTree:\n"));
KdPrint(("\tHive=%08lx Cell=%08lx\n",Hive,Cell));
}
ptr1 = Cell;
while(TRUE) {
Node = (PCM_KEY_NODE)HvGetCell(Hive, ptr1);
count = Node->SubKeyCounts[Stable] +
Node->SubKeyCounts[Volatile];
parent = Node->Parent;
if (count > 0) { // ptr1->count > 0?
//
// subkeys exist, find and delete them
//
ptr2 = CmpFindSubKeyByNumber(Hive, Node, 0);
Node = (PCM_KEY_NODE)HvGetCell(Hive, ptr2);
count = Node->SubKeyCounts[Stable] +
Node->SubKeyCounts[Volatile];
if (count > 0) { // ptr2->count > 0?
//
// subkey has subkeys, descend to next level
//
ptr1 = ptr2;
continue;
} else {
//
// have found leaf, delete it
//
CmpFreeKeyByCell(Hive, ptr2, TRUE);
continue;
}
} else {
//
// no more subkeys at this level, we are now a leaf.
//
if (ptr1 != Cell) {
//
// we are not at the root cell, so ascend to parent
//
ptr1 = parent; // ptr1 = ptr1->parent
continue;
} else {
//
// we are at the root cell, we are done
//
return;
}
} // outer if
} // while
}
NTSTATUS
CmpFreeKeyByCell(
PHHIVE Hive,
HCELL_INDEX Cell,
BOOLEAN Unlink
)
/*++
Routine Description:
Actually free the storage for the specified cell. We will first
remove it from its parent's child key list, then free all of its
values, then the key body itself.
Arguments:
Hive - pointer to hive control structure for hive of interest
Cell - index for cell to free storage for (the target)
Unlink - if TRUE, target cell will be removed from parent cell's
subkeylist, if FALSE, it will NOT be.
Return Value:
NONE.
--*/
{
PCELL_DATA ptarget;
PCELL_DATA pparent;
PCELL_DATA plist;
ULONG i;
//
// Mark dirty everything that we might touch
//
if (! CmpMarkKeyDirty(Hive, Cell)) {
return STATUS_NO_LOG_SPACE;
}
//
// Map in the target
//
ptarget = HvGetCell(Hive, Cell);
ASSERT((ptarget->u.KeyNode.SubKeyCounts[Stable] +
ptarget->u.KeyNode.SubKeyCounts[Volatile]) == 0);
if (Unlink == TRUE) {
BOOLEAN Success;
Success = CmpRemoveSubKey(Hive, ptarget->u.KeyNode.Parent, Cell);
if (!Success) {
return STATUS_INSUFFICIENT_RESOURCES;
}
pparent = HvGetCell(Hive, ptarget->u.KeyNode.Parent);
if ( (pparent->u.KeyNode.SubKeyCounts[Stable] +
pparent->u.KeyNode.SubKeyCounts[Volatile]) == 0)
{
pparent->u.KeyNode.MaxNameLen = 0;
pparent->u.KeyNode.MaxClassLen = 0;
}
}
//
// Target is now an unreferenced key, free it's actual storage
//
//
// First, free the value entries
//
if (ptarget->u.KeyNode.ValueList.Count > 0) {
// target list
plist = HvGetCell(Hive, ptarget->u.KeyNode.ValueList.List);
for (i = 0; i < ptarget->u.KeyNode.ValueList.Count; i++) {
CmpFreeValue(Hive, plist->u.KeyList[i]);
}
HvFreeCell(Hive, ptarget->u.KeyNode.ValueList.List);
}
//
// Free misc stuff
//
if (!(ptarget->u.KeyNode.Flags & KEY_HIVE_EXIT)) {
//
// Free the security descriptor
//
CmpFreeSecurityDescriptor(Hive, Cell);
}
//
// Free the key body itself, and Class data.
//
CmpFreeKeyBody(Hive, Cell);
return STATUS_SUCCESS;
}
BOOLEAN
CmpMarkKeyDirty(
PHHIVE Hive,
HCELL_INDEX Cell
)
/*++
Routine Description:
Mark all of the cells related to a key being deleted dirty.
Includes the parent, the parent's child list, the key body,
class, security, all value entry bodies, and all of their data cells.
Arguments:
Hive - pointer to hive control structure for hive of interest
Cell - index for cell holding keybody to make dirty
Return Value:
TRUE - it worked
FALSE - some error, most likely cannot get log space
--*/
{
PCELL_DATA ptarget;
PCELL_DATA plist;
PCELL_DATA security;
PCELL_DATA pvalue;
ULONG i;
ULONG realsize;
//
// Map in the target
//
ptarget = HvGetCell(Hive, Cell);
ASSERT(ptarget->u.KeyNode.SubKeyCounts[Stable] == 0);
ASSERT(ptarget->u.KeyNode.SubKeyCounts[Volatile] == 0);
if (ptarget->u.KeyNode.Flags & KEY_HIVE_EXIT) {
//
// If this is a link node, we are done. Link nodes never have
// classes, values, subkeys, or security descriptors. Since
// they always reside in the master hive, they're always volatile.
//
return(TRUE);
}
//
// mark cell itself
//
if (! HvMarkCellDirty(Hive, Cell)) {
return FALSE;
}
//
// Mark the class
//
if (ptarget->u.KeyNode.u1.s1.Class != HCELL_NIL) {
if (! HvMarkCellDirty(Hive, ptarget->u.KeyNode.u1.s1.Class)) {
return FALSE;
}
}
//
// Mark security
//
if (ptarget->u.KeyNode.u1.s1.Security != HCELL_NIL) {
if (! HvMarkCellDirty(Hive, ptarget->u.KeyNode.u1.s1.Security)) {
return FALSE;
}
security = HvGetCell(Hive, ptarget->u.KeyNode.u1.s1.Security);
if (! (HvMarkCellDirty(Hive, security->u.KeySecurity.Flink) &&
HvMarkCellDirty(Hive, security->u.KeySecurity.Blink)))
{
return FALSE;
}
}
//
// Mark the value entries and their data
//
if (ptarget->u.KeyNode.ValueList.Count > 0) {
// target list
if (! HvMarkCellDirty(Hive, ptarget->u.KeyNode.ValueList.List)) {
return FALSE;
}
plist = HvGetCell(Hive, ptarget->u.KeyNode.ValueList.List);
for (i = 0; i < ptarget->u.KeyNode.ValueList.Count; i++) {
if (! HvMarkCellDirty(Hive, plist->u.KeyList[i])) {
return FALSE;
}
pvalue = HvGetCell(Hive, plist->u.KeyList[i]);
if (!CmpIsHKeyValueSmall(realsize, pvalue->u.KeyValue.DataLength)) {
if (! HvMarkCellDirty(Hive, pvalue->u.KeyValue.Data)) {
return(FALSE);
}
}
}
}
if (ptarget->u.KeyNode.Flags & KEY_HIVE_ENTRY) {
//
// if this is an entry node, we are done. our parent will
// be in the master hive (and thus volatile)
//
return TRUE;
}
//
// Mark the parent's Subkey list
//
if (! CmpMarkIndexDirty(Hive, ptarget->u.KeyNode.Parent, Cell)) {
return FALSE;
}
//
// Mark the parent
//
if (! HvMarkCellDirty(Hive, ptarget->u.KeyNode.Parent)) {
return FALSE;
}
return TRUE;
}