/*++ 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; // Verbose control. BOOLEAN VerboseMode = 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; // size of the file DWORD FileSize; // Usage string char *Usage="\ Checks a hive file and perform repairs, compacts or displays a status report.\n\n\ CHKREG /F ]> [/H] [/D [] [/S []] [/C] [/L] [/R] [/V]\n\n\ FileName of hive to be analyzed\n\ /H This manual\n\ /D [] Dump subkeys up to level . If level is not\n\ specified, dumps the entire hive. No checks are done\n\ when dumping.\n\ /S [] Displays space usage for the 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 .BAK\n\ /L Lost space detection.\n\ /R Repair the hive.\n\ /V Verbose Mode.\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= 0 ) { MaxLevel = (ULONG)atol(argv[i]); } break; case BIN_MODE: BinIndex = (LONG) atol(argv[i]); if( BinIndex < -1 ) { BinIndex = 1; } break; default: break; } } } } __cdecl main( int argc, char *argv[] ) { ULONG FileIndex; HANDLE myFileHandle, myMMFHandle; LPBYTE myMMFViewHandle; BYTE lowChar, hiChar, modVal; 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. FileSize = 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, FileSize, 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, FileSize); 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;IndexRootCell; OutputFile = stdout; Base = (PUCHAR)(PHBaseBlock) + HBLOCK_SIZE; Offset=HBLOCK_SIZE; HiveLength = PHBaseBlock->Length; if( HiveLength > (FileSize - HBLOCK_SIZE) ) { HiveLength = (FileSize - HBLOCK_SIZE); } MaxBin= (PHBIN) (Base + HiveLength); FirstBin = (PHBIN) (Base); KeyName.Buffer = NameBuffer; KeyName.MaximumLength = NAME_BUFFERSIZE; ChkBaseBlock(PHBaseBlock,FileSize); 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"); { double RateTotal = CountKeyNodeCompacted; RateTotal *= 100.00; RateTotal /= (double)CountKeyNode; fprintf(OutputFile,"\n%15lu (%.2f%%) compacted keys (all related cells in the same view)\n",CountKeyNodeCompacted,(float)RateTotal); } } UnmapViewOfFile(myMMFViewHandle); CloseHandle(myMMFHandle); CloseHandle(myFileHandle); if(CompactHive) { DoCompactHive(); } return(0); }