Leaked source code of windows server 2003
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.

948 lines
30 KiB

  1. /*++
  2. Copyright (c) 1998 Microsoft Corporation
  3. Module Name:
  4. regbin.c
  5. Abstract:
  6. This module contains functions to check bin header and bin body consistency.
  7. Author:
  8. Dragos C. Sambotin (dragoss) 30-Dec-1998
  9. Revision History:
  10. --*/
  11. #include "chkreg.h"
  12. extern ULONG TotalKeyNode;
  13. extern ULONG TotalKeyValue;
  14. extern ULONG TotalKeyIndex;
  15. extern ULONG TotalKeySecurity;
  16. extern ULONG TotalValueIndex;
  17. extern ULONG TotalUnknown;
  18. extern ULONG CountKeyNode;
  19. extern ULONG CountKeyValue;
  20. extern ULONG CountKeyIndex;
  21. extern ULONG CountKeySecurity;
  22. extern ULONG CountValueIndex;
  23. extern ULONG CountUnknown;
  24. extern ULONG TotalFree;
  25. extern ULONG FreeCount;
  26. extern ULONG TotalUsed;
  27. extern PUCHAR Base;
  28. extern FILE *OutputFile;
  29. extern HCELL_INDEX RootCell;
  30. extern PHBIN FirstBin;
  31. extern PHBIN MaxBin;
  32. extern ULONG HiveLength;
  33. extern LONG BinIndex;
  34. extern BOOLEAN FixHive;
  35. extern BOOLEAN SpaceUsage;
  36. extern BOOLEAN CompactHive;
  37. extern BOOLEAN VerboseMode;
  38. ULONG BinFreeDisplaySize[HHIVE_FREE_DISPLAY_SIZE];
  39. ULONG BinFreeDisplayCount[HHIVE_FREE_DISPLAY_SIZE];
  40. ULONG FreeDisplaySize[HHIVE_FREE_DISPLAY_SIZE];
  41. ULONG FreeDisplayCount[HHIVE_FREE_DISPLAY_SIZE];
  42. ULONG BinUsedDisplaySize[HHIVE_FREE_DISPLAY_SIZE];
  43. ULONG BinUsedDisplayCount[HHIVE_FREE_DISPLAY_SIZE];
  44. ULONG UsedDisplaySize[HHIVE_FREE_DISPLAY_SIZE];
  45. ULONG UsedDisplayCount[HHIVE_FREE_DISPLAY_SIZE];
  46. BOOLEAN ChkAllocatedCell(HCELL_INDEX Cell);
  47. CCHAR ChkRegFindFirstSetLeft[256] = {
  48. 0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
  49. 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
  50. 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
  51. 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
  52. 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
  53. 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
  54. 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
  55. 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
  56. 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
  57. 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
  58. 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
  59. 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
  60. 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
  61. 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
  62. 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
  63. 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7};
  64. #define ComputeFreeIndex(Index, Size) \
  65. { \
  66. Index = (Size >> HHIVE_FREE_DISPLAY_SHIFT) - 1; \
  67. if (Index >= HHIVE_LINEAR_INDEX ) { \
  68. \
  69. /* \
  70. ** Too big for the linear lists, compute the exponential \
  71. ** list. \
  72. */ \
  73. \
  74. if (Index > 255) { \
  75. /* \
  76. ** Too big for all the lists, use the last index. \
  77. */ \
  78. Index = HHIVE_FREE_DISPLAY_SIZE-1; \
  79. } else { \
  80. Index = ChkRegFindFirstSetLeft[Index] + \
  81. HHIVE_FREE_DISPLAY_BIAS; \
  82. } \
  83. } \
  84. }
  85. BOOLEAN
  86. ChkBinHeader(PHBIN Bin,
  87. ULONG FileOffset,
  88. ULONG Index
  89. )
  90. /*++
  91. Routine Description:
  92. Checks the validity of the Bin header.
  93. The following tests are done:
  94. 1. the Size should not be bigger than the remaining of the file
  95. 2. the Size should not be smaller than HBLOCK_SIZE
  96. 3. the signature should be valid (HBIN_SIGNATURE)
  97. 4. the file offset should match the actual position in the hive file.
  98. Arguments:
  99. Bin - supplies a pointer to the bin to be checked.
  100. FileOffset - provides the actual pposition within the file
  101. Index - the index of the bin within the bin list of the hive
  102. Return Value:
  103. FALSE - the bin header is corrupted and was not fixed. Either this is a
  104. critical corruption, or the /R argument was not present in the
  105. command line.
  106. TRUE - The bin header is OK, or it was successfully recovered.
  107. --*/
  108. {
  109. BOOLEAN bRez = TRUE;
  110. PHCELL p;
  111. p = (PHCELL)((PUCHAR)Bin + sizeof(HBIN));
  112. if(Bin->Size > (HiveLength - FileOffset)) {
  113. bRez = FALSE;
  114. fprintf(stderr, "Size too big (%lu) in Bin header of Bin (%lu)\n",Bin->Size,Index);
  115. if(FixHive) {
  116. //
  117. // REPAIR: set the actual size to HiveLength-FileOffset
  118. //
  119. Bin->Size = HiveLength-FileOffset;
  120. p->Size = Bin->Size -sizeof(HBIN);
  121. bRez = TRUE;
  122. } else {
  123. if(CompactHive) {
  124. // any attempt to compact a corrupted hive will fail
  125. CompactHive = FALSE;
  126. fprintf(stderr, "Run chkreg /R to fix.\n");
  127. }
  128. }
  129. }
  130. if((Bin->Size < HBLOCK_SIZE) || ((Bin->Size % HBLOCK_SIZE) != 0) || (!Bin->Size) ) {
  131. bRez = FALSE;
  132. fprintf(stderr, "Size too small (%lu) in Bin header of Bin (%lu)\n",Bin->Size,Index);
  133. if(FixHive) {
  134. //
  135. // REPAIR: set the actual size to minimmum possible size HBLOCK_SIZE
  136. //
  137. Bin->Size = HBLOCK_SIZE;
  138. p->Size = Bin->Size -sizeof(HBIN);
  139. bRez = TRUE;
  140. } else {
  141. if(CompactHive) {
  142. // any attempt to compact a corrupted hive will fail
  143. CompactHive = FALSE;
  144. fprintf(stderr, "Run chkreg /R to fix.\n");
  145. }
  146. }
  147. }
  148. if(Bin->Signature != HBIN_SIGNATURE) {
  149. bRez = FALSE;
  150. fprintf(stderr, "Invalid signature (%lx) in Bin header of Bin (%lu)\n",Bin->Signature,Index);
  151. if(FixHive) {
  152. //
  153. // REPAIR: reset the bin signature
  154. //
  155. Bin->Signature = HBIN_SIGNATURE;
  156. Bin->Spare = 0;
  157. bRez = TRUE;
  158. } else {
  159. if(CompactHive) {
  160. // any attempt to compact a corrupted hive will fail
  161. CompactHive = FALSE;
  162. fprintf(stderr, "Run chkreg /R to fix.\n");
  163. }
  164. }
  165. }
  166. if(Bin->FileOffset != FileOffset) {
  167. bRez = FALSE;
  168. fprintf(stderr, "Actual FileOffset [%lx] and Bin FileOffset [%lx] do not match in Bin (%lu); Size = (%lx)\n",FileOffset,Bin->FileOffset,Index,Bin->Size);
  169. if(FixHive) {
  170. //
  171. // REPAIR: reset the bin FileOffset
  172. //
  173. Bin->FileOffset = FileOffset;
  174. bRez = TRUE;
  175. } else {
  176. if(CompactHive) {
  177. // any attempt to compact a corrupted hive will fail
  178. CompactHive = FALSE;
  179. fprintf(stderr, "Run chkreg /R to fix.\n");
  180. }
  181. }
  182. }
  183. return bRez;
  184. }
  185. BOOLEAN
  186. ChkBin(
  187. PHBIN Bin,
  188. ULONG IndexBin,
  189. ULONG Starting,
  190. double *Rate
  191. )
  192. /*++
  193. Routine Description:
  194. Steps through all of the cells in the bin. Make sure that
  195. they are consistent with each other, and with the bin header.
  196. Compute the usage rate for the current bin.
  197. Add all used cells to the unknown list (candidates to lost cells).
  198. Compute the used space and allocated cells by cell signature.
  199. Compute the free space size and number of cells.
  200. Test the cell size for reasonable limits. A cell should be smaller
  201. than the containing bin and should not exceed the bin boundaries.
  202. A cell should fit in only one contiguos bin!!!
  203. Arguments:
  204. Bin - supplies a pointer to the bin to be checked.
  205. Index - the index of the bin within the bin list of the hive
  206. Starting - starting address of the in-memory hive representation.
  207. Rate - usage rate for this bin
  208. Return Value:
  209. FALSE - the bin is corrupted and was not fixed. Either this is a
  210. critical corruption, or the /R argument was not present in the
  211. command line.
  212. TRUE - The bin is OK, or it was successfully recovered.
  213. --*/
  214. {
  215. ULONG freespace = 0L;
  216. ULONG allocated = 0L;
  217. BOOLEAN bRez = TRUE;
  218. HCELL_INDEX cellindex;
  219. PHCELL p;
  220. ULONG Size;
  221. ULONG Index;
  222. double TmpRate;
  223. p = (PHCELL)((PUCHAR)Bin + sizeof(HBIN));
  224. while (p < (PHCELL)((PUCHAR)Bin + Bin->Size)) {
  225. cellindex = (HCELL_INDEX)((PUCHAR)p - Base);
  226. if (p->Size >= 0) {
  227. //
  228. // It is a free cell.
  229. //
  230. Size = (ULONG)p->Size;
  231. if ( (Size > Bin->Size) ||
  232. ( (PHCELL)(Size + (PUCHAR)p) >
  233. (PHCELL)((PUCHAR)Bin + Bin->Size) ) ||
  234. (!p->Size)
  235. ) {
  236. bRez = FALSE;
  237. fprintf(stderr, "Impossible cell size in free cell (%lu) in Bin header of Bin (%lu)\n",Size,IndexBin);
  238. if(FixHive) {
  239. //
  240. // REPAIR: set the cell size to the largest possible hereon (ie. Bin + Bin->Size - p ); reset the Size too!!!
  241. //
  242. bRez = TRUE;
  243. p->Size = (LONG)((PUCHAR)((PUCHAR)Bin + Bin->Size) - (PUCHAR)p);
  244. RtlZeroMemory((PUCHAR)p + sizeof(ULONG),p->Size - sizeof(ULONG));
  245. } else {
  246. if(CompactHive) {
  247. // any attempt to compact a corrupted hive will fail
  248. CompactHive = FALSE;
  249. fprintf(stderr, "Run chkreg /R to fix.\n");
  250. }
  251. return FALSE;
  252. }
  253. }
  254. freespace += Size;
  255. TotalFree += Size;
  256. FreeCount++;
  257. if( SpaceUsage ) {
  258. // only if we are interested in the usage map
  259. // store the length of this free cell
  260. ComputeFreeIndex(Index, Size);
  261. BinFreeDisplaySize[Index] += Size;
  262. // and increment the count of free cells of this particular size
  263. BinFreeDisplayCount[Index]++;
  264. }
  265. }else{
  266. //
  267. // It is used cell. Check for signature
  268. //
  269. UCHAR *C;
  270. USHORT Sig;
  271. int i,j;
  272. // All used cells are leak candidates
  273. AddCellToUnknownList(cellindex);
  274. Size = (ULONG)(p->Size * -1);
  275. if ( (Size > Bin->Size) ||
  276. ( (PHCELL)(Size + (PUCHAR)p) >
  277. (PHCELL)((PUCHAR)Bin + Bin->Size) )
  278. ) {
  279. bRez = FALSE;
  280. fprintf(stderr, "Impossible cell size in allocated cell (%lu) in Bin header of Bin (%lu)\n",Size,IndexBin);
  281. if(FixHive) {
  282. //
  283. // REPAIR: set the cell size to the largest possible hereon (ie. Bin + Bin->Size - p ); reset the Size too!!!
  284. //
  285. bRez = TRUE;
  286. p->Size = (LONG)((PUCHAR)Bin + Bin->Size - (PUCHAR)p);
  287. // it's a used cell, remember ?
  288. p->Size *= -1;
  289. } else {
  290. if(CompactHive) {
  291. // any attempt to compact a corrupted hive will fail
  292. CompactHive = FALSE;
  293. fprintf(stderr, "Run chkreg /R to fix.\n");
  294. }
  295. }
  296. }
  297. allocated += Size;
  298. if( SpaceUsage ) {
  299. // only if we are interested in the usage map
  300. // store the length of this used cell
  301. ComputeFreeIndex(Index, Size);
  302. BinUsedDisplaySize[Index] += Size;
  303. // and increment the count of used cells of this particular size
  304. BinUsedDisplayCount[Index]++;
  305. }
  306. TotalUsed=TotalUsed+Size;
  307. C= (UCHAR *) &(p->u.NewCell.u.UserData);
  308. Sig=(USHORT) p->u.NewCell.u.UserData;
  309. switch(Sig){
  310. case CM_LINK_NODE_SIGNATURE:
  311. printf("Link Node !\n");
  312. TotalKeyNode=TotalKeyNode+Size;
  313. CountKeyNode++;
  314. break;
  315. case CM_KEY_NODE_SIGNATURE:
  316. {
  317. PCM_KEY_NODE Pcan;
  318. TotalKeyNode=TotalKeyNode+Size;
  319. CountKeyNode++;
  320. Pcan = (PCM_KEY_NODE)C;
  321. if((Pcan->ValueList.Count) && IsCellAllocated( Pcan->ValueList.List)){
  322. PHCELL TmpP;
  323. TmpP = (PHCELL) (Starting + Pcan->ValueList.List);
  324. TotalValueIndex=TotalValueIndex - TmpP->Size;
  325. CountValueIndex++;
  326. }
  327. }
  328. break;
  329. case CM_KEY_VALUE_SIGNATURE:
  330. TotalKeyValue=TotalKeyValue+Size;
  331. CountKeyValue++;
  332. break;
  333. case CM_KEY_FAST_LEAF:
  334. case CM_KEY_HASH_LEAF:
  335. case CM_KEY_INDEX_LEAF:
  336. case CM_KEY_INDEX_ROOT:
  337. TotalKeyIndex=TotalKeyIndex+Size;
  338. CountKeyIndex++;
  339. break;
  340. case CM_KEY_SECURITY_SIGNATURE:
  341. TotalKeySecurity=TotalKeySecurity+Size;
  342. CountKeySecurity++;
  343. break;
  344. default:
  345. //
  346. // No signature, it can be data or index cells.
  347. // Or there must be some registry leak here.
  348. //
  349. TotalUnknown=TotalUnknown+Size;
  350. CountUnknown++;
  351. break;
  352. }
  353. }
  354. p = (PHCELL)((PUCHAR)p + Size);
  355. }
  356. *Rate = TmpRate = (double)(((double)allocated)/((double)(allocated+freespace)));
  357. TmpRate *= 100.00;
  358. fprintf(OutputFile,"Bin [%5lu], usage %.2f%%\r",IndexBin,(float)TmpRate);
  359. return bRez;
  360. }
  361. BOOLEAN ChkPhysicalHive()
  362. /*++
  363. Routine Description:
  364. Checks the integrity of the hive by stepping through all of the cells
  365. in the hive. Collects and displays statistics, according to the command
  366. line parameters.
  367. Arguments:
  368. None.
  369. Return Value:
  370. FALSE - the hive is corrupted and was not fixed. Either this is a
  371. critical corruption, or the /R argument was not present in the
  372. command line.
  373. TRUE - The hive is OK, or it was successfully recovered.
  374. --*/
  375. {
  376. ULONG Starting;
  377. PHBIN Bin = FirstBin;
  378. LONG Index;
  379. ULONG FileOffset;
  380. double Rate,RateTotal = 0.0;
  381. BOOLEAN bRez = TRUE;
  382. int i;
  383. Starting=(ULONG) Bin;
  384. Index=0;
  385. FileOffset = 0;
  386. for(i=0;i<HHIVE_FREE_DISPLAY_SIZE;i++) {
  387. FreeDisplaySize[i] = 0;
  388. FreeDisplayCount[i] = 0;
  389. UsedDisplaySize[i] = 0;
  390. UsedDisplayCount[i] = 0;
  391. }
  392. while(Bin < MaxBin){
  393. if( SpaceUsage ) {
  394. // only if we are interested in the usage map
  395. for(i=0;i<HHIVE_FREE_DISPLAY_SIZE;i++) {
  396. BinFreeDisplaySize[i] = 0;
  397. BinFreeDisplayCount[i] = 0;
  398. BinUsedDisplaySize[i] = 0;
  399. BinUsedDisplayCount[i] = 0;
  400. }
  401. }
  402. bRez = (bRez && ChkBinHeader(Bin,FileOffset,Index));
  403. bRez = (bRez && ChkBin(Bin,Index,Starting,&Rate));
  404. RateTotal += Rate;
  405. if( SpaceUsage ) {
  406. // only if we are interested in the usage map
  407. if( BinIndex == Index ) {
  408. // summary wanted for this particular bin
  409. fprintf(OutputFile,"\nBin[%5lu] Display Map: Free Cells, Free Size\t Used Cells, Used Size\n",(ULONG)Index);
  410. for(i=0;i<HHIVE_FREE_DISPLAY_SIZE;i++) {
  411. fprintf(OutputFile,"Display[%2d] : %8lu , %8lu \t %8lu , %8lu \n",i,BinFreeDisplayCount[i],BinFreeDisplaySize[i],BinUsedDisplayCount[i],BinUsedDisplaySize[i]);
  412. }
  413. }
  414. for(i=0;i<HHIVE_FREE_DISPLAY_SIZE;i++) {
  415. FreeDisplaySize[i] += BinFreeDisplaySize[i];
  416. FreeDisplayCount[i] += BinFreeDisplayCount[i];
  417. UsedDisplaySize[i] += BinUsedDisplaySize[i];
  418. UsedDisplayCount[i] += BinUsedDisplayCount[i];
  419. }
  420. }
  421. if( Bin<MaxBin) {
  422. FileOffset += Bin->Size;
  423. }
  424. if( !bRez ) break;
  425. Bin = (PHBIN)((ULONG)Bin + Bin->Size);
  426. Index++;
  427. }
  428. RateTotal *= 100.00;
  429. RateTotal /= (double)Index;
  430. fprintf(OutputFile,"Number of Bins in hive: %lu \n",Index);
  431. fprintf(OutputFile,"Total Hive space usage: %.2f%% \n",(float)RateTotal);
  432. if( SpaceUsage ) {
  433. // only if we are interested in the usage map
  434. if( BinIndex == -1 ) {
  435. // space usage display per entire hive
  436. fprintf(OutputFile,"\nHive Display Map: Free Cells, Free Size\t\t Used Cells, Used Size\n");
  437. for(i=0;i<HHIVE_FREE_DISPLAY_SIZE;i++) {
  438. fprintf(OutputFile,"Display[%2d] : %8lu , %8lu \t %8lu , %8lu \n",i,FreeDisplayCount[i],FreeDisplaySize[i],UsedDisplayCount[i],UsedDisplaySize[i]);
  439. }
  440. }
  441. }
  442. return bRez;
  443. }
  444. ULONG
  445. ComputeHeaderCheckSum(
  446. PHBASE_BLOCK BaseBlock
  447. )
  448. /*++
  449. Routine Description:
  450. Compute the checksum for a hive disk header.
  451. Arguments:
  452. BaseBlock - supplies pointer to the header to checksum
  453. Return Value:
  454. the check sum.
  455. --*/
  456. {
  457. ULONG sum;
  458. ULONG i;
  459. sum = 0;
  460. for (i = 0; i < 127; i++) {
  461. sum ^= ((PULONG)BaseBlock)[i];
  462. }
  463. if (sum == (ULONG)-1) {
  464. sum = (ULONG)-2;
  465. }
  466. if (sum == 0) {
  467. sum = 1;
  468. }
  469. return sum;
  470. }
  471. BOOLEAN
  472. ChkBaseBlock(PHBASE_BLOCK BaseBlock,
  473. DWORD dwFileSize)
  474. /*++
  475. Routine Description:
  476. Checks the integrity of the base block of a hive.
  477. Eventually makes the following corrections:
  478. 1. enforce Sequence1 == Sequence2
  479. 2. recalculate the header checksum
  480. Arguments:
  481. BaseBlock - the BaseBlock in-memory mapped image.
  482. dwFileSize - the actual size of the hive file
  483. Return Value:
  484. FALSE - the BaseBlock is corrupted and was not fixed. Either this is a
  485. critical corruption, or the /R argument was not present in the
  486. command line.
  487. TRUE - The BaseBlock is OK, or it was successfully recovered.
  488. --*/
  489. {
  490. BOOLEAN bRez = TRUE;
  491. ULONG CheckSum;
  492. if(BaseBlock->Signature != HBASE_BLOCK_SIGNATURE) {
  493. fprintf(stderr, "Fatal: Invalid Base Block signature (0x%lx)",BaseBlock->Signature);
  494. bRez = FALSE;
  495. if(FixHive) {
  496. //
  497. // REPAIR: reset the signature
  498. //
  499. fprintf(stderr, " ... unable to fix");
  500. } else {
  501. if(CompactHive) {
  502. // any attempt to compact a corrupted hive will fail
  503. CompactHive = FALSE;
  504. }
  505. }
  506. fprintf(stderr, "\n");
  507. }
  508. if(BaseBlock->Major != HSYS_MAJOR) {
  509. bRez = FALSE;
  510. fprintf(stderr, "Fatal: Invalid hive file Major version (%lu)",BaseBlock->Major);
  511. if(FixHive) {
  512. //
  513. // Fatal: unable to fix this
  514. //
  515. fprintf(stderr, " ... unable to fix");
  516. } else {
  517. if(CompactHive) {
  518. // any attempt to compact a corrupted hive will fail
  519. CompactHive = FALSE;
  520. }
  521. }
  522. fprintf(stderr, "\n");
  523. }
  524. if(BaseBlock->Minor > HSYS_MINOR_SUPPORTED) {
  525. bRez = FALSE;
  526. fprintf(stderr, "Fatal: Invalid hive file Minor version (%lu)",BaseBlock->Minor);
  527. if(FixHive) {
  528. //
  529. // Fatal: unable to fix this
  530. //
  531. fprintf(stderr, " ... unable to fix");
  532. } else {
  533. if(CompactHive) {
  534. // any attempt to compact a corrupted hive will fail
  535. CompactHive = FALSE;
  536. }
  537. }
  538. fprintf(stderr, "\n");
  539. }
  540. if(BaseBlock->Format != HBASE_FORMAT_MEMORY) {
  541. bRez = FALSE;
  542. fprintf(stderr, "Fatal: Invalid hive memory format (%lu)",BaseBlock->Format);
  543. if(FixHive) {
  544. //
  545. // Fatal: unable to fix this
  546. //
  547. fprintf(stderr, " ... unable to fix");
  548. } else {
  549. if(CompactHive) {
  550. // any attempt to compact a corrupted hive will fail
  551. CompactHive = FALSE;
  552. }
  553. }
  554. fprintf(stderr, "\n");
  555. }
  556. if((BaseBlock->Length + HBLOCK_SIZE) > dwFileSize) {
  557. fprintf(stderr, "Fatal: Invalid Hive file Length (%lu)",BaseBlock->Length);
  558. bRez = FALSE;
  559. if(FixHive) {
  560. //
  561. // REPAIR: unable to fix this
  562. //
  563. BaseBlock->Length = (dwFileSize/HBLOCK_SIZE)*HBLOCK_SIZE - HBLOCK_SIZE;
  564. bRez = TRUE;
  565. fprintf(stderr, " ... fixed");
  566. } else {
  567. if(CompactHive) {
  568. // any attempt to compact a corrupted hive will fail
  569. CompactHive = FALSE;
  570. }
  571. }
  572. fprintf(stderr, "\n");
  573. }
  574. if(!bRez) {
  575. //
  576. // Fatal Base Block corruption; no point to continue.
  577. //
  578. return bRez;
  579. }
  580. if(BaseBlock->Sequence1 != BaseBlock->Sequence2) {
  581. fprintf(stderr, "Sequence numbers do not match (%lu,%lu)",BaseBlock->Sequence1,BaseBlock->Sequence2);
  582. bRez = FALSE;
  583. if(FixHive) {
  584. //
  585. // REPAIR: enforce Sequence2 to Sequence1
  586. //
  587. bRez = TRUE;
  588. BaseBlock->Sequence2 = BaseBlock->Sequence1;
  589. fprintf(stderr, " ... fixed");
  590. } else {
  591. if(CompactHive) {
  592. // any attempt to compact a corrupted hive will fail
  593. CompactHive = FALSE;
  594. fprintf(stderr, "\nRun chkreg /R to fix.");
  595. }
  596. }
  597. fprintf(stderr, "\n");
  598. }
  599. CheckSum = ComputeHeaderCheckSum(BaseBlock);
  600. if(BaseBlock->CheckSum != CheckSum) {
  601. fprintf(stderr, "Invalid Base Block CheckSum (0x%lx)",BaseBlock->CheckSum);
  602. bRez = FALSE;
  603. if(FixHive) {
  604. //
  605. // REPAIR: reset the signature
  606. //
  607. bRez = TRUE;
  608. BaseBlock->CheckSum = CheckSum;
  609. fprintf(stderr, " ... fixed");
  610. } else {
  611. if(CompactHive) {
  612. // any attempt to compact a corrupted hive will fail
  613. CompactHive = FALSE;
  614. fprintf(stderr, "\nRun chkreg /R to fix.");
  615. }
  616. }
  617. fprintf(stderr, "\n");
  618. }
  619. return bRez;
  620. }
  621. BOOLEAN
  622. ChkSecurityDescriptors( )
  623. /*++
  624. Routine Description:
  625. Walks the list of security descriptors present in the hive and passes
  626. each security descriptor to RtlValidSecurityDescriptor.
  627. Also checks the validity of the FLink <==> BLink relationship between cells.
  628. Arguments:
  629. Return Value:
  630. TRUE - All security descriptors are valid
  631. FALSE - At least one security descriptor is invalid, and/or cannot be fixed
  632. --*/
  633. {
  634. PCM_KEY_NODE RootNode;
  635. PCM_KEY_SECURITY SecurityCell;
  636. HCELL_INDEX ListAnchor;
  637. HCELL_INDEX NextCell;
  638. HCELL_INDEX LastCell;
  639. BOOLEAN bRez = TRUE;
  640. // check/fix the root cell (is allocated?)
  641. if( !ChkAllocatedCell(RootCell) ) {
  642. return FALSE;
  643. }
  644. RootNode = (PCM_KEY_NODE) GetCell(RootCell);
  645. ListAnchor = NextCell = RootNode->Security;
  646. do {
  647. // is the next cell allocated?
  648. ChkAllocatedCell(NextCell);
  649. SecurityCell = (PCM_KEY_SECURITY) GetCell(NextCell);
  650. if (SecurityCell->Signature != CM_KEY_SECURITY_SIGNATURE) {
  651. bRez = FALSE;
  652. fprintf(stderr, "Fatal: Invalid signature (0x%lx) in Security cell 0x%lx ",SecurityCell->Signature,NextCell);
  653. if(FixHive) {
  654. //
  655. // REPAIR:
  656. // FATAL: Mismatched signature cannot be fixed. Unable to fix this.
  657. //
  658. fprintf(stderr, " ... unable to fix");
  659. } else {
  660. if(CompactHive) {
  661. // any attempt to compact a corrupted hive will fail
  662. CompactHive = FALSE;
  663. }
  664. }
  665. fprintf(stderr, "\n");
  666. return bRez;
  667. }
  668. if (NextCell != ListAnchor) {
  669. //
  670. // Check to make sure that our Blink points to where we just
  671. // came from.
  672. //
  673. if (SecurityCell->Blink != LastCell) {
  674. fprintf(stderr, "Invalid backward link in security cell (0x%lx)",NextCell);
  675. if(FixHive) {
  676. //
  677. // REPAIR: reset the link
  678. //
  679. SecurityCell->Blink = LastCell;
  680. fprintf(stderr, " ... fixed");
  681. } else {
  682. bRez = FALSE;
  683. if(CompactHive) {
  684. // any attempt to compact a corrupted hive will fail
  685. CompactHive = FALSE;
  686. fprintf(stderr, "\nRun chkreg /R to fix.");
  687. }
  688. }
  689. fprintf(stderr, "\n");
  690. }
  691. }
  692. if (!RtlValidSecurityDescriptor(&SecurityCell->Descriptor)) {
  693. bRez = FALSE;
  694. fprintf(stderr, "Invalid security descriptor in Security cell 0x%lx ",NextCell);
  695. if(FixHive) {
  696. //
  697. // REPAIR: remove the cell from the list and delete it!
  698. //
  699. PCM_KEY_SECURITY Before = (PCM_KEY_SECURITY) GetCell(SecurityCell->Blink);
  700. PCM_KEY_SECURITY After = (PCM_KEY_SECURITY) GetCell(SecurityCell->Flink);
  701. if( Before != After ) {
  702. // make sure the list will not remain empty
  703. Before->Flink = SecurityCell->Flink;
  704. After->Blink = SecurityCell->Blink;
  705. }
  706. FreeCell(NextCell);
  707. NextCell = SecurityCell->Flink;
  708. fprintf(stderr, " ... deleted");
  709. } else {
  710. bRez = FALSE;
  711. if(CompactHive) {
  712. // any attempt to compact a corrupted hive will fail
  713. CompactHive = FALSE;
  714. fprintf(stderr, "\nRun chkreg /R to fix.");
  715. }
  716. }
  717. fprintf(stderr, "\n");
  718. } else {
  719. // validate the next one
  720. LastCell = NextCell;
  721. NextCell = SecurityCell->Flink;
  722. }
  723. } while ( NextCell != ListAnchor );
  724. return bRez;
  725. }
  726. BOOLEAN
  727. ChkSecurityCellInList(HCELL_INDEX Security)
  728. /*++
  729. Routine Description:
  730. Searches the specified cell within the security descriptors list
  731. Arguments:
  732. Security - Provides the current cell
  733. Return Value:
  734. TRUE - the current cell was found in the security list
  735. FALSE - the current cell is not present in the security list and it couldn't be added.
  736. --*/
  737. {
  738. PCM_KEY_NODE RootNode;
  739. PCM_KEY_SECURITY SecurityCell;
  740. PCM_KEY_SECURITY SecurityCellCurrent;
  741. PCM_KEY_SECURITY SecurityCellAfter;
  742. HCELL_INDEX ListAnchor;
  743. HCELL_INDEX NextCell;
  744. BOOLEAN bRez = TRUE;
  745. RootNode = (PCM_KEY_NODE) GetCell(RootCell);
  746. ListAnchor = NextCell = RootNode->Security;
  747. do {
  748. if( NextCell == Security) {
  749. // found it!
  750. return bRez;
  751. }
  752. if( !IsCellAllocated( NextCell ) ) {
  753. return FALSE;
  754. }
  755. SecurityCell = (PCM_KEY_SECURITY) GetCell(NextCell);
  756. NextCell = SecurityCell->Flink;
  757. } while ( NextCell != ListAnchor );
  758. // cell not found; try to fix it
  759. bRez = FALSE;
  760. fprintf(stderr, "Security Cell (0x%lx) not in security descriptors list",Security);
  761. if(FixHive) {
  762. //
  763. // REPAIR: Add the security cell at the begining of the list
  764. //
  765. bRez = TRUE;
  766. SecurityCell = (PCM_KEY_SECURITY) GetCell(ListAnchor);
  767. SecurityCellCurrent = (PCM_KEY_SECURITY) GetCell(Security);
  768. SecurityCellAfter = (PCM_KEY_SECURITY) GetCell(SecurityCell->Flink);
  769. // restore the connections
  770. SecurityCellCurrent->Flink = SecurityCell->Flink;
  771. SecurityCellCurrent->Blink = ListAnchor;
  772. SecurityCell->Flink = Security;
  773. SecurityCellAfter->Blink = Security;
  774. fprintf(stderr, " ... security cell added to the list");
  775. } else {
  776. if(CompactHive) {
  777. // any attempt to compact a corrupted hive will fail
  778. CompactHive = FALSE;
  779. fprintf(stderr, "\nRun chkreg /R to fix.");
  780. }
  781. }
  782. fprintf(stderr, "\n");
  783. return bRez;
  784. }