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.

1157 lines
36 KiB

  1. /*++
  2. Copyright (c) 1998 Microsoft Corporation
  3. Module Name:
  4. regdmp.c
  5. Abstract:
  6. This module contains routines to check/dump the logical structure of the hive.
  7. Author:
  8. Dragos C. Sambotin (dragoss) 30-Dec-1998
  9. Revision History:
  10. --*/
  11. #include "chkreg.h"
  12. extern ULONG MaxLevel;
  13. extern UNICODE_STRING KeyName;
  14. extern WCHAR NameBuffer[];
  15. extern FILE *OutputFile;
  16. extern BOOLEAN FixHive;
  17. extern BOOLEAN CompactHive;
  18. extern ULONG CountKeyNodeCompacted;
  19. extern HCELL_INDEX RootCell;
  20. #define REG_MAX_PLAUSIBLE_KEY_SIZE \
  21. ((FIELD_OFFSET(CM_KEY_NODE, Name)) + \
  22. (sizeof(WCHAR) * REG_MAX_KEY_NAME_LENGTH) + 16)
  23. BOOLEAN ChkSecurityCellInList(HCELL_INDEX Security);
  24. BOOLEAN
  25. ChkAreCellsInSameVicinity(HCELL_INDEX Cell1,HCELL_INDEX Cell2)
  26. {
  27. ULONG Start = Cell1&(~HCELL_TYPE_MASK);
  28. ULONG End = Cell2&(~HCELL_TYPE_MASK);
  29. Start += HBLOCK_SIZE;
  30. End += HBLOCK_SIZE;
  31. //
  32. // truncate to the CM_VIEW_SIZE segment
  33. //
  34. Start &= (~(CM_VIEW_SIZE - 1));
  35. End &= (~(CM_VIEW_SIZE - 1));
  36. if( Start != End ){
  37. return FALSE;
  38. }
  39. return TRUE;
  40. }
  41. BOOLEAN
  42. ChkAllocatedCell(HCELL_INDEX Cell)
  43. /*
  44. Routine Description:
  45. Checks if the cell is allocated (i.e. the size is negative).
  46. Arguments:
  47. Cell - supplies the cell index of the cell of interest.
  48. Return Value:
  49. TRUE if Cell is allocated. FALSE otherwise.
  50. */
  51. {
  52. BOOLEAN bRez = TRUE;
  53. if( Cell == HCELL_NIL ) {
  54. fprintf(stderr, "Warning : HCELL_NIL referrenced !\n");
  55. return bRez;
  56. }
  57. if( !IsCellAllocated( Cell ) ) {
  58. bRez = FALSE;
  59. fprintf(stderr, "Used free cell 0x%lx ",Cell);
  60. if(FixHive) {
  61. //
  62. // REPAIR: mark the cell as allocated
  63. //
  64. AllocateCell(Cell);
  65. fprintf(stderr, " ... fixed");
  66. bRez = TRUE;
  67. } else {
  68. if(CompactHive) {
  69. // any attempt to compact a corrupted hive will fail
  70. CompactHive = FALSE;
  71. fprintf(stderr, "\nRun chkreg /R to fix.");
  72. }
  73. }
  74. fprintf(stderr, "\n");
  75. }
  76. return bRez;
  77. }
  78. static CHAR FixKeyNameCount = 0;
  79. BOOLEAN
  80. ChkKeyNodeCell(HCELL_INDEX KeyNodeCell,
  81. HCELL_INDEX ParentCell
  82. )
  83. /*
  84. Routine Description:
  85. Checks if the cell is is a consistent keynode. Make fixes when neccessary/required.
  86. The following tests are performed against the keynode cell:
  87. 1. the size should be smaller than the REG_MAX_PLAUSIBLE_KEY_SIZE ==> fatal error
  88. 2. the Name should not exceed the size of the cell
  89. 3. the signature should match CM_KEY_NODE_SIGNATURE
  90. 4. the parent cell in keynode should match the actual parent cell
  91. Arguments:
  92. KeyNodeCell - supplies the cell index of the key node of interest.
  93. ParentCell - the actual parent of the current key node
  94. Return Value:
  95. TRUE if KeyNodeCell is reffering a consistent key node, or it was successfully recovered.
  96. FALSE otherwise.
  97. */
  98. {
  99. PCM_KEY_NODE KeyNode = (PCM_KEY_NODE) GetCell(KeyNodeCell);
  100. ULONG size;
  101. BOOLEAN bRez = TRUE;
  102. ULONG usedlen;
  103. PUCHAR pName;
  104. // this cell should not be considered as lost
  105. RemoveCellFromUnknownList(KeyNodeCell);
  106. ChkAllocatedCell(KeyNodeCell);
  107. // Validate the size of the
  108. size = GetCellSize(KeyNodeCell);
  109. if (size > REG_MAX_PLAUSIBLE_KEY_SIZE) {
  110. bRez = FALSE;
  111. fprintf(stderr, "Implausible Key size %lx in cell 0x%lx ",size,KeyNodeCell);
  112. if(FixHive) {
  113. //
  114. // REPAIR: unable to fix
  115. //
  116. fprintf(stderr, " ... deleting key\n");
  117. return bRez;
  118. }
  119. }
  120. usedlen = FIELD_OFFSET(CM_KEY_NODE, Name) + KeyNode->NameLength;
  121. if (usedlen > size) {
  122. bRez = FALSE;
  123. fprintf(stderr, "Key (size = %lu) is bigger than containing cell 0x%lx (size = %lu) ",usedlen,KeyNodeCell,size);
  124. if(FixHive) {
  125. //
  126. // REPAIR: set NameLength to fit the cell size (i.e. set it to size - FIELD_OFFSET(CM_KEY_NODE, Name) )
  127. //
  128. //
  129. // WARNING: the name might be truncated!!!
  130. //
  131. bRez = TRUE;
  132. KeyNode->NameLength = (USHORT)(size - FIELD_OFFSET(CM_KEY_NODE, Name));
  133. fprintf(stderr, " ... fixed");
  134. } else {
  135. if(CompactHive) {
  136. // any attempt to compact a corrupted hive will fail
  137. CompactHive = FALSE;
  138. fprintf(stderr, "\nRun chkreg /R to fix.");
  139. }
  140. }
  141. fprintf(stderr, "\n");
  142. }
  143. if( KeyNode->Flags & KEY_COMP_NAME ) {
  144. pName = (PUCHAR)KeyNode->Name;
  145. for( usedlen = 0; usedlen < KeyNode->NameLength;usedlen++) {
  146. if( pName[usedlen] == '\\' ) {
  147. bRez = FALSE;
  148. fprintf(stderr, "Invalid key Name for Key (0x%lx) == %s ",KeyNodeCell,pName);
  149. if(FixHive) {
  150. //
  151. // REPAIR: unable to fix
  152. //
  153. fprintf(stderr, " ... deleting key\n");
  154. return bRez;
  155. } else {
  156. if(CompactHive) {
  157. // any attempt to compact a corrupted hive will fail
  158. CompactHive = FALSE;
  159. fprintf(stderr, "\nRun chkreg /R to fix.");
  160. }
  161. }
  162. fprintf(stderr, "\n");
  163. }
  164. }
  165. }
  166. if (ParentCell != HCELL_NIL) {
  167. if (KeyNode->Parent != ParentCell) {
  168. bRez = FALSE;
  169. fprintf(stderr, "Parent of Key (0x%lx) does not match with its ParentCell (0x%lx) ",ParentCell,KeyNode->Parent);
  170. if(FixHive) {
  171. //
  172. // REPAIR: reset the parent
  173. //
  174. bRez = TRUE;
  175. KeyNode->Parent = ParentCell;
  176. fprintf(stderr, " ... fixed");
  177. } else {
  178. if(CompactHive) {
  179. // any attempt to compact a corrupted hive will fail
  180. CompactHive = FALSE;
  181. fprintf(stderr, "\nRun chkreg /R to fix.");
  182. }
  183. }
  184. fprintf(stderr, "\n");
  185. }
  186. }
  187. if (KeyNode->Signature != CM_KEY_NODE_SIGNATURE) {
  188. bRez = FALSE;
  189. fprintf(stderr, "Invalid signature (0x%lx) in Key cell 0x%lx ",KeyNode->Signature,KeyNodeCell);
  190. if(FixHive) {
  191. //
  192. // REPAIR:
  193. // FATAL: Mismatched signature cannot be fixed. The key should be deleted!
  194. //
  195. fprintf(stderr, " ... deleting key");
  196. } else {
  197. if(CompactHive) {
  198. // any attempt to compact a corrupted hive will fail
  199. CompactHive = FALSE;
  200. fprintf(stderr, "\nRun chkreg /R to fix.");
  201. }
  202. }
  203. fprintf(stderr, "\n");
  204. }
  205. return bRez;
  206. }
  207. BOOLEAN
  208. ChkClassCell(HCELL_INDEX Class)
  209. /*
  210. Routine Description:
  211. Checks if the cell is a consistent class cell.
  212. There is not much to be checked here.
  213. Arguments:
  214. Class - supplies the cell index of the cell of interest.
  215. Return Value:
  216. TRUE if Class is a valid cell.
  217. FALSE otherwise.
  218. */
  219. {
  220. // this cell should not be considered as lost
  221. RemoveCellFromUnknownList(Class);
  222. return ChkAllocatedCell(Class);
  223. }
  224. BOOLEAN
  225. ChkSecurityCell(HCELL_INDEX Security)
  226. /*
  227. Routine Description:
  228. Checks if the cell is a consistent security cell.
  229. A security cell must be allocated and must have a valid signature.
  230. Arguments:
  231. Security - supplies the cell index of the cell of interest.
  232. Return Value:
  233. TRUE if Security is a valid cell.
  234. FALSE otherwise.
  235. */
  236. {
  237. PCM_KEY_SECURITY KeySecurity = (PCM_KEY_SECURITY) GetCell(Security);
  238. BOOLEAN bRez = TRUE;
  239. // this cell should not be considered as lost
  240. RemoveCellFromUnknownList(Security);
  241. if( !IsCellAllocated( Security ) ) {
  242. // unalocated security cells are invalid.
  243. // they are marked as free in the validate security descriptors check!
  244. if(FixHive) {
  245. //
  246. // REPAIR:
  247. // FATAL: Invalid security cells could not be fixed. Containg keys will be deleted.
  248. //
  249. } else {
  250. if(CompactHive) {
  251. // any attempt to compact a corrupted hive will fail
  252. CompactHive = FALSE;
  253. }
  254. }
  255. return FALSE;
  256. }
  257. if (KeySecurity->Signature != CM_KEY_SECURITY_SIGNATURE) {
  258. fprintf(stderr, "Invalid signature (0x%lx) in Security Key cell 0x%lx ",KeySecurity->Signature,Security);
  259. if(FixHive) {
  260. //
  261. // REPAIR:
  262. // FATAL: Mismatched signature cannot be fixed. The key should be deleted!
  263. //
  264. fprintf(stderr, " ... deleting refering key");
  265. } else {
  266. bRez = FALSE;
  267. if(CompactHive) {
  268. // any attempt to compact a corrupted hive will fail
  269. CompactHive = FALSE;
  270. fprintf(stderr, "\nRun chkreg /R to fix.");
  271. }
  272. }
  273. fprintf(stderr, "\n");
  274. }
  275. // check if this security cell is present in the security list.
  276. if(!ChkSecurityCellInList(Security) ) {
  277. bRez = FALSE;
  278. }
  279. return bRez;
  280. }
  281. BOOLEAN
  282. ChkKeyValue(HCELL_INDEX KeyValue,
  283. PREG_USAGE OwnUsage,
  284. BOOLEAN *KeyCompacted
  285. )
  286. /*
  287. Routine Description:
  288. Checks if the cell is a consistent keyvalue cell.
  289. The following tests are performed:
  290. 1. the cell must be allocated
  291. 2. the cell is tested against HCELL_NIL ==> fatal error
  292. 3. the signature should match CM_KEY_VALUE_SIGNATURE
  293. 4. the name should not exceed the size of the cell
  294. 5. the data cell should be allocated and its size should match DataLength
  295. Arguments:
  296. KeyValue - supplies the cell index of the cell of interest.
  297. OwnUsage - used to collect data statistics
  298. Return Value:
  299. TRUE if KeyCell is a valid cell or it was successfully fixed.
  300. FALSE otherwise.
  301. */
  302. {
  303. PCM_KEY_VALUE ValueNode;
  304. ULONG realsize;
  305. ULONG usedlen;
  306. ULONG DataLength;
  307. HCELL_INDEX Data;
  308. ULONG size;
  309. BOOLEAN bRez = TRUE;
  310. if( KeyValue == HCELL_NIL ) {
  311. bRez = FALSE;
  312. fprintf(stderr, "NIL Key value encountered; Fatal error!");
  313. if(FixHive) {
  314. //
  315. // REPAIR: fatal error, the value should be removed from the value list
  316. //
  317. fprintf(stderr, " ... deleting empty entry\n");
  318. return bRez;
  319. }
  320. }
  321. ChkAllocatedCell(KeyValue);
  322. //
  323. // Value size
  324. //
  325. size = GetCellSize(KeyValue);
  326. OwnUsage->Size += size;
  327. // this cell should not be considered as lost
  328. RemoveCellFromUnknownList(KeyValue);
  329. ValueNode = (PCM_KEY_VALUE) GetCell(KeyValue);
  330. //
  331. // Check out the value entry itself
  332. //
  333. usedlen = FIELD_OFFSET(CM_KEY_VALUE, Name) + ValueNode->NameLength;
  334. if (usedlen > size) {
  335. bRez = FALSE;
  336. fprintf(stderr, "Key Value (size = %lu) is bigger than containing cell 0x%lx (size = %lu) ",usedlen,KeyValue,size);
  337. if(FixHive) {
  338. //
  339. // REPAIR: set the actual size to HiveLength-FileOffset
  340. //
  341. //
  342. // WARNING: the name might be truncated!!!
  343. //
  344. bRez = TRUE;
  345. ValueNode->NameLength = (USHORT)(size - FIELD_OFFSET(CM_KEY_VALUE, Name));
  346. fprintf(stderr, " ... fixed");
  347. } else {
  348. if(CompactHive) {
  349. // any attempt to compact a corrupted hive will fail
  350. CompactHive = FALSE;
  351. fprintf(stderr, "\nRun chkreg /R to fix.");
  352. }
  353. }
  354. fprintf(stderr, "\n");
  355. }
  356. //
  357. // Check out value entry's data
  358. //
  359. DataLength = ValueNode->DataLength;
  360. if (DataLength < CM_KEY_VALUE_SPECIAL_SIZE) {
  361. Data = ValueNode->Data;
  362. if ((DataLength == 0) && (Data != HCELL_NIL)) {
  363. bRez = FALSE;
  364. fprintf(stderr, "Data not null in Key Value (0x%lx) ",KeyValue);
  365. if(FixHive) {
  366. //
  367. // REPAIR: set the actual size to HiveLength-FileOffset
  368. //
  369. //
  370. // WARNING: a cell might get lost here!
  371. //
  372. bRez = TRUE;
  373. ValueNode->Data = HCELL_NIL;
  374. fprintf(stderr, " ... fixed");
  375. } else {
  376. if(CompactHive) {
  377. // any attempt to compact a corrupted hive will fail
  378. CompactHive = FALSE;
  379. fprintf(stderr, "\nRun chkreg /R to fix.");
  380. }
  381. }
  382. fprintf(stderr, "\n");
  383. }
  384. }
  385. if (!CmpIsHKeyValueSmall(realsize, ValueNode->DataLength)) {
  386. //
  387. // Data Size
  388. //
  389. OwnUsage->Size += GetCellSize(ValueNode->Data);
  390. OwnUsage->DataCount++;
  391. OwnUsage->DataSize += GetCellSize(ValueNode->Data);
  392. // this cell should not be considered as lost
  393. RemoveCellFromUnknownList(ValueNode->Data);
  394. ChkAllocatedCell(ValueNode->Data);
  395. (*KeyCompacted) = ((*KeyCompacted) && ChkAreCellsInSameVicinity(KeyValue,ValueNode->Data));
  396. }
  397. //
  398. // Now the signature
  399. //
  400. if (ValueNode->Signature != CM_KEY_VALUE_SIGNATURE) {
  401. bRez = FALSE;
  402. fprintf(stderr, "Invalid signature (0x%lx) in Key Value cell 0x%lx ",ValueNode->Signature,KeyValue);
  403. if(FixHive) {
  404. //
  405. // REPAIR:
  406. // FATAL: Mismatched signature cannot be fixed. The key should be deleted!
  407. //
  408. fprintf(stderr, " ... deleting value.");
  409. } else {
  410. if(CompactHive) {
  411. // any attempt to compact a corrupted hive will fail
  412. CompactHive = FALSE;
  413. fprintf(stderr, "\nRun chkreg /R to fix.");
  414. }
  415. }
  416. fprintf(stderr, "\n");
  417. }
  418. return bRez;
  419. }
  420. ULONG
  421. DeleteNilCells( ULONG Count,
  422. HCELL_INDEX List[]
  423. )
  424. /*
  425. Routine Description:
  426. steps through a list of HCELL_INDEXes and removes the HCELL_NIL ones
  427. Arguments:
  428. Count - the number of cells in list
  429. List - the list to be checked
  430. Return Value:
  431. The new Count value for the list
  432. */
  433. {
  434. ULONG i;
  435. BOOLEAN bFound = TRUE;
  436. while(bFound) {
  437. // assume we are done after this iteration
  438. bFound = FALSE;
  439. for( i=0;i<Count;i++) {
  440. if( List[i] == HCELL_NIL ) {
  441. for(;i<(Count-1);i++) {
  442. List[i] = List[i+1];
  443. }
  444. bFound = TRUE;
  445. Count--;
  446. break;
  447. }
  448. }
  449. }
  450. return Count;
  451. }
  452. BOOLEAN
  453. ChkValueList( HCELL_INDEX ValueList,
  454. ULONG *ValueCount,
  455. PREG_USAGE OwnUsage,
  456. BOOLEAN *KeyCompacted)
  457. /*
  458. Routine Description:
  459. Checks the consistency of a ValueList.
  460. Each value is checked.
  461. Bogus values are freed and removed.
  462. Arguments:
  463. ValueList - the list to be checked
  464. ValueCount - count of the list
  465. OwnUsage - used to collect data statistics
  466. Return Value:
  467. TRUE if KeyCell is a valid cell or it was successfully fixed.
  468. FALSE otherwise.
  469. */
  470. {
  471. ULONG i;
  472. PCELL_DATA List;
  473. BOOLEAN bRez = TRUE;
  474. //
  475. // Value Index size
  476. //
  477. OwnUsage->Size += GetCellSize(ValueList);
  478. OwnUsage->ValueIndexCount = 1;
  479. // this cell should not be considered as lost
  480. RemoveCellFromUnknownList(ValueList);
  481. ChkAllocatedCell(ValueList);
  482. List = (PCELL_DATA)GetCell(ValueList);
  483. for (i=0; i<(*ValueCount); i++) {
  484. if( !ChkKeyValue(List->u.KeyList[i],OwnUsage,KeyCompacted) ) {
  485. // we should remove this value
  486. bRez = FALSE;
  487. // Warning: this my create generate lost cells
  488. if(FixHive) {
  489. if( List->u.KeyList[i] != HCELL_NIL ) {
  490. //FreeCell(List->u.KeyList[i]);
  491. List->u.KeyList[i] = HCELL_NIL;
  492. }
  493. }
  494. }
  495. (*KeyCompacted) = ((*KeyCompacted) && ChkAreCellsInSameVicinity(ValueList,List->u.KeyList[i]));
  496. }
  497. if( FixHive && !bRez) {
  498. (*ValueCount) = DeleteNilCells( *ValueCount,List->u.KeyList);
  499. bRez = TRUE;
  500. }
  501. // for now
  502. return bRez;
  503. }
  504. BOOLEAN
  505. DumpChkRegistry(
  506. ULONG Level,
  507. USHORT ParentLength,
  508. HCELL_INDEX Cell,
  509. HCELL_INDEX ParentCell,
  510. PREG_USAGE PUsage
  511. )
  512. /*
  513. Routine Description:
  514. Recursively walks through the hive. Performs logical vallidation
  515. checks on all cells along the path and fix errors when possible.
  516. Arguments:
  517. Level - the current depth level within the hive key tree
  518. ParentLength - the length of the parent name (dump purposes only)
  519. Cell - current key to be checked
  520. ParentCell - parent cell, used for parent-son relationship checkings
  521. OwnUsage - used to collect data statistics
  522. Return Value:
  523. TRUE if Cell is a consistent key, or it was fixed OK.
  524. FALSE otherwise.
  525. */
  526. {
  527. PCM_KEY_FAST_INDEX FastIndex;
  528. HCELL_INDEX LeafCell;
  529. PCM_KEY_INDEX Leaf;
  530. PCM_KEY_INDEX Index;
  531. PCM_KEY_NODE KeyNode;
  532. REG_USAGE ChildUsage, TotalChildUsage, OwnUsage;
  533. ULONG i, j;
  534. USHORT k;
  535. WCHAR *w1;
  536. UCHAR *u1;
  537. USHORT CurrentLength;
  538. ULONG CellCount;
  539. BOOLEAN bRez = TRUE;
  540. BOOLEAN KeyCompacted = TRUE;
  541. ULONG ClassLength;
  542. HCELL_INDEX Class;
  543. ULONG ValueCount;
  544. HCELL_INDEX ValueList;
  545. HCELL_INDEX Security;
  546. if( Cell == HCELL_NIL ) {
  547. // TODO
  548. // we should return an error code so the caller could deleted this child from the structure
  549. fprintf(stderr, "HCELL_NIL referrenced as a child key of 0x%lx \n",ParentCell);
  550. bRez = FALSE;
  551. return bRez;
  552. }
  553. KeyNode = (PCM_KEY_NODE) GetCell(Cell);
  554. // Verify KeyNode consistency
  555. if(!ChkKeyNodeCell(Cell,ParentCell)) {
  556. //
  557. // Bad karma ==> this key should be deleted
  558. //
  559. QuitToParentWithError:
  560. if(ParentCell == HCELL_NIL) {
  561. //
  562. // Root cell not consistent ==> unable to fix the hive
  563. //
  564. fprintf(stderr, "Fatal : Inconsistent Root Key 0x%lx",Cell);
  565. if(FixHive) {
  566. //
  567. // FATAL: nothing to do
  568. //
  569. fprintf(stderr, " ... unable to fix");
  570. } else {
  571. if(CompactHive) {
  572. // any attempt to compact a corrupted hive will fail
  573. CompactHive = FALSE;
  574. }
  575. }
  576. fprintf(stderr, "\n");
  577. }
  578. bRez = FALSE;
  579. return bRez;
  580. }
  581. ClassLength = KeyNode->ClassLength;
  582. Class = KeyNode->Class;
  583. ValueCount = KeyNode->ValueList.Count;
  584. ValueList = KeyNode->ValueList.List;
  585. Security = KeyNode->Security;
  586. if (ClassLength > 0) {
  587. if( Class != HCELL_NIL ) {
  588. ChkClassCell(Class);
  589. KeyCompacted = (KeyCompacted && ChkAreCellsInSameVicinity(Cell,Class));
  590. } else {
  591. bRez = FALSE;
  592. fprintf(stderr,"ClassLength (=%u) doesn't match NIL values in Class for Key 0x%lx",ClassLength,Cell);
  593. if(FixHive) {
  594. //
  595. // REPAIR: reset the ClassLength
  596. //
  597. bRez = TRUE;
  598. KeyNode->ClassLength = 0;
  599. fprintf(stderr, " ... fixed");
  600. } else {
  601. if(CompactHive) {
  602. // any attempt to compact a corrupted hive will fail
  603. CompactHive = FALSE;
  604. fprintf(stderr, "\nRun chkreg /R to fix.");
  605. }
  606. }
  607. fprintf(stderr, "\n");
  608. }
  609. }
  610. if (Security != HCELL_NIL) {
  611. if( !ChkSecurityCell(Security) ) {
  612. //
  613. // Fatal : We don't mess up with security cells. We can't recover from invalid security cells.
  614. //
  615. //
  616. // QUESTION : Is it acceptable to drop a security cell?
  617. //
  618. bRez = FALSE;
  619. }
  620. } else {
  621. //
  622. // Fatal: security cell is not allowed to be NIL
  623. //
  624. bRez = FALSE;
  625. fprintf(stderr,"Security cell is NIL for Key 0x%lx",Cell);
  626. if(FixHive) {
  627. //
  628. // REPAIR: reset the security to the root security
  629. //
  630. PCM_KEY_NODE RootNode;
  631. PCM_KEY_SECURITY SecurityNode;
  632. bRez = TRUE;
  633. RootNode = (PCM_KEY_NODE) GetCell(RootCell);
  634. KeyNode->Security = RootNode->Security;
  635. SecurityNode = (PCM_KEY_SECURITY)GetCell(RootNode->Security);
  636. SecurityNode->ReferenceCount++;
  637. fprintf(stderr, " ... fixed");
  638. }
  639. }
  640. //
  641. // Construct the full path name of the key
  642. //
  643. if (Level > 0) {
  644. KeyName.Length = ParentLength;
  645. if (KeyNode->Flags & KEY_COMP_NAME) {
  646. u1 = (UCHAR*) &(KeyNode->Name[0]);
  647. w1 = &(NameBuffer[KeyName.Length/sizeof(WCHAR)]);
  648. for (k=0;k<KeyNode->NameLength;k++) {
  649. // NameBuffer[k] = (UCHAR)(KeyNode->Name[k]);
  650. // NameBuffer[k] = (WCHAR)(u1[k]);
  651. *w1 = (WCHAR) *u1;
  652. w1++;
  653. u1++;
  654. }
  655. KeyName.Length += KeyNode->NameLength*sizeof(WCHAR);
  656. } else {
  657. RtlCopyMemory((PVOID)&(NameBuffer[KeyName.Length]), (PVOID)(KeyNode->Name), KeyNode->NameLength);
  658. KeyName.Length += KeyNode->NameLength;
  659. }
  660. NameBuffer[KeyName.Length/sizeof(WCHAR)] = OBJ_NAME_PATH_SEPARATOR;
  661. KeyName.Length += sizeof(WCHAR);
  662. }
  663. CurrentLength = KeyName.Length;
  664. //
  665. // Calculate the count of this key and value
  666. //
  667. OwnUsage.KeyNodeCount = 1;
  668. OwnUsage.KeyValueCount = KeyNode->ValueList.Count;
  669. OwnUsage.ValueIndexCount = 0;
  670. OwnUsage.DataCount = 0;
  671. OwnUsage.DataSize = 0;
  672. //
  673. // Calculate the count (including overhead and value) of this key
  674. //
  675. // Key node size
  676. //
  677. OwnUsage.Size = GetCellSize(Cell);
  678. if( ValueCount ) {
  679. if( ValueList == HCELL_NIL ) {
  680. bRez = FALSE;
  681. fprintf(stderr,"ValueCount is %lu, but ValueList is NIL for key 0x%lx",ValueCount,Cell);
  682. if(FixHive) {
  683. //
  684. // REPAIR: adjust the ValueList count
  685. //
  686. bRez = TRUE;
  687. KeyNode->ValueList.Count = 0;
  688. fprintf(stderr, " ... fixed");
  689. } else {
  690. if(CompactHive) {
  691. // any attempt to compact a corrupted hive will fail
  692. CompactHive = FALSE;
  693. fprintf(stderr, "\nRun chkreg /R to fix.");
  694. }
  695. }
  696. fprintf(stderr, "\n");
  697. } else {
  698. if(!ChkValueList(ValueList,&(KeyNode->ValueList.Count),&OwnUsage,&KeyCompacted) ) {
  699. // the ValueList is not consistent or cannot be fixed
  700. bRez = FALSE;
  701. if(FixHive) {
  702. //
  703. // REPAIR: empty the ValueList
  704. //
  705. bRez = TRUE;
  706. KeyNode->ValueList.Count = 0;
  707. //FreeCell(ValueList);
  708. KeyNode->ValueList.List = HCELL_NIL;
  709. fprintf(stderr,"ValueList 0x%lx for key 0x%lx dropped!",ValueCount,Cell);
  710. } else {
  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. }
  719. KeyCompacted = (KeyCompacted && ChkAreCellsInSameVicinity(Cell,ValueList));
  720. }
  721. }
  722. //
  723. // Calculate the size of the children
  724. //
  725. TotalChildUsage.KeyNodeCount = 0;
  726. TotalChildUsage.KeyValueCount = 0;
  727. TotalChildUsage.ValueIndexCount = 0;
  728. TotalChildUsage.KeyIndexCount = 0;
  729. TotalChildUsage.DataCount = 0;
  730. TotalChildUsage.DataSize = 0;
  731. TotalChildUsage.Size = 0;
  732. if (KeyNode->SubKeyCounts[0]) {
  733. //
  734. // Size for index cell
  735. //
  736. if( KeyNode->SubKeyLists[0] == HCELL_NIL ) {
  737. //
  738. // We got a problem here: the count says there should be some keys, but the list is NIL
  739. //
  740. bRez = FALSE;
  741. fprintf(stderr,"SubKeyCounts is %lu, but the SubKeyLists is NIL for key 0x%lx",KeyNode->SubKeyCounts[0],Cell);
  742. if(FixHive) {
  743. //
  744. // REPAIR: adjust the subkeys count
  745. //
  746. bRez = TRUE;
  747. KeyNode->SubKeyCounts[0] = 0;
  748. fprintf(stderr, " ... fixed");
  749. } else {
  750. if(CompactHive) {
  751. // any attempt to compact a corrupted hive will fail
  752. CompactHive = FALSE;
  753. fprintf(stderr, "\nRun chkreg /R to fix.");
  754. }
  755. }
  756. fprintf(stderr, "\n");
  757. return bRez;
  758. }
  759. KeyCompacted = (KeyCompacted && ChkAreCellsInSameVicinity(Cell,KeyNode->SubKeyLists[0]));
  760. TotalChildUsage.Size += GetCellSize(KeyNode->SubKeyLists[0]);
  761. TotalChildUsage.KeyIndexCount++;
  762. Index = (PCM_KEY_INDEX)GetCell(KeyNode->SubKeyLists[0]);
  763. // this cell should not be considered as lost
  764. RemoveCellFromUnknownList(KeyNode->SubKeyLists[0]);
  765. ChkAllocatedCell(KeyNode->SubKeyLists[0]);
  766. if (Index->Signature == CM_KEY_INDEX_ROOT) {
  767. for (i = 0; i < Index->Count; i++) {
  768. //
  769. // Size of Index Leaf
  770. //
  771. LeafCell = Index->List[i];
  772. TotalChildUsage.Size += GetCellSize(Index->List[i]);
  773. TotalChildUsage.KeyIndexCount++;
  774. // this cell should not be considered as lost
  775. RemoveCellFromUnknownList(LeafCell);
  776. ChkAllocatedCell(LeafCell);
  777. Leaf = (PCM_KEY_INDEX)GetCell(LeafCell);
  778. if ( (Leaf->Signature == CM_KEY_FAST_LEAF) ||
  779. (Leaf->Signature == CM_KEY_HASH_LEAF) ) {
  780. FastIndex = (PCM_KEY_FAST_INDEX)Leaf;
  781. againFastLeaf1:
  782. for (j = 0; j < FastIndex->Count; j++) {
  783. if(!DumpChkRegistry(Level+1, CurrentLength, FastIndex->List[j].Cell,Cell,&ChildUsage)) {
  784. // this child is not consistent or cannot be fixed. Remove it!!!
  785. if(FixHive) {
  786. //
  787. // REPAIR: drop this child
  788. //
  789. fprintf(stderr,"Subkey 0x%lx of 0x%lx deleted!\n",FastIndex->List[j].Cell,Cell);
  790. for( ;j<(ULONG)(FastIndex->Count-1);j++) {
  791. FastIndex->List[j] = FastIndex->List[j+1];
  792. }
  793. FastIndex->Count--;
  794. KeyNode->SubKeyCounts[0]--;
  795. goto againFastLeaf1;
  796. } else {
  797. bRez = FALSE;
  798. if(CompactHive) {
  799. // any attempt to compact a corrupted hive will fail
  800. CompactHive = FALSE;
  801. fprintf(stderr, "\nRun chkreg /R to fix.");
  802. }
  803. }
  804. fprintf(stderr, "\n");
  805. }
  806. //
  807. // Add to total count
  808. //
  809. TotalChildUsage.KeyNodeCount += ChildUsage.KeyNodeCount;
  810. TotalChildUsage.KeyValueCount += ChildUsage.KeyValueCount;
  811. TotalChildUsage.ValueIndexCount += ChildUsage.ValueIndexCount;
  812. TotalChildUsage.KeyIndexCount += ChildUsage.KeyIndexCount;
  813. TotalChildUsage.DataCount += ChildUsage.DataCount;
  814. TotalChildUsage.DataSize += ChildUsage.DataSize;
  815. TotalChildUsage.Size += ChildUsage.Size;
  816. }
  817. } else if(Leaf->Signature == CM_KEY_INDEX_LEAF) {
  818. againFastLeaf2:
  819. for (j = 0; j < Leaf->Count; j++) {
  820. if(!DumpChkRegistry(Level+1, CurrentLength, Leaf->List[j],Cell,&ChildUsage)) {
  821. // this child is not consistent or cannot be fixed. Remove it!!!
  822. if(FixHive) {
  823. //
  824. // REPAIR: drop this child
  825. //
  826. fprintf(stderr,"Subkey 0x%lx of 0x%lx deleted!\n",Leaf->List[j],Cell);
  827. for( ;j<(ULONG)(Leaf->Count-1);j++) {
  828. Leaf->List[j] = Leaf->List[j+1];
  829. }
  830. Leaf->Count--;
  831. KeyNode->SubKeyCounts[0]--;
  832. goto againFastLeaf2;
  833. } else {
  834. bRez = FALSE;
  835. if(CompactHive) {
  836. // any attempt to compact a corrupted hive will fail
  837. CompactHive = FALSE;
  838. fprintf(stderr, "\nRun chkreg /R to fix.");
  839. }
  840. }
  841. fprintf(stderr, "\n");
  842. }
  843. //
  844. // Add to total count
  845. //
  846. TotalChildUsage.KeyNodeCount += ChildUsage.KeyNodeCount;
  847. TotalChildUsage.KeyValueCount += ChildUsage.KeyValueCount;
  848. TotalChildUsage.ValueIndexCount += ChildUsage.ValueIndexCount;
  849. TotalChildUsage.KeyIndexCount += ChildUsage.KeyIndexCount;
  850. TotalChildUsage.DataCount += ChildUsage.DataCount;
  851. TotalChildUsage.DataSize += ChildUsage.DataSize;
  852. TotalChildUsage.Size += ChildUsage.Size;
  853. }
  854. } else {
  855. // invalid index signature: only way to fix it is by dropping the entire key
  856. fprintf(stderr,"Invalid Index signature 0x%lx in key 0x%lx",(ULONG)Leaf->Signature,Cell);
  857. if(FixHive) {
  858. //
  859. // REPAIR:
  860. // FATAL: Mismatched signature cannot be fixed. The key should be deleted!
  861. //
  862. fprintf(stderr, " ... deleting containing key");
  863. }
  864. fprintf(stderr,"\n");
  865. goto QuitToParentWithError;
  866. }
  867. }
  868. } else if( (Index->Signature == CM_KEY_FAST_LEAF) ||
  869. (Index->Signature == CM_KEY_HASH_LEAF) ) {
  870. FastIndex = (PCM_KEY_FAST_INDEX)Index;
  871. againFastLeaf3:
  872. for (i = 0; i < FastIndex->Count; i++) {
  873. if(!DumpChkRegistry(Level+1, CurrentLength, FastIndex->List[i].Cell,Cell,&ChildUsage)) {
  874. // this child is not consistent or cannot be fixed. Remove it!!!
  875. if(FixHive) {
  876. //
  877. // REPAIR: drop this child
  878. //
  879. fprintf(stderr,"Subkey 0x%lx of 0x%lx deleted!\n",FastIndex->List[i].Cell,Cell);
  880. for( ;i<(ULONG)(FastIndex->Count-1);i++) {
  881. FastIndex->List[i] = FastIndex->List[i+1];
  882. }
  883. FastIndex->Count--;
  884. KeyNode->SubKeyCounts[0]--;
  885. goto againFastLeaf3;
  886. } else {
  887. bRez = FALSE;
  888. if(CompactHive) {
  889. // any attempt to compact a corrupted hive will fail
  890. CompactHive = FALSE;
  891. fprintf(stderr, "\nRun chkreg /R to fix.");
  892. }
  893. }
  894. fprintf(stderr, "\n");
  895. }
  896. //
  897. // Add to total count
  898. //
  899. TotalChildUsage.KeyNodeCount += ChildUsage.KeyNodeCount;
  900. TotalChildUsage.KeyValueCount += ChildUsage.KeyValueCount;
  901. TotalChildUsage.ValueIndexCount += ChildUsage.ValueIndexCount;
  902. TotalChildUsage.KeyIndexCount += ChildUsage.KeyIndexCount;
  903. TotalChildUsage.DataCount += ChildUsage.DataCount;
  904. TotalChildUsage.DataSize += ChildUsage.DataSize;
  905. TotalChildUsage.Size += ChildUsage.Size;
  906. }
  907. } else if(Index->Signature == CM_KEY_INDEX_LEAF) {
  908. for (i = 0; i < Index->Count; i++) {
  909. againFastLeaf4:
  910. if(!DumpChkRegistry(Level+1, CurrentLength, Index->List[i],Cell, &ChildUsage)) {
  911. // this child is not consistent or cannot be fixed. Remove it!!!
  912. if(FixHive) {
  913. //
  914. // REPAIR: drop this child
  915. //
  916. fprintf(stderr,"Subkey 0x%lx of 0x%lx deleted!\n",Index->List[i],Cell);
  917. for( ;i<(ULONG)(Index->Count-1);i++) {
  918. Index->List[i] = Index->List[i+1];
  919. }
  920. Index->Count--;
  921. KeyNode->SubKeyCounts[0]--;
  922. goto againFastLeaf4;
  923. } else {
  924. bRez = FALSE;
  925. if(CompactHive) {
  926. // any attempt to compact a corrupted hive will fail
  927. CompactHive = FALSE;
  928. fprintf(stderr, "\nRun chkreg /R to fix.");
  929. }
  930. }
  931. fprintf(stderr, "\n");
  932. }
  933. //
  934. // Add to total count
  935. //
  936. TotalChildUsage.KeyNodeCount += ChildUsage.KeyNodeCount;
  937. TotalChildUsage.KeyValueCount += ChildUsage.KeyValueCount;
  938. TotalChildUsage.ValueIndexCount += ChildUsage.ValueIndexCount;
  939. TotalChildUsage.KeyIndexCount += ChildUsage.KeyIndexCount;
  940. TotalChildUsage.DataCount += ChildUsage.DataCount;
  941. TotalChildUsage.DataSize += ChildUsage.DataSize;
  942. TotalChildUsage.Size += ChildUsage.Size;
  943. }
  944. } else {
  945. // invalid index signature: only way to fix it is by dropping the entire key
  946. fprintf(stderr,"Invalid Index signature 0x%lx in key 0x%lx",(ULONG)Index->Signature,Cell);
  947. if(FixHive) {
  948. //
  949. // REPAIR:
  950. // FATAL: Mismatched signature cannot be fixed. The key should be deleted!
  951. //
  952. fprintf(stderr, " ... deleting containing key");
  953. }
  954. fprintf(stderr,"\n");
  955. goto QuitToParentWithError;
  956. }
  957. KeyName.Length = CurrentLength;
  958. }
  959. PUsage->KeyNodeCount = OwnUsage.KeyNodeCount + TotalChildUsage.KeyNodeCount;
  960. PUsage->KeyValueCount = OwnUsage.KeyValueCount + TotalChildUsage.KeyValueCount;
  961. PUsage->ValueIndexCount = OwnUsage.ValueIndexCount + TotalChildUsage.ValueIndexCount;
  962. PUsage->KeyIndexCount = TotalChildUsage.KeyIndexCount;
  963. PUsage->DataCount = OwnUsage.DataCount + TotalChildUsage.DataCount;
  964. PUsage->DataSize = OwnUsage.DataSize + TotalChildUsage.DataSize;
  965. PUsage->Size = OwnUsage.Size + TotalChildUsage.Size;
  966. if(KeyCompacted) {
  967. CountKeyNodeCompacted++;
  968. }
  969. if ((Level <= MaxLevel) && (Level > 0)) {
  970. CellCount = PUsage->KeyNodeCount +
  971. PUsage->KeyValueCount +
  972. PUsage->ValueIndexCount +
  973. PUsage->KeyIndexCount +
  974. PUsage->DataCount;
  975. fprintf(OutputFile,"%6d,%6d,%7d,%10d, %wZ\n",
  976. PUsage->KeyNodeCount,
  977. PUsage->KeyValueCount,
  978. CellCount,
  979. PUsage->Size,
  980. &KeyName);
  981. }
  982. return bRez;
  983. }