|
|
/*++
Copyright (c) 1998 Microsoft Corporation
Module Name:
regdmp.c
Abstract:
This module contains routines to check/dump the logical structure of the hive.
Author:
Dragos C. Sambotin (dragoss) 30-Dec-1998
Revision History:
--*/
#include "chkreg.h"
extern ULONG MaxLevel; extern UNICODE_STRING KeyName; extern WCHAR NameBuffer[]; extern FILE *OutputFile; extern BOOLEAN FixHive; extern BOOLEAN CompactHive; extern ULONG CountKeyNodeCompacted; extern HCELL_INDEX RootCell;
#define REG_MAX_PLAUSIBLE_KEY_SIZE \
((FIELD_OFFSET(CM_KEY_NODE, Name)) + \ (sizeof(WCHAR) * REG_MAX_KEY_NAME_LENGTH) + 16)
BOOLEAN ChkSecurityCellInList(HCELL_INDEX Security);
BOOLEAN ChkAreCellsInSameVicinity(HCELL_INDEX Cell1,HCELL_INDEX Cell2) { ULONG Start = Cell1&(~HCELL_TYPE_MASK); ULONG End = Cell2&(~HCELL_TYPE_MASK); Start += HBLOCK_SIZE; End += HBLOCK_SIZE; //
// truncate to the CM_VIEW_SIZE segment
//
Start &= (~(CM_VIEW_SIZE - 1)); End &= (~(CM_VIEW_SIZE - 1));
if( Start != End ){ return FALSE; } return TRUE;
}
BOOLEAN ChkAllocatedCell(HCELL_INDEX Cell) /*
Routine Description:
Checks if the cell is allocated (i.e. the size is negative).
Arguments:
Cell - supplies the cell index of the cell of interest.
Return Value:
TRUE if Cell is allocated. FALSE otherwise.
*/ { BOOLEAN bRez = TRUE;
if( Cell == HCELL_NIL ) { fprintf(stderr, "Warning : HCELL_NIL referrenced !\n"); return bRez; } if( !IsCellAllocated( Cell ) ) { bRez = FALSE; fprintf(stderr, "Used free cell 0x%lx ",Cell); if(FixHive) { //
// REPAIR: mark the cell as allocated
//
AllocateCell(Cell); fprintf(stderr, " ... fixed"); bRez = TRUE; } else { if(CompactHive) { // any attempt to compact a corrupted hive will fail
CompactHive = FALSE; fprintf(stderr, "\nRun chkreg /R to fix."); } } fprintf(stderr, "\n"); } return bRez; }
static CHAR FixKeyNameCount = 0;
BOOLEAN ChkKeyNodeCell(HCELL_INDEX KeyNodeCell, HCELL_INDEX ParentCell ) /*
Routine Description:
Checks if the cell is is a consistent keynode. Make fixes when neccessary/required. The following tests are performed against the keynode cell: 1. the size should be smaller than the REG_MAX_PLAUSIBLE_KEY_SIZE ==> fatal error 2. the Name should not exceed the size of the cell 3. the signature should match CM_KEY_NODE_SIGNATURE 4. the parent cell in keynode should match the actual parent cell
Arguments:
KeyNodeCell - supplies the cell index of the key node of interest.
ParentCell - the actual parent of the current key node
Return Value:
TRUE if KeyNodeCell is reffering a consistent key node, or it was successfully recovered.
FALSE otherwise.
*/ { PCM_KEY_NODE KeyNode = (PCM_KEY_NODE) GetCell(KeyNodeCell); ULONG size; BOOLEAN bRez = TRUE; ULONG usedlen; PUCHAR pName;
// this cell should not be considered as lost
RemoveCellFromUnknownList(KeyNodeCell);
ChkAllocatedCell(KeyNodeCell);
// Validate the size of the
size = GetCellSize(KeyNodeCell); if (size > REG_MAX_PLAUSIBLE_KEY_SIZE) { bRez = FALSE; fprintf(stderr, "Implausible Key size %lx in cell 0x%lx ",size,KeyNodeCell); if(FixHive) { //
// REPAIR: unable to fix
//
fprintf(stderr, " ... deleting key\n"); return bRez; } } usedlen = FIELD_OFFSET(CM_KEY_NODE, Name) + KeyNode->NameLength; if (usedlen > size) { bRez = FALSE; fprintf(stderr, "Key (size = %lu) is bigger than containing cell 0x%lx (size = %lu) ",usedlen,KeyNodeCell,size); if(FixHive) { //
// REPAIR: set NameLength to fit the cell size (i.e. set it to size - FIELD_OFFSET(CM_KEY_NODE, Name) )
//
//
// WARNING: the name might be truncated!!!
//
bRez = TRUE; KeyNode->NameLength = (USHORT)(size - FIELD_OFFSET(CM_KEY_NODE, Name)); fprintf(stderr, " ... fixed"); } else { if(CompactHive) { // any attempt to compact a corrupted hive will fail
CompactHive = FALSE; fprintf(stderr, "\nRun chkreg /R to fix."); } } fprintf(stderr, "\n"); }
if( KeyNode->Flags & KEY_COMP_NAME ) { pName = (PUCHAR)KeyNode->Name; for( usedlen = 0; usedlen < KeyNode->NameLength;usedlen++) { if( pName[usedlen] == '\\' ) { bRez = FALSE; fprintf(stderr, "Invalid key Name for Key (0x%lx) == %s ",KeyNodeCell,pName); if(FixHive) { //
// REPAIR: unable to fix
//
fprintf(stderr, " ... deleting key\n"); return bRez; } else { if(CompactHive) { // any attempt to compact a corrupted hive will fail
CompactHive = FALSE; fprintf(stderr, "\nRun chkreg /R to fix."); } } fprintf(stderr, "\n"); } } }
if (ParentCell != HCELL_NIL) { if (KeyNode->Parent != ParentCell) { bRez = FALSE; fprintf(stderr, "Parent of Key (0x%lx) does not match with its ParentCell (0x%lx) ",ParentCell,KeyNode->Parent); if(FixHive) { //
// REPAIR: reset the parent
//
bRez = TRUE; KeyNode->Parent = ParentCell; fprintf(stderr, " ... fixed"); } else { if(CompactHive) { // any attempt to compact a corrupted hive will fail
CompactHive = FALSE; fprintf(stderr, "\nRun chkreg /R to fix."); } } fprintf(stderr, "\n"); } }
if (KeyNode->Signature != CM_KEY_NODE_SIGNATURE) { bRez = FALSE; fprintf(stderr, "Invalid signature (0x%lx) in Key cell 0x%lx ",KeyNode->Signature,KeyNodeCell); if(FixHive) { //
// REPAIR:
// FATAL: Mismatched signature cannot be fixed. The key should be deleted!
//
fprintf(stderr, " ... deleting key"); } else { if(CompactHive) { // any attempt to compact a corrupted hive will fail
CompactHive = FALSE; fprintf(stderr, "\nRun chkreg /R to fix."); } } fprintf(stderr, "\n");
}
return bRez; }
BOOLEAN ChkClassCell(HCELL_INDEX Class) /*
Routine Description:
Checks if the cell is a consistent class cell. There is not much to be checked here.
Arguments:
Class - supplies the cell index of the cell of interest.
Return Value:
TRUE if Class is a valid cell.
FALSE otherwise.
*/ { // this cell should not be considered as lost
RemoveCellFromUnknownList(Class);
return ChkAllocatedCell(Class); }
BOOLEAN ChkSecurityCell(HCELL_INDEX Security) /*
Routine Description:
Checks if the cell is a consistent security cell. A security cell must be allocated and must have a valid signature.
Arguments:
Security - supplies the cell index of the cell of interest.
Return Value:
TRUE if Security is a valid cell.
FALSE otherwise.
*/ { PCM_KEY_SECURITY KeySecurity = (PCM_KEY_SECURITY) GetCell(Security); BOOLEAN bRez = TRUE;
// this cell should not be considered as lost
RemoveCellFromUnknownList(Security);
if( !IsCellAllocated( Security ) ) { // unalocated security cells are invalid.
// they are marked as free in the validate security descriptors check!
if(FixHive) { //
// REPAIR:
// FATAL: Invalid security cells could not be fixed. Containg keys will be deleted.
//
} else { if(CompactHive) { // any attempt to compact a corrupted hive will fail
CompactHive = FALSE; } } return FALSE; }
if (KeySecurity->Signature != CM_KEY_SECURITY_SIGNATURE) { fprintf(stderr, "Invalid signature (0x%lx) in Security Key cell 0x%lx ",KeySecurity->Signature,Security); if(FixHive) { //
// REPAIR:
// FATAL: Mismatched signature cannot be fixed. The key should be deleted!
//
fprintf(stderr, " ... deleting refering key"); } else { bRez = FALSE; if(CompactHive) { // any attempt to compact a corrupted hive will fail
CompactHive = FALSE; fprintf(stderr, "\nRun chkreg /R to fix."); } } fprintf(stderr, "\n"); }
// check if this security cell is present in the security list.
if(!ChkSecurityCellInList(Security) ) { bRez = FALSE; }
return bRez; }
BOOLEAN ChkKeyValue(HCELL_INDEX KeyValue, PREG_USAGE OwnUsage, BOOLEAN *KeyCompacted ) /*
Routine Description:
Checks if the cell is a consistent keyvalue cell. The following tests are performed: 1. the cell must be allocated 2. the cell is tested against HCELL_NIL ==> fatal error 3. the signature should match CM_KEY_VALUE_SIGNATURE 4. the name should not exceed the size of the cell 5. the data cell should be allocated and its size should match DataLength
Arguments:
KeyValue - supplies the cell index of the cell of interest.
OwnUsage - used to collect data statistics
Return Value:
TRUE if KeyCell is a valid cell or it was successfully fixed.
FALSE otherwise.
*/ { PCM_KEY_VALUE ValueNode; ULONG realsize; ULONG usedlen; ULONG DataLength; HCELL_INDEX Data; ULONG size;
BOOLEAN bRez = TRUE; if( KeyValue == HCELL_NIL ) { bRez = FALSE; fprintf(stderr, "NIL Key value encountered; Fatal error!"); if(FixHive) { //
// REPAIR: fatal error, the value should be removed from the value list
//
fprintf(stderr, " ... deleting empty entry\n"); return bRez; } }
ChkAllocatedCell(KeyValue); //
// Value size
//
size = GetCellSize(KeyValue); OwnUsage->Size += size;
// this cell should not be considered as lost
RemoveCellFromUnknownList(KeyValue);
ValueNode = (PCM_KEY_VALUE) GetCell(KeyValue);
//
// Check out the value entry itself
//
usedlen = FIELD_OFFSET(CM_KEY_VALUE, Name) + ValueNode->NameLength; if (usedlen > size) { bRez = FALSE; fprintf(stderr, "Key Value (size = %lu) is bigger than containing cell 0x%lx (size = %lu) ",usedlen,KeyValue,size); if(FixHive) { //
// REPAIR: set the actual size to HiveLength-FileOffset
//
//
// WARNING: the name might be truncated!!!
//
bRez = TRUE; ValueNode->NameLength = (USHORT)(size - FIELD_OFFSET(CM_KEY_VALUE, Name)); fprintf(stderr, " ... fixed"); } else { if(CompactHive) { // any attempt to compact a corrupted hive will fail
CompactHive = FALSE; fprintf(stderr, "\nRun chkreg /R to fix."); } } fprintf(stderr, "\n"); }
//
// Check out value entry's data
//
DataLength = ValueNode->DataLength; if (DataLength < CM_KEY_VALUE_SPECIAL_SIZE) { Data = ValueNode->Data; if ((DataLength == 0) && (Data != HCELL_NIL)) { bRez = FALSE; fprintf(stderr, "Data not null in Key Value (0x%lx) ",KeyValue); if(FixHive) { //
// REPAIR: set the actual size to HiveLength-FileOffset
//
//
// WARNING: a cell might get lost here!
//
bRez = TRUE; ValueNode->Data = HCELL_NIL; fprintf(stderr, " ... fixed"); } else { if(CompactHive) { // any attempt to compact a corrupted hive will fail
CompactHive = FALSE; fprintf(stderr, "\nRun chkreg /R to fix."); } } fprintf(stderr, "\n"); } } if (!CmpIsHKeyValueSmall(realsize, ValueNode->DataLength)) { //
// Data Size
//
OwnUsage->Size += GetCellSize(ValueNode->Data); OwnUsage->DataCount++; OwnUsage->DataSize += GetCellSize(ValueNode->Data);
// this cell should not be considered as lost
RemoveCellFromUnknownList(ValueNode->Data);
ChkAllocatedCell(ValueNode->Data); (*KeyCompacted) = ((*KeyCompacted) && ChkAreCellsInSameVicinity(KeyValue,ValueNode->Data)); }
//
// Now the signature
//
if (ValueNode->Signature != CM_KEY_VALUE_SIGNATURE) { bRez = FALSE; fprintf(stderr, "Invalid signature (0x%lx) in Key Value cell 0x%lx ",ValueNode->Signature,KeyValue); if(FixHive) { //
// REPAIR:
// FATAL: Mismatched signature cannot be fixed. The key should be deleted!
//
fprintf(stderr, " ... deleting value."); } else { if(CompactHive) { // any attempt to compact a corrupted hive will fail
CompactHive = FALSE; fprintf(stderr, "\nRun chkreg /R to fix."); } } fprintf(stderr, "\n"); } return bRez; }
ULONG DeleteNilCells( ULONG Count, HCELL_INDEX List[] ) /*
Routine Description:
steps through a list of HCELL_INDEXes and removes the HCELL_NIL ones
Arguments:
Count - the number of cells in list
List - the list to be checked
Return Value:
The new Count value for the list
*/ { ULONG i; BOOLEAN bFound = TRUE; while(bFound) { // assume we are done after this iteration
bFound = FALSE; for( i=0;i<Count;i++) { if( List[i] == HCELL_NIL ) { for(;i<(Count-1);i++) { List[i] = List[i+1]; } bFound = TRUE; Count--; break; } } } return Count; }
BOOLEAN ChkValueList( HCELL_INDEX ValueList, ULONG *ValueCount, PREG_USAGE OwnUsage, BOOLEAN *KeyCompacted) /*
Routine Description:
Checks the consistency of a ValueList. Each value is checked. Bogus values are freed and removed.
Arguments:
ValueList - the list to be checked
ValueCount - count of the list
OwnUsage - used to collect data statistics
Return Value:
TRUE if KeyCell is a valid cell or it was successfully fixed.
FALSE otherwise.
*/ { ULONG i; PCELL_DATA List; BOOLEAN bRez = TRUE;
//
// Value Index size
//
OwnUsage->Size += GetCellSize(ValueList); OwnUsage->ValueIndexCount = 1; // this cell should not be considered as lost
RemoveCellFromUnknownList(ValueList);
ChkAllocatedCell(ValueList); List = (PCELL_DATA)GetCell(ValueList); for (i=0; i<(*ValueCount); i++) { if( !ChkKeyValue(List->u.KeyList[i],OwnUsage,KeyCompacted) ) { // we should remove this value
bRez = FALSE; // Warning: this my create generate lost cells
if(FixHive) { if( List->u.KeyList[i] != HCELL_NIL ) { //FreeCell(List->u.KeyList[i]);
List->u.KeyList[i] = HCELL_NIL; } } } (*KeyCompacted) = ((*KeyCompacted) && ChkAreCellsInSameVicinity(ValueList,List->u.KeyList[i])); } if( FixHive && !bRez) { (*ValueCount) = DeleteNilCells( *ValueCount,List->u.KeyList); bRez = TRUE; } // for now
return bRez; }
BOOLEAN DumpChkRegistry( ULONG Level, USHORT ParentLength, HCELL_INDEX Cell, HCELL_INDEX ParentCell, PREG_USAGE PUsage ) /*
Routine Description:
Recursively walks through the hive. Performs logical vallidation checks on all cells along the path and fix errors when possible.
Arguments:
Level - the current depth level within the hive key tree
ParentLength - the length of the parent name (dump purposes only)
Cell - current key to be checked
ParentCell - parent cell, used for parent-son relationship checkings
OwnUsage - used to collect data statistics
Return Value:
TRUE if Cell is a consistent key, or it was fixed OK.
FALSE otherwise.
*/ { PCM_KEY_FAST_INDEX FastIndex; HCELL_INDEX LeafCell; PCM_KEY_INDEX Leaf; PCM_KEY_INDEX Index; PCM_KEY_NODE KeyNode; REG_USAGE ChildUsage, TotalChildUsage, OwnUsage; ULONG i, j; USHORT k; WCHAR *w1; UCHAR *u1; USHORT CurrentLength; ULONG CellCount; BOOLEAN bRez = TRUE; BOOLEAN KeyCompacted = TRUE;
ULONG ClassLength; HCELL_INDEX Class; ULONG ValueCount; HCELL_INDEX ValueList; HCELL_INDEX Security;
if( Cell == HCELL_NIL ) { // TODO
// we should return an error code so the caller could deleted this child from the structure
fprintf(stderr, "HCELL_NIL referrenced as a child key of 0x%lx \n",ParentCell); bRez = FALSE; return bRez; }
KeyNode = (PCM_KEY_NODE) GetCell(Cell);
// Verify KeyNode consistency
if(!ChkKeyNodeCell(Cell,ParentCell)) { //
// Bad karma ==> this key should be deleted
//
QuitToParentWithError:
if(ParentCell == HCELL_NIL) { //
// Root cell not consistent ==> unable to fix the hive
//
fprintf(stderr, "Fatal : Inconsistent Root Key 0x%lx",Cell); if(FixHive) { //
// FATAL: nothing to do
//
fprintf(stderr, " ... unable to fix"); } else { if(CompactHive) { // any attempt to compact a corrupted hive will fail
CompactHive = FALSE; } } fprintf(stderr, "\n"); } bRez = FALSE; return bRez; }
ClassLength = KeyNode->ClassLength; Class = KeyNode->Class; ValueCount = KeyNode->ValueList.Count; ValueList = KeyNode->ValueList.List; Security = KeyNode->Security;
if (ClassLength > 0) { if( Class != HCELL_NIL ) { ChkClassCell(Class); KeyCompacted = (KeyCompacted && ChkAreCellsInSameVicinity(Cell,Class)); } else { bRez = FALSE; fprintf(stderr,"ClassLength (=%u) doesn't match NIL values in Class for Key 0x%lx",ClassLength,Cell); if(FixHive) { //
// REPAIR: reset the ClassLength
//
bRez = TRUE; KeyNode->ClassLength = 0; fprintf(stderr, " ... fixed"); } else { if(CompactHive) { // any attempt to compact a corrupted hive will fail
CompactHive = FALSE; fprintf(stderr, "\nRun chkreg /R to fix."); } } fprintf(stderr, "\n"); } }
if (Security != HCELL_NIL) { if( !ChkSecurityCell(Security) ) { //
// Fatal : We don't mess up with security cells. We can't recover from invalid security cells.
//
//
// QUESTION : Is it acceptable to drop a security cell?
//
bRez = FALSE; } } else { //
// Fatal: security cell is not allowed to be NIL
//
bRez = FALSE; fprintf(stderr,"Security cell is NIL for Key 0x%lx",Cell); if(FixHive) { //
// REPAIR: reset the security to the root security
//
PCM_KEY_NODE RootNode; PCM_KEY_SECURITY SecurityNode; bRez = TRUE; RootNode = (PCM_KEY_NODE) GetCell(RootCell); KeyNode->Security = RootNode->Security; SecurityNode = (PCM_KEY_SECURITY)GetCell(RootNode->Security); SecurityNode->ReferenceCount++; fprintf(stderr, " ... fixed"); } }
//
// Construct the full path name of the key
//
if (Level > 0) { KeyName.Length = ParentLength; if (KeyNode->Flags & KEY_COMP_NAME) { u1 = (UCHAR*) &(KeyNode->Name[0]); w1 = &(NameBuffer[KeyName.Length/sizeof(WCHAR)]); for (k=0;k<KeyNode->NameLength;k++) { // NameBuffer[k] = (UCHAR)(KeyNode->Name[k]);
// NameBuffer[k] = (WCHAR)(u1[k]);
*w1 = (WCHAR) *u1; w1++; u1++; } KeyName.Length += KeyNode->NameLength*sizeof(WCHAR); } else { RtlCopyMemory((PVOID)&(NameBuffer[KeyName.Length]), (PVOID)(KeyNode->Name), KeyNode->NameLength); KeyName.Length += KeyNode->NameLength; } NameBuffer[KeyName.Length/sizeof(WCHAR)] = OBJ_NAME_PATH_SEPARATOR; KeyName.Length += sizeof(WCHAR);
} CurrentLength = KeyName.Length;
//
// Calculate the count of this key and value
//
OwnUsage.KeyNodeCount = 1; OwnUsage.KeyValueCount = KeyNode->ValueList.Count; OwnUsage.ValueIndexCount = 0; OwnUsage.DataCount = 0; OwnUsage.DataSize = 0;
//
// Calculate the count (including overhead and value) of this key
//
// Key node size
//
OwnUsage.Size = GetCellSize(Cell);
if( ValueCount ) { if( ValueList == HCELL_NIL ) { bRez = FALSE; fprintf(stderr,"ValueCount is %lu, but ValueList is NIL for key 0x%lx",ValueCount,Cell); if(FixHive) { //
// REPAIR: adjust the ValueList count
//
bRez = TRUE; KeyNode->ValueList.Count = 0; fprintf(stderr, " ... fixed"); } else { if(CompactHive) { // any attempt to compact a corrupted hive will fail
CompactHive = FALSE; fprintf(stderr, "\nRun chkreg /R to fix."); } } fprintf(stderr, "\n"); } else { if(!ChkValueList(ValueList,&(KeyNode->ValueList.Count),&OwnUsage,&KeyCompacted) ) { // the ValueList is not consistent or cannot be fixed
bRez = FALSE; if(FixHive) { //
// REPAIR: empty the ValueList
//
bRez = TRUE; KeyNode->ValueList.Count = 0; //FreeCell(ValueList);
KeyNode->ValueList.List = HCELL_NIL; fprintf(stderr,"ValueList 0x%lx for key 0x%lx dropped!",ValueCount,Cell); } else { if(CompactHive) { // any attempt to compact a corrupted hive will fail
CompactHive = FALSE; fprintf(stderr, "\nRun chkreg /R to fix."); } } fprintf(stderr, "\n"); } KeyCompacted = (KeyCompacted && ChkAreCellsInSameVicinity(Cell,ValueList)); } } //
// Calculate the size of the children
//
TotalChildUsage.KeyNodeCount = 0; TotalChildUsage.KeyValueCount = 0; TotalChildUsage.ValueIndexCount = 0; TotalChildUsage.KeyIndexCount = 0; TotalChildUsage.DataCount = 0; TotalChildUsage.DataSize = 0; TotalChildUsage.Size = 0;
if (KeyNode->SubKeyCounts[0]) { //
// Size for index cell
//
if( KeyNode->SubKeyLists[0] == HCELL_NIL ) { //
// We got a problem here: the count says there should be some keys, but the list is NIL
//
bRez = FALSE; fprintf(stderr,"SubKeyCounts is %lu, but the SubKeyLists is NIL for key 0x%lx",KeyNode->SubKeyCounts[0],Cell); if(FixHive) { //
// REPAIR: adjust the subkeys count
//
bRez = TRUE; KeyNode->SubKeyCounts[0] = 0; fprintf(stderr, " ... fixed"); } else { if(CompactHive) { // any attempt to compact a corrupted hive will fail
CompactHive = FALSE; fprintf(stderr, "\nRun chkreg /R to fix."); } } fprintf(stderr, "\n"); return bRez; } KeyCompacted = (KeyCompacted && ChkAreCellsInSameVicinity(Cell,KeyNode->SubKeyLists[0])); TotalChildUsage.Size += GetCellSize(KeyNode->SubKeyLists[0]); TotalChildUsage.KeyIndexCount++;
Index = (PCM_KEY_INDEX)GetCell(KeyNode->SubKeyLists[0]);
// this cell should not be considered as lost
RemoveCellFromUnknownList(KeyNode->SubKeyLists[0]);
ChkAllocatedCell(KeyNode->SubKeyLists[0]);
if (Index->Signature == CM_KEY_INDEX_ROOT) { for (i = 0; i < Index->Count; i++) { //
// Size of Index Leaf
//
LeafCell = Index->List[i];
TotalChildUsage.Size += GetCellSize(Index->List[i]); TotalChildUsage.KeyIndexCount++;
// this cell should not be considered as lost
RemoveCellFromUnknownList(LeafCell);
ChkAllocatedCell(LeafCell);
Leaf = (PCM_KEY_INDEX)GetCell(LeafCell); if ( (Leaf->Signature == CM_KEY_FAST_LEAF) || (Leaf->Signature == CM_KEY_HASH_LEAF) ) { FastIndex = (PCM_KEY_FAST_INDEX)Leaf; againFastLeaf1: for (j = 0; j < FastIndex->Count; j++) { if(!DumpChkRegistry(Level+1, CurrentLength, FastIndex->List[j].Cell,Cell,&ChildUsage)) { // this child is not consistent or cannot be fixed. Remove it!!!
if(FixHive) { //
// REPAIR: drop this child
//
fprintf(stderr,"Subkey 0x%lx of 0x%lx deleted!\n",FastIndex->List[j].Cell,Cell); for( ;j<(ULONG)(FastIndex->Count-1);j++) { FastIndex->List[j] = FastIndex->List[j+1]; } FastIndex->Count--; KeyNode->SubKeyCounts[0]--; goto againFastLeaf1; } else { bRez = FALSE; if(CompactHive) { // any attempt to compact a corrupted hive will fail
CompactHive = FALSE; fprintf(stderr, "\nRun chkreg /R to fix."); } } fprintf(stderr, "\n"); } //
// Add to total count
//
TotalChildUsage.KeyNodeCount += ChildUsage.KeyNodeCount; TotalChildUsage.KeyValueCount += ChildUsage.KeyValueCount; TotalChildUsage.ValueIndexCount += ChildUsage.ValueIndexCount; TotalChildUsage.KeyIndexCount += ChildUsage.KeyIndexCount; TotalChildUsage.DataCount += ChildUsage.DataCount; TotalChildUsage.DataSize += ChildUsage.DataSize; TotalChildUsage.Size += ChildUsage.Size; } } else if(Leaf->Signature == CM_KEY_INDEX_LEAF) { againFastLeaf2: for (j = 0; j < Leaf->Count; j++) { if(!DumpChkRegistry(Level+1, CurrentLength, Leaf->List[j],Cell,&ChildUsage)) { // this child is not consistent or cannot be fixed. Remove it!!!
if(FixHive) { //
// REPAIR: drop this child
//
fprintf(stderr,"Subkey 0x%lx of 0x%lx deleted!\n",Leaf->List[j],Cell); for( ;j<(ULONG)(Leaf->Count-1);j++) { Leaf->List[j] = Leaf->List[j+1]; } Leaf->Count--; KeyNode->SubKeyCounts[0]--; goto againFastLeaf2; } else { bRez = FALSE; if(CompactHive) { // any attempt to compact a corrupted hive will fail
CompactHive = FALSE; fprintf(stderr, "\nRun chkreg /R to fix."); } } fprintf(stderr, "\n"); } //
// Add to total count
//
TotalChildUsage.KeyNodeCount += ChildUsage.KeyNodeCount; TotalChildUsage.KeyValueCount += ChildUsage.KeyValueCount; TotalChildUsage.ValueIndexCount += ChildUsage.ValueIndexCount; TotalChildUsage.KeyIndexCount += ChildUsage.KeyIndexCount; TotalChildUsage.DataCount += ChildUsage.DataCount; TotalChildUsage.DataSize += ChildUsage.DataSize; TotalChildUsage.Size += ChildUsage.Size; } } else { // invalid index signature: only way to fix it is by dropping the entire key
fprintf(stderr,"Invalid Index signature 0x%lx in key 0x%lx",(ULONG)Leaf->Signature,Cell); if(FixHive) { //
// REPAIR:
// FATAL: Mismatched signature cannot be fixed. The key should be deleted!
//
fprintf(stderr, " ... deleting containing key"); } fprintf(stderr,"\n"); goto QuitToParentWithError; } }
} else if( (Index->Signature == CM_KEY_FAST_LEAF) || (Index->Signature == CM_KEY_HASH_LEAF) ) { FastIndex = (PCM_KEY_FAST_INDEX)Index;
againFastLeaf3:
for (i = 0; i < FastIndex->Count; i++) { if(!DumpChkRegistry(Level+1, CurrentLength, FastIndex->List[i].Cell,Cell,&ChildUsage)) { // this child is not consistent or cannot be fixed. Remove it!!!
if(FixHive) { //
// REPAIR: drop this child
//
fprintf(stderr,"Subkey 0x%lx of 0x%lx deleted!\n",FastIndex->List[i].Cell,Cell); for( ;i<(ULONG)(FastIndex->Count-1);i++) { FastIndex->List[i] = FastIndex->List[i+1]; } FastIndex->Count--; KeyNode->SubKeyCounts[0]--; goto againFastLeaf3; } else { bRez = FALSE; if(CompactHive) { // any attempt to compact a corrupted hive will fail
CompactHive = FALSE; fprintf(stderr, "\nRun chkreg /R to fix."); } } fprintf(stderr, "\n"); }
//
// Add to total count
//
TotalChildUsage.KeyNodeCount += ChildUsage.KeyNodeCount; TotalChildUsage.KeyValueCount += ChildUsage.KeyValueCount; TotalChildUsage.ValueIndexCount += ChildUsage.ValueIndexCount; TotalChildUsage.KeyIndexCount += ChildUsage.KeyIndexCount; TotalChildUsage.DataCount += ChildUsage.DataCount; TotalChildUsage.DataSize += ChildUsage.DataSize; TotalChildUsage.Size += ChildUsage.Size; } } else if(Index->Signature == CM_KEY_INDEX_LEAF) { for (i = 0; i < Index->Count; i++) { againFastLeaf4: if(!DumpChkRegistry(Level+1, CurrentLength, Index->List[i],Cell, &ChildUsage)) { // this child is not consistent or cannot be fixed. Remove it!!!
if(FixHive) { //
// REPAIR: drop this child
//
fprintf(stderr,"Subkey 0x%lx of 0x%lx deleted!\n",Index->List[i],Cell); for( ;i<(ULONG)(Index->Count-1);i++) { Index->List[i] = Index->List[i+1]; } Index->Count--; KeyNode->SubKeyCounts[0]--; goto againFastLeaf4; } else { bRez = FALSE; if(CompactHive) { // any attempt to compact a corrupted hive will fail
CompactHive = FALSE; fprintf(stderr, "\nRun chkreg /R to fix."); } } fprintf(stderr, "\n"); } //
// Add to total count
//
TotalChildUsage.KeyNodeCount += ChildUsage.KeyNodeCount; TotalChildUsage.KeyValueCount += ChildUsage.KeyValueCount; TotalChildUsage.ValueIndexCount += ChildUsage.ValueIndexCount; TotalChildUsage.KeyIndexCount += ChildUsage.KeyIndexCount; TotalChildUsage.DataCount += ChildUsage.DataCount; TotalChildUsage.DataSize += ChildUsage.DataSize; TotalChildUsage.Size += ChildUsage.Size; } } else { // invalid index signature: only way to fix it is by dropping the entire key
fprintf(stderr,"Invalid Index signature 0x%lx in key 0x%lx",(ULONG)Index->Signature,Cell); if(FixHive) { //
// REPAIR:
// FATAL: Mismatched signature cannot be fixed. The key should be deleted!
//
fprintf(stderr, " ... deleting containing key"); } fprintf(stderr,"\n"); goto QuitToParentWithError; }
KeyName.Length = CurrentLength; }
PUsage->KeyNodeCount = OwnUsage.KeyNodeCount + TotalChildUsage.KeyNodeCount; PUsage->KeyValueCount = OwnUsage.KeyValueCount + TotalChildUsage.KeyValueCount; PUsage->ValueIndexCount = OwnUsage.ValueIndexCount + TotalChildUsage.ValueIndexCount; PUsage->KeyIndexCount = TotalChildUsage.KeyIndexCount; PUsage->DataCount = OwnUsage.DataCount + TotalChildUsage.DataCount; PUsage->DataSize = OwnUsage.DataSize + TotalChildUsage.DataSize; PUsage->Size = OwnUsage.Size + TotalChildUsage.Size; if(KeyCompacted) { CountKeyNodeCompacted++; }
if ((Level <= MaxLevel) && (Level > 0)) { CellCount = PUsage->KeyNodeCount + PUsage->KeyValueCount + PUsage->ValueIndexCount + PUsage->KeyIndexCount + PUsage->DataCount;
fprintf(OutputFile,"%6d,%6d,%7d,%10d, %wZ\n", PUsage->KeyNodeCount, PUsage->KeyValueCount, CellCount, PUsage->Size, &KeyName); }
return bRez; }
|