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.

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