|
|
/*++
Copyright (c) 1998 Microsoft Corporation
Module Name:
regmain.c
Abstract:
Main module. Data definitions.
Author:
Dragos C. Sambotin (dragoss) 30-Dec-1998
Revision History:
--*/
#include "chkreg.h"
// check the hive structure.
BOOLEAN CheckHive = TRUE;
// compact the hive.
BOOLEAN CompactHive = FALSE;
// check for lost space (marked as used but not reffered).
BOOLEAN LostSpace = FALSE;
// repair damaged hives.
BOOLEAN FixHive = FALSE;
// repair damaged hives.
BOOLEAN SpaceUsage = FALSE;
// maximum level to dump
ULONG MaxLevel = 0;
// bin to examine space display
LONG BinIndex = -1;
// the hive file name
TCHAR *Hive = NULL;
// the root of the hive
HCELL_INDEX RootCell;
// Usage string
char *Usage="\
Checks a hive file and perform repairs, compacts or displays a status report.\n\n\ CHKREG /F <filename[.<LOG>]> [/H] [/D [<level>] [/S [<bin>]] [/C] [/L] [/R]\n\n\ <filename> FileName of hive to be analyzed\n\ /H This manual\n\ /D [<level>] Dump subkeys up to level <level>. If level is not\n\ specified, dumps the entire hive. No checks are done\n\ when dumping.\n\ /S [<bin>] Displays space usage for the bin <bin>. When bin is\n\ not specified, displays usage for the entire hive.\n\ /C Compacts the hive. Bad hives cannot be compacted.\n\ The compacted hive will be written to <filename>.BAK\n\ /L Lost space detection.\n\ /R Repair the hive.\n\ ";
// Lost Space Warning
char *LostSpaceWarning="\n\
WARNING : Lost space detection may take a while. Are you sure you want this (y/n)?";
// Starting address of the in-memory maped hive image
PUCHAR Base;
// LostCells list used for lost space detection
UNKNOWN_LIST LostCells[FRAGMENTATION];
// OutputFile : future changes may use it to write the results to a file rather than to stdout
FILE *OutputFile;
#define NAME_BUFFERSIZE 2000
UNICODE_STRING KeyName; WCHAR NameBuffer[NAME_BUFFERSIZE];
// Miscelaneous variables used fo data statistics
ULONG TotalKeyNode=0; ULONG TotalKeyValue=0; ULONG TotalKeyIndex=0; ULONG TotalKeySecurity=0; ULONG TotalValueIndex=0; ULONG TotalUnknown=0;
ULONG CountKeyNode=0; ULONG CountKeyValue=0; ULONG CountKeyIndex=0; ULONG CountKeySecurity=0; ULONG CountValueIndex=0; ULONG CountUnknown=0;
ULONG CountKeyNodeCompacted=0;
ULONG TotalFree=0; ULONG FreeCount=0; ULONG TotalUsed=0;
PHBIN FirstBin; PHBIN MaxBin; ULONG HiveLength;
#define OPTION_MODE 0
#define FILE_MODE 1
#define LEVEL_MODE 2
#define BIN_MODE 3
VOID ChkDumpLogFile( PHBASE_BLOCK BaseBlock,ULONG Length );
VOID ParseArgs ( int argc, char *argv[] ) {
char *p; int i; // specified what should we expect from the command line
int iMode = OPTION_MODE; for(i=0;i<argc;i++) { p = argv[i]; if ( *p == '/' || *p == '-' ) { // option mode
p++; iMode = OPTION_MODE; while ((*p != '\0') && (*p != ' ')) { switch (*p) { case 'h': case 'H': case '?': fprintf(stderr, "%s\n", Usage); ExitProcess(1); break; case 'f': case 'F': iMode = FILE_MODE; break; case 'd': case 'D': iMode = LEVEL_MODE; // when not specified, dump at least 100 levels
MaxLevel = 100; CheckHive = FALSE; break; case 's': case 'S': SpaceUsage = TRUE; iMode = BIN_MODE; break; case 'c': case 'C': p++; CompactHive = TRUE; break; case 'l': case 'L': p++; LostSpace = TRUE; break; case 'r': case 'R': p++; FixHive = TRUE; break; default: break; } if( iMode != OPTION_MODE ) { // break the loop; ignore the rest of the current argv
break; } } // while
} else { switch(iMode) { case FILE_MODE: Hive = argv[i]; break; case LEVEL_MODE: MaxLevel = (ULONG) atol(argv[i]); break; case BIN_MODE: BinIndex = (LONG) atol(argv[i]); break; default: break; } } } }
__cdecl main( int argc, char *argv[] ) { ULONG FileIndex; HANDLE myFileHandle, myMMFHandle; LPBYTE myMMFViewHandle; BYTE lowChar, hiChar, modVal; DWORD dwFileSize; ULONG Index,Index2;
PHBASE_BLOCK PHBaseBlock; PHBIN NewBins; ULONG Offset; ULONG CellCount; ULONG SizeCount;
REG_USAGE TotalUsage; DWORD dwHiveFileAccess = GENERIC_READ; DWORD flHiveViewProtect = PAGE_READONLY; DWORD dwHiveViewAccess = FILE_MAP_READ; ParseArgs( argc, argv );
if (!Hive) { fprintf(stderr, "\nMust provide a hive name !!!\n\n"); fprintf(stderr, "%s\n", Usage); ExitProcess(-1); }
if(LostSpace) { // are you sure you want lost cells detection? It may take a while!
int chLost; fprintf(stdout, "%s",LostSpaceWarning); fflush(stdin); chLost = getchar(); if( (chLost != 'y') && (chLost != 'Y') ) { // he changed his mind
LostSpace = FALSE; } fprintf(stderr, "\n"); }
if( FixHive ) { dwHiveFileAccess |= GENERIC_WRITE; flHiveViewProtect = PAGE_READWRITE; dwHiveViewAccess = FILE_MAP_WRITE; } /* Create temporary file for mapping. */ if ((myFileHandle = CreateFile (Hive, dwHiveFileAccess, 0 , NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) == (HANDLE) INVALID_HANDLE_VALUE) /* Bad handle */ { fprintf(stderr,"Could not create file %s\n", Hive); exit(-1); }
// Get the size of the file. I am assuming here that the
// file is smaller than 4 GB.
dwFileSize = GetFileSize(myFileHandle, NULL);
/* If we get here, we managed to name and create a temp file. Now we need
to create a mapping */
myMMFHandle = CreateFileMapping (myFileHandle, NULL, flHiveViewProtect, 0, dwFileSize, NULL); if (myMMFHandle == (HANDLE) INVALID_HANDLE_VALUE) { fprintf(stderr,"Could not map file %s\n", Hive); exit(-1); }
/* So we've mapped the file. Now try to map a view */
myMMFViewHandle = (LPBYTE) MapViewOfFile (myMMFHandle, dwHiveViewAccess, 0, 0, dwFileSize); if (!myMMFViewHandle) { fprintf(stderr,"Could not map view of file %s error = %lx\n", Hive,(ULONG)GetLastError()); exit(-1); }
/* Now we have a view. Read through it */
PHBaseBlock = (PHBASE_BLOCK) myMMFViewHandle;
if( strstr(Hive,".LOG") != NULL ) { // dumping log file
ChkDumpLogFile(PHBaseBlock,MaxLevel); } else { /*
if (PHBaseBlock->Minor < 4) { fprintf(stderr,"Hive version %d is too old, must be 3 or later\n", PHBaseBlock->Minor); ExitProcess(-1); } */ // Initialization stuff
for(Index =0;Index<FRAGMENTATION;Index++) { LostCells[Index].Count = 0; for(Index2 = 0;Index2<SUBLISTS;Index2++) { LostCells[Index].List[Index2] = NULL; } } RootCell = PHBaseBlock->RootCell; OutputFile = stdout; Base = (PUCHAR)(PHBaseBlock) + HBLOCK_SIZE;
Offset=HBLOCK_SIZE; HiveLength = PHBaseBlock->Length;
MaxBin= (PHBIN) (Base + HiveLength); FirstBin = (PHBIN) (Base);
KeyName.Buffer = NameBuffer; KeyName.MaximumLength = NAME_BUFFERSIZE;
ChkBaseBlock(PHBaseBlock,dwFileSize); ChkSecurityDescriptors();
ChkPhysicalHive();
if (MaxLevel) { fprintf(stdout,"%6s,%6s,%7s,%10s, %s\n", "Keys", "Values", "Cells", "Size", "SubKeys"); }
DumpChkRegistry(0, 0, PHBaseBlock->RootCell,HCELL_NIL,&TotalUsage);
if(LostSpace) { // clear the dirt on the screen
fprintf(OutputFile,"\r \n"); }
DumpUnknownList(); FreeUnknownList();
fprintf(OutputFile,"\nSUMMARY: \n"); fprintf(OutputFile,"%15s,%15s, %s\n", "Cells", "Size", "Category");
fprintf(OutputFile,"%15lu,%15lu, Keys\n", CountKeyNode, TotalKeyNode ); fprintf(OutputFile,"%15lu,%15lu, Values\n", CountKeyValue, TotalKeyValue ); fprintf(OutputFile,"%15lu,%15lu, Key Index\n", CountKeyIndex, TotalKeyIndex ); fprintf(OutputFile,"%15lu,%15lu, Value Index\n", CountValueIndex, TotalValueIndex ); fprintf(OutputFile,"%15lu,%15lu, Security\n", CountKeySecurity, TotalKeySecurity ); fprintf(OutputFile,"%15lu,%15lu, Data\n", CountUnknown - CountValueIndex, TotalUnknown - TotalValueIndex );
fprintf(OutputFile,"%15lu,%15lu, Free\n", FreeCount, TotalFree );
CellCount = CountKeyNode + CountKeyValue + CountKeyIndex + CountKeySecurity + CountUnknown + FreeCount;
SizeCount = TotalKeyNode + TotalKeyValue + TotalKeyIndex + TotalKeySecurity + TotalUnknown + TotalFree;
fprintf(OutputFile,"%15lu,%15lu, %s\n", CellCount, SizeCount, "Total Hive");
fprintf(OutputFile,"\n%15lu compacted keys (all related cells in the same view)\n",CountKeyNodeCompacted); } UnmapViewOfFile(myMMFViewHandle); CloseHandle(myMMFHandle); CloseHandle(myFileHandle);
if(CompactHive) { DoCompactHive(); }
return(0); }
|