/*++ 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 VerboseMode; extern BOOLEAN CompactHive; extern ULONG CountKeyNodeCompacted; extern HCELL_INDEX RootCell; extern ULONG HiveLength; #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); VOID DumpKeyName(HCELL_INDEX Cell, ULONG Level); 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 FALSE; } if( !IsCellAllocated( Cell ) ) { bRez = FALSE; fprintf(stderr, "Used free cell 0x%lx ",Cell); //DbgBreakPoint(); if(FixHive) { // // REPAIR: remove the containing entity // /* if( AllocateCell(Cell) ) { fprintf(stderr, " ... fixed"); bRez = TRUE; } else { */ fprintf(stderr, " ... unable to fix"); //} } 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); if( !ChkAllocatedCell(KeyNodeCell) ) { bRez = FALSE; fprintf(stderr, "Key not allocated cell 0x%lx ",KeyNodeCell); 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."); } return FALSE; } } // 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) || (!KeyNode->NameLength)) { bRez = FALSE; fprintf(stderr, "Key (size = %lu) is bigger than containing cell 0x%lx (size = %lu) ",usedlen,KeyNodeCell,size); if(FixHive) { 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( 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; } if( !IsCellAllocated(KeyValue) ) { bRez = FALSE; fprintf(stderr, "KeyValue not allocated cell 0x%lx ",KeyValue); if(FixHive) { // // REPAIR: unable to fix // fprintf(stderr, " ... deleting value \n"); } else { fprintf(stderr, "\n"); } return bRez; } // // 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) ) { if( (ValueNode->DataLength == 0) && (ValueNode->Data == HCELL_NIL) ) { // we're ok here } else if( ChkAllocatedCell(ValueNode->Data) ) { // // 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); (*KeyCompacted) = ((*KeyCompacted) && ChkAreCellsInSameVicinity(KeyValue,ValueNode->Data)); } else { bRez = FALSE; fprintf(stderr, "Data cell corrupted 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; ValueNode->DataLength = 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"); } } // // 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;iSize += GetCellSize(ValueList); OwnUsage->ValueIndexCount = 1; // this cell should not be considered as lost RemoveCellFromUnknownList(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; } } if( VerboseMode ) { fprintf(stderr, "KEY: "); DumpKeyName(Cell,Level); fprintf(stderr, " has a bogus value at index %lu \n",i); } } (*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"); } if(FixHive) { fprintf(stderr, "Removing "); } if( VerboseMode ) { fprintf(stderr, "KEY: "); DumpKeyName(Cell,Level); if(FixHive) { fprintf(stderr, " is corrupted\n"); } else { 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. // bRez = FALSE; fprintf(stderr,"Security cell is unallocated for Key 0x%lx",Cell); if(FixHive) { goto FixSecurity; } else { fprintf(stderr, "\nRun chkreg /R to fix."); return FALSE; } } } else { // // Fatal: security cell is not allowed to be NIL // bRez = FALSE; fprintf(stderr,"Security cell is NIL for Key 0x%lx",Cell); FixSecurity: 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\n"); } } // // 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;kNameLength;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( VerboseMode ) { fprintf(stderr,"\n KEY:"); DumpKeyName(Cell,Level); } 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(Cell,ValueList,&(KeyNode->ValueList.Count),&OwnUsage,&KeyCompacted,Level) ) { // 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); if( VerboseMode ) { fprintf(stderr,"\n KEY:"); DumpKeyName(Cell,Level); } } else { if(CompactHive) { // any attempt to compact a corrupted hive will fail CompactHive = FALSE; fprintf(stderr, "\nRun chkreg /R to fix."); } if( VerboseMode ) { fprintf(stderr,"Corrupted ValueList for KEY:"); DumpKeyName(Cell,Level); } } 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; } char StrDumpKeyName[3000]; VOID Rev( char * str ) { int j; int i = strlen(str); for(j = 0;jFlags & KEY_COMP_NAME) { u1 = (UCHAR*) &(KeyNode->Name[0]); for (k=0;kNameLength;k++) { str[k] = *u1; u1++; } str[k] = 0; Rev(str); strncat(StrDumpKeyName,str,3000 - strlen(StrDumpKeyName) - 1); } else { strncat(StrDumpKeyName,"nwonknU",3000 - strlen(StrDumpKeyName) - 1); } Cell = KeyNode->Parent; strncat(StrDumpKeyName,"\\",3000 - strlen(StrDumpKeyName) - 1); } Rev(StrDumpKeyName); fprintf(stderr, "%s",StrDumpKeyName); }