716 lines
20 KiB
C
716 lines
20 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1991 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
cmchek.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
This module implements consistency checking for the registry.
|
|||
|
This module can be linked standalone, cmchek2.c cannot.
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Bryan M. Willman (bryanwi) 27-Jan-92
|
|||
|
|
|||
|
Environment:
|
|||
|
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#include "cmp.h"
|
|||
|
|
|||
|
#define REG_MAX_PLAUSIBLE_KEY_SIZE \
|
|||
|
((FIELD_OFFSET(CM_KEY_NODE, Name)) + \
|
|||
|
(sizeof(WCHAR) * MAX_KEY_NAME_LENGTH) + 16)
|
|||
|
|
|||
|
//
|
|||
|
// Global data used to support checkout
|
|||
|
//
|
|||
|
extern ULONG CmpUsedStorage;
|
|||
|
|
|||
|
extern PCMHIVE CmpMasterHive;
|
|||
|
|
|||
|
//
|
|||
|
// Private prototypes
|
|||
|
//
|
|||
|
|
|||
|
ULONG
|
|||
|
CmpCheckRegistry2(
|
|||
|
HCELL_INDEX Cell,
|
|||
|
HCELL_INDEX ParentCell
|
|||
|
);
|
|||
|
|
|||
|
ULONG
|
|||
|
CmpCheckKey(
|
|||
|
HCELL_INDEX Cell,
|
|||
|
HCELL_INDEX ParentCell
|
|||
|
);
|
|||
|
|
|||
|
ULONG
|
|||
|
CmpCheckValueList(
|
|||
|
PHHIVE Hive,
|
|||
|
PCELL_DATA List,
|
|||
|
ULONG Count
|
|||
|
);
|
|||
|
|
|||
|
#ifdef ALLOC_PRAGMA
|
|||
|
#pragma alloc_text(PAGE,CmCheckRegistry)
|
|||
|
#pragma alloc_text(PAGE,CmpCheckRegistry2)
|
|||
|
#pragma alloc_text(PAGE,CmpCheckKey)
|
|||
|
#pragma alloc_text(PAGE,CmpCheckValueList)
|
|||
|
#endif
|
|||
|
|
|||
|
//
|
|||
|
// debug structures
|
|||
|
//
|
|||
|
|
|||
|
extern struct {
|
|||
|
PHHIVE Hive;
|
|||
|
ULONG Status;
|
|||
|
} CmCheckRegistryDebug;
|
|||
|
|
|||
|
extern struct {
|
|||
|
PHHIVE Hive;
|
|||
|
ULONG Status;
|
|||
|
} CmpCheckRegistry2Debug;
|
|||
|
|
|||
|
extern struct {
|
|||
|
PHHIVE Hive;
|
|||
|
ULONG Status;
|
|||
|
HCELL_INDEX Cell;
|
|||
|
PCELL_DATA CellPoint;
|
|||
|
PVOID RootPoint;
|
|||
|
ULONG Index;
|
|||
|
} CmpCheckKeyDebug;
|
|||
|
|
|||
|
extern struct {
|
|||
|
PHHIVE Hive;
|
|||
|
ULONG Status;
|
|||
|
PCELL_DATA List;
|
|||
|
ULONG Index;
|
|||
|
HCELL_INDEX Cell;
|
|||
|
PCELL_DATA CellPoint;
|
|||
|
} CmpCheckValueListDebug;
|
|||
|
|
|||
|
//
|
|||
|
// globals private to check code
|
|||
|
//
|
|||
|
extern PHHIVE CmpCheckHive;
|
|||
|
extern BOOLEAN CmpCheckClean;
|
|||
|
|
|||
|
|
|||
|
ULONG
|
|||
|
CmCheckRegistry(
|
|||
|
PCMHIVE CmHive,
|
|||
|
BOOLEAN Clean
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Check consistency of the registry within a given hive. Start from
|
|||
|
root, and check that:
|
|||
|
. Each child key points back to its parent.
|
|||
|
. All allocated cells are refered to exactly once
|
|||
|
(requires looking inside the hive structure...)
|
|||
|
[This also detects space leaks.]
|
|||
|
. All allocated cells are reachable from the root.
|
|||
|
|
|||
|
NOTE: Exactly 1 ref rule may change with security.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
CmHive - supplies a pointer to the CM hive control structure for the
|
|||
|
hive of interest.
|
|||
|
|
|||
|
Clean - if TRUE, references to volatile cells will be zapped
|
|||
|
(done at startup only to avoid groveling hives twice.)
|
|||
|
if FALSE, nothing will be changed.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
0 if Hive is OK. Error return indicator if not.
|
|||
|
|
|||
|
RANGE: 3000 - 3999
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
PHHIVE Hive;
|
|||
|
ULONG rc = 0;
|
|||
|
ULONG Storage;
|
|||
|
|
|||
|
if (CmHive == CmpMasterHive) {
|
|||
|
return(0);
|
|||
|
}
|
|||
|
|
|||
|
CmpUsedStorage = 0;
|
|||
|
|
|||
|
CmCheckRegistryDebug.Hive = (PHHIVE)CmHive;
|
|||
|
CmCheckRegistryDebug.Status = 0;
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// check the underlying hive and get storage use
|
|||
|
//
|
|||
|
Hive = &CmHive->Hive;
|
|||
|
|
|||
|
rc = HvCheckHive(Hive, &Storage);
|
|||
|
if (rc != 0) {
|
|||
|
CmCheckRegistryDebug.Status = rc;
|
|||
|
return rc;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Call recursive helper to check out the values and subkeys
|
|||
|
//
|
|||
|
CmpCheckHive = (PHHIVE)CmHive;
|
|||
|
CmpCheckClean = Clean;
|
|||
|
rc = CmpCheckRegistry2(Hive->BaseBlock->RootCell, HCELL_NIL);
|
|||
|
|
|||
|
//
|
|||
|
// Validate all the security descriptors in the hive
|
|||
|
//
|
|||
|
if (!CmpValidateHiveSecurityDescriptors(Hive)) {
|
|||
|
KdPrint(("CmCheckRegistry:"));
|
|||
|
KdPrint((" CmpValidateHiveSecurityDescriptors failed\n"));
|
|||
|
rc = 3040;
|
|||
|
CmCheckRegistryDebug.Status = rc;
|
|||
|
}
|
|||
|
|
|||
|
#if 0
|
|||
|
//
|
|||
|
// Check allocated storage against used storage
|
|||
|
//
|
|||
|
if (CmpUsedStorage != Storage) {
|
|||
|
KdPrint(("CmCheckRegistry:"));
|
|||
|
KdPrint((" Storage Used:%08lx Allocated:%08lx\n", UsedStorage, Storage));
|
|||
|
rc = 3042;
|
|||
|
CmCheckRegistryDebug.Status = rc;
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
//
|
|||
|
// Print a bit of a summary (make sure this data avail in all error cases)
|
|||
|
//
|
|||
|
if (rc > 0) {
|
|||
|
KdPrint(("CmCheckRegistry Failed (%d): CmHive:%08lx\n", rc, CmHive));
|
|||
|
KdPrint((" Hive:%08lx Root:%08lx\n", Hive, Hive->BaseBlock->RootCell));
|
|||
|
}
|
|||
|
|
|||
|
return rc;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
ULONG
|
|||
|
CmpCheckRegistry2(
|
|||
|
HCELL_INDEX Cell,
|
|||
|
HCELL_INDEX ParentCell
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Check consistency of the registry, from a particular cell on down.
|
|||
|
|
|||
|
. Check that the cell's value list, child key list, class,
|
|||
|
security are OK.
|
|||
|
. Check that each value entry IN the list is OK.
|
|||
|
. Apply self to each child key list.
|
|||
|
|
|||
|
Globals:
|
|||
|
|
|||
|
CmpCheckHive - hive we're working on
|
|||
|
|
|||
|
CmpCheckClean - flag TRUE -> clean off volatiles, FALSE -> don't
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Cell - HCELL_INDEX of subkey to work on.
|
|||
|
|
|||
|
ParentCell - expected value of parent cell for Cell, unless
|
|||
|
HCELL_NIL, in which case ignore.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
0 if Hive is OK. Error return indicator if not.
|
|||
|
|
|||
|
RANGE: 4000 - 4999
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
ULONG Index = 0;
|
|||
|
HCELL_INDEX StartCell = Cell;
|
|||
|
HCELL_INDEX SubKey;
|
|||
|
ULONG rc = 0;
|
|||
|
PCELL_DATA pcell;
|
|||
|
|
|||
|
|
|||
|
CmpCheckRegistry2Debug.Hive = CmpCheckHive;
|
|||
|
CmpCheckRegistry2Debug.Status = 0;
|
|||
|
|
|||
|
//
|
|||
|
// A jump to NewKey amounts to a virtual call to check the
|
|||
|
// next child cell. (a descent into the tree)
|
|||
|
//
|
|||
|
// Cell, ParentCell, Index, and globals are defined
|
|||
|
//
|
|||
|
NewKey:
|
|||
|
rc = CmpCheckKey(Cell, ParentCell);
|
|||
|
if (rc != 0) {
|
|||
|
KdPrint(("\tChild is list entry #%08lx\n", Index));
|
|||
|
CmpCheckRegistry2Debug.Status = rc;
|
|||
|
return rc;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// save Index and check out children
|
|||
|
//
|
|||
|
pcell = HvGetCell(CmpCheckHive, Cell);
|
|||
|
pcell->u.KeyNode.WorkVar = Index;
|
|||
|
|
|||
|
for (Index = 0; Index<pcell->u.KeyNode.SubKeyCounts[Stable]; Index++) {
|
|||
|
|
|||
|
SubKey = CmpFindSubKeyByNumber(CmpCheckHive,
|
|||
|
(PCM_KEY_NODE)HvGetCell(CmpCheckHive,Cell),
|
|||
|
Index);
|
|||
|
|
|||
|
//
|
|||
|
// "recurse" onto child
|
|||
|
//
|
|||
|
ParentCell = Cell;
|
|||
|
Cell = SubKey;
|
|||
|
goto NewKey;
|
|||
|
|
|||
|
ResumeKey:; // A jump here is a virtual return
|
|||
|
// Cell, ParentCell and Index
|
|||
|
// must be defined
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// since we're here, we've checked out all the children
|
|||
|
// of the current cell.
|
|||
|
//
|
|||
|
if (Cell == StartCell) {
|
|||
|
|
|||
|
//
|
|||
|
// we are done
|
|||
|
//
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// "return" to "parent instance"
|
|||
|
//
|
|||
|
pcell = HvGetCell(CmpCheckHive, Cell);
|
|||
|
Index = pcell->u.KeyNode.WorkVar;
|
|||
|
|
|||
|
Cell = ParentCell;
|
|||
|
|
|||
|
pcell = HvGetCell(CmpCheckHive, Cell);
|
|||
|
ParentCell = pcell->u.KeyNode.Parent;
|
|||
|
|
|||
|
goto ResumeKey;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
ULONG
|
|||
|
CmpCheckKey(
|
|||
|
HCELL_INDEX Cell,
|
|||
|
HCELL_INDEX ParentCell
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Check consistency of the registry, for a particular cell
|
|||
|
|
|||
|
. Check that the cell's value list, child key list, class,
|
|||
|
security are OK.
|
|||
|
. Check that each value entry IN the list is OK.
|
|||
|
|
|||
|
Globals:
|
|||
|
|
|||
|
CmpCheckHive - hive we're working on
|
|||
|
|
|||
|
CmpCheckClean - flag TRUE -> clean off volatiles, FALSE -> don't
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Cell - HCELL_INDEX of subkey to work on.
|
|||
|
|
|||
|
ParentCell - expected value of parent cell for Cell, unless
|
|||
|
HCELL_NIL, in which case ignore.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
0 if Hive is OK. Error return indicator if not.
|
|||
|
|
|||
|
RANGE: 4000 - 4999
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
PCELL_DATA pcell;
|
|||
|
ULONG size;
|
|||
|
ULONG usedlen;
|
|||
|
ULONG ClassLength;
|
|||
|
HCELL_INDEX Class;
|
|||
|
ULONG ValueCount;
|
|||
|
HCELL_INDEX ValueList;
|
|||
|
HCELL_INDEX Security;
|
|||
|
ULONG rc = 0;
|
|||
|
ULONG nrc = 0;
|
|||
|
ULONG i;
|
|||
|
PCM_KEY_INDEX Root;
|
|||
|
PCM_KEY_INDEX Leaf;
|
|||
|
ULONG SubCount;
|
|||
|
|
|||
|
CmpCheckKeyDebug.Hive = CmpCheckHive;
|
|||
|
CmpCheckKeyDebug.Status = 0;
|
|||
|
CmpCheckKeyDebug.Cell = Cell;
|
|||
|
CmpCheckKeyDebug.CellPoint = NULL;
|
|||
|
CmpCheckKeyDebug.RootPoint = NULL;
|
|||
|
CmpCheckKeyDebug.Index = (ULONG)-1;
|
|||
|
|
|||
|
//
|
|||
|
// Check key itself
|
|||
|
//
|
|||
|
if (! HvIsCellAllocated(CmpCheckHive, Cell)) {
|
|||
|
KdPrint(("CmpCheckKey: CmpCheckHive:%08lx Cell:%08lx\n", CmpCheckHive, Cell));
|
|||
|
KdPrint(("\tNot allocated\n"));
|
|||
|
rc = 4010;
|
|||
|
CmpCheckKeyDebug.Status = rc;
|
|||
|
return rc;
|
|||
|
}
|
|||
|
pcell = HvGetCell(CmpCheckHive, Cell);
|
|||
|
SetUsed(CmpCheckHive, Cell);
|
|||
|
|
|||
|
CmpCheckKeyDebug.CellPoint = pcell;
|
|||
|
|
|||
|
size = HvGetCellSize(CmpCheckHive, pcell);
|
|||
|
if (size > REG_MAX_PLAUSIBLE_KEY_SIZE) {
|
|||
|
KdPrint(("CmpCheckKey: CmpCheckHive:%08lx Cell:%08lx\n", CmpCheckHive, Cell));
|
|||
|
KdPrint(("\tImplausible size\n"));
|
|||
|
rc = 4020;
|
|||
|
CmpCheckKeyDebug.Status = rc;
|
|||
|
return rc;
|
|||
|
}
|
|||
|
usedlen = FIELD_OFFSET(CM_KEY_NODE, Name) + pcell->u.KeyNode.NameLength;
|
|||
|
if (usedlen > size) {
|
|||
|
KdPrint(("CmpCheckKey: CmpCheckHive:%08lx Cell:%08lx\n", CmpCheckHive, Cell));
|
|||
|
KdPrint(("\tKey is bigger than containing cell.\n"));
|
|||
|
rc = 4030;
|
|||
|
CmpCheckKeyDebug.Status = rc;
|
|||
|
return rc;
|
|||
|
}
|
|||
|
if (pcell->u.KeyNode.Signature != CM_KEY_NODE_SIGNATURE) {
|
|||
|
KdPrint(("CmpCheckKey: CmpCheckHive:%08lx Cell:%08lx\n", CmpCheckHive, Cell));
|
|||
|
KdPrint(("\tNo key signature\n"));
|
|||
|
rc = 4040;
|
|||
|
CmpCheckKeyDebug.Status = rc;
|
|||
|
return rc;
|
|||
|
}
|
|||
|
if (ParentCell != HCELL_NIL) {
|
|||
|
if (pcell->u.KeyNode.Parent != ParentCell) {
|
|||
|
KdPrint(("CmpCheckKey: CmpCheckHive:%08lx Cell:%08lx\n", CmpCheckHive, Cell));
|
|||
|
KdPrint(("\tWrong parent value.\n"));
|
|||
|
rc = 4045;
|
|||
|
CmpCheckKeyDebug.Status = rc;
|
|||
|
return rc;
|
|||
|
}
|
|||
|
}
|
|||
|
ClassLength = pcell->u.KeyNode.ClassLength;
|
|||
|
Class = pcell->u.KeyNode.u1.s1.Class;
|
|||
|
ValueCount = pcell->u.KeyNode.ValueList.Count;
|
|||
|
ValueList = pcell->u.KeyNode.ValueList.List;
|
|||
|
Security = pcell->u.KeyNode.u1.s1.Security;
|
|||
|
|
|||
|
//
|
|||
|
// Check simple non-empty cases
|
|||
|
//
|
|||
|
if (ClassLength > 0) {
|
|||
|
if (HvIsCellAllocated(CmpCheckHive, Class) == FALSE) {
|
|||
|
KdPrint(("CmpCheckKey: CmpCheckHive:%08lx Cell:%08lx\n", CmpCheckHive, Cell));
|
|||
|
KdPrint(("\tClass:%08lx - unallocated class\n", Class));
|
|||
|
rc = 4080;
|
|||
|
CmpCheckKeyDebug.Status = rc;
|
|||
|
return rc;
|
|||
|
} else {
|
|||
|
SetUsed(CmpCheckHive, Class);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (Security != HCELL_NIL) {
|
|||
|
if (HvIsCellAllocated(CmpCheckHive, Security) == FALSE) {
|
|||
|
KdPrint(("CmpCheckKey: CmpCheckHive:%08lx Cell:%08lx\n", CmpCheckHive, Cell));
|
|||
|
KdPrint(("\tSecurity:%08lx - unallocated security\n", Security));
|
|||
|
rc = 4090;
|
|||
|
CmpCheckKeyDebug.Status = rc;
|
|||
|
return rc;
|
|||
|
} else if (HvGetCellType(Security) == Volatile) {
|
|||
|
SetUsed(CmpCheckHive, Security);
|
|||
|
}
|
|||
|
//
|
|||
|
// Else CmpValidateHiveSecurityDescriptors must do computation
|
|||
|
//
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Check value list case
|
|||
|
//
|
|||
|
if (ValueCount > 0) {
|
|||
|
if (HvIsCellAllocated(CmpCheckHive, ValueList) == FALSE) {
|
|||
|
KdPrint(("CmpCheckKey: CmpCheckHive:%08lx Cell:%08lx\n", CmpCheckHive, Cell));
|
|||
|
KdPrint(("\tValueList:%08lx - unallocated valuelist\n", ValueList));
|
|||
|
rc = 4100;
|
|||
|
CmpCheckKeyDebug.Status = rc;
|
|||
|
return rc;
|
|||
|
} else {
|
|||
|
SetUsed(CmpCheckHive, ValueList);
|
|||
|
pcell = HvGetCell(CmpCheckHive, ValueList);
|
|||
|
nrc = CmpCheckValueList(CmpCheckHive, pcell, ValueCount);
|
|||
|
if (nrc != 0) {
|
|||
|
KdPrint(("List was for CmpCheckHive:%08lx Cell:%08lx\n", CmpCheckHive, Cell));
|
|||
|
rc = nrc;
|
|||
|
CmpCheckKeyDebug.CellPoint = pcell;
|
|||
|
CmpCheckKeyDebug.Status = rc;
|
|||
|
return rc;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Check subkey list case
|
|||
|
//
|
|||
|
|
|||
|
pcell = HvGetCell(CmpCheckHive, Cell);
|
|||
|
CmpCheckKeyDebug.CellPoint = pcell;
|
|||
|
if ((HvGetCellType(Cell) == Volatile) &&
|
|||
|
(pcell->u.KeyNode.SubKeyCounts[Stable] != 0))
|
|||
|
{
|
|||
|
KdPrint(("CmpCheckKey: CmpCheckHive:%08lx Cell:%08lx\n", CmpCheckHive, Cell));
|
|||
|
KdPrint(("\tVolatile Cell has Stable children\n"));
|
|||
|
rc = 4108;
|
|||
|
CmpCheckKeyDebug.Status = rc;
|
|||
|
return rc;
|
|||
|
} else if (pcell->u.KeyNode.SubKeyCounts[Stable] > 0) {
|
|||
|
if (! HvIsCellAllocated(CmpCheckHive, pcell->u.KeyNode.SubKeyLists[Stable])) {
|
|||
|
KdPrint(("CmpCheckKey: CmpCheckHive:%08lx Cell:%08lx\n", CmpCheckHive, Cell));
|
|||
|
KdPrint(("\tStableKeyList:%08lx - unallocated\n", pcell->u.KeyNode.SubKeyLists[Stable]));
|
|||
|
rc = 4110;
|
|||
|
CmpCheckKeyDebug.Status = rc;
|
|||
|
return rc;
|
|||
|
} else {
|
|||
|
SetUsed(CmpCheckHive, pcell->u.KeyNode.SubKeyLists[Stable]);
|
|||
|
|
|||
|
//
|
|||
|
// Prove that the index is OK
|
|||
|
//
|
|||
|
Root = (PCM_KEY_INDEX)HvGetCell(
|
|||
|
CmpCheckHive,
|
|||
|
pcell->u.KeyNode.SubKeyLists[Stable]
|
|||
|
);
|
|||
|
CmpCheckKeyDebug.RootPoint = Root;
|
|||
|
if ((Root->Signature == CM_KEY_INDEX_LEAF) ||
|
|||
|
(Root->Signature == CM_KEY_FAST_LEAF)) {
|
|||
|
if ((ULONG)Root->Count != pcell->u.KeyNode.SubKeyCounts[Stable]) {
|
|||
|
KdPrint(("CmpCheckKey: CmpCheckHive:%08lx Cell:%08lx\n", CmpCheckHive, Cell));
|
|||
|
KdPrint(("\tBad Index count @%08lx\n", Root));
|
|||
|
rc = 4120;
|
|||
|
CmpCheckKeyDebug.Status = rc;
|
|||
|
return rc;
|
|||
|
}
|
|||
|
} else if (Root->Signature == CM_KEY_INDEX_ROOT) {
|
|||
|
SubCount = 0;
|
|||
|
for (i = 0; i < Root->Count; i++) {
|
|||
|
CmpCheckKeyDebug.Index = i;
|
|||
|
if (! HvIsCellAllocated(CmpCheckHive, Root->List[i])) {
|
|||
|
KdPrint(("CmpCheckKey: Hive:%08lx Cell:%08lx\n", CmpCheckHive, Cell));
|
|||
|
KdPrint(("\tBad Leaf Cell %08lx Root@%08lx\n", Root->List[i], Root));
|
|||
|
rc = 4130;
|
|||
|
CmpCheckKeyDebug.Status = rc;
|
|||
|
return rc;
|
|||
|
}
|
|||
|
Leaf = (PCM_KEY_INDEX)HvGetCell(CmpCheckHive,
|
|||
|
Root->List[i]);
|
|||
|
if ((Leaf->Signature != CM_KEY_INDEX_LEAF) &&
|
|||
|
(Leaf->Signature != CM_KEY_FAST_LEAF)) {
|
|||
|
KdPrint(("CmpCheckKey: CmpCheckHive:%08lx Cell:%08lx\n", CmpCheckHive, Cell));
|
|||
|
KdPrint(("\tBad Leaf Index @%08lx Root@%08lx\n", Leaf, Root));
|
|||
|
rc = 4140;
|
|||
|
CmpCheckKeyDebug.Status = rc;
|
|||
|
return rc;
|
|||
|
}
|
|||
|
SetUsed(CmpCheckHive, Root->List[i]);
|
|||
|
SubCount += Leaf->Count;
|
|||
|
}
|
|||
|
if (pcell->u.KeyNode.SubKeyCounts[Stable] != SubCount) {
|
|||
|
KdPrint(("CmpCheckKey: CmpCheckHive:%08lx Cell:%08lx\n", CmpCheckHive, Cell));
|
|||
|
KdPrint(("\tBad count in index, SubCount=%08lx\n", SubCount));
|
|||
|
rc = 4150;
|
|||
|
CmpCheckKeyDebug.Status = rc;
|
|||
|
return rc;
|
|||
|
}
|
|||
|
} else {
|
|||
|
KdPrint(("CmpCheckKey: CmpCheckHive:%08lx Cell:%08lx\n", CmpCheckHive, Cell));
|
|||
|
KdPrint(("\tBad Root index signature @%08lx\n", Root));
|
|||
|
rc = 4120;
|
|||
|
CmpCheckKeyDebug.Status = rc;
|
|||
|
return rc;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
//
|
|||
|
// force volatiles to be empty, if this is a load operation
|
|||
|
//
|
|||
|
if (CmpCheckClean == TRUE) {
|
|||
|
pcell->u.KeyNode.SubKeyCounts[Volatile] = 0;
|
|||
|
pcell->u.KeyNode.SubKeyLists[Volatile] = HCELL_NIL;
|
|||
|
}
|
|||
|
|
|||
|
return rc;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
ULONG
|
|||
|
CmpCheckValueList(
|
|||
|
PHHIVE Hive,
|
|||
|
PCELL_DATA List,
|
|||
|
ULONG Count
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Check consistency of a value list.
|
|||
|
. Each element allocated?
|
|||
|
. Each element have valid signature?
|
|||
|
. Data properly allocated?
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Hive - containing Hive.
|
|||
|
|
|||
|
List - pointer to an array of HCELL_INDEX entries.
|
|||
|
|
|||
|
Count - number of entries in list.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
0 if Hive is OK. Error return indicator if not.
|
|||
|
|
|||
|
RANGE: 5000 - 5999
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
ULONG i;
|
|||
|
HCELL_INDEX Cell;
|
|||
|
PCELL_DATA pcell;
|
|||
|
ULONG size;
|
|||
|
ULONG usedlen;
|
|||
|
ULONG DataLength;
|
|||
|
HCELL_INDEX Data;
|
|||
|
ULONG rc = 0;
|
|||
|
|
|||
|
CmpCheckValueListDebug.Hive = Hive;
|
|||
|
CmpCheckValueListDebug.Status = 0;
|
|||
|
CmpCheckValueListDebug.List = List;
|
|||
|
CmpCheckValueListDebug.Index = (ULONG)-1;
|
|||
|
CmpCheckValueListDebug.Cell = 0; // NOT HCELL_NIL
|
|||
|
CmpCheckValueListDebug.CellPoint = NULL;
|
|||
|
|
|||
|
for (i = 0; i < Count; i++) {
|
|||
|
|
|||
|
//
|
|||
|
// Check out value entry's refs.
|
|||
|
//
|
|||
|
Cell = List->u.KeyList[i];
|
|||
|
if (Cell == HCELL_NIL) {
|
|||
|
KdPrint(("CmpCheckValueList: List:%08lx i:%08lx\n", List, i));
|
|||
|
KdPrint(("\tEntry is null\n"));
|
|||
|
rc = 5010;
|
|||
|
CmpCheckValueListDebug.Status = rc;
|
|||
|
CmpCheckValueListDebug.Index = i;
|
|||
|
CmpCheckValueListDebug.Cell = Cell;
|
|||
|
return rc;
|
|||
|
}
|
|||
|
if (HvIsCellAllocated(Hive, Cell) == FALSE) {
|
|||
|
KdPrint(("CmpCheckValueList: List:%08lx i:%08lx\n", List, i));
|
|||
|
KdPrint(("\tEntry is not allocated\n"));
|
|||
|
rc = 5020;
|
|||
|
CmpCheckValueListDebug.Status = rc;
|
|||
|
CmpCheckValueListDebug.Index = i;
|
|||
|
CmpCheckValueListDebug.Cell = Cell;
|
|||
|
return rc;
|
|||
|
} else {
|
|||
|
SetUsed(Hive, Cell);
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Check out the value entry itself
|
|||
|
//
|
|||
|
pcell = HvGetCell(Hive, Cell);
|
|||
|
size = HvGetCellSize(Hive, pcell);
|
|||
|
if (pcell->u.KeyValue.Signature != CM_KEY_VALUE_SIGNATURE) {
|
|||
|
KdPrint(("CmpCheckValueList: List:%08lx i:%08lx\n", List, i));
|
|||
|
KdPrint(("\tCell:%08lx - invalid value signature\n", Cell));
|
|||
|
rc = 5030;
|
|||
|
CmpCheckValueListDebug.Status = rc;
|
|||
|
CmpCheckValueListDebug.Index = i;
|
|||
|
CmpCheckValueListDebug.Cell = Cell;
|
|||
|
CmpCheckValueListDebug.CellPoint = pcell;
|
|||
|
return rc;
|
|||
|
}
|
|||
|
usedlen = FIELD_OFFSET(CM_KEY_VALUE, Name) + pcell->u.KeyValue.NameLength;
|
|||
|
if (usedlen > size) {
|
|||
|
KdPrint(("CmpCheckValueList: List:%08lx i:%08lx\n", List, i));
|
|||
|
KdPrint(("\tCell:%08lx - value bigger than containing cell\n", Cell));
|
|||
|
rc = 5040;
|
|||
|
CmpCheckValueListDebug.Status = rc;
|
|||
|
CmpCheckValueListDebug.Index = i;
|
|||
|
CmpCheckValueListDebug.Cell = Cell;
|
|||
|
CmpCheckValueListDebug.CellPoint = pcell;
|
|||
|
return rc;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Check out value entry's data
|
|||
|
//
|
|||
|
DataLength = pcell->u.KeyValue.DataLength;
|
|||
|
if (DataLength < CM_KEY_VALUE_SPECIAL_SIZE) {
|
|||
|
Data = pcell->u.KeyValue.Data;
|
|||
|
if ((DataLength == 0) && (Data != HCELL_NIL)) {
|
|||
|
KdPrint(("CmpCheckValueList: List:%08lx i:%08lx\n", List, i));
|
|||
|
KdPrint(("\tCell:%08lx Data:%08lx - data not null\n", Cell, Data));
|
|||
|
rc = 5050;
|
|||
|
CmpCheckValueListDebug.Status = rc;
|
|||
|
CmpCheckValueListDebug.Index = i;
|
|||
|
CmpCheckValueListDebug.Cell = Cell;
|
|||
|
CmpCheckValueListDebug.CellPoint = pcell;
|
|||
|
return rc;
|
|||
|
}
|
|||
|
if (DataLength > 0) {
|
|||
|
if (HvIsCellAllocated(Hive, Data) == FALSE) {
|
|||
|
KdPrint(("CmpCheckValueList: List:%08lx i:%08lx\n", List, i));
|
|||
|
KdPrint(("\tCell:%08lx Data:%08lx - unallocated\n", Cell, Data));
|
|||
|
rc = 5060;
|
|||
|
CmpCheckValueListDebug.Status = rc;
|
|||
|
CmpCheckValueListDebug.Index = i;
|
|||
|
CmpCheckValueListDebug.Cell = Cell;
|
|||
|
CmpCheckValueListDebug.CellPoint = pcell;
|
|||
|
return rc;
|
|||
|
} else {
|
|||
|
SetUsed(Hive, Data);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
return rc;
|
|||
|
}
|