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.

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