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.

1363 lines
46 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. cmchek.c
  5. Abstract:
  6. This module implements consistency checking for the registry.
  7. This module can be linked standalone, cmchek2.c cannot.
  8. Author:
  9. Bryan M. Willman (bryanwi) 27-Jan-92
  10. Environment:
  11. Revision History:
  12. --*/
  13. #include "cmp.h"
  14. #define REG_MAX_PLAUSIBLE_KEY_SIZE \
  15. ((FIELD_OFFSET(CM_KEY_NODE, Name)) + \
  16. (sizeof(WCHAR) * REG_MAX_KEY_NAME_LENGTH) + 16)
  17. extern PCMHIVE CmpMasterHive;
  18. //
  19. // Private prototypes
  20. //
  21. ULONG
  22. CmpCheckRegistry2(
  23. PHHIVE HiveToCheck,
  24. ULONG CheckFlags,
  25. HCELL_INDEX Cell,
  26. HCELL_INDEX ParentCell,
  27. BOOLEAN ResetSD
  28. );
  29. ULONG
  30. CmpCheckKey(
  31. PHHIVE HiveToCheck,
  32. ULONG CheckFlags,
  33. HCELL_INDEX Cell,
  34. HCELL_INDEX ParentCell,
  35. BOOLEAN ResetSD
  36. );
  37. ULONG
  38. CmpCheckValueList(
  39. PHHIVE Hive,
  40. PCELL_DATA List,
  41. ULONG Count,
  42. HCELL_INDEX KeyCell
  43. );
  44. #ifdef ALLOC_PRAGMA
  45. #pragma alloc_text(PAGE,CmCheckRegistry)
  46. #pragma alloc_text(PAGE,CmpCheckRegistry2)
  47. #pragma alloc_text(PAGE,CmpCheckKey)
  48. #pragma alloc_text(PAGE,CmpCheckValueList)
  49. #ifdef CHECK_REGISTRY_USECOUNT
  50. #pragma alloc_text(PAGE,CmpCheckRegistryUseCount)
  51. #endif
  52. #endif
  53. //
  54. // debug structures
  55. //
  56. extern struct {
  57. PHHIVE Hive;
  58. ULONG Status;
  59. } CmCheckRegistryDebug;
  60. extern struct {
  61. PHHIVE Hive;
  62. ULONG Status;
  63. } CmpCheckRegistry2Debug;
  64. extern struct {
  65. PHHIVE Hive;
  66. ULONG Status;
  67. HCELL_INDEX Cell;
  68. PCELL_DATA CellPoint;
  69. PVOID RootPoint;
  70. ULONG Index;
  71. } CmpCheckKeyDebug;
  72. extern struct {
  73. PHHIVE Hive;
  74. ULONG Status;
  75. PCELL_DATA List;
  76. ULONG Index;
  77. HCELL_INDEX Cell;
  78. PCELL_DATA CellPoint;
  79. } CmpCheckValueListDebug;
  80. ULONG
  81. CmCheckRegistry(
  82. PCMHIVE CmHive,
  83. ULONG Flags
  84. )
  85. /*++
  86. Routine Description:
  87. Check consistency of the registry within a given hive. Start from
  88. root, and check that:
  89. . Each child key points back to its parent.
  90. . All allocated cells are refered to exactly once
  91. (requires looking inside the hive structure...)
  92. [This also detects space leaks.]
  93. . All allocated cells are reachable from the root.
  94. NOTE: Exactly 1 ref rule may change with security.
  95. Arguments:
  96. CmHive - supplies a pointer to the CM hive control structure for the
  97. hive of interest.
  98. Clean - if TRUE, references to volatile cells will be zapped
  99. (done at startup only to avoid groveling hives twice.)
  100. if FALSE, nothing will be changed.
  101. HiveCheck - If TRUE, performs hive consistency check too (i.e. checks
  102. the bins)
  103. Return Value:
  104. 0 if Hive is OK. Error return indicator if not.
  105. RANGE: 3000 - 3999
  106. --*/
  107. {
  108. PHHIVE Hive;
  109. ULONG rc = 0;
  110. ULONG Storage;
  111. PRELEASE_CELL_ROUTINE ReleaseCellRoutine;
  112. BOOLEAN ResetSD = FALSE;
  113. if (CmHive == CmpMasterHive) {
  114. return(0);
  115. }
  116. CmCheckRegistryDebug.Hive = (PHHIVE)CmHive;
  117. CmCheckRegistryDebug.Status = 0;
  118. //
  119. // check the underlying hive and get storage use
  120. //
  121. Hive = &CmHive->Hive;
  122. if( Flags & CM_CHECK_REGISTRY_HIVE_CHECK ) {
  123. rc = HvCheckHive(Hive, &Storage);
  124. if (rc != 0) {
  125. CmCheckRegistryDebug.Status = rc;
  126. return rc;
  127. }
  128. }
  129. //
  130. // Store the release cell procedure so we can restore at the end;
  131. // Set it to NULL so we don't count : this saves us some pain during the check
  132. //
  133. ReleaseCellRoutine = Hive->ReleaseCellRoutine;
  134. Hive->ReleaseCellRoutine = NULL;
  135. //
  136. // Validate all the security descriptors in the hive
  137. //
  138. if (!CmpValidateHiveSecurityDescriptors(Hive,&ResetSD)) {
  139. CmKdPrintEx((DPFLTR_CONFIG_ID,DPFLTR_ERROR_LEVEL,"CmCheckRegistry:"));
  140. CmKdPrintEx((DPFLTR_CONFIG_ID,DPFLTR_ERROR_LEVEL," CmpValidateHiveSecurityDescriptors failed\n"));
  141. rc = 3040;
  142. CmCheckRegistryDebug.Status = rc;
  143. }
  144. rc = CmpCheckRegistry2((PHHIVE)CmHive,Flags,Hive->BaseBlock->RootCell, HCELL_NIL,ResetSD);
  145. //
  146. // Print a bit of a summary (make sure this data avail in all error cases)
  147. //
  148. if (rc > 0) {
  149. CmKdPrintEx((DPFLTR_CONFIG_ID,DPFLTR_ERROR_LEVEL,"CmCheckRegistry Failed (%d): CmHive:%p\n", rc, CmHive));
  150. CmKdPrintEx((DPFLTR_CONFIG_ID,DPFLTR_ERROR_LEVEL," Hive:%p Root:%08lx\n", Hive, Hive->BaseBlock->RootCell));
  151. }
  152. //
  153. // restore the release cell routine
  154. // this saves us some pain during the check
  155. //
  156. Hive->ReleaseCellRoutine = ReleaseCellRoutine;
  157. return rc;
  158. }
  159. #ifndef _CM_LDR_
  160. ULONG
  161. CmpCheckRegistry2(
  162. PHHIVE HiveToCheck,
  163. ULONG CheckFlags,
  164. HCELL_INDEX Cell,
  165. HCELL_INDEX ParentCell,
  166. BOOLEAN ResetSD
  167. )
  168. /*++
  169. Routine Description:
  170. Check consistency of the registry, from a particular cell on down.
  171. . Check that the cell's value list, child key list, class,
  172. security are OK.
  173. . Check that each value entry IN the list is OK.
  174. . Apply self to each child key list.
  175. This version uses a stack in order to parse the tree "in-depth",
  176. but not to touch any key_node.
  177. Arguments:
  178. Cell - HCELL_INDEX of subkey to work on.
  179. ParentCell - expected value of parent cell for Cell, unless
  180. HCELL_NIL, in which case ignore.
  181. Return Value:
  182. 0 if Hive is OK. Error return indicator if not.
  183. RANGE: 4000 - 4999
  184. --*/
  185. {
  186. PCMP_CHECK_REGISTRY_STACK_ENTRY CheckStack;
  187. LONG StackIndex;
  188. PCM_KEY_NODE Node;
  189. ULONG rc = 0;
  190. HCELL_INDEX SubKey;
  191. CmpCheckRegistry2Debug.Hive = HiveToCheck;
  192. CmpCheckRegistry2Debug.Status = 0;
  193. ASSERT( HiveToCheck->ReleaseCellRoutine == NULL );
  194. //
  195. // Initialize the stack to simulate recursion here
  196. //
  197. CheckStack = ExAllocatePool(PagedPool,sizeof(CMP_CHECK_REGISTRY_STACK_ENTRY)*CMP_MAX_REGISTRY_DEPTH);
  198. if (CheckStack == NULL) {
  199. CmpCheckRegistry2Debug.Status = 4099;
  200. return 4099;
  201. }
  202. Restart:
  203. CheckStack[0].Cell = Cell;
  204. CheckStack[0].ParentCell = ParentCell;
  205. CheckStack[0].ChildIndex = 0;
  206. CheckStack[0].CellChecked = FALSE;
  207. StackIndex = 0;
  208. while(StackIndex >=0) {
  209. //
  210. // first check the current cell
  211. //
  212. if( CheckStack[StackIndex].CellChecked == FALSE ) {
  213. CheckStack[StackIndex].CellChecked = TRUE;
  214. rc = CmpCheckKey(HiveToCheck,CheckFlags,CheckStack[StackIndex].Cell, CheckStack[StackIndex].ParentCell,ResetSD);
  215. if (rc != 0) {
  216. CmKdPrintEx((DPFLTR_CONFIG_ID,DPFLTR_ERROR_LEVEL,"\tChild is list entry #%08lx\n", CheckStack[StackIndex].ChildIndex));
  217. CmpCheckRegistry2Debug.Status = rc;
  218. if( CmDoSelfHeal() && StackIndex ) { // root cell damage is fatal.
  219. //
  220. // delete this key from the parent's list and restart the whole iteration (not best performance, but safest).
  221. //
  222. if( !CmpRemoveSubKeyCellNoCellRef(HiveToCheck,CheckStack[StackIndex].ParentCell,CheckStack[StackIndex].Cell) ) {
  223. //
  224. // unable to delete subkey; punt.
  225. //
  226. break;
  227. }
  228. CmMarkSelfHeal(HiveToCheck);
  229. rc = 0;
  230. goto Restart;
  231. } else {
  232. // bail out
  233. break;
  234. }
  235. }
  236. }
  237. Node = (PCM_KEY_NODE)HvGetCell(HiveToCheck, CheckStack[StackIndex].Cell);
  238. if( Node == NULL ) {
  239. //
  240. // we couldn't map a view for the bin containing this cell
  241. //
  242. CmKdPrintEx((DPFLTR_CONFIG_ID,DPFLTR_ERROR_LEVEL,"\tCould not map cell #%08lx\n", CheckStack[StackIndex].Cell));
  243. CmpCheckRegistry2Debug.Status = 4098;
  244. rc = 4098;
  245. // bail out
  246. break;
  247. }
  248. if( CheckStack[StackIndex].ChildIndex < Node->SubKeyCounts[Stable] ) {
  249. //
  250. // we still have childs to check; add another entry for them and advance the
  251. // StackIndex
  252. //
  253. SubKey = CmpFindSubKeyByNumber(HiveToCheck,
  254. Node,
  255. CheckStack[StackIndex].ChildIndex);
  256. if( SubKey == HCELL_NIL ) {
  257. //
  258. // we couldn't map cell;bail out
  259. //
  260. CmKdPrintEx((DPFLTR_CONFIG_ID,DPFLTR_ERROR_LEVEL,"\tCould not map cell #%08lx\n", CheckStack[StackIndex].Cell));
  261. CmpCheckRegistry2Debug.Status = 4097;
  262. rc = 4097;
  263. break;
  264. }
  265. //
  266. // next iteration will check the next child
  267. //
  268. CheckStack[StackIndex].ChildIndex++;
  269. StackIndex++;
  270. if( StackIndex == CMP_MAX_REGISTRY_DEPTH ) {
  271. //
  272. // we've run out of stack; registry tree has too many levels
  273. //
  274. CmpCheckRegistry2Debug.Status = 4096;
  275. rc = 4096;
  276. // bail out
  277. break;
  278. }
  279. CheckStack[StackIndex].Cell = SubKey;
  280. CheckStack[StackIndex].ParentCell = CheckStack[StackIndex-1].Cell;
  281. CheckStack[StackIndex].ChildIndex = 0;
  282. CheckStack[StackIndex].CellChecked = FALSE;
  283. } else {
  284. //
  285. // we have checked all childs for this node; go back
  286. //
  287. StackIndex--;
  288. }
  289. }
  290. ExFreePool(CheckStack);
  291. return rc;
  292. }
  293. #else
  294. ULONG
  295. CmpCheckRegistry2(
  296. PHHIVE HiveToCheck,
  297. ULONG CheckFlags,
  298. HCELL_INDEX Cell,
  299. HCELL_INDEX ParentCell,
  300. BOOLEAN ResetSD
  301. )
  302. /*++
  303. Routine Description:
  304. Check consistency of the registry, from a particular cell on down.
  305. . Check that the cell's value list, child key list, class,
  306. security are OK.
  307. . Check that each value entry IN the list is OK.
  308. . Apply self to each child key list.
  309. Arguments:
  310. Cell - HCELL_INDEX of subkey to work on.
  311. ParentCell - expected value of parent cell for Cell, unless
  312. HCELL_NIL, in which case ignore.
  313. Return Value:
  314. 0 if Hive is OK. Error return indicator if not.
  315. RANGE: 4000 - 4999
  316. --*/
  317. {
  318. ULONG Index;
  319. HCELL_INDEX StartCell;
  320. HCELL_INDEX SubKey;
  321. ULONG rc = 0;
  322. PCELL_DATA pcell;
  323. PCM_KEY_NODE Node;
  324. HCELL_INDEX EnterParent = ParentCell;
  325. HCELL_INDEX EnterCell = Cell;
  326. CmpCheckRegistry2Debug.Hive = HiveToCheck;
  327. CmpCheckRegistry2Debug.Status = 0;
  328. ASSERT( HiveToCheck->ReleaseCellRoutine == NULL );
  329. Restart:
  330. Cell = EnterCell;
  331. ParentCell = EnterParent;
  332. StartCell = EnterCell;
  333. Index = 0;
  334. //
  335. // A jump to NewKey amounts to a virtual call to check the
  336. // next child cell. (a descent into the tree)
  337. //
  338. // Cell, ParentCell, Index, and globals are defined
  339. //
  340. NewKey:
  341. rc = CmpCheckKey(HiveToCheck,CheckFlags,Cell, ParentCell,ResetSD);
  342. if (rc != 0) {
  343. CmKdPrintEx((DPFLTR_CONFIG_ID,DPFLTR_ERROR_LEVEL,"\tChild is list entry #%08lx\n", Index));
  344. CmpCheckRegistry2Debug.Status = rc;
  345. if( CmDoSelfHeal() && (Cell != EnterCell)) { // root cell damage is fatal.
  346. //
  347. // delete this key from the parent's list and restart the whole iteration (not best performance, but safest).
  348. //
  349. if( !CmpRemoveSubKeyCellNoCellRef(HiveToCheck,ParentCell,Cell) ) {
  350. //
  351. // unable to delete subkey; punt.
  352. //
  353. return rc;
  354. }
  355. CmMarkSelfHeal(HiveToCheck);
  356. rc = 0;
  357. goto Restart;
  358. } else {
  359. // bail out
  360. return rc;
  361. }
  362. }
  363. //
  364. // save Index and check out children
  365. //
  366. pcell = HvGetCell(HiveToCheck, Cell);
  367. if( pcell == NULL ) {
  368. //
  369. // we couldn't map a view for the bin containing this cell
  370. //
  371. CmKdPrintEx((DPFLTR_CONFIG_ID,DPFLTR_ERROR_LEVEL,"\tCould not map cell #%08lx\n", Cell));
  372. CmpCheckRegistry2Debug.Status = 4099;
  373. return 4099;
  374. }
  375. pcell->u.KeyNode.WorkVar = Index;
  376. for (Index = 0; Index<pcell->u.KeyNode.SubKeyCounts[Stable]; Index++) {
  377. Node = (PCM_KEY_NODE)HvGetCell(HiveToCheck,Cell);
  378. if( Node == NULL ) {
  379. //
  380. // we couldn't map a view for the bin containing this cell
  381. //
  382. CmKdPrintEx((DPFLTR_CONFIG_ID,DPFLTR_ERROR_LEVEL,"\tCould not map cell #%08lx\n", Cell));
  383. CmpCheckRegistry2Debug.Status = 4098;
  384. return 4098;
  385. }
  386. SubKey = CmpFindSubKeyByNumber(HiveToCheck,
  387. Node,
  388. Index);
  389. if( SubKey == HCELL_NIL ) {
  390. //
  391. // we couldn't map cell;bail out
  392. //
  393. return 0;
  394. }
  395. //
  396. // "recurse" onto child
  397. //
  398. ParentCell = Cell;
  399. Cell = SubKey;
  400. goto NewKey;
  401. ResumeKey:; // A jump here is a virtual return
  402. // Cell, ParentCell and Index
  403. // must be defined
  404. }
  405. //
  406. // since we're here, we've checked out all the children
  407. // of the current cell.
  408. //
  409. if (Cell == StartCell) {
  410. //
  411. // we are done
  412. //
  413. return 0;
  414. }
  415. //
  416. // "return" to "parent instance"
  417. //
  418. pcell = HvGetCell(HiveToCheck, Cell);
  419. if( pcell == NULL ) {
  420. //
  421. // we couldn't map a view for the bin containing this cell
  422. //
  423. CmKdPrintEx((DPFLTR_CONFIG_ID,DPFLTR_ERROR_LEVEL,"\tCould not map cell #%08lx\n", Cell));
  424. CmpCheckRegistry2Debug.Status = 4097;
  425. return 4097;
  426. }
  427. Index = pcell->u.KeyNode.WorkVar;
  428. Cell = ParentCell;
  429. pcell = HvGetCell(HiveToCheck, Cell);
  430. if( pcell == NULL ) {
  431. //
  432. // we couldn't map a view for the bin containing this cell
  433. //
  434. CmKdPrintEx((DPFLTR_CONFIG_ID,DPFLTR_ERROR_LEVEL,"\tCould not map cell #%08lx\n", Cell));
  435. CmpCheckRegistry2Debug.Status = 4096;
  436. return 4096;
  437. }
  438. ParentCell = pcell->u.KeyNode.Parent;
  439. goto ResumeKey;
  440. }
  441. #endif //_CM_LDR_
  442. #if DBG
  443. #define VOLATILE_KEY_NAME_LENGTH PAGE_SIZE
  444. HCELL_INDEX CmpKeyCellDebug = 0;
  445. WCHAR CmpVolatileKeyNameBuffer[VOLATILE_KEY_NAME_LENGTH/2];
  446. #endif //DBG
  447. ULONG
  448. CmpCheckKey(
  449. PHHIVE HiveToCheck,
  450. ULONG CheckFlags,
  451. HCELL_INDEX Cell,
  452. HCELL_INDEX ParentCell,
  453. BOOLEAN ResetSD
  454. )
  455. /*++
  456. Routine Description:
  457. Check consistency of the registry, for a particular cell
  458. . Check that the cell's value list, child key list, class,
  459. security are OK.
  460. . Check that each value entry IN the list is OK.
  461. Arguments:
  462. Cell - HCELL_INDEX of subkey to work on.
  463. ParentCell - expected value of parent cell for Cell, unless
  464. HCELL_NIL, in which case ignore.
  465. Return Value:
  466. 0 if Hive is OK. Error return indicator if not.
  467. RANGE: 4000 - 4999
  468. --*/
  469. {
  470. PCELL_DATA pcell;
  471. ULONG size;
  472. ULONG usedlen;
  473. ULONG ClassLength;
  474. HCELL_INDEX Class;
  475. ULONG ValueCount;
  476. HCELL_INDEX ValueList;
  477. HCELL_INDEX Security;
  478. ULONG rc = 0;
  479. ULONG nrc = 0;
  480. ULONG i;
  481. PCM_KEY_INDEX Root;
  482. PCM_KEY_INDEX Leaf;
  483. ULONG SubCount;
  484. CmpCheckKeyDebug.Hive = HiveToCheck;
  485. CmpCheckKeyDebug.Status = 0;
  486. CmpCheckKeyDebug.Cell = Cell;
  487. CmpCheckKeyDebug.CellPoint = NULL;
  488. CmpCheckKeyDebug.RootPoint = NULL;
  489. CmpCheckKeyDebug.Index = (ULONG)-1;
  490. #if DBG
  491. if(CmpKeyCellDebug == Cell) {
  492. CmKdPrintEx((DPFLTR_CONFIG_ID,DPFLTR_TRACE_LEVEL,"Hive = %p :: Cell to debug = %lx\n",HiveToCheck,(ULONG)Cell));
  493. DbgBreakPoint();
  494. }
  495. #endif //DBG
  496. //
  497. // Check key itself
  498. //
  499. if (! HvIsCellAllocated(HiveToCheck, Cell)) {
  500. CmKdPrintEx((DPFLTR_CONFIG_ID,DPFLTR_ERROR_LEVEL,"CmpCheckKey: HiveToCheck:%p Cell:%08lx\n", HiveToCheck, Cell));
  501. CmKdPrintEx((DPFLTR_CONFIG_ID,DPFLTR_ERROR_LEVEL,"\tNot allocated\n"));
  502. rc = 4010;
  503. CmpCheckKeyDebug.Status = rc;
  504. return rc;
  505. }
  506. pcell = HvGetCell(HiveToCheck, Cell);
  507. if( pcell == NULL ) {
  508. //
  509. // we couldn't map a view for the bin containing this cell
  510. //
  511. CmKdPrintEx((DPFLTR_CONFIG_ID,DPFLTR_ERROR_LEVEL,"\tCould not map cell #%08lx\n", Cell));
  512. CmpCheckKeyDebug.Status = 4095;
  513. return 4095;
  514. }
  515. CmpCheckKeyDebug.CellPoint = pcell;
  516. size = HvGetCellSize(HiveToCheck, pcell);
  517. if (size > REG_MAX_PLAUSIBLE_KEY_SIZE) {
  518. CmKdPrintEx((DPFLTR_CONFIG_ID,DPFLTR_ERROR_LEVEL,"CmpCheckKey: HiveToCheck:%p Cell:%08lx\n", HiveToCheck, Cell));
  519. CmKdPrintEx((DPFLTR_CONFIG_ID,DPFLTR_ERROR_LEVEL,"\tImplausible size %lx\n", size));
  520. rc = 4020;
  521. CmpCheckKeyDebug.Status = rc;
  522. return rc;
  523. }
  524. usedlen = FIELD_OFFSET(CM_KEY_NODE, Name) + pcell->u.KeyNode.NameLength;
  525. if( (!pcell->u.KeyNode.NameLength) || (usedlen > size)) {
  526. CmKdPrintEx((DPFLTR_CONFIG_ID,DPFLTR_ERROR_LEVEL,"CmpCheckKey: HiveToCheck:%p Cell:%08lx\n", HiveToCheck, Cell));
  527. CmKdPrintEx((DPFLTR_CONFIG_ID,DPFLTR_ERROR_LEVEL,"\tKey is bigger than containing cell.\n"));
  528. rc = 4030;
  529. CmpCheckKeyDebug.Status = rc;
  530. return rc;
  531. }
  532. if (pcell->u.KeyNode.Signature != CM_KEY_NODE_SIGNATURE) {
  533. CmKdPrintEx((DPFLTR_CONFIG_ID,DPFLTR_ERROR_LEVEL,"CmpCheckKey: HiveToCheck:%p Cell:%08lx\n", HiveToCheck, Cell));
  534. CmKdPrintEx((DPFLTR_CONFIG_ID,DPFLTR_ERROR_LEVEL,"\tNo key signature\n"));
  535. rc = 4040;
  536. CmpCheckKeyDebug.Status = rc;
  537. if( CmDoSelfHeal() ) {
  538. //
  539. // this could be only signature corruption; fix it;
  540. //
  541. if( HvMarkCellDirty(HiveToCheck, Cell) ) {
  542. pcell->u.KeyNode.Signature = CM_KEY_NODE_SIGNATURE;
  543. rc = 0;
  544. CmMarkSelfHeal(HiveToCheck);
  545. } else {
  546. return rc;
  547. }
  548. } else {
  549. return rc;
  550. }
  551. }
  552. if (ParentCell != HCELL_NIL) {
  553. if (pcell->u.KeyNode.Parent != ParentCell) {
  554. CmKdPrintEx((DPFLTR_CONFIG_ID,DPFLTR_ERROR_LEVEL,"CmpCheckKey: HiveToCheck:%p Cell:%08lx\n", HiveToCheck, Cell));
  555. CmKdPrintEx((DPFLTR_CONFIG_ID,DPFLTR_ERROR_LEVEL,"\tWrong parent value.\n"));
  556. rc = 4045;
  557. CmpCheckKeyDebug.Status = rc;
  558. if( CmDoSelfHeal() ) {
  559. //
  560. // this could isolated corruption; fix it;
  561. //
  562. if( HvMarkCellDirty(HiveToCheck, Cell) ) {
  563. pcell->u.KeyNode.Parent = ParentCell;
  564. CmMarkSelfHeal(HiveToCheck);
  565. rc = 0;
  566. } else {
  567. return rc;
  568. }
  569. } else {
  570. return rc;
  571. }
  572. }
  573. }
  574. ClassLength = pcell->u.KeyNode.ClassLength;
  575. Class = pcell->u.KeyNode.Class;
  576. ValueCount = pcell->u.KeyNode.ValueList.Count;
  577. ValueList = pcell->u.KeyNode.ValueList.List;
  578. Security = pcell->u.KeyNode.Security;
  579. //
  580. // Check simple non-empty cases
  581. //
  582. if (ClassLength > 0) {
  583. if( Class == HCELL_NIL ) {
  584. pcell->u.KeyNode.ClassLength = 0;
  585. HvMarkCellDirty(HiveToCheck, Cell);
  586. CmKdPrintEx((DPFLTR_CONFIG_ID,DPFLTR_ERROR_LEVEL,"CmpCheckKey: HiveToCheck:%p Cell:%08lx has ClassLength = %lu and Class == HCELL_NIL\n", HiveToCheck, Cell,ClassLength));
  587. } else {
  588. if (HvIsCellAllocated(HiveToCheck, Class) == FALSE) {
  589. CmKdPrintEx((DPFLTR_CONFIG_ID,DPFLTR_ERROR_LEVEL,"CmpCheckKey: HiveToCheck:%p Cell:%08lx\n", HiveToCheck, Cell));
  590. CmKdPrintEx((DPFLTR_CONFIG_ID,DPFLTR_ERROR_LEVEL,"\tClass:%08lx - unallocated class\n", Class));
  591. rc = 4080;
  592. CmpCheckKeyDebug.Status = rc;
  593. if( CmDoSelfHeal() ) {
  594. //
  595. // yank the class
  596. //
  597. if( HvMarkCellDirty(HiveToCheck, Cell) ) {
  598. pcell->u.KeyNode.Class = HCELL_NIL;
  599. pcell->u.KeyNode.ClassLength = 0;
  600. CmMarkSelfHeal(HiveToCheck);
  601. rc = 0;
  602. } else {
  603. return rc;
  604. }
  605. } else {
  606. return rc;
  607. }
  608. }
  609. }
  610. }
  611. if (Security != HCELL_NIL) {
  612. if ((HvIsCellAllocated(HiveToCheck, Security) == FALSE) ||
  613. ((ParentCell != HCELL_NIL) && CmDoSelfHeal() && ResetSD) ) {
  614. CmKdPrintEx((DPFLTR_CONFIG_ID,DPFLTR_ERROR_LEVEL,"CmpCheckKey: HiveToCheck:%p Cell:%08lx\n", HiveToCheck, Cell));
  615. CmKdPrintEx((DPFLTR_CONFIG_ID,DPFLTR_ERROR_LEVEL,"\tSecurity:%08lx - unallocated security\n", Security));
  616. rc = 4090;
  617. CmpCheckKeyDebug.Status = rc;
  618. goto SetParentSecurity;
  619. }
  620. //
  621. // Else CmpValidateHiveSecurityDescriptors must do computation
  622. //
  623. } else {
  624. CmKdPrintEx((DPFLTR_CONFIG_ID,DPFLTR_ERROR_LEVEL,"SecurityCell is HCELL_NIL for (%p,%08lx) !!!\n", HiveToCheck, Cell));
  625. rc = 4130;
  626. CmpCheckKeyDebug.Status = rc;
  627. SetParentSecurity:
  628. if( CmDoSelfHeal() ) {
  629. //
  630. // attempt to set the same security as it's parent
  631. //
  632. PCM_KEY_NODE ParentNode = NULL;
  633. PCM_KEY_SECURITY SecurityNode = NULL;
  634. if( ParentCell != HCELL_NIL ) {
  635. ParentNode = (PCM_KEY_NODE )HvGetCell(HiveToCheck, ParentCell);
  636. SecurityNode = (PCM_KEY_SECURITY)HvGetCell(HiveToCheck, ParentNode->Security);
  637. }
  638. if( ParentNode == NULL || SecurityNode == NULL ) {
  639. //
  640. // we couldn't map a view for the bin containing this cell
  641. //
  642. return rc;
  643. }
  644. if( HvMarkCellDirty(HiveToCheck, Cell) && HvMarkCellDirty(HiveToCheck, ParentNode->Security) ) {
  645. pcell->u.KeyNode.Security = ParentNode->Security;
  646. SecurityNode->ReferenceCount++;
  647. rc = 0;
  648. CmMarkSelfHeal(HiveToCheck);
  649. } else {
  650. return rc;
  651. }
  652. } else {
  653. return rc;
  654. }
  655. }
  656. //
  657. // Check value list case
  658. //
  659. if (ValueCount > 0) {
  660. if (HvIsCellAllocated(HiveToCheck, ValueList) == FALSE) {
  661. CmKdPrintEx((DPFLTR_CONFIG_ID,DPFLTR_ERROR_LEVEL,"CmpCheckKey: HiveToCheck:%p Cell:%08lx\n", HiveToCheck, Cell));
  662. CmKdPrintEx((DPFLTR_CONFIG_ID,DPFLTR_ERROR_LEVEL,"\tValueList:%08lx - unallocated valuelist\n", ValueList));
  663. rc = 4100;
  664. CmpCheckKeyDebug.Status = rc;
  665. goto YankValueList;
  666. } else {
  667. pcell = HvGetCell(HiveToCheck, ValueList);
  668. if( pcell == NULL ) {
  669. //
  670. // we couldn't map a view for the bin containing this cell
  671. //
  672. CmKdPrintEx((DPFLTR_CONFIG_ID,DPFLTR_ERROR_LEVEL,"\tCould not map cell #%08lx\n", ValueList));
  673. CmpCheckKeyDebug.Status = 4094;
  674. return 4094;
  675. }
  676. if( ValueCount * sizeof(HCELL_INDEX) > (ULONG)HvGetCellSize(HiveToCheck,pcell) ) {
  677. //
  678. // implausible value count.
  679. //
  680. CmKdPrintEx((DPFLTR_CONFIG_ID,DPFLTR_ERROR_LEVEL,"CmpCheckKey: HiveToCheck:%p Cell:%08lx\n", HiveToCheck, Cell));
  681. CmKdPrintEx((DPFLTR_CONFIG_ID,DPFLTR_ERROR_LEVEL,"\tValueList:%08lx - Implausible ValueCount = %08lx\n", ValueList,ValueCount));
  682. rc = 4095;
  683. CmpCheckKeyDebug.Status = rc;
  684. goto YankValueList;
  685. }
  686. nrc = CmpCheckValueList(HiveToCheck, pcell, ValueCount,Cell);
  687. if (nrc != 0) {
  688. CmKdPrintEx((DPFLTR_CONFIG_ID,DPFLTR_ERROR_LEVEL,"List was for HiveToCheck:%p Cell:%08lx\n", HiveToCheck, Cell));
  689. rc = nrc;
  690. CmpCheckKeyDebug.CellPoint = pcell;
  691. CmpCheckKeyDebug.Status = rc;
  692. YankValueList:
  693. if( CmDoSelfHeal() ) {
  694. PCM_KEY_NODE KeyNode;
  695. //
  696. // make the key valueless
  697. //
  698. if( HvMarkCellDirty(HiveToCheck, Cell) && (KeyNode = (PCM_KEY_NODE)HvGetCell(HiveToCheck, Cell) ) ) {
  699. KeyNode->ValueList.Count = 0;
  700. KeyNode->ValueList.List = HCELL_NIL;
  701. CmMarkSelfHeal(HiveToCheck);
  702. rc = 0;
  703. } else {
  704. return rc;
  705. }
  706. } else {
  707. return rc;
  708. }
  709. }
  710. }
  711. }
  712. //
  713. // Check subkey list case
  714. //
  715. pcell = HvGetCell(HiveToCheck, Cell);
  716. if( pcell == NULL ) {
  717. //
  718. // we couldn't map a view for the bin containing this cell
  719. //
  720. CmKdPrintEx((DPFLTR_CONFIG_ID,DPFLTR_ERROR_LEVEL,"\tCould not map cell #%08lx\n", Cell));
  721. CmpCheckKeyDebug.Status = 4093;
  722. return 4093;
  723. }
  724. CmpCheckKeyDebug.CellPoint = pcell;
  725. if ((HvGetCellType(Cell) == Volatile) &&
  726. (pcell->u.KeyNode.SubKeyCounts[Stable] != 0))
  727. {
  728. CmKdPrintEx((DPFLTR_CONFIG_ID,DPFLTR_ERROR_LEVEL,"CmpCheckKey: HiveToCheck:%p Cell:%08lx\n", HiveToCheck, Cell));
  729. CmKdPrintEx((DPFLTR_CONFIG_ID,DPFLTR_ERROR_LEVEL,"\tVolatile Cell has Stable children\n"));
  730. rc = 4108;
  731. CmpCheckKeyDebug.Status = rc;
  732. return rc;
  733. } else if (pcell->u.KeyNode.SubKeyCounts[Stable] > 0) {
  734. if (! HvIsCellAllocated(HiveToCheck, pcell->u.KeyNode.SubKeyLists[Stable])) {
  735. CmKdPrintEx((DPFLTR_CONFIG_ID,DPFLTR_ERROR_LEVEL,"CmpCheckKey: HiveToCheck:%p Cell:%08lx\n", HiveToCheck, Cell));
  736. CmKdPrintEx((DPFLTR_CONFIG_ID,DPFLTR_ERROR_LEVEL,"\tStableKeyList:%08lx - unallocated\n", pcell->u.KeyNode.SubKeyLists[Stable]));
  737. rc = 4110;
  738. CmpCheckKeyDebug.Status = rc;
  739. goto YankStableSubkeys;
  740. } else {
  741. //
  742. // Prove that the index is OK
  743. //
  744. Root = (PCM_KEY_INDEX)HvGetCell(
  745. HiveToCheck,
  746. pcell->u.KeyNode.SubKeyLists[Stable]
  747. );
  748. if( Root == NULL ) {
  749. //
  750. // we couldn't map a view for the bin containing this cell
  751. //
  752. CmKdPrintEx((DPFLTR_CONFIG_ID,DPFLTR_ERROR_LEVEL,"\tCould not map cell #%08lx\n", pcell->u.KeyNode.SubKeyLists[Stable]));
  753. CmpCheckKeyDebug.Status = 4093;
  754. return 4093;
  755. }
  756. CmpCheckKeyDebug.RootPoint = Root;
  757. if ((Root->Signature == CM_KEY_INDEX_LEAF) ||
  758. (Root->Signature == CM_KEY_FAST_LEAF) ||
  759. (Root->Signature == CM_KEY_HASH_LEAF) ) {
  760. if ((ULONG)Root->Count != pcell->u.KeyNode.SubKeyCounts[Stable]) {
  761. CmKdPrintEx((DPFLTR_CONFIG_ID,DPFLTR_ERROR_LEVEL,"CmpCheckKey: HiveToCheck:%p Cell:%08lx\n", HiveToCheck, Cell));
  762. CmKdPrintEx((DPFLTR_CONFIG_ID,DPFLTR_ERROR_LEVEL,"\tBad Index count @%08lx\n", Root));
  763. rc = 4120;
  764. CmpCheckKeyDebug.Status = rc;
  765. if( CmDoSelfHeal() ) {
  766. //
  767. // fix the subkeycount
  768. //
  769. if( HvMarkCellDirty(HiveToCheck, Cell) ) {
  770. pcell->u.KeyNode.SubKeyCounts[Stable] = (ULONG)Root->Count;
  771. CmMarkSelfHeal(HiveToCheck);
  772. rc = 0;
  773. } else {
  774. return rc;
  775. }
  776. } else {
  777. return rc;
  778. }
  779. }
  780. } else if (Root->Signature == CM_KEY_INDEX_ROOT) {
  781. SubCount = 0;
  782. for (i = 0; i < Root->Count; i++) {
  783. CmpCheckKeyDebug.Index = i;
  784. if (! HvIsCellAllocated(HiveToCheck, Root->List[i])) {
  785. CmKdPrintEx((DPFLTR_CONFIG_ID,DPFLTR_ERROR_LEVEL,"CmpCheckKey: Hive:%p Cell:%08lx\n", HiveToCheck, Cell));
  786. CmKdPrintEx((DPFLTR_CONFIG_ID,DPFLTR_ERROR_LEVEL,"\tBad Leaf Cell %08lx Root@%08lx\n", Root->List[i], Root));
  787. rc = 4130;
  788. CmpCheckKeyDebug.Status = rc;
  789. goto YankStableSubkeys;
  790. }
  791. Leaf = (PCM_KEY_INDEX)HvGetCell(HiveToCheck,
  792. Root->List[i]);
  793. if( Leaf == NULL ) {
  794. //
  795. // we couldn't map a view for the bin containing this cell
  796. //
  797. CmKdPrintEx((DPFLTR_CONFIG_ID,DPFLTR_ERROR_LEVEL,"\tCould not map cell #%08lx\n", Root->List[i]));
  798. CmpCheckKeyDebug.Status = 4092;
  799. return 4092;
  800. }
  801. if ((Leaf->Signature != CM_KEY_INDEX_LEAF) &&
  802. (Leaf->Signature != CM_KEY_FAST_LEAF) &&
  803. (Leaf->Signature != CM_KEY_HASH_LEAF) ) {
  804. CmKdPrintEx((DPFLTR_CONFIG_ID,DPFLTR_ERROR_LEVEL,"CmpCheckKey: HiveToCheck:%p Cell:%08lx\n", HiveToCheck, Cell));
  805. CmKdPrintEx((DPFLTR_CONFIG_ID,DPFLTR_ERROR_LEVEL,"\tBad Leaf Index @%08lx Root@%08lx\n", Leaf, Root));
  806. rc = 4140;
  807. CmpCheckKeyDebug.Status = rc;
  808. goto YankStableSubkeys;
  809. }
  810. SubCount += Leaf->Count;
  811. }
  812. if (pcell->u.KeyNode.SubKeyCounts[Stable] != SubCount) {
  813. CmKdPrintEx((DPFLTR_CONFIG_ID,DPFLTR_ERROR_LEVEL,"CmpCheckKey: HiveToCheck:%p Cell:%08lx\n", HiveToCheck, Cell));
  814. CmKdPrintEx((DPFLTR_CONFIG_ID,DPFLTR_ERROR_LEVEL,"\tBad count in index, SubCount=%08lx\n", SubCount));
  815. rc = 4150;
  816. CmpCheckKeyDebug.Status = rc;
  817. if( CmDoSelfHeal() ) {
  818. //
  819. // fix the subkeycount
  820. //
  821. if( HvMarkCellDirty(HiveToCheck, Cell) ) {
  822. pcell->u.KeyNode.SubKeyCounts[Stable] = SubCount;
  823. CmMarkSelfHeal(HiveToCheck);
  824. rc = 0;
  825. } else {
  826. return rc;
  827. }
  828. } else {
  829. return rc;
  830. }
  831. }
  832. } else {
  833. CmKdPrintEx((DPFLTR_CONFIG_ID,DPFLTR_ERROR_LEVEL,"CmpCheckKey: HiveToCheck:%p Cell:%08lx\n", HiveToCheck, Cell));
  834. CmKdPrintEx((DPFLTR_CONFIG_ID,DPFLTR_ERROR_LEVEL,"\tBad Root index signature @%08lx\n", Root));
  835. rc = 4120;
  836. CmpCheckKeyDebug.Status = rc;
  837. goto YankStableSubkeys;
  838. }
  839. }
  840. }
  841. if( FALSE ) {
  842. YankStableSubkeys:
  843. if( CmDoSelfHeal() ) {
  844. //
  845. // mark the key as no subkeys
  846. //
  847. if( HvMarkCellDirty(HiveToCheck, Cell) ) {
  848. pcell->u.KeyNode.SubKeyCounts[Stable] = 0;
  849. pcell->u.KeyNode.SubKeyLists[Stable] = HCELL_NIL;
  850. CmMarkSelfHeal(HiveToCheck);
  851. rc = 0;
  852. } else {
  853. return rc;
  854. }
  855. } else {
  856. return rc;
  857. }
  858. }
  859. //
  860. // force volatiles to be empty, if this is a load operation
  861. //
  862. if ( (CheckFlags & CM_CHECK_REGISTRY_FORCE_CLEAN) || // force clear out volatile info
  863. (
  864. ( CheckFlags & (CM_CHECK_REGISTRY_CHECK_CLEAN | CM_CHECK_REGISTRY_LOADER_CLEAN) ) && // if asked to clear volatile info
  865. ( pcell->u.KeyNode.SubKeyCounts[Volatile] != 0 ) // there is some volatile info saved from a previous version
  866. ) ||
  867. (
  868. ( CheckFlags & CM_CHECK_REGISTRY_SYSTEM_CLEAN ) && // system hive special case; the loader has cleaned only subkeycount
  869. (( pcell->u.KeyNode.SubKeyLists[Volatile] != HCELL_NIL ) || // now it is our job to clear Subkeylist, too
  870. (HiveToCheck->Version < HSYS_WHISTLER_BETA1) )
  871. )
  872. ) {
  873. //
  874. // go ahead and clear the volatile info for this key
  875. //
  876. if( CheckFlags & CM_CHECK_REGISTRY_SYSTEM_CLEAN ) {
  877. //
  878. // the loader must've left this on the previous value and cleared only the count
  879. //
  880. ASSERT( pcell->u.KeyNode.SubKeyLists[Volatile] == 0xBAADF00D || HiveToCheck->Version < HSYS_WHISTLER_BETA1 );
  881. ASSERT( pcell->u.KeyNode.SubKeyCounts[Volatile] == 0 );
  882. #if DBG
  883. #ifndef _CM_LDR_
  884. //
  885. // see who those volatile keys are
  886. //
  887. {
  888. ULONG TotalLength = 0;
  889. HCELL_INDEX CurrCell = Cell;
  890. PCM_KEY_NODE CurrNode;
  891. PUCHAR Dest;
  892. ULONG k;
  893. Dest = ((PUCHAR)CmpVolatileKeyNameBuffer) + VOLATILE_KEY_NAME_LENGTH - 2;
  894. while(TRUE) {
  895. CurrNode = (PCM_KEY_NODE)HvGetCell(HiveToCheck,CurrCell);
  896. Dest -= CurrNode->NameLength;
  897. TotalLength += CurrNode->NameLength;
  898. if (CurrNode->Flags & KEY_COMP_NAME) {
  899. Dest -= CurrNode->NameLength;
  900. for (k=0;k<CurrNode->NameLength;k++) {
  901. ((PWCHAR)Dest)[k] = (WCHAR)(((PUCHAR)CurrNode->Name)[k]);
  902. }
  903. } else {
  904. RtlCopyMemory(
  905. Dest,
  906. CurrNode->Name,
  907. CurrNode->NameLength
  908. );
  909. }
  910. Dest -= 2;
  911. TotalLength += (CurrNode->NameLength +2);
  912. ((PWCHAR)Dest)[0] = (WCHAR)'\\';
  913. if( CurrCell == HiveToCheck->BaseBlock->RootCell ) {
  914. break;
  915. }
  916. CurrCell = CurrNode->Parent;
  917. }
  918. CmKdPrintEx((DPFLTR_CONFIG_ID,DPFLTR_TRACE_LEVEL,"%.*S\n",TotalLength/2,Dest));
  919. }
  920. #endif
  921. #endif
  922. }
  923. HvMarkCellDirty(HiveToCheck, Cell);
  924. //CmKdPrintEx((DPFLTR_CONFIG_ID,DPFLTR_TRACE_LEVEL,"Clear Volatile Info for Hive = %p Cell = %lx\n", HiveToCheck, Cell));
  925. pcell->u.KeyNode.SubKeyCounts[Volatile] = 0;
  926. if( (CheckFlags & CM_CHECK_REGISTRY_LOADER_CLEAN) &&
  927. (HiveToCheck->Version >= HSYS_WHISTLER_BETA1)
  928. ) {
  929. //
  930. // mark this as bad food
  931. //
  932. pcell->u.KeyNode.SubKeyLists[Volatile] = 0xBAADF00D;
  933. } else {
  934. //
  935. // clean it up
  936. //
  937. pcell->u.KeyNode.SubKeyLists[Volatile] = HCELL_NIL;
  938. }
  939. }
  940. return rc;
  941. }
  942. ULONG
  943. CmpCheckValueList(
  944. PHHIVE Hive,
  945. PCELL_DATA List,
  946. ULONG Count,
  947. HCELL_INDEX KeyCell
  948. )
  949. /*++
  950. Routine Description:
  951. Check consistency of a value list.
  952. . Each element allocated?
  953. . Each element have valid signature?
  954. . Data properly allocated?
  955. Arguments:
  956. Hive - containing Hive.
  957. List - pointer to an array of HCELL_INDEX entries.
  958. Count - number of entries in list.
  959. Return Value:
  960. 0 if Hive is OK. Error return indicator if not.
  961. RANGE: 5000 - 5999
  962. --*/
  963. {
  964. ULONG i = 0,j;
  965. HCELL_INDEX Cell;
  966. PCELL_DATA pcell;
  967. ULONG size;
  968. ULONG usedlen;
  969. ULONG DataLength;
  970. HCELL_INDEX Data;
  971. ULONG rc = 0;
  972. CmpCheckValueListDebug.Hive = Hive;
  973. CmpCheckValueListDebug.Status = 0;
  974. CmpCheckValueListDebug.List = List;
  975. CmpCheckValueListDebug.Index = (ULONG)-1;
  976. CmpCheckValueListDebug.Cell = 0; // NOT HCELL_NIL
  977. CmpCheckValueListDebug.CellPoint = NULL;
  978. if( FALSE ) {
  979. RemoveThisValue:
  980. if( CmDoSelfHeal() ) {
  981. //
  982. // remove value at index i
  983. //
  984. PCM_KEY_NODE Node;
  985. Node = (PCM_KEY_NODE)HvGetCell(Hive,KeyCell);
  986. if( Node == NULL ) {
  987. return rc;
  988. }
  989. HvReleaseCell(Hive,KeyCell);
  990. if( HvMarkCellDirty(Hive, KeyCell) &&
  991. HvMarkCellDirty(Hive, Node->ValueList.List)) {
  992. Node->ValueList.Count--;
  993. Count--;
  994. RtlMoveMemory(&(List->u.KeyList[i]),&(List->u.KeyList[i+1]),(Count - i)*sizeof(HCELL_INDEX));
  995. rc = 0;
  996. CmMarkSelfHeal(Hive);
  997. } else {
  998. return rc;
  999. }
  1000. } else {
  1001. return rc;
  1002. }
  1003. }
  1004. for (; i < Count; i++) {
  1005. //
  1006. // Check out value entry's refs.
  1007. //
  1008. Cell = List->u.KeyList[i];
  1009. if (Cell == HCELL_NIL) {
  1010. CmKdPrintEx((DPFLTR_CONFIG_ID,DPFLTR_ERROR_LEVEL,"CmpCheckValueList: List:%p i:%08lx\n", List, i));
  1011. CmKdPrintEx((DPFLTR_CONFIG_ID,DPFLTR_ERROR_LEVEL,"\tEntry is null\n"));
  1012. rc = 5010;
  1013. CmpCheckValueListDebug.Status = rc;
  1014. CmpCheckValueListDebug.Index = i;
  1015. CmpCheckValueListDebug.Cell = Cell;
  1016. goto RemoveThisValue;
  1017. }
  1018. if (HvIsCellAllocated(Hive, Cell) == FALSE) {
  1019. CmKdPrintEx((DPFLTR_CONFIG_ID,DPFLTR_ERROR_LEVEL,"CmpCheckValueList: List:%p i:%08lx\n", List, i));
  1020. CmKdPrintEx((DPFLTR_CONFIG_ID,DPFLTR_ERROR_LEVEL,"\tEntry is not allocated\n"));
  1021. rc = 5020;
  1022. CmpCheckValueListDebug.Status = rc;
  1023. CmpCheckValueListDebug.Index = i;
  1024. CmpCheckValueListDebug.Cell = Cell;
  1025. goto RemoveThisValue;
  1026. }
  1027. //
  1028. // Check out the value entry itself
  1029. //
  1030. pcell = HvGetCell(Hive, Cell);
  1031. if( pcell == NULL ) {
  1032. //
  1033. // we couldn't map a view for the bin containing this cell
  1034. //
  1035. CmKdPrintEx((DPFLTR_CONFIG_ID,DPFLTR_ERROR_LEVEL,"\tCould not map cell #%08lx\n", Cell));
  1036. CmpCheckValueListDebug.Status = 5099;
  1037. CmpCheckValueListDebug.Index = i;
  1038. CmpCheckValueListDebug.Cell = Cell;
  1039. rc = 5099;
  1040. goto Exit;
  1041. }
  1042. size = HvGetCellSize(Hive, pcell);
  1043. if (pcell->u.KeyValue.Signature != CM_KEY_VALUE_SIGNATURE) {
  1044. CmKdPrintEx((DPFLTR_CONFIG_ID,DPFLTR_ERROR_LEVEL,"CmpCheckValueList: List:%p i:%08lx\n", List, i));
  1045. CmKdPrintEx((DPFLTR_CONFIG_ID,DPFLTR_ERROR_LEVEL,"\tCell:%08lx - invalid value signature\n", Cell));
  1046. rc = 5030;
  1047. CmpCheckValueListDebug.Status = rc;
  1048. CmpCheckValueListDebug.Index = i;
  1049. CmpCheckValueListDebug.Cell = Cell;
  1050. CmpCheckValueListDebug.CellPoint = pcell;
  1051. goto RemoveThisValue;
  1052. }
  1053. usedlen = FIELD_OFFSET(CM_KEY_VALUE, Name) + pcell->u.KeyValue.NameLength;
  1054. if (usedlen > size) {
  1055. CmKdPrintEx((DPFLTR_CONFIG_ID,DPFLTR_ERROR_LEVEL,"CmpCheckValueList: List:%p i:%08lx\n", List, i));
  1056. CmKdPrintEx((DPFLTR_CONFIG_ID,DPFLTR_ERROR_LEVEL,"\tCell:%08lx - value bigger than containing cell\n", Cell));
  1057. rc = 5040;
  1058. CmpCheckValueListDebug.Status = rc;
  1059. CmpCheckValueListDebug.Index = i;
  1060. CmpCheckValueListDebug.Cell = Cell;
  1061. CmpCheckValueListDebug.CellPoint = pcell;
  1062. goto RemoveThisValue;
  1063. }
  1064. //
  1065. // Check out value entry's data
  1066. //
  1067. DataLength = pcell->u.KeyValue.DataLength;
  1068. if (DataLength < CM_KEY_VALUE_SPECIAL_SIZE) {
  1069. Data = pcell->u.KeyValue.Data;
  1070. if ((DataLength == 0) && (Data != HCELL_NIL)) {
  1071. CmKdPrintEx((DPFLTR_CONFIG_ID,DPFLTR_ERROR_LEVEL,"CmpCheckValueList: List:%p i:%08lx\n", List, i));
  1072. CmKdPrintEx((DPFLTR_CONFIG_ID,DPFLTR_ERROR_LEVEL,"\tCell:%08lx Data:%08lx - data not null\n", Cell, Data));
  1073. rc = 5050;
  1074. CmpCheckValueListDebug.Status = rc;
  1075. CmpCheckValueListDebug.Index = i;
  1076. CmpCheckValueListDebug.Cell = Cell;
  1077. CmpCheckValueListDebug.CellPoint = pcell;
  1078. goto RemoveThisValue;
  1079. }
  1080. if (DataLength > 0) {
  1081. if (HvIsCellAllocated(Hive, Data) == FALSE) {
  1082. CmKdPrintEx((DPFLTR_CONFIG_ID,DPFLTR_ERROR_LEVEL,"CmpCheckValueList: List:%p i:%08lx\n", List, i));
  1083. CmKdPrintEx((DPFLTR_CONFIG_ID,DPFLTR_ERROR_LEVEL,"\tCell:%08lx Data:%08lx - unallocated\n", Cell, Data));
  1084. rc = 5060;
  1085. CmpCheckValueListDebug.Status = rc;
  1086. CmpCheckValueListDebug.Index = i;
  1087. CmpCheckValueListDebug.Cell = Cell;
  1088. CmpCheckValueListDebug.CellPoint = pcell;
  1089. goto RemoveThisValue;
  1090. }
  1091. }
  1092. if( CmpIsHKeyValueBig(Hive,DataLength) == TRUE ) {
  1093. PCM_BIG_DATA BigData;
  1094. PHCELL_INDEX Plist;
  1095. BigData = (PCM_BIG_DATA)HvGetCell(Hive, Data);
  1096. if( BigData == NULL ) {
  1097. //
  1098. // we couldn't map a view for the bin containing this cell
  1099. //
  1100. CmKdPrintEx((DPFLTR_CONFIG_ID,DPFLTR_ERROR_LEVEL,"\tCould not map cell #%08lx\n", Data));
  1101. CmpCheckValueListDebug.Status = 5098;
  1102. CmpCheckValueListDebug.Index = i;
  1103. CmpCheckValueListDebug.Cell = Data;
  1104. rc = 5098;
  1105. goto Exit;
  1106. }
  1107. if( (BigData->Signature != CM_BIG_DATA_SIGNATURE) ||
  1108. (BigData->Count == 0 ) ||
  1109. (BigData->List == HCELL_NIL)
  1110. ) {
  1111. CmKdPrintEx((DPFLTR_CONFIG_ID,DPFLTR_ERROR_LEVEL,"\tinvalid big data cell #%08lx\n", Data));
  1112. CmpCheckValueListDebug.Status = 5097;
  1113. CmpCheckValueListDebug.Index = i;
  1114. CmpCheckValueListDebug.Cell = Data;
  1115. rc = 5097;
  1116. goto RemoveThisValue;
  1117. }
  1118. if (HvIsCellAllocated(Hive, BigData->List) == FALSE) {
  1119. CmKdPrintEx((DPFLTR_CONFIG_ID,DPFLTR_ERROR_LEVEL,"CmpCheckValueList: List:%p i:%08lx\n", List, i));
  1120. CmKdPrintEx((DPFLTR_CONFIG_ID,DPFLTR_ERROR_LEVEL,"\tCell:%08lx DataList:%08lx - unallocated\n", Cell, BigData->List));
  1121. rc = 5096;
  1122. CmpCheckValueListDebug.Status = rc;
  1123. CmpCheckValueListDebug.Index = i;
  1124. CmpCheckValueListDebug.Cell = BigData->List;
  1125. CmpCheckValueListDebug.CellPoint = (PCELL_DATA)BigData;
  1126. goto RemoveThisValue;
  1127. }
  1128. Plist = (PHCELL_INDEX)HvGetCell(Hive,BigData->List);
  1129. if( Plist == NULL ) {
  1130. //
  1131. // we couldn't map a view for the bin containing this cell
  1132. //
  1133. CmKdPrintEx((DPFLTR_CONFIG_ID,DPFLTR_ERROR_LEVEL,"\tCould not map cell #%08lx\n", BigData->List));
  1134. CmpCheckValueListDebug.Status = 5098;
  1135. CmpCheckValueListDebug.Index = i;
  1136. CmpCheckValueListDebug.Cell = BigData->List;
  1137. rc = 5095;
  1138. goto Exit;
  1139. }
  1140. //
  1141. // check each and every big data cell to see if it is allocated.
  1142. //
  1143. for(j=0;j<BigData->Count;j++) {
  1144. if (HvIsCellAllocated(Hive, Plist[j]) == FALSE) {
  1145. CmKdPrintEx((DPFLTR_CONFIG_ID,DPFLTR_ERROR_LEVEL,"CmpCheckValueList: List:%p j:%08lx\n", BigData->List, j));
  1146. CmKdPrintEx((DPFLTR_CONFIG_ID,DPFLTR_ERROR_LEVEL,"\tCell:%08lx BigData:%08lx - unallocated\n", Plist[j], BigData->List));
  1147. rc = 5094;
  1148. CmpCheckValueListDebug.Status = rc;
  1149. CmpCheckValueListDebug.Index = j;
  1150. CmpCheckValueListDebug.Cell = Plist[j];
  1151. CmpCheckValueListDebug.CellPoint = (PCELL_DATA)BigData;
  1152. goto RemoveThisValue;
  1153. }
  1154. }
  1155. }
  1156. }
  1157. }
  1158. Exit:
  1159. // cleanup
  1160. return rc;
  1161. }
  1162. #ifdef CHECK_REGISTRY_USECOUNT
  1163. extern LIST_ENTRY CmpHiveListHead;
  1164. VOID
  1165. CmpCheckRegistryUseCount( )
  1166. {
  1167. PLIST_ENTRY p;
  1168. PCMHIVE CmHive;
  1169. ASSERT_CM_LOCK_OWNED_EXCLUSIVE();
  1170. LOCK_HIVE_LIST();
  1171. p = CmpHiveListHead.Flink;
  1172. while(p != &CmpHiveListHead) {
  1173. CmHive = CONTAINING_RECORD(p, CMHIVE, HiveList);
  1174. if( CmHive->UseCount != 0 ){
  1175. DbgPrintEx(DPFLTR_CONFIG_ID,DPFLTR_ERROR_LEVEL,"Hive (%p) is supposed to have USECount == 0 at this point; instead UseCount = %lu\n",CmHive,CmHive->UseCount);
  1176. DbgBreakPoint();
  1177. }
  1178. p=p->Flink;
  1179. }
  1180. UNLOCK_HIVE_LIST();
  1181. }
  1182. #endif