Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

670 lines
16 KiB

/*++
Copyright (c) 1992 Microsoft Corporation
Module Name:
cmtrecpy.c
Abstract:
This file contains code for CmpCopyTree, misc copy utility routines.
Author:
Bryan M. Willman (bryanwi) 15-Jan-92
Revision History:
--*/
#include "cmp.h"
//
// stack used for directing nesting of tree copy. gets us off
// the kernel stack and thus allows for VERY deep nesting
//
#define CMP_INITIAL_STACK_SIZE 1024 // ENTRIES
typedef struct {
HCELL_INDEX SourceCell;
HCELL_INDEX TargetCell;
ULONG i;
} CMP_COPY_STACK_ENTRY, *PCMP_COPY_STACK_ENTRY;
BOOLEAN
CmpCopyTree2(
PCMP_COPY_STACK_ENTRY CmpCopyStack,
ULONG CmpCopyStackSize,
ULONG CmpCopyStackTop,
PHHIVE CmpSourceHive,
PHHIVE CmpTargetHive
);
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE,CmpCopyTree)
#pragma alloc_text(PAGE,CmpCopyTree2)
#pragma alloc_text(PAGE,CmpCopyKeyPartial)
#pragma alloc_text(PAGE,CmpCopyValue)
#pragma alloc_text(PAGE,CmpCopyCell)
#endif
//
// Routine to actually call to do a tree copy
//
BOOLEAN
CmpCopyTree(
PHHIVE SourceHive,
HCELL_INDEX SourceCell,
PHHIVE TargetHive,
HCELL_INDEX TargetCell
)
/*++
Routine Description:
Do a tree copy from source to destination. The source root key
and target root key must exist in advance. Their subkeys,
and full trees under the subkeys will be copied.
The root nodes themselves, and their value entries, will NOT
be copied.
NOTE: If this call fails part way through, it will NOT undo
any successfully completed key copies, thus a partial
tree copy CAN occur.
NOTE: VOLATILE KEYS and their CHILDREN are NOT COPIED.
Arguments:
SourceHive - pointer to hive control structure for source
SourceCell - index of cell at root of tree to copy
TargetHive - pointer to hive control structure for target
TargetCell - pointer to cell at root of target tree
Return Value:
BOOLEAN - Result code from call, among the following:
TRUE - it worked
FALSE - the tree copy was not completed (though more than 0
keys may have been copied)
--*/
{
BOOLEAN result;
PCMP_COPY_STACK_ENTRY CmpCopyStack;
CMLOG(CML_MAJOR, CMS_SAVRES) {
KdPrint(("CmpCopyTree:\n"));
}
CmpCopyStack = ExAllocatePool(
PagedPool,
sizeof(CMP_COPY_STACK_ENTRY)*CMP_INITIAL_STACK_SIZE
);
if (CmpCopyStack == NULL) {
return FALSE;
}
CmpCopyStack[0].SourceCell = SourceCell;
CmpCopyStack[0].TargetCell = TargetCell;
result = CmpCopyTree2(
CmpCopyStack,
CMP_INITIAL_STACK_SIZE,
0,
SourceHive,
TargetHive
);
ExFreePool(CmpCopyStack);
return result;
}
//
// Helper
//
BOOLEAN
CmpCopyTree2(
PCMP_COPY_STACK_ENTRY CmpCopyStack,
ULONG CmpCopyStackSize,
ULONG CmpCopyStackTop,
PHHIVE CmpSourceHive,
PHHIVE CmpTargetHive
)
/*++
Routine Description:
Do a tree copy from source to destination. The source root key
and target root key must exist in advance. Their subkeys,
and full trees under the subkeys will be copied.
The root notes themselves, and their value entries, will NOT
be copied.
NOTE: If this call fails part way through, it will NOT undo
any successfully completed key copies, thus a partial
tree copy CAN occur.
NOTE: DO NOT CALL THIS DIRECTLY, CALL CmpCopyTree()!
NOTE: VOLATILE KEYS and their CHILDREN are NOT COPIED.
Arguments:
(All of these are "virtual globals")
CmpCopyStack - "global" pointer to stack for frames
CmpCopyStackSize - alloced size of stack
CmpCopyStackTop - current top
CmpSourceHive, CmpTargetHive - source and target hives
Return Value:
BOOLEAN - Result code from call, among the following:
TRUE - it worked
FALSE - the tree copy was not completed (though more than 0
keys may have been copied)
--*/
{
PCMP_COPY_STACK_ENTRY Frame;
HCELL_INDEX SourceChild;
HCELL_INDEX NewSubKey;
CMLOG(CML_MINOR, CMS_SAVRES) {
KdPrint(("CmpCopyTree2:\n"));
}
//
// outer loop, apply to entire tree, emulate recursion here
// jump to here is a virtual call
//
Outer: while (TRUE) {
Frame = &(CmpCopyStack[CmpCopyStackTop]);
Frame->i = 0;
//
// inner loop, applies to one key
// jump to here is a virtual return
//
Inner: while (TRUE) {
SourceChild = CmpFindSubKeyByNumber(CmpSourceHive,
(PCM_KEY_NODE)HvGetCell(CmpSourceHive,Frame->SourceCell),
Frame->i);
if (SourceChild == HCELL_NIL) {
break;
}
(Frame->i)++;
if (HvGetCellType(SourceChild) == Volatile) {
//
// we've stepped through all the stable children into
// the volatile ones, we are done.
//
break;
}
if (HvGetCellType(SourceChild) == Stable) {
NewSubKey = CmpCopyKeyPartial(
CmpSourceHive,
SourceChild,
CmpTargetHive,
Frame->TargetCell,
TRUE
);
if (NewSubKey != HCELL_NIL) {
if ( ! CmpAddSubKey(
CmpTargetHive,
Frame->TargetCell,
NewSubKey
)
)
{
return FALSE;
}
//
// We succeeded in copying the subkey, apply
// ourselves to it
//
CmpCopyStackTop++;
if (CmpCopyStackTop >= CmpCopyStackSize) {
//
// if we're here, it means that the tree
// we're trying to copy is more than 1024
// COMPONENTS deep (from 2048 to 256k bytes)
// we could grow the stack, but this is pretty
// severe, so return FALSE and fail the copy
//
return FALSE;
}
CmpCopyStack[CmpCopyStackTop].SourceCell =
SourceChild;
CmpCopyStack[CmpCopyStackTop].TargetCell =
NewSubKey;
goto Outer;
} else {
return FALSE;
}
} // if HvGetCellType()
} // Inner: while
if (CmpCopyStackTop == 0) {
return TRUE;
}
CmpCopyStackTop--;
Frame = &(CmpCopyStack[CmpCopyStackTop]);
goto Inner;
} // Outer: while
}
HCELL_INDEX
CmpCopyKeyPartial(
PHHIVE SourceHive,
HCELL_INDEX SourceKeyCell,
PHHIVE TargetHive,
HCELL_INDEX Parent,
BOOLEAN CopyValues
)
/*++
Routine Description:
Copy a key body and all of its values, but NOT its subkeylist or
subkey entries. SubKeyList.Count will be set to 0.
Arguments:
SourceHive - pointer to hive control structure for source
SourceKeyCell - value entry being copied
TargetHive - pointer to hive control structure for target
Parent - parent value to set into newly created key body
CopyValues - if FALSE value entries will not be copied, if TRUE, they will
Return Value:
HCELL_INDEX - Cell of body of new key entry, or HCELL_NIL
if some error.
--*/
{
NTSTATUS status;
HCELL_INDEX newkey = HCELL_NIL;
HCELL_INDEX newclass = HCELL_NIL;
HCELL_INDEX newsecurity = HCELL_NIL;
HCELL_INDEX newlist = HCELL_NIL;
HCELL_INDEX newvalue;
BOOLEAN success = FALSE;
ULONG i;
PCELL_DATA psrckey;
PCM_KEY_NODE ptarkey;
PCELL_DATA psrclist;
PCELL_DATA ptarlist;
PCELL_DATA psrcsecurity;
HCELL_INDEX security;
HCELL_INDEX class;
ULONG classlength;
ULONG count;
ULONG Type;
CMLOG(CML_MINOR, CMS_SAVRES) {
KdPrint(("CmpCopyKeyPartial:\n"));
KdPrint(("\tSHive=%08lx SCell=%08lx\n",SourceHive,SourceKeyCell));
KdPrint(("\tTHive=%08lx\n",TargetHive));
}
//
// get description of source
//
if (Parent == HCELL_NIL) {
//
// This is a root node we are creating, so don't make it volatile.
//
Type = Stable;
} else {
Type = HvGetCellType(Parent);
}
psrckey = HvGetCell(SourceHive, SourceKeyCell);
security = psrckey->u.KeyNode.u1.s1.Security;
class = psrckey->u.KeyNode.u1.s1.Class;
classlength = psrckey->u.KeyNode.ClassLength;
//
// Allocate and copy the body
//
newkey = CmpCopyCell(SourceHive, SourceKeyCell, TargetHive, Type);
if (newkey == HCELL_NIL) {
goto DoFinally;
}
//
// Allocate and copy class
//
if (classlength > 0) {
newclass = CmpCopyCell(SourceHive, class, TargetHive, Type);
if (newclass == HCELL_NIL) {
goto DoFinally;
}
}
//
// Fill in the target body
//
ptarkey = (PCM_KEY_NODE)HvGetCell(TargetHive, newkey);
ptarkey->u1.s1.Class = newclass;
ptarkey->u1.s1.Security = HCELL_NIL;
ptarkey->SubKeyLists[Stable] = HCELL_NIL;
ptarkey->SubKeyLists[Volatile] = HCELL_NIL;
ptarkey->SubKeyCounts[Stable] = 0;
ptarkey->SubKeyCounts[Volatile] = 0;
ptarkey->Parent = Parent;
ptarkey->Flags = (psrckey->u.KeyNode.Flags & KEY_COMP_NAME);
if (Parent == HCELL_NIL) {
ptarkey->Flags |= KEY_HIVE_ENTRY + KEY_NO_DELETE;
}
//
// Allocate and copy security
//
psrcsecurity = HvGetCell(SourceHive, security);
status = CmpAssignSecurityDescriptor(TargetHive,
newkey,
ptarkey,
&(psrcsecurity->u.KeySecurity.Descriptor),
PagedPool);
if (!NT_SUCCESS(status)) {
goto DoFinally;
}
//
// Set up the value list
//
count = psrckey->u.KeyNode.ValueList.Count;
if ((count == 0) || (CopyValues == FALSE)) {
ptarkey->ValueList.List = HCELL_NIL;
ptarkey->ValueList.Count = 0;
success = TRUE;
} else {
psrclist = HvGetCell(SourceHive, psrckey->u.KeyNode.ValueList.List);
newlist = HvAllocateCell(
TargetHive,
count * sizeof(HCELL_INDEX),
Type
);
if (newlist == HCELL_NIL) {
goto DoFinally;
}
ptarkey->ValueList.List = newlist;
ptarlist = HvGetCell(TargetHive, newlist);
//
// Copy the values
//
for (i = 0; i < count; i++) {
newvalue = CmpCopyValue(
SourceHive,
psrclist->u.KeyList[i],
TargetHive,
Type
);
if (newvalue != HCELL_NIL) {
ptarlist->u.KeyList[i] = newvalue;
} else {
for (; i > 0; i--) {
HvFreeCell(
TargetHive,
ptarlist->u.KeyList[i - 1]
);
}
goto DoFinally;
}
}
success = TRUE;
}
DoFinally:
if (success == FALSE) {
if (newlist != HCELL_NIL) {
HvFreeCell(TargetHive, newlist);
}
if (newsecurity != HCELL_NIL) {
HvFreeCell(TargetHive, newsecurity);
}
if (newclass != HCELL_NIL) {
HvFreeCell(TargetHive, newclass);
}
if (newkey != HCELL_NIL) {
HvFreeCell(TargetHive, newkey);
}
return HCELL_NIL;
} else {
return newkey;
}
}
HCELL_INDEX
CmpCopyValue(
PHHIVE SourceHive,
HCELL_INDEX SourceValueCell,
PHHIVE TargetHive,
HSTORAGE_TYPE Type
)
/*++
Routine Description:
Copy a value entry. Copies the body of a value entry and the
data. Returns cell of new value entry.
Arguments:
SourceHive - pointer to hive control structure for source
SourceValueCell - value entry being copied
TargetHive - pointer to hive control structure for target
Type - storage type to allocate for target (stable or volatile)
Return Value:
HCELL_INDEX - Cell of body of new value entry, or HCELL_NIL
if some error.
--*/
{
HCELL_INDEX newvalue;
HCELL_INDEX newdata;
PCELL_DATA pvalue;
ULONG datalength;
HCELL_INDEX olddata;
ULONG tempdata;
BOOLEAN small;
CMLOG(CML_MINOR, CMS_SAVRES) {
KdPrint(("CmpCopyValue:\n"));
KdPrint(("\tSHive=%08lx SCell=%08lx\n",SourceHive,SourceValueCell));
KdPrint(("\tTargetHive=%08lx\n",TargetHive));
}
//
// get source data
//
pvalue = HvGetCell(SourceHive, SourceValueCell);
small = CmpIsHKeyValueSmall(datalength, pvalue->u.KeyValue.DataLength);
olddata = pvalue->u.KeyValue.Data;
//
// Copy body
//
newvalue = CmpCopyCell(SourceHive, SourceValueCell, TargetHive, Type);
if (newvalue == HCELL_NIL) {
return HCELL_NIL;
}
//
// Copy data (if any)
//
if (datalength > 0) {
if (datalength > CM_KEY_VALUE_SMALL) {
//
// there's data, and it's "big", so do standard copy
//
newdata = CmpCopyCell(SourceHive, olddata, TargetHive, Type);
if (newdata == HCELL_NIL) {
HvFreeCell(TargetHive, newvalue);
return HCELL_NIL;
}
pvalue = HvGetCell(TargetHive, newvalue);
pvalue->u.KeyValue.Data = newdata;
pvalue->u.KeyValue.DataLength = datalength;
} else {
//
// the data is small, but may be stored in either large or
// small format for historical reasons
//
if (small) {
//
// data is already small, so just do a body to body copy
//
tempdata = pvalue->u.KeyValue.Data;
} else {
//
// data is stored externally in old cell, will be internal in new
//
pvalue = HvGetCell(SourceHive, pvalue->u.KeyValue.Data);
tempdata = *((PULONG)pvalue);
}
pvalue = HvGetCell(TargetHive, newvalue);
pvalue->u.KeyValue.Data = tempdata;
pvalue->u.KeyValue.DataLength =
datalength + CM_KEY_VALUE_SPECIAL_SIZE;
}
}
return newvalue;
}
HCELL_INDEX
CmpCopyCell(
PHHIVE SourceHive,
HCELL_INDEX SourceCell,
PHHIVE TargetHive,
HSTORAGE_TYPE Type
)
/*++
Routine Description:
Copy SourceHive.SourceCell to TargetHive.TargetCell.
Arguments:
SourceHive - pointer to hive control structure for source
SourceCell - index of cell to copy from
TargetHive - pointer to hive control structure for target
Type - storage type (stable or volatile) of new cell
Return Value:
HCELL_INDEX of new cell, or HCELL_NIL if failure.
--*/
{
PVOID psource;
PVOID ptarget;
ULONG size;
HCELL_INDEX newcell;
CMLOG(CML_MINOR, CMS_SAVRES) {
KdPrint(("CmpCopyCell:\n"));
KdPrint(("\tSourceHive=%08lx SourceCell=%08lx\n",SourceHive,SourceCell));
KdPrint(("\tTargetHive=%08lx\n",TargetHive));
}
psource = HvGetCell(SourceHive, SourceCell);
size = HvGetCellSize(SourceHive, psource);
newcell = HvAllocateCell(TargetHive, size, Type);
if (newcell == HCELL_NIL) {
return HCELL_NIL;
}
ptarget = HvGetCell(TargetHive, newcell);
RtlCopyMemory(ptarget, psource, size);
return newcell;
}