windows-nt/Source/XPSP1/NT/base/ntos/config/chkreg/regbin.c
2020-09-26 16:20:57 +08:00

935 lines
28 KiB
C

/*++
Copyright (c) 1998 Microsoft Corporation
Module Name:
regbin.c
Abstract:
This module contains functions to check bin header and bin body consistency.
Author:
Dragos C. Sambotin (dragoss) 30-Dec-1998
Revision History:
--*/
#include "chkreg.h"
extern ULONG TotalKeyNode;
extern ULONG TotalKeyValue;
extern ULONG TotalKeyIndex;
extern ULONG TotalKeySecurity;
extern ULONG TotalValueIndex;
extern ULONG TotalUnknown;
extern ULONG CountKeyNode;
extern ULONG CountKeyValue;
extern ULONG CountKeyIndex;
extern ULONG CountKeySecurity;
extern ULONG CountValueIndex;
extern ULONG CountUnknown;
extern ULONG TotalFree;
extern ULONG FreeCount;
extern ULONG TotalUsed;
extern PUCHAR Base;
extern FILE *OutputFile;
extern HCELL_INDEX RootCell;
extern PHBIN FirstBin;
extern PHBIN MaxBin;
extern ULONG HiveLength;
extern LONG BinIndex;
extern BOOLEAN FixHive;
extern BOOLEAN SpaceUsage;
extern BOOLEAN CompactHive;
ULONG BinFreeDisplaySize[HHIVE_FREE_DISPLAY_SIZE];
ULONG BinFreeDisplayCount[HHIVE_FREE_DISPLAY_SIZE];
ULONG FreeDisplaySize[HHIVE_FREE_DISPLAY_SIZE];
ULONG FreeDisplayCount[HHIVE_FREE_DISPLAY_SIZE];
ULONG BinUsedDisplaySize[HHIVE_FREE_DISPLAY_SIZE];
ULONG BinUsedDisplayCount[HHIVE_FREE_DISPLAY_SIZE];
ULONG UsedDisplaySize[HHIVE_FREE_DISPLAY_SIZE];
ULONG UsedDisplayCount[HHIVE_FREE_DISPLAY_SIZE];
BOOLEAN ChkAllocatedCell(HCELL_INDEX Cell);
CCHAR ChkRegFindFirstSetLeft[256] = {
0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7};
#define ComputeFreeIndex(Index, Size) \
{ \
Index = (Size >> HHIVE_FREE_DISPLAY_SHIFT) - 1; \
if (Index >= HHIVE_LINEAR_INDEX ) { \
\
/* \
** Too big for the linear lists, compute the exponential \
** list. \
*/ \
\
if (Index > 255) { \
/* \
** Too big for all the lists, use the last index. \
*/ \
Index = HHIVE_FREE_DISPLAY_SIZE-1; \
} else { \
Index = ChkRegFindFirstSetLeft[Index] + \
HHIVE_FREE_DISPLAY_BIAS; \
} \
} \
}
BOOLEAN
ChkBinHeader(PHBIN Bin,
ULONG FileOffset,
ULONG Index
)
/*++
Routine Description:
Checks the validity of the Bin header.
The following tests are done:
1. the Size should not be bigger than the remaining of the file
2. the Size should not be smaller than HBLOCK_SIZE
3. the signature should be valid (HBIN_SIGNATURE)
4. the file offset should match the actual position in the hive file.
Arguments:
Bin - supplies a pointer to the bin to be checked.
FileOffset - provides the actual pposition within the file
Index - the index of the bin within the bin list of the hive
Return Value:
FALSE - the bin header is corrupted and was not fixed. Either this is a
critical corruption, or the /R argument was not present in the
command line.
TRUE - The bin header is OK, or it was successfully recovered.
--*/
{
BOOLEAN bRez = TRUE;
PHCELL p;
p = (PHCELL)((PUCHAR)Bin + sizeof(HBIN));
if(Bin->Size > (HiveLength - FileOffset)) {
bRez = FALSE;
fprintf(stderr, "Size too big (%lu) in Bin header of Bin (%lu)\n",Bin->Size,Index);
if(FixHive) {
//
// REPAIR: set the actual size to HiveLength-FileOffset
//
Bin->Size = HiveLength-FileOffset;
p->Size = Bin->Size -sizeof(HBIN);
bRez = TRUE;
} else {
if(CompactHive) {
// any attempt to compact a corrupted hive will fail
CompactHive = FALSE;
fprintf(stderr, "Run chkreg /R to fix.\n");
}
}
}
if((Bin->Size < HBLOCK_SIZE) || ((Bin->Size % HBLOCK_SIZE) != 0)) {
bRez = FALSE;
fprintf(stderr, "Size too small (%lu) in Bin header of Bin (%lu)\n",Bin->Size,Index);
if(FixHive) {
//
// REPAIR: set the actual size to minimmum possible size HBLOCK_SIZE
//
Bin->Size = HBLOCK_SIZE;
p->Size = Bin->Size -sizeof(HBIN);
bRez = TRUE;
} else {
if(CompactHive) {
// any attempt to compact a corrupted hive will fail
CompactHive = FALSE;
fprintf(stderr, "Run chkreg /R to fix.\n");
}
}
}
if(Bin->Signature != HBIN_SIGNATURE) {
bRez = FALSE;
fprintf(stderr, "Invalid signature (%lx) in Bin header of Bin (%lu)\n",Bin->Signature,Index);
if(FixHive) {
//
// REPAIR: reset the bin signature
//
Bin->Signature = HBIN_SIGNATURE;
bRez = TRUE;
} else {
if(CompactHive) {
// any attempt to compact a corrupted hive will fail
CompactHive = FALSE;
fprintf(stderr, "Run chkreg /R to fix.\n");
}
}
}
if(Bin->FileOffset != FileOffset) {
bRez = FALSE;
fprintf(stderr, "Actual FileOffset [%lx] and Bin FileOffset [%lx] do not match in Bin (%lu); Size = (%lx)\n",FileOffset,Bin->FileOffset,Index,Bin->Size);
if(FixHive) {
//
// REPAIR: reset the bin FileOffset
//
Bin->FileOffset = FileOffset;
bRez = TRUE;
} else {
if(CompactHive) {
// any attempt to compact a corrupted hive will fail
CompactHive = FALSE;
fprintf(stderr, "Run chkreg /R to fix.\n");
}
}
}
return bRez;
}
BOOLEAN
ChkBin(
PHBIN Bin,
ULONG IndexBin,
ULONG Starting,
double *Rate
)
/*++
Routine Description:
Steps through all of the cells in the bin. Make sure that
they are consistent with each other, and with the bin header.
Compute the usage rate for the current bin.
Add all used cells to the unknown list (candidates to lost cells).
Compute the used space and allocated cells by cell signature.
Compute the free space size and number of cells.
Test the cell size for reasonable limits. A cell should be smaller
than the containing bin and should not exceed the bin boundaries.
A cell should fit in only one contiguos bin!!!
Arguments:
Bin - supplies a pointer to the bin to be checked.
Index - the index of the bin within the bin list of the hive
Starting - starting address of the in-memory hive representation.
Rate - usage rate for this bin
Return Value:
FALSE - the bin is corrupted and was not fixed. Either this is a
critical corruption, or the /R argument was not present in the
command line.
TRUE - The bin is OK, or it was successfully recovered.
--*/
{
ULONG freespace = 0L;
ULONG allocated = 0L;
BOOLEAN bRez = TRUE;
HCELL_INDEX cellindex;
PHCELL p;
ULONG Size;
ULONG Index;
double TmpRate;
p = (PHCELL)((PUCHAR)Bin + sizeof(HBIN));
while (p < (PHCELL)((PUCHAR)Bin + Bin->Size)) {
cellindex = (HCELL_INDEX)((PUCHAR)p - Base);
if (p->Size >= 0) {
//
// It is a free cell.
//
Size = (ULONG)p->Size;
if ( (Size > Bin->Size) ||
( (PHCELL)(Size + (PUCHAR)p) >
(PHCELL)((PUCHAR)Bin + Bin->Size) )
) {
bRez = FALSE;
fprintf(stderr, "Impossible cell size in free cell (%lu) in Bin header of Bin (%lu)\n",Size,IndexBin);
if(FixHive) {
//
// REPAIR: set the cell size to the largest possible hereon (ie. Bin + Bin->Size - p ); reset the Size too!!!
//
bRez = TRUE;
p->Size = (ULONG)((PUCHAR)Bin + Bin->Size - (PUCHAR)p);
} else {
if(CompactHive) {
// any attempt to compact a corrupted hive will fail
CompactHive = FALSE;
fprintf(stderr, "Run chkreg /R to fix.\n");
}
}
}
freespace += Size;
TotalFree += Size;
FreeCount++;
if( SpaceUsage ) {
// only if we are interested in the usage map
// store the length of this free cell
ComputeFreeIndex(Index, Size);
BinFreeDisplaySize[Index] += Size;
// and increment the count of free cells of this particular size
BinFreeDisplayCount[Index]++;
}
}else{
//
// It is used cell. Check for signature
//
UCHAR *C;
USHORT Sig;
int i,j;
// All used cells are leak candidates
AddCellToUnknownList(cellindex);
Size = (ULONG)(p->Size * -1);
if ( (Size > Bin->Size) ||
( (PHCELL)(Size + (PUCHAR)p) >
(PHCELL)((PUCHAR)Bin + Bin->Size) )
) {
bRez = FALSE;
fprintf(stderr, "Impossible cell size in allocated cell (%lu) in Bin header of Bin (%lu)\n",Size,IndexBin);
if(FixHive) {
//
// REPAIR: set the cell size to the largest possible hereon (ie. Bin + Bin->Size - p ); reset the Size too!!!
//
bRez = TRUE;
p->Size = (LONG)((PUCHAR)Bin + Bin->Size - (PUCHAR)p);
// it's a used cell, remember ?
p->Size *= -1;
} else {
if(CompactHive) {
// any attempt to compact a corrupted hive will fail
CompactHive = FALSE;
fprintf(stderr, "Run chkreg /R to fix.\n");
}
}
}
allocated += Size;
if( SpaceUsage ) {
// only if we are interested in the usage map
// store the length of this used cell
ComputeFreeIndex(Index, Size);
BinUsedDisplaySize[Index] += Size;
// and increment the count of used cells of this particular size
BinUsedDisplayCount[Index]++;
}
TotalUsed=TotalUsed+Size;
C= (UCHAR *) &(p->u.NewCell.u.UserData);
Sig=(USHORT) p->u.NewCell.u.UserData;
switch(Sig){
case CM_LINK_NODE_SIGNATURE:
printf("Link Node !\n");
TotalKeyNode=TotalKeyNode+Size;
CountKeyNode++;
break;
case CM_KEY_NODE_SIGNATURE:
{
PCM_KEY_NODE Pcan;
TotalKeyNode=TotalKeyNode+Size;
CountKeyNode++;
Pcan = (PCM_KEY_NODE)C;
if(Pcan->ValueList.Count){
PHCELL TmpP;
TmpP = (PHCELL) (Starting + Pcan->ValueList.List);
TotalValueIndex=TotalValueIndex - TmpP->Size;
CountValueIndex++;
}
}
break;
case CM_KEY_VALUE_SIGNATURE:
TotalKeyValue=TotalKeyValue+Size;
CountKeyValue++;
break;
case CM_KEY_FAST_LEAF:
case CM_KEY_HASH_LEAF:
case CM_KEY_INDEX_LEAF:
case CM_KEY_INDEX_ROOT:
TotalKeyIndex=TotalKeyIndex+Size;
CountKeyIndex++;
break;
case CM_KEY_SECURITY_SIGNATURE:
TotalKeySecurity=TotalKeySecurity+Size;
CountKeySecurity++;
break;
default:
//
// No signature, it can be data or index cells.
// Or there must be some registry leak here.
//
TotalUnknown=TotalUnknown+Size;
CountUnknown++;
break;
}
}
p = (PHCELL)((PUCHAR)p + Size);
}
*Rate = TmpRate = (double)(((double)allocated)/((double)(allocated+freespace)));
TmpRate *= 100.00;
fprintf(OutputFile,"Bin [%5lu], usage %.2f%%\r",IndexBin,(float)TmpRate);
return bRez;
}
BOOLEAN ChkPhysicalHive()
/*++
Routine Description:
Checks the integrity of the hive by stepping through all of the cells
in the hive. Collects and displays statistics, according to the command
line parameters.
Arguments:
None.
Return Value:
FALSE - the hive is corrupted and was not fixed. Either this is a
critical corruption, or the /R argument was not present in the
command line.
TRUE - The hive is OK, or it was successfully recovered.
--*/
{
ULONG Starting;
PHBIN Bin = FirstBin;
LONG Index;
ULONG FileOffset;
double Rate,RateTotal = 0.0;
BOOLEAN bRez = TRUE;
int i;
Starting=(ULONG) Bin;
Index=0;
FileOffset = 0;
for(i=0;i<HHIVE_FREE_DISPLAY_SIZE;i++) {
FreeDisplaySize[i] = 0;
FreeDisplayCount[i] = 0;
UsedDisplaySize[i] = 0;
UsedDisplayCount[i] = 0;
}
while(Bin < MaxBin){
if( SpaceUsage ) {
// only if we are interested in the usage map
for(i=0;i<HHIVE_FREE_DISPLAY_SIZE;i++) {
BinFreeDisplaySize[i] = 0;
BinFreeDisplayCount[i] = 0;
BinUsedDisplaySize[i] = 0;
BinUsedDisplayCount[i] = 0;
}
}
bRez = (bRez && ChkBinHeader(Bin,FileOffset,Index));
bRez = (bRez && ChkBin(Bin,Index,Starting,&Rate));
RateTotal += Rate;
if( SpaceUsage ) {
// only if we are interested in the usage map
if( BinIndex == Index ) {
// summary wanted for this particular bin
fprintf(OutputFile,"\nBin[%5lu] Display Map: Free Cells, Free Size\t Used Cells, Used Size\n",(ULONG)Index);
for(i=0;i<HHIVE_FREE_DISPLAY_SIZE;i++) {
fprintf(OutputFile,"Display[%2d] : %8lu , %8lu \t %8lu , %8lu \n",i,BinFreeDisplayCount[i],BinFreeDisplaySize[i],BinUsedDisplayCount[i],BinUsedDisplaySize[i]);
}
}
for(i=0;i<HHIVE_FREE_DISPLAY_SIZE;i++) {
FreeDisplaySize[i] += BinFreeDisplaySize[i];
FreeDisplayCount[i] += BinFreeDisplayCount[i];
UsedDisplaySize[i] += BinUsedDisplaySize[i];
UsedDisplayCount[i] += BinUsedDisplayCount[i];
}
}
if( Bin<MaxBin) {
FileOffset += Bin->Size;
}
Bin = (PHBIN)((ULONG)Bin + Bin->Size);
Index++;
}
RateTotal *= 100.00;
RateTotal /= (double)Index;
fprintf(OutputFile,"Number of Bins in hive: %lu \n",Index);
fprintf(OutputFile,"Total Hive space usage: %.2f%% \n",(float)RateTotal);
if( SpaceUsage ) {
// only if we are interested in the usage map
if( BinIndex == -1 ) {
// space usage display per entire hive
fprintf(OutputFile,"\nHive Display Map: Free Cells, Free Size\t\t Used Cells, Used Size\n");
for(i=0;i<HHIVE_FREE_DISPLAY_SIZE;i++) {
fprintf(OutputFile,"Display[%2d] : %8lu , %8lu \t %8lu , %8lu \n",i,FreeDisplayCount[i],FreeDisplaySize[i],UsedDisplayCount[i],UsedDisplaySize[i]);
}
}
}
return bRez;
}
ULONG
ComputeHeaderCheckSum(
PHBASE_BLOCK BaseBlock
)
/*++
Routine Description:
Compute the checksum for a hive disk header.
Arguments:
BaseBlock - supplies pointer to the header to checksum
Return Value:
the check sum.
--*/
{
ULONG sum;
ULONG i;
sum = 0;
for (i = 0; i < 127; i++) {
sum ^= ((PULONG)BaseBlock)[i];
}
if (sum == (ULONG)-1) {
sum = (ULONG)-2;
}
if (sum == 0) {
sum = 1;
}
return sum;
}
BOOLEAN
ChkBaseBlock(PHBASE_BLOCK BaseBlock,
DWORD dwFileSize)
/*++
Routine Description:
Checks the integrity of the base block of a hive.
Eventually makes the following corrections:
1. enforce Sequence1 == Sequence2
2. recalculate the header checksum
Arguments:
BaseBlock - the BaseBlock in-memory mapped image.
dwFileSize - the actual size of the hive file
Return Value:
FALSE - the BaseBlock is corrupted and was not fixed. Either this is a
critical corruption, or the /R argument was not present in the
command line.
TRUE - The BaseBlock is OK, or it was successfully recovered.
--*/
{
BOOLEAN bRez = TRUE;
ULONG CheckSum;
if(BaseBlock->Signature != HBASE_BLOCK_SIGNATURE) {
fprintf(stderr, "Fatal: Invalid Base Block signature (0x%lx)",BaseBlock->Signature);
bRez = FALSE;
if(FixHive) {
//
// REPAIR: reset the signature
//
fprintf(stderr, " ... unable to fix");
} else {
if(CompactHive) {
// any attempt to compact a corrupted hive will fail
CompactHive = FALSE;
}
}
fprintf(stderr, "\n");
}
if(BaseBlock->Major != HSYS_MAJOR) {
bRez = FALSE;
fprintf(stderr, "Fatal: Invalid hive file Major version (%lu)",BaseBlock->Major);
if(FixHive) {
//
// Fatal: unable to fix this
//
fprintf(stderr, " ... unable to fix");
} else {
if(CompactHive) {
// any attempt to compact a corrupted hive will fail
CompactHive = FALSE;
}
}
fprintf(stderr, "\n");
}
if(BaseBlock->Minor > HSYS_MINOR_SUPPORTED) {
bRez = FALSE;
fprintf(stderr, "Fatal: Invalid hive file Minor version (%lu)",BaseBlock->Minor);
if(FixHive) {
//
// Fatal: unable to fix this
//
fprintf(stderr, " ... unable to fix");
} else {
if(CompactHive) {
// any attempt to compact a corrupted hive will fail
CompactHive = FALSE;
}
}
fprintf(stderr, "\n");
}
if(BaseBlock->Format != HBASE_FORMAT_MEMORY) {
bRez = FALSE;
fprintf(stderr, "Fatal: Invalid hive memory format (%lu)",BaseBlock->Format);
if(FixHive) {
//
// Fatal: unable to fix this
//
fprintf(stderr, " ... unable to fix");
} else {
if(CompactHive) {
// any attempt to compact a corrupted hive will fail
CompactHive = FALSE;
}
}
fprintf(stderr, "\n");
}
if((BaseBlock->Length + HBLOCK_SIZE) > dwFileSize) {
fprintf(stderr, "Fatal: Invalid Hive file Length (%lu)",BaseBlock->Length);
bRez = FALSE;
if(FixHive) {
//
// REPAIR: unable to fix this
//
fprintf(stderr, " ... unable to fix");
} else {
if(CompactHive) {
// any attempt to compact a corrupted hive will fail
CompactHive = FALSE;
}
}
fprintf(stderr, "\n");
}
if(!bRez) {
//
// Fatal Base Block corruption; no point to continue.
//
return bRez;
}
if(BaseBlock->Sequence1 != BaseBlock->Sequence2) {
fprintf(stderr, "Sequence numbers do not match (%lu,%lu)",BaseBlock->Sequence1,BaseBlock->Sequence2);
bRez = FALSE;
if(FixHive) {
//
// REPAIR: enforce Sequence2 to Sequence1
//
bRez = TRUE;
BaseBlock->Sequence2 = BaseBlock->Sequence1;
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");
}
CheckSum = ComputeHeaderCheckSum(BaseBlock);
if(BaseBlock->CheckSum != CheckSum) {
fprintf(stderr, "Invalid Base Block CheckSum (0x%lx)",BaseBlock->CheckSum);
bRez = FALSE;
if(FixHive) {
//
// REPAIR: reset the signature
//
bRez = TRUE;
BaseBlock->CheckSum = CheckSum;
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;
}
BOOLEAN
ChkSecurityDescriptors( )
/*++
Routine Description:
Walks the list of security descriptors present in the hive and passes
each security descriptor to RtlValidSecurityDescriptor.
Also checks the validity of the FLink <==> BLink relationship between cells.
Arguments:
Return Value:
TRUE - All security descriptors are valid
FALSE - At least one security descriptor is invalid, and/or cannot be fixed
--*/
{
PCM_KEY_NODE RootNode;
PCM_KEY_SECURITY SecurityCell;
HCELL_INDEX ListAnchor;
HCELL_INDEX NextCell;
HCELL_INDEX LastCell;
BOOLEAN bRez = TRUE;
// check/fix the root cell (is allocated?)
ChkAllocatedCell(RootCell);
RootNode = (PCM_KEY_NODE) GetCell(RootCell);
ListAnchor = NextCell = RootNode->Security;
do {
// is the next cell allocated?
ChkAllocatedCell(NextCell);
SecurityCell = (PCM_KEY_SECURITY) GetCell(NextCell);
if (SecurityCell->Signature != CM_KEY_SECURITY_SIGNATURE) {
bRez = FALSE;
fprintf(stderr, "Fatal: Invalid signature (0x%lx) in Security cell 0x%lx ",SecurityCell->Signature,NextCell);
if(FixHive) {
//
// REPAIR:
// FATAL: Mismatched signature cannot be fixed. Unable to fix this.
//
fprintf(stderr, " ... unable to fix");
} else {
if(CompactHive) {
// any attempt to compact a corrupted hive will fail
CompactHive = FALSE;
}
}
fprintf(stderr, "\n");
return bRez;
}
if (NextCell != ListAnchor) {
//
// Check to make sure that our Blink points to where we just
// came from.
//
if (SecurityCell->Blink != LastCell) {
fprintf(stderr, "Invalid backward link in security cell (0x%lx)",NextCell);
if(FixHive) {
//
// REPAIR: reset the link
//
SecurityCell->Blink = LastCell;
fprintf(stderr, " ... fixed");
} 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");
}
}
if (!RtlValidSecurityDescriptor(&SecurityCell->Descriptor)) {
bRez = FALSE;
fprintf(stderr, "Invalid security descriptor in Security cell 0x%lx ",NextCell);
if(FixHive) {
//
// REPAIR: remove the cell from the list and delete it!
//
PCM_KEY_SECURITY Before = (PCM_KEY_SECURITY) GetCell(SecurityCell->Blink);
PCM_KEY_SECURITY After = (PCM_KEY_SECURITY) GetCell(SecurityCell->Flink);
if( Before != After ) {
// make sure the list will not remain empty
Before->Flink = SecurityCell->Flink;
After->Blink = SecurityCell->Blink;
}
FreeCell(NextCell);
NextCell = SecurityCell->Flink;
fprintf(stderr, " ... deleted");
} 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");
} else {
// validate the next one
LastCell = NextCell;
NextCell = SecurityCell->Flink;
}
} while ( NextCell != ListAnchor );
return bRez;
}
BOOLEAN
ChkSecurityCellInList(HCELL_INDEX Security)
/*++
Routine Description:
Searches the specified cell within the security descriptors list
Arguments:
Security - Provides the current cell
Return Value:
TRUE - the current cell was found in the security list
FALSE - the current cell is not present in the security list and it couldn't be added.
--*/
{
PCM_KEY_NODE RootNode;
PCM_KEY_SECURITY SecurityCell;
PCM_KEY_SECURITY SecurityCellCurrent;
PCM_KEY_SECURITY SecurityCellAfter;
HCELL_INDEX ListAnchor;
HCELL_INDEX NextCell;
BOOLEAN bRez = TRUE;
RootNode = (PCM_KEY_NODE) GetCell(RootCell);
ListAnchor = NextCell = RootNode->Security;
do {
if( NextCell == Security) {
// found it!
return bRez;
}
SecurityCell = (PCM_KEY_SECURITY) GetCell(NextCell);
NextCell = SecurityCell->Flink;
} while ( NextCell != ListAnchor );
// cell not found; try to fix it
bRez = FALSE;
fprintf(stderr, "Security Cell (0x%lx) not in security descriptors list",Security);
if(FixHive) {
//
// REPAIR: Add the security cell at the begining of the list
//
bRez = TRUE;
SecurityCell = (PCM_KEY_SECURITY) GetCell(ListAnchor);
SecurityCellCurrent = (PCM_KEY_SECURITY) GetCell(Security);
SecurityCellAfter = (PCM_KEY_SECURITY) GetCell(SecurityCell->Flink);
// restore the connections
SecurityCellCurrent->Flink = SecurityCell->Flink;
SecurityCellCurrent->Blink = ListAnchor;
SecurityCell->Flink = Security;
SecurityCellAfter->Blink = Security;
fprintf(stderr, " ... security cell added to the list");
} 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;
}