Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

414 lines
11 KiB

  1. /*++
  2. Copyright (c) 1998 Microsoft Corporation
  3. Module Name:
  4. regmain.c
  5. Abstract:
  6. Main module. Data definitions.
  7. Author:
  8. Dragos C. Sambotin (dragoss) 30-Dec-1998
  9. Revision History:
  10. --*/
  11. #include "chkreg.h"
  12. // check the hive structure.
  13. BOOLEAN CheckHive = TRUE;
  14. // compact the hive.
  15. BOOLEAN CompactHive = FALSE;
  16. // check for lost space (marked as used but not reffered).
  17. BOOLEAN LostSpace = FALSE;
  18. // repair damaged hives.
  19. BOOLEAN FixHive = FALSE;
  20. // repair damaged hives.
  21. BOOLEAN SpaceUsage = FALSE;
  22. // maximum level to dump
  23. ULONG MaxLevel = 0;
  24. // bin to examine space display
  25. LONG BinIndex = -1;
  26. // the hive file name
  27. TCHAR *Hive = NULL;
  28. // the root of the hive
  29. HCELL_INDEX RootCell;
  30. // Usage string
  31. char *Usage="\
  32. Checks a hive file and perform repairs, compacts or displays a status report.\n\n\
  33. CHKREG /F <filename[.<LOG>]> [/H] [/D [<level>] [/S [<bin>]] [/C] [/L] [/R]\n\n\
  34. <filename> FileName of hive to be analyzed\n\
  35. /H This manual\n\
  36. /D [<level>] Dump subkeys up to level <level>. If level is not\n\
  37. specified, dumps the entire hive. No checks are done\n\
  38. when dumping.\n\
  39. /S [<bin>] Displays space usage for the bin <bin>. When bin is\n\
  40. not specified, displays usage for the entire hive.\n\
  41. /C Compacts the hive. Bad hives cannot be compacted.\n\
  42. The compacted hive will be written to <filename>.BAK\n\
  43. /L Lost space detection.\n\
  44. /R Repair the hive.\n\
  45. ";
  46. // Lost Space Warning
  47. char *LostSpaceWarning="\n\
  48. WARNING : Lost space detection may take a while. Are you sure you want this (y/n)?";
  49. // Starting address of the in-memory maped hive image
  50. PUCHAR Base;
  51. // LostCells list used for lost space detection
  52. UNKNOWN_LIST LostCells[FRAGMENTATION];
  53. // OutputFile : future changes may use it to write the results to a file rather than to stdout
  54. FILE *OutputFile;
  55. #define NAME_BUFFERSIZE 2000
  56. UNICODE_STRING KeyName;
  57. WCHAR NameBuffer[NAME_BUFFERSIZE];
  58. // Miscelaneous variables used fo data statistics
  59. ULONG TotalKeyNode=0;
  60. ULONG TotalKeyValue=0;
  61. ULONG TotalKeyIndex=0;
  62. ULONG TotalKeySecurity=0;
  63. ULONG TotalValueIndex=0;
  64. ULONG TotalUnknown=0;
  65. ULONG CountKeyNode=0;
  66. ULONG CountKeyValue=0;
  67. ULONG CountKeyIndex=0;
  68. ULONG CountKeySecurity=0;
  69. ULONG CountValueIndex=0;
  70. ULONG CountUnknown=0;
  71. ULONG CountKeyNodeCompacted=0;
  72. ULONG TotalFree=0;
  73. ULONG FreeCount=0;
  74. ULONG TotalUsed=0;
  75. PHBIN FirstBin;
  76. PHBIN MaxBin;
  77. ULONG HiveLength;
  78. #define OPTION_MODE 0
  79. #define FILE_MODE 1
  80. #define LEVEL_MODE 2
  81. #define BIN_MODE 3
  82. VOID
  83. ChkDumpLogFile( PHBASE_BLOCK BaseBlock,ULONG Length );
  84. VOID
  85. ParseArgs (
  86. int argc,
  87. char *argv[]
  88. )
  89. {
  90. char *p;
  91. int i;
  92. // specified what should we expect from the command line
  93. int iMode = OPTION_MODE;
  94. for(i=0;i<argc;i++) {
  95. p = argv[i];
  96. if ( *p == '/' || *p == '-' ) {
  97. // option mode
  98. p++;
  99. iMode = OPTION_MODE;
  100. while ((*p != '\0') && (*p != ' ')) {
  101. switch (*p) {
  102. case 'h':
  103. case 'H':
  104. case '?':
  105. fprintf(stderr, "%s\n", Usage);
  106. ExitProcess(1);
  107. break;
  108. case 'f':
  109. case 'F':
  110. iMode = FILE_MODE;
  111. break;
  112. case 'd':
  113. case 'D':
  114. iMode = LEVEL_MODE;
  115. // when not specified, dump at least 100 levels
  116. MaxLevel = 100;
  117. CheckHive = FALSE;
  118. break;
  119. case 's':
  120. case 'S':
  121. SpaceUsage = TRUE;
  122. iMode = BIN_MODE;
  123. break;
  124. case 'c':
  125. case 'C':
  126. p++;
  127. CompactHive = TRUE;
  128. break;
  129. case 'l':
  130. case 'L':
  131. p++;
  132. LostSpace = TRUE;
  133. break;
  134. case 'r':
  135. case 'R':
  136. p++;
  137. FixHive = TRUE;
  138. break;
  139. default:
  140. break;
  141. }
  142. if( iMode != OPTION_MODE ) {
  143. // break the loop; ignore the rest of the current argv
  144. break;
  145. }
  146. } // while
  147. } else {
  148. switch(iMode) {
  149. case FILE_MODE:
  150. Hive = argv[i];
  151. break;
  152. case LEVEL_MODE:
  153. MaxLevel = (ULONG) atol(argv[i]);
  154. break;
  155. case BIN_MODE:
  156. BinIndex = (LONG) atol(argv[i]);
  157. break;
  158. default:
  159. break;
  160. }
  161. }
  162. }
  163. }
  164. __cdecl
  165. main(
  166. int argc,
  167. char *argv[]
  168. )
  169. {
  170. ULONG FileIndex;
  171. HANDLE myFileHandle, myMMFHandle;
  172. LPBYTE myMMFViewHandle;
  173. BYTE lowChar, hiChar, modVal;
  174. DWORD dwFileSize;
  175. ULONG Index,Index2;
  176. PHBASE_BLOCK PHBaseBlock;
  177. PHBIN NewBins;
  178. ULONG Offset;
  179. ULONG CellCount;
  180. ULONG SizeCount;
  181. REG_USAGE TotalUsage;
  182. DWORD dwHiveFileAccess = GENERIC_READ;
  183. DWORD flHiveViewProtect = PAGE_READONLY;
  184. DWORD dwHiveViewAccess = FILE_MAP_READ;
  185. ParseArgs( argc, argv );
  186. if (!Hive) {
  187. fprintf(stderr, "\nMust provide a hive name !!!\n\n");
  188. fprintf(stderr, "%s\n", Usage);
  189. ExitProcess(-1);
  190. }
  191. if(LostSpace) {
  192. // are you sure you want lost cells detection? It may take a while!
  193. int chLost;
  194. fprintf(stdout, "%s",LostSpaceWarning);
  195. fflush(stdin);
  196. chLost = getchar();
  197. if( (chLost != 'y') && (chLost != 'Y') ) {
  198. // he changed his mind
  199. LostSpace = FALSE;
  200. }
  201. fprintf(stderr, "\n");
  202. }
  203. if( FixHive ) {
  204. dwHiveFileAccess |= GENERIC_WRITE;
  205. flHiveViewProtect = PAGE_READWRITE;
  206. dwHiveViewAccess = FILE_MAP_WRITE;
  207. }
  208. /* Create temporary file for mapping. */
  209. if ((myFileHandle = CreateFile (Hive, dwHiveFileAccess,
  210. 0 , NULL, OPEN_EXISTING,
  211. FILE_ATTRIBUTE_NORMAL,
  212. NULL))
  213. == (HANDLE) INVALID_HANDLE_VALUE) /* Bad handle */ {
  214. fprintf(stderr,"Could not create file %s\n", Hive);
  215. exit(-1);
  216. }
  217. // Get the size of the file. I am assuming here that the
  218. // file is smaller than 4 GB.
  219. dwFileSize = GetFileSize(myFileHandle, NULL);
  220. /* If we get here, we managed to name and create a temp file. Now we need
  221. to create a mapping */
  222. myMMFHandle = CreateFileMapping (myFileHandle, NULL, flHiveViewProtect,
  223. 0, dwFileSize, NULL);
  224. if (myMMFHandle == (HANDLE) INVALID_HANDLE_VALUE) {
  225. fprintf(stderr,"Could not map file %s\n", Hive);
  226. exit(-1);
  227. }
  228. /* So we've mapped the file. Now try to map a view */
  229. myMMFViewHandle = (LPBYTE) MapViewOfFile (myMMFHandle, dwHiveViewAccess, 0, 0, dwFileSize);
  230. if (!myMMFViewHandle) {
  231. fprintf(stderr,"Could not map view of file %s error = %lx\n", Hive,(ULONG)GetLastError());
  232. exit(-1);
  233. }
  234. /* Now we have a view. Read through it */
  235. PHBaseBlock = (PHBASE_BLOCK) myMMFViewHandle;
  236. if( strstr(Hive,".LOG") != NULL ) {
  237. // dumping log file
  238. ChkDumpLogFile(PHBaseBlock,MaxLevel);
  239. } else {
  240. /*
  241. if (PHBaseBlock->Minor < 4) {
  242. fprintf(stderr,"Hive version %d is too old, must be 3 or later\n", PHBaseBlock->Minor);
  243. ExitProcess(-1);
  244. }
  245. */
  246. // Initialization stuff
  247. for(Index =0;Index<FRAGMENTATION;Index++) {
  248. LostCells[Index].Count = 0;
  249. for(Index2 = 0;Index2<SUBLISTS;Index2++) {
  250. LostCells[Index].List[Index2] = NULL;
  251. }
  252. }
  253. RootCell = PHBaseBlock->RootCell;
  254. OutputFile = stdout;
  255. Base = (PUCHAR)(PHBaseBlock) + HBLOCK_SIZE;
  256. Offset=HBLOCK_SIZE;
  257. HiveLength = PHBaseBlock->Length;
  258. MaxBin= (PHBIN) (Base + HiveLength);
  259. FirstBin = (PHBIN) (Base);
  260. KeyName.Buffer = NameBuffer;
  261. KeyName.MaximumLength = NAME_BUFFERSIZE;
  262. ChkBaseBlock(PHBaseBlock,dwFileSize);
  263. ChkSecurityDescriptors();
  264. ChkPhysicalHive();
  265. if (MaxLevel) {
  266. fprintf(stdout,"%6s,%6s,%7s,%10s, %s\n",
  267. "Keys",
  268. "Values",
  269. "Cells",
  270. "Size",
  271. "SubKeys");
  272. }
  273. DumpChkRegistry(0, 0, PHBaseBlock->RootCell,HCELL_NIL,&TotalUsage);
  274. if(LostSpace) {
  275. // clear the dirt on the screen
  276. fprintf(OutputFile,"\r \n");
  277. }
  278. DumpUnknownList();
  279. FreeUnknownList();
  280. fprintf(OutputFile,"\nSUMMARY: \n");
  281. fprintf(OutputFile,"%15s,%15s, %s\n",
  282. "Cells",
  283. "Size",
  284. "Category");
  285. fprintf(OutputFile,"%15lu,%15lu, Keys\n",
  286. CountKeyNode,
  287. TotalKeyNode
  288. );
  289. fprintf(OutputFile,"%15lu,%15lu, Values\n",
  290. CountKeyValue,
  291. TotalKeyValue
  292. );
  293. fprintf(OutputFile,"%15lu,%15lu, Key Index\n",
  294. CountKeyIndex,
  295. TotalKeyIndex
  296. );
  297. fprintf(OutputFile,"%15lu,%15lu, Value Index\n",
  298. CountValueIndex,
  299. TotalValueIndex
  300. );
  301. fprintf(OutputFile,"%15lu,%15lu, Security\n",
  302. CountKeySecurity,
  303. TotalKeySecurity
  304. );
  305. fprintf(OutputFile,"%15lu,%15lu, Data\n",
  306. CountUnknown - CountValueIndex,
  307. TotalUnknown - TotalValueIndex
  308. );
  309. fprintf(OutputFile,"%15lu,%15lu, Free\n",
  310. FreeCount,
  311. TotalFree
  312. );
  313. CellCount = CountKeyNode +
  314. CountKeyValue +
  315. CountKeyIndex +
  316. CountKeySecurity +
  317. CountUnknown +
  318. FreeCount;
  319. SizeCount = TotalKeyNode +
  320. TotalKeyValue +
  321. TotalKeyIndex +
  322. TotalKeySecurity +
  323. TotalUnknown +
  324. TotalFree;
  325. fprintf(OutputFile,"%15lu,%15lu, %s\n",
  326. CellCount,
  327. SizeCount,
  328. "Total Hive");
  329. fprintf(OutputFile,"\n%15lu compacted keys (all related cells in the same view)\n",CountKeyNodeCompacted);
  330. }
  331. UnmapViewOfFile(myMMFViewHandle);
  332. CloseHandle(myMMFHandle);
  333. CloseHandle(myFileHandle);
  334. if(CompactHive) {
  335. DoCompactHive();
  336. }
  337. return(0);
  338. }