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.

3239 lines
88 KiB

  1. //depot/main/Base/ntos/config/cmindex.c#12 - integrate change 19035 (text)
  2. /*++
  3. Copyright (c) 1991 Microsoft Corporation
  4. Module Name:
  5. cmindex.c
  6. Abstract:
  7. This module contains cm routines that understand the structure
  8. of child subkey indicies.
  9. Author:
  10. Bryan M. Willman (bryanwi) 21-Apr-92
  11. Revision History:
  12. --*/
  13. /*
  14. The Structure:
  15. Use a 1 or 2 level tree. Leaf nodes are arrays of pointers to
  16. cells, sorted. Binary search to find cell of interest. Directory
  17. node (can be only one) is an array of pointers to leaf blocks.
  18. Do compare on last entry of each leaf block.
  19. One Level:
  20. Key--->+----+
  21. | |
  22. | x----------><key whose name is "apple", string in key>
  23. | |
  24. +----+
  25. | |
  26. | x----------><as above, but key named "banana">
  27. | |
  28. +----+
  29. | |
  30. | |
  31. | |
  32. +----+
  33. | |
  34. | |
  35. | |
  36. +----+
  37. | |
  38. | x----------><as above, but key named "zumwat">
  39. | |
  40. +----+
  41. Two Level:
  42. Key--->+----+
  43. | | +-----+
  44. | x----->| |
  45. | | | x----------------->"aaa"
  46. +----+ | |
  47. | | +-----+
  48. | | | |
  49. | | | |
  50. +----+ | |
  51. | | +-----+
  52. | | | |
  53. | | | x----------------->"abc"
  54. +----+ | |
  55. | | +-----+
  56. | |
  57. | |
  58. +----+
  59. | | +-----+
  60. | x----->| |
  61. | | | x----------------->"w"
  62. +----+ | |
  63. +-----+
  64. | |
  65. | |
  66. | |
  67. +-----+
  68. | |
  69. | x----------------->"z"
  70. | |
  71. +-----+
  72. Never more than two levels.
  73. Each block must fix in on HBLOCK_SIZE Cell. Allows about 1000
  74. entries. Max of 1 million total, best case. Worst case something
  75. like 1/4 of that.
  76. */
  77. #include "cmp.h"
  78. ULONG
  79. CmpFindSubKeyInRoot(
  80. PHHIVE Hive,
  81. PCM_KEY_INDEX Index,
  82. PUNICODE_STRING SearchName,
  83. PHCELL_INDEX Child
  84. );
  85. ULONG
  86. CmpFindSubKeyInLeaf(
  87. PHHIVE Hive,
  88. PCM_KEY_INDEX Index,
  89. PUNICODE_STRING SearchName,
  90. PHCELL_INDEX Child
  91. );
  92. LONG
  93. CmpCompareInIndex(
  94. PHHIVE Hive,
  95. PUNICODE_STRING SearchName,
  96. ULONG Count,
  97. PCM_KEY_INDEX Index,
  98. PHCELL_INDEX Child
  99. );
  100. LONG
  101. CmpDoCompareKeyName(
  102. PHHIVE Hive,
  103. PUNICODE_STRING SearchName,
  104. HCELL_INDEX Cell
  105. );
  106. HCELL_INDEX
  107. CmpDoFindSubKeyByNumber(
  108. PHHIVE Hive,
  109. PCM_KEY_INDEX Index,
  110. ULONG Number
  111. );
  112. HCELL_INDEX
  113. CmpAddToLeaf(
  114. PHHIVE Hive,
  115. HCELL_INDEX LeafCell,
  116. HCELL_INDEX NewKey,
  117. PUNICODE_STRING NewName
  118. );
  119. HCELL_INDEX
  120. CmpSelectLeaf(
  121. PHHIVE Hive,
  122. PCM_KEY_NODE ParentKey,
  123. PUNICODE_STRING NewName,
  124. HSTORAGE_TYPE Type,
  125. PHCELL_INDEX *RootPointer
  126. );
  127. HCELL_INDEX
  128. CmpSplitLeaf(
  129. PHHIVE Hive,
  130. HCELL_INDEX RootCell,
  131. ULONG RootSelect,
  132. HSTORAGE_TYPE Type
  133. );
  134. HCELL_INDEX
  135. CmpFindSubKeyByHash(
  136. PHHIVE Hive,
  137. PCM_KEY_FAST_INDEX FastIndex,
  138. PUNICODE_STRING SearchName
  139. );
  140. #ifdef ALLOC_PRAGMA
  141. #pragma alloc_text(PAGE,CmpFindSubKeyByName)
  142. #pragma alloc_text(PAGE,CmpFindSubKeyInRoot)
  143. #pragma alloc_text(PAGE,CmpFindSubKeyInLeaf)
  144. #pragma alloc_text(PAGE,CmpDoCompareKeyName)
  145. #pragma alloc_text(PAGE,CmpCompareInIndex)
  146. #pragma alloc_text(PAGE,CmpFindSubKeyByNumber)
  147. #pragma alloc_text(PAGE,CmpDoFindSubKeyByNumber)
  148. #pragma alloc_text(PAGE,CmpAddSubKey)
  149. #pragma alloc_text(PAGE,CmpAddToLeaf)
  150. #pragma alloc_text(PAGE,CmpSelectLeaf)
  151. #pragma alloc_text(PAGE,CmpSplitLeaf)
  152. #pragma alloc_text(PAGE,CmpMarkIndexDirty)
  153. #pragma alloc_text(PAGE,CmpRemoveSubKey)
  154. #pragma alloc_text(PAGE,CmpComputeHashKey)
  155. #pragma alloc_text(PAGE,CmpComputeHashKeyForCompressedName)
  156. #pragma alloc_text(PAGE,CmpFindSubKeyByHash)
  157. #ifdef NT_RENAME_KEY
  158. #pragma alloc_text(PAGE,CmpDuplicateIndex)
  159. #pragma alloc_text(PAGE,CmpUpdateParentForEachSon)
  160. #endif //NT_RENAME_KEY
  161. #pragma alloc_text(PAGE,CmpRemoveSubKeyCellNoCellRef)
  162. #endif
  163. HCELL_INDEX
  164. CmpFindSubKeyByName(
  165. PHHIVE Hive,
  166. PCM_KEY_NODE Parent,
  167. PUNICODE_STRING SearchName
  168. )
  169. /*++
  170. Routine Description:
  171. Find the child cell (either subkey or value) specified by name.
  172. Arguments:
  173. Hive - pointer to hive control structure for hive of interest
  174. Parent - cell of key body which is parent of child of interest
  175. SearchName - name of child of interest
  176. Return Value:
  177. Cell of matching child key, or HCELL_NIL if none.
  178. --*/
  179. {
  180. PCM_KEY_INDEX IndexRoot;
  181. HCELL_INDEX Child;
  182. ULONG i;
  183. ULONG FoundIndex;
  184. HCELL_INDEX CellToRelease = HCELL_NIL;
  185. #ifndef _CM_LDR_
  186. PAGED_CODE();
  187. #endif //_CM_LDR_
  188. CmKdPrintEx((DPFLTR_CONFIG_ID,CML_INDEX,"CmpFindSubKeyByName:\n\t"));
  189. CmKdPrintEx((DPFLTR_CONFIG_ID,CML_INDEX,"Hive=%p Parent=%p SearchName=%p\n", Hive, Parent, SearchName));
  190. //
  191. // Try first the Stable, then the Volatile store. Assumes that
  192. // all Volatile refs in Stable space are zeroed out at boot.
  193. //
  194. for (i = 0; i < Hive->StorageTypeCount; i++) {
  195. if (Parent->SubKeyCounts[i] != 0) {
  196. IndexRoot = (PCM_KEY_INDEX)HvGetCell(Hive, Parent->SubKeyLists[i]);
  197. ASSERT( (IndexRoot == NULL) || HvIsCellAllocated(Hive, Parent->SubKeyLists[i]) );
  198. if( IndexRoot == NULL ) {
  199. //
  200. // we couldn't map a view for the bin containing this cell
  201. //
  202. return HCELL_NIL;
  203. }
  204. CellToRelease = Parent->SubKeyLists[i];
  205. if (IndexRoot->Signature == CM_KEY_INDEX_ROOT) {
  206. if( INVALID_INDEX & CmpFindSubKeyInRoot(Hive, IndexRoot, SearchName, &Child) ) {
  207. //
  208. // couldn't map view inside
  209. //
  210. ASSERT( CellToRelease != HCELL_NIL );
  211. HvReleaseCell(Hive,CellToRelease);
  212. return HCELL_NIL;
  213. }
  214. ASSERT( CellToRelease != HCELL_NIL );
  215. HvReleaseCell(Hive,CellToRelease);
  216. if (Child == HCELL_NIL) {
  217. continue;
  218. }
  219. IndexRoot = (PCM_KEY_INDEX)HvGetCell(Hive, Child);
  220. if( IndexRoot == NULL ) {
  221. //
  222. // we couldn't map a view for the bin containing this cell
  223. //
  224. return HCELL_NIL;
  225. }
  226. CellToRelease = Child;
  227. }
  228. ASSERT((IndexRoot->Signature == CM_KEY_INDEX_LEAF) ||
  229. (IndexRoot->Signature == CM_KEY_FAST_LEAF) ||
  230. (IndexRoot->Signature == CM_KEY_HASH_LEAF)
  231. );
  232. if( IndexRoot->Signature == CM_KEY_HASH_LEAF ) {
  233. Child = CmpFindSubKeyByHash(Hive,(PCM_KEY_FAST_INDEX)IndexRoot,SearchName);
  234. ASSERT( CellToRelease != HCELL_NIL );
  235. HvReleaseCell(Hive,CellToRelease);
  236. } else {
  237. FoundIndex = CmpFindSubKeyInLeaf(Hive,
  238. IndexRoot,
  239. SearchName,
  240. &Child);
  241. ASSERT( CellToRelease != HCELL_NIL );
  242. HvReleaseCell(Hive,CellToRelease);
  243. if( INVALID_INDEX & FoundIndex ) {
  244. //
  245. // couldn't map view
  246. //
  247. return HCELL_NIL;
  248. }
  249. }
  250. if (Child != HCELL_NIL) {
  251. //
  252. // success
  253. //
  254. return Child;
  255. }
  256. }
  257. }
  258. #if 0 //DBG
  259. //
  260. // Validation code. manually search for the key and break when found
  261. //
  262. if (Parent->SubKeyCounts[Stable] != 0) {
  263. ULONG Cnt1,Cnt2;
  264. LONG Result;
  265. HCELL_INDEX Cell;
  266. PCM_KEY_INDEX Leaf;
  267. PCM_KEY_INDEX DbgIndexRoot = (PCM_KEY_INDEX)HvGetCell(Hive, Parent->SubKeyLists[Stable]);
  268. if(DbgIndexRoot->Signature == CM_KEY_INDEX_ROOT ) {
  269. for(Cnt1=0;Cnt1<DbgIndexRoot->Count;Cnt1++) {
  270. Leaf = (PCM_KEY_INDEX)HvGetCell(Hive, DbgIndexRoot->List[Cnt1]);
  271. for( Cnt2=0;Cnt2<Leaf->Count;Cnt2++) {
  272. Result = CmpCompareInIndex( Hive,
  273. SearchName,
  274. Cnt2,
  275. Leaf,
  276. &Cell);
  277. if( Result == 0 ) {
  278. //
  279. // Found it !!! Error above !!!
  280. //
  281. DbgPrint("CmpFindSubKeyByName: Hive = %p, Parent = %p, SearchName = %p\n",Hive,Parent,SearchName);
  282. DbgPrint(" : IndexRoot = %p, DbgIndexRoot = %p, Cnt1 = %lx, Cnt2 = %lx\n",IndexRoot,DbgIndexRoot,Cnt1,Cnt2);
  283. DbgPrint(" : Leaf = %p\n",Leaf);
  284. DbgBreakPoint();
  285. }
  286. }
  287. HvReleaseCell(Hive,DbgIndexRoot->List[Cnt1]);
  288. }
  289. }
  290. HvReleaseCell(Hive,Parent->SubKeyLists[Stable]);
  291. }
  292. #endif //0
  293. return HCELL_NIL;
  294. }
  295. ULONG
  296. CmpFindSubKeyInRoot(
  297. PHHIVE Hive,
  298. PCM_KEY_INDEX Index,
  299. PUNICODE_STRING SearchName,
  300. PHCELL_INDEX Child
  301. )
  302. /*++
  303. Routine Description:
  304. Find the leaf index that would contain a key, if there is one.
  305. Arguments:
  306. Hive - pointer to hive control structure for hive of interest
  307. Index - pointer to root index block
  308. SearchName - pointer to name of key of interest
  309. Child - pointer to variable to receive hcell_index of found leaf index
  310. block, HCELL_NIL if none. Non nil does not necessarily mean
  311. the key is present, call FindSubKeyInLeaf to decide that.
  312. Return Value:
  313. Index in List of last Leaf Cell entry examined. If Child != HCELL_NIL,
  314. Index is entry that matched, else, index is for last entry we looked
  315. at. (Target Leaf will be this value plus or minus 1)
  316. If an error appears while searching the subkey (i.e. a cell cannot be
  317. mapped into memory) INVALID_INDEX is returned.
  318. --*/
  319. {
  320. ULONG High;
  321. ULONG Low;
  322. ULONG CanCount;
  323. HCELL_INDEX LeafCell;
  324. PCM_KEY_INDEX Leaf;
  325. LONG Result;
  326. ULONG ReturnIndex = INVALID_INDEX;
  327. CmKdPrintEx((DPFLTR_CONFIG_ID,CML_INDEX,"CmpFindSubKeyInRoot:\n\t"));
  328. CmKdPrintEx((DPFLTR_CONFIG_ID,CML_INDEX,"Hive=%p Index=%p SearchName=%p\n",Hive,Index,SearchName));
  329. ASSERT(Index->Count != 0);
  330. ASSERT(Index->Signature == CM_KEY_INDEX_ROOT);
  331. High = Index->Count - 1;
  332. Low = 0;
  333. while (TRUE) {
  334. //
  335. // Compute where to look next, get correct pointer, do compare
  336. //
  337. CanCount = ((High-Low)/2)+Low;
  338. LeafCell = Index->List[CanCount];
  339. Leaf = (PCM_KEY_INDEX)HvGetCell(Hive, LeafCell);
  340. if( Leaf == NULL ) {
  341. //
  342. // we couldn't map the bin containing this cell
  343. //
  344. *Child = HCELL_NIL;
  345. ReturnIndex = INVALID_INDEX;
  346. goto JustReturn;
  347. }
  348. ASSERT((Leaf->Signature == CM_KEY_INDEX_LEAF) ||
  349. (Leaf->Signature == CM_KEY_FAST_LEAF) ||
  350. (Leaf->Signature == CM_KEY_HASH_LEAF)
  351. );
  352. ASSERT(Leaf->Count != 0);
  353. Result = CmpCompareInIndex(Hive,
  354. SearchName,
  355. Leaf->Count-1,
  356. Leaf,
  357. Child);
  358. if( Result == 2 ) {
  359. //
  360. // couldn't map view inside; bail out
  361. //
  362. *Child = HCELL_NIL;
  363. ReturnIndex = INVALID_INDEX;
  364. goto JustReturn;
  365. }
  366. if (Result == 0) {
  367. //
  368. // SearchName == KeyName of last key in leaf, so
  369. // this is our leaf
  370. //
  371. *Child = LeafCell;
  372. ReturnIndex = CanCount;
  373. goto JustReturn;
  374. }
  375. if (Result < 0) {
  376. ASSERT( Result == -1 );
  377. //
  378. // SearchName < KeyName, so this may still be our leaf
  379. //
  380. Result = CmpCompareInIndex(Hive,
  381. SearchName,
  382. 0,
  383. Leaf,
  384. Child);
  385. if( Result == 2 ) {
  386. //
  387. // couldn't map view inside; bail out
  388. //
  389. *Child = HCELL_NIL;
  390. ReturnIndex = INVALID_INDEX;
  391. goto JustReturn;
  392. }
  393. if (Result >= 0) {
  394. ASSERT( (Result == 1) || (Result == 0) );
  395. //
  396. // we know from above that SearchName is less than
  397. // last key in leaf.
  398. // since it is also >= first key in leaf, it must
  399. // reside in leaf somewhere, and we are done
  400. //
  401. *Child = LeafCell;
  402. ReturnIndex = CanCount;
  403. goto JustReturn;
  404. }
  405. High = CanCount;
  406. } else {
  407. //
  408. // SearchName > KeyName
  409. //
  410. Low = CanCount;
  411. }
  412. if ((High - Low) <= 1) {
  413. break;
  414. }
  415. HvReleaseCell(Hive, LeafCell);
  416. }
  417. HvReleaseCell(Hive, LeafCell);
  418. //
  419. // If we get here, High - Low = 1 or High == Low
  420. //
  421. ASSERT((High - Low == 1) || (High == Low));
  422. LeafCell = Index->List[Low];
  423. Leaf = (PCM_KEY_INDEX)HvGetCell(Hive, LeafCell);
  424. if( Leaf == NULL ) {
  425. //
  426. // we couldn't map the bin containing this cell
  427. //
  428. *Child = HCELL_NIL;
  429. ReturnIndex = INVALID_INDEX;
  430. goto JustReturn;
  431. }
  432. Result = CmpCompareInIndex(Hive,
  433. SearchName,
  434. Leaf->Count-1,
  435. Leaf,
  436. Child);
  437. if( Result == 2 ) {
  438. //
  439. // couldn't map view inside; bail out
  440. //
  441. *Child = HCELL_NIL;
  442. ReturnIndex = INVALID_INDEX;
  443. goto JustReturn;
  444. }
  445. if (Result == 0) {
  446. //
  447. // found it
  448. //
  449. *Child = LeafCell;
  450. ReturnIndex = Low;
  451. goto JustReturn;
  452. }
  453. if (Result < 0) {
  454. ASSERT( Result == -1 );
  455. //
  456. // SearchName < KeyName, so this may still be our leaf
  457. //
  458. Result = CmpCompareInIndex(Hive,
  459. SearchName,
  460. 0,
  461. Leaf,
  462. Child);
  463. if( Result == 2 ) {
  464. //
  465. // couldn't map view inside; bail out
  466. //
  467. *Child = HCELL_NIL;
  468. ReturnIndex = INVALID_INDEX;
  469. goto JustReturn;
  470. }
  471. if (Result >= 0) {
  472. ASSERT( (Result == 1) || (Result == 0) );
  473. //
  474. // we know from above that SearchName is less than
  475. // last key in leaf.
  476. // since it is also >= first key in leaf, it must
  477. // reside in leaf somewhere, and we are done
  478. //
  479. *Child = LeafCell;
  480. ReturnIndex = Low;
  481. goto JustReturn;
  482. }
  483. //
  484. // does not exist, but belongs in Low or Leaf below low
  485. //
  486. *Child = HCELL_NIL;
  487. ReturnIndex = Low;
  488. goto JustReturn;
  489. }
  490. HvReleaseCell(Hive, LeafCell);
  491. //
  492. // see if High matches
  493. //
  494. LeafCell = Index->List[High];
  495. Leaf = (PCM_KEY_INDEX)HvGetCell(Hive, LeafCell);
  496. if( Leaf == NULL ) {
  497. //
  498. // we couldn't map the bin containing this cell
  499. //
  500. *Child = HCELL_NIL;
  501. ReturnIndex = INVALID_INDEX;
  502. goto JustReturn;
  503. }
  504. Result = CmpCompareInIndex(Hive,
  505. SearchName,
  506. Leaf->Count - 1,
  507. Leaf,
  508. Child);
  509. if( Result == 2 ) {
  510. //
  511. // couldn't map view inside; bail out
  512. //
  513. *Child = HCELL_NIL;
  514. ReturnIndex = INVALID_INDEX;
  515. goto JustReturn;
  516. }
  517. if (Result == 0) {
  518. //
  519. // found it
  520. //
  521. *Child = LeafCell;
  522. ReturnIndex = High;
  523. goto JustReturn;
  524. } else if (Result < 0) {
  525. ASSERT( Result == -1 );
  526. //
  527. // Clearly greater than low, or we wouldn't be here.
  528. // So regardless of whether it's below the start
  529. // of this leaf, it would be in this leaf if it were
  530. // where, so report this leaf.
  531. //
  532. *Child = LeafCell;
  533. ReturnIndex = High;
  534. goto JustReturn;
  535. }
  536. //
  537. // Off the high end
  538. //
  539. *Child = HCELL_NIL;
  540. ReturnIndex = High;
  541. JustReturn:
  542. if(Leaf != NULL){
  543. HvReleaseCell(Hive, LeafCell);
  544. }
  545. return ReturnIndex;
  546. }
  547. ULONG
  548. CmpFindSubKeyInLeaf(
  549. PHHIVE Hive,
  550. PCM_KEY_INDEX Index,
  551. PUNICODE_STRING SearchName,
  552. PHCELL_INDEX Child
  553. )
  554. /*++
  555. Routine Description:
  556. Find a named key in a leaf index, if it exists. The supplied index
  557. may be either a fast index or a slow one.
  558. Arguments:
  559. Hive - pointer to hive control structure for hive of interest
  560. Index - pointer to leaf block
  561. SearchName - pointer to name of key of interest
  562. Child - pointer to variable to receive hcell_index of found key
  563. HCELL_NIL if none found
  564. Return Value:
  565. Index in List of last cell. If Child != HCELL_NIL, is offset in
  566. list at which Child was found. Else, is offset of last place
  567. we looked.
  568. INVALID_INDEX - resources problem; couldn't map view
  569. --*/
  570. {
  571. ULONG High;
  572. ULONG Low;
  573. ULONG CanCount;
  574. LONG Result;
  575. CmKdPrintEx((DPFLTR_CONFIG_ID,CML_INDEX,"CmpFindSubKeyInLeaf:\n\t"));
  576. CmKdPrintEx((DPFLTR_CONFIG_ID,CML_INDEX,"Hive=%p Index=%p SearchName=%p\n",Hive,Index,SearchName));
  577. ASSERT((Index->Signature == CM_KEY_INDEX_LEAF) ||
  578. (Index->Signature == CM_KEY_FAST_LEAF) ||
  579. (Index->Signature == CM_KEY_HASH_LEAF)
  580. );
  581. High = Index->Count - 1;
  582. Low = 0;
  583. CanCount = High/2;
  584. if (Index->Count == 0) {
  585. *Child = HCELL_NIL;
  586. return 0;
  587. }
  588. while (TRUE) {
  589. //
  590. // Compute where to look next, get correct pointer, do compare
  591. //
  592. Result = CmpCompareInIndex(Hive,
  593. SearchName,
  594. CanCount,
  595. Index,
  596. Child);
  597. if( Result == 2 ) {
  598. //
  599. // couldn't map view inside; bail out
  600. //
  601. *Child = HCELL_NIL;
  602. return INVALID_INDEX;
  603. }
  604. if (Result == 0) {
  605. //
  606. // SearchName == KeyName
  607. //
  608. return CanCount;
  609. }
  610. if (Result < 0) {
  611. ASSERT( Result == -1 );
  612. //
  613. // SearchName < KeyName
  614. //
  615. High = CanCount;
  616. } else {
  617. ASSERT( Result == 1 );
  618. //
  619. // SearchName > KeyName
  620. //
  621. Low = CanCount;
  622. }
  623. if ((High - Low) <= 1) {
  624. break;
  625. }
  626. CanCount = ((High-Low)/2)+Low;
  627. }
  628. //
  629. // If we get here, High - Low = 1 or High == Low
  630. // Simply look first at Low, then at High
  631. //
  632. Result = CmpCompareInIndex(Hive,
  633. SearchName,
  634. Low,
  635. Index,
  636. Child);
  637. if( Result == 2 ) {
  638. //
  639. // couldn't map view inside; bail out
  640. //
  641. *Child = HCELL_NIL;
  642. return INVALID_INDEX;
  643. }
  644. if (Result == 0) {
  645. //
  646. // found it
  647. //
  648. return Low;
  649. }
  650. if (Result < 0) {
  651. ASSERT( Result == -1 );
  652. //
  653. // does not exist, under
  654. //
  655. return Low;
  656. }
  657. //
  658. // see if High matches, we will return High as the
  659. // closest key regardless.
  660. //
  661. Result = CmpCompareInIndex(Hive,
  662. SearchName,
  663. High,
  664. Index,
  665. Child);
  666. if( Result == 2 ) {
  667. //
  668. // couldn't map view inside; bail out
  669. //
  670. *Child = HCELL_NIL;
  671. return INVALID_INDEX;
  672. }
  673. return High;
  674. }
  675. LONG
  676. CmpCompareInIndex(
  677. PHHIVE Hive,
  678. PUNICODE_STRING SearchName,
  679. ULONG Count,
  680. PCM_KEY_INDEX Index,
  681. PHCELL_INDEX Child
  682. )
  683. /*++
  684. Routine Description:
  685. Do a compare of a name in an index. This routine handles both
  686. fast leafs and slow ones.
  687. Arguments:
  688. Hive - pointer to hive control structure for hive of interest
  689. SearchName - pointer to name of key we are searching for
  690. Count - supplies index that we are searching at.
  691. Index - Supplies pointer to either a CM_KEY_INDEX or
  692. a CM_KEY_FAST_INDEX. This routine will determine which
  693. type of index it is passed.
  694. Child - pointer to variable to receive hcell_index of found key
  695. HCELL_NIL if result != 0
  696. Return Value:
  697. 0 = SearchName == KeyName (of Cell)
  698. -1 = SearchName < KeyName
  699. +1 = SearchName > KeyName
  700. +2 = Error, insufficient resources
  701. --*/
  702. {
  703. PCM_KEY_FAST_INDEX FastIndex;
  704. LONG Result;
  705. ULONG i;
  706. WCHAR c1;
  707. WCHAR c2;
  708. ULONG HintLength;
  709. ULONG ValidChars;
  710. ULONG NameLength;
  711. PCM_INDEX Hint;
  712. *Child = HCELL_NIL;
  713. if ( (Index->Signature == CM_KEY_FAST_LEAF) ||
  714. (Index->Signature == CM_KEY_HASH_LEAF) ) {
  715. FastIndex = (PCM_KEY_FAST_INDEX)Index;
  716. Hint = &FastIndex->List[Count];
  717. if(Index->Signature == CM_KEY_FAST_LEAF) {
  718. //
  719. // Compute the number of valid characters in the hint to compare.
  720. //
  721. HintLength = 4;
  722. for (i=0;i<4;i++) {
  723. if (Hint->NameHint[i] == 0) {
  724. HintLength = i;
  725. break;
  726. }
  727. }
  728. NameLength = SearchName->Length / sizeof(WCHAR);
  729. if (NameLength < HintLength) {
  730. ValidChars = NameLength;
  731. } else {
  732. ValidChars = HintLength;
  733. }
  734. for (i=0; i<ValidChars; i++) {
  735. c1 = SearchName->Buffer[i];
  736. c2 = FastIndex->List[Count].NameHint[i];
  737. Result = (LONG)RtlUpcaseUnicodeChar(c1) -
  738. (LONG)RtlUpcaseUnicodeChar(c2);
  739. if (Result != 0) {
  740. //
  741. // We have found a mismatched character in the hint,
  742. // we can now tell which direction to go.
  743. //
  744. return (Result > 0) ? 1 : -1 ;
  745. }
  746. }
  747. }
  748. //
  749. // We have compared all the available characters without a
  750. // discrepancy. Go ahead and do the actual comparison now.
  751. //
  752. Result = CmpDoCompareKeyName(Hive,SearchName,FastIndex->List[Count].Cell);
  753. if( Result == 2 ) {
  754. //
  755. // couldn't map view inside; signal it to the caller
  756. //
  757. return 2;
  758. }
  759. if (Result == 0) {
  760. *Child = Hint->Cell;
  761. }
  762. } else {
  763. //
  764. // This is just a normal old slow index.
  765. //
  766. Result = CmpDoCompareKeyName(Hive,SearchName,Index->List[Count]);
  767. if( Result == 2 ) {
  768. //
  769. // couldn't map view inside; signal it to the caller
  770. //
  771. return 2;
  772. }
  773. if (Result == 0) {
  774. *Child = Index->List[Count];
  775. }
  776. }
  777. return(Result);
  778. }
  779. LONG
  780. CmpDoCompareKeyName(
  781. PHHIVE Hive,
  782. PUNICODE_STRING SearchName,
  783. HCELL_INDEX Cell
  784. )
  785. /*++
  786. Routine Description:
  787. Do a compare of a name with a key.
  788. Arguments:
  789. Hive - pointer to hive control structure for hive of interest
  790. SearchName - pointer to name of key we are searching for
  791. Cell - cell of key we are to compare with
  792. Return Value:
  793. 0 = SearchName == KeyName (of Cell)
  794. -1 = SearchName < KeyName
  795. +1 = SearchName > KeyName
  796. +2 = Error (couldn't map bin)
  797. --*/
  798. {
  799. PCM_KEY_NODE Pcan;
  800. UNICODE_STRING KeyName;
  801. LONG Result;
  802. Pcan = (PCM_KEY_NODE)HvGetCell(Hive, Cell);
  803. if( Pcan == NULL ) {
  804. //
  805. // we couldn't map the bin containing this cell
  806. // return error, so the caller could safely bail out
  807. //
  808. return 2;
  809. }
  810. if (Pcan->Flags & KEY_COMP_NAME) {
  811. Result = CmpCompareCompressedName(SearchName,
  812. Pcan->Name,
  813. Pcan->NameLength,
  814. 0);
  815. } else {
  816. KeyName.Buffer = &(Pcan->Name[0]);
  817. KeyName.Length = Pcan->NameLength;
  818. KeyName.MaximumLength = KeyName.Length;
  819. Result = RtlCompareUnicodeString(SearchName,
  820. &KeyName,
  821. TRUE);
  822. }
  823. HvReleaseCell(Hive, Cell);
  824. if( Result == 0 ) {
  825. //
  826. // match
  827. //
  828. return 0;
  829. }
  830. return (Result < 0) ? -1 : 1;
  831. }
  832. HCELL_INDEX
  833. CmpFindSubKeyByNumber(
  834. PHHIVE Hive,
  835. PCM_KEY_NODE Node,
  836. ULONG Number
  837. )
  838. /*++
  839. Routine Description:
  840. Find the Number'th entry in the index, starting from 0.
  841. Arguments:
  842. Hive - pointer to hive control structure for hive of interest
  843. Node - pointer to key body which is parent of child of interest
  844. Number - ordinal of child key to return
  845. Return Value:
  846. Cell of matching child key, or HCELL_NIL if none or error.
  847. --*/
  848. {
  849. PCM_KEY_INDEX Index;
  850. HCELL_INDEX Result = HCELL_NIL;
  851. CmKdPrintEx((DPFLTR_CONFIG_ID,CML_INDEX,"CmpFindSubKeyByNumber:\n\t"));
  852. CmKdPrintEx((DPFLTR_CONFIG_ID,CML_INDEX,"Hive=%p Node=%p Number=%08lx\n",Hive,Node,Number));
  853. if (Number < Node->SubKeyCounts[Stable]) {
  854. //
  855. // It's in the stable set
  856. //
  857. Index = (PCM_KEY_INDEX)HvGetCell(Hive, Node->SubKeyLists[Stable]);
  858. if( Index == NULL ) {
  859. //
  860. // we couldn't map the bin containing this cell
  861. //
  862. return HCELL_NIL;
  863. }
  864. Result = CmpDoFindSubKeyByNumber(Hive, Index, Number);
  865. HvReleaseCell(Hive, Node->SubKeyLists[Stable]);
  866. return Result;
  867. } else if (Hive->StorageTypeCount > Volatile) {
  868. //
  869. // It's in the volatile set
  870. //
  871. Number = Number - Node->SubKeyCounts[Stable];
  872. if (Number < Node->SubKeyCounts[Volatile]) {
  873. Index = (PCM_KEY_INDEX)HvGetCell(Hive, Node->SubKeyLists[Volatile]);
  874. if( Index == NULL ) {
  875. //
  876. // we couldn't map the bin containing this cell
  877. //
  878. return HCELL_NIL;
  879. }
  880. Result = CmpDoFindSubKeyByNumber(Hive, Index, Number);
  881. HvReleaseCell(Hive, Node->SubKeyLists[Volatile]);
  882. return Result;
  883. }
  884. }
  885. //
  886. // It's nowhere
  887. //
  888. return HCELL_NIL;
  889. }
  890. HCELL_INDEX
  891. CmpDoFindSubKeyByNumber(
  892. PHHIVE Hive,
  893. PCM_KEY_INDEX Index,
  894. ULONG Number
  895. )
  896. /*++
  897. Routine Description:
  898. Helper for CmpFindSubKeyByNumber,
  899. Find the Number'th entry in the index, starting from 0.
  900. Arguments:
  901. Hive - pointer to hive control structure for hive of interest
  902. Index - root or leaf of the index
  903. Number - ordinal of child key to return
  904. Return Value:
  905. Cell of requested entry. HCELL_NIL on resources problem
  906. --*/
  907. {
  908. ULONG i;
  909. HCELL_INDEX LeafCell;
  910. PCM_KEY_INDEX Leaf;
  911. PCM_KEY_FAST_INDEX FastIndex;
  912. HCELL_INDEX Result;
  913. if (Index->Signature == CM_KEY_INDEX_ROOT) {
  914. //
  915. // step through root, till we find the right leaf
  916. //
  917. for (i = 0; i < Index->Count; i++) {
  918. if( i ) {
  919. ASSERT( Leaf!= NULL );
  920. ASSERT( LeafCell == Index->List[i-1] );
  921. HvReleaseCell(Hive,LeafCell);
  922. }
  923. LeafCell = Index->List[i];
  924. Leaf = (PCM_KEY_INDEX)HvGetCell(Hive, LeafCell);
  925. if( Leaf == NULL ) {
  926. //
  927. // we couldn't map the bin containing this cell
  928. //
  929. return HCELL_NIL;
  930. }
  931. if (Number < Leaf->Count) {
  932. if ( (Leaf->Signature == CM_KEY_FAST_LEAF) ||
  933. (Leaf->Signature == CM_KEY_HASH_LEAF) ) {
  934. FastIndex = (PCM_KEY_FAST_INDEX)Leaf;
  935. Result = FastIndex->List[Number].Cell;
  936. HvReleaseCell(Hive,LeafCell);
  937. return Result;
  938. } else {
  939. Result = Leaf->List[Number];
  940. HvReleaseCell(Hive,LeafCell);
  941. return Result;
  942. }
  943. } else {
  944. Number = Number - Leaf->Count;
  945. }
  946. }
  947. ASSERT(FALSE);
  948. }
  949. ASSERT(Number < Index->Count);
  950. if ( (Index->Signature == CM_KEY_FAST_LEAF) ||
  951. (Index->Signature == CM_KEY_HASH_LEAF) ) {
  952. FastIndex = (PCM_KEY_FAST_INDEX)Index;
  953. return(FastIndex->List[Number].Cell);
  954. } else {
  955. return (Index->List[Number]);
  956. }
  957. }
  958. BOOLEAN
  959. CmpRemoveSubKeyCellNoCellRef(
  960. PHHIVE Hive,
  961. HCELL_INDEX Parent,
  962. HCELL_INDEX Child
  963. )
  964. /*++
  965. Routine Description:
  966. Removes a subkey by cell index; Also marks relevant data dirty.
  967. Intended for self healing process.
  968. Arguments:
  969. Hive - pointer to hive control structure for hive of interest
  970. Parent - cell of key that will be parent of new key
  971. Child - key to delete from Paren't sub key list
  972. Return Value:
  973. TRUE - it worked
  974. FALSE - resource problem
  975. --*/
  976. {
  977. PCM_KEY_NODE Node = NULL;
  978. PCM_KEY_INDEX Index = NULL;
  979. BOOLEAN Result = TRUE;
  980. ULONG i,j;
  981. HCELL_INDEX LeafCell = 0;
  982. PCM_KEY_INDEX Leaf = NULL;
  983. PCM_KEY_FAST_INDEX FastIndex;
  984. #ifndef _CM_LDR_
  985. PAGED_CODE();
  986. #endif //_CM_LDR_
  987. Node = (PCM_KEY_NODE)HvGetCell(Hive,Parent);
  988. if( Node == NULL ) {
  989. Result = FALSE;
  990. goto Exit;
  991. }
  992. Index = (PCM_KEY_INDEX)HvGetCell(Hive, Node->SubKeyLists[Stable]);
  993. if( Index == NULL ) {
  994. Result = FALSE;
  995. goto Exit;
  996. }
  997. if (Index->Signature == CM_KEY_INDEX_ROOT) {
  998. //
  999. // step through root, till we find the right leaf
  1000. //
  1001. for (i = 0; i < Index->Count; i++) {
  1002. if( i ) {
  1003. ASSERT( Leaf!= NULL );
  1004. ASSERT( LeafCell == Index->List[i-1] );
  1005. HvReleaseCell(Hive,LeafCell);
  1006. }
  1007. LeafCell = Index->List[i];
  1008. Leaf = (PCM_KEY_INDEX)HvGetCell(Hive, LeafCell);
  1009. if( Leaf == NULL ) {
  1010. Result = FALSE;
  1011. goto Exit;
  1012. }
  1013. for(j=0;j<Leaf->Count;j++) {
  1014. if ( (Leaf->Signature == CM_KEY_FAST_LEAF) ||
  1015. (Leaf->Signature == CM_KEY_HASH_LEAF) ) {
  1016. FastIndex = (PCM_KEY_FAST_INDEX)Leaf;
  1017. if( FastIndex->List[j].Cell == Child ) {
  1018. //
  1019. // found it!
  1020. //
  1021. HvReleaseCell(Hive,LeafCell);
  1022. HvMarkCellDirty(Hive,LeafCell);
  1023. FastIndex->Count--;
  1024. RtlMoveMemory((PVOID)&(FastIndex->List[j]),
  1025. (PVOID)&(FastIndex->List[j+1]),
  1026. (FastIndex->Count - j) * sizeof(CM_INDEX));
  1027. goto DirtyParentAndIndex;
  1028. }
  1029. } else {
  1030. if( Leaf->List[j] == Child ) {
  1031. //
  1032. // found it!
  1033. //
  1034. HvReleaseCell(Hive,LeafCell);
  1035. HvMarkCellDirty(Hive,LeafCell);
  1036. Leaf->Count--;
  1037. RtlMoveMemory((PVOID)&(Leaf->List[j]),
  1038. (PVOID)&(Leaf->List[j+1]),
  1039. (Leaf->Count - j) * sizeof(HCELL_INDEX));
  1040. goto DirtyParentAndIndex;
  1041. }
  1042. }
  1043. }
  1044. }
  1045. } else {
  1046. for(j=0;j<Index->Count;j++) {
  1047. if ( (Index->Signature == CM_KEY_FAST_LEAF) ||
  1048. (Index->Signature == CM_KEY_HASH_LEAF) ) {
  1049. FastIndex = (PCM_KEY_FAST_INDEX)Index;
  1050. if( FastIndex->List[j].Cell == Child ) {
  1051. //
  1052. // found it!
  1053. //
  1054. RtlMoveMemory((PVOID)&(FastIndex->List[j]),
  1055. (PVOID)&(FastIndex->List[j+1]),
  1056. (FastIndex->Count - j) * sizeof(CM_INDEX));
  1057. goto DirtyParentAndIndex;
  1058. }
  1059. } else {
  1060. if( Index->List[j] == Child ) {
  1061. //
  1062. // found it!
  1063. //
  1064. RtlMoveMemory((PVOID)&(Index->List[j]),
  1065. (PVOID)&(Index->List[j+1]),
  1066. (Index->Count - j) * sizeof(HCELL_INDEX));
  1067. goto DirtyParentAndIndex;
  1068. }
  1069. }
  1070. }
  1071. }
  1072. ASSERT( FALSE );
  1073. DirtyParentAndIndex:
  1074. //
  1075. // mark parent and index dirty and decrement index count.
  1076. //
  1077. HvMarkCellDirty(Hive,Node->SubKeyLists[Stable]);
  1078. HvMarkCellDirty(Hive,Parent);
  1079. Index->Count--;
  1080. Node->SubKeyCounts[Stable]--;
  1081. Exit:
  1082. if( Index ) {
  1083. ASSERT( Node );
  1084. HvReleaseCell(Hive,Node->SubKeyLists[Stable]);
  1085. }
  1086. if( Node ) {
  1087. HvReleaseCell(Hive,Parent);
  1088. }
  1089. return Result;
  1090. }
  1091. BOOLEAN
  1092. CmpAddSubKey(
  1093. PHHIVE Hive,
  1094. HCELL_INDEX Parent,
  1095. HCELL_INDEX Child
  1096. )
  1097. /*++
  1098. Routine Description:
  1099. Add a new child subkey to the subkey index for a cell. The
  1100. child MUST NOT already be present (bugcheck if so.)
  1101. NOTE: We expect Parent to already be marked dirty.
  1102. We will mark stuff in Index dirty
  1103. Arguments:
  1104. Hive - pointer to hive control structure for hive of interest
  1105. Parent - cell of key that will be parent of new key
  1106. Child - new key to put in Paren't sub key list
  1107. Return Value:
  1108. TRUE - it worked
  1109. FALSE - resource problem
  1110. --*/
  1111. {
  1112. PCM_KEY_NODE pcell;
  1113. HCELL_INDEX WorkCell;
  1114. PCM_KEY_INDEX Index;
  1115. PCM_KEY_FAST_INDEX FastIndex;
  1116. UNICODE_STRING NewName;
  1117. HCELL_INDEX LeafCell;
  1118. PHCELL_INDEX RootPointer = NULL;
  1119. ULONG cleanup = 0;
  1120. ULONG Type;
  1121. BOOLEAN IsCompressed;
  1122. ULONG i;
  1123. #ifndef _CM_LDR_
  1124. PAGED_CODE();
  1125. #endif //_CM_LDR_
  1126. CmKdPrintEx((DPFLTR_CONFIG_ID,CML_INDEX,"CmpAddSubKey:\n\t"));
  1127. CmKdPrintEx((DPFLTR_CONFIG_ID,CML_INDEX,"Hive=%p Parent=%08lx Child=%08lx\n",Hive,Parent,Child));
  1128. //
  1129. // we have the lock exclusive or nobody is operating inside this hive
  1130. //
  1131. //ASSERT_CM_LOCK_OWNED_EXCLUSIVE();
  1132. ASSERT_CM_EXCLUSIVE_HIVE_ACCESS(Hive);
  1133. //
  1134. // build a name string
  1135. //
  1136. pcell = (PCM_KEY_NODE)HvGetCell(Hive, Child);
  1137. if( pcell == NULL ) {
  1138. //
  1139. // we couldn't map the bin containing this cell
  1140. //
  1141. return FALSE;
  1142. }
  1143. // release the cell here; as the registry is locked exclusive (i.e. we don't care)
  1144. HvReleaseCell(Hive, Child);
  1145. if (pcell->Flags & KEY_COMP_NAME) {
  1146. IsCompressed = TRUE;
  1147. NewName.Length = CmpCompressedNameSize(pcell->Name, pcell->NameLength);
  1148. NewName.MaximumLength = NewName.Length;
  1149. NewName.Buffer = (Hive->Allocate)(NewName.Length, FALSE,CM_FIND_LEAK_TAG8);
  1150. if (NewName.Buffer==NULL) {
  1151. return(FALSE);
  1152. }
  1153. CmpCopyCompressedName(NewName.Buffer,
  1154. NewName.MaximumLength,
  1155. pcell->Name,
  1156. pcell->NameLength);
  1157. } else {
  1158. IsCompressed = FALSE;
  1159. NewName.Length = pcell->NameLength;
  1160. NewName.MaximumLength = pcell->NameLength;
  1161. NewName.Buffer = &(pcell->Name[0]);
  1162. }
  1163. pcell = (PCM_KEY_NODE)HvGetCell(Hive, Parent);
  1164. if( pcell == NULL ) {
  1165. //
  1166. // we couldn't map the bin containing this cell
  1167. //
  1168. goto ErrorExit;
  1169. }
  1170. //ASSERT_CELL_DIRTY(Hive,Parent);
  1171. // release the cell here; as the registry is locked exclusive (i.e. we don't care)
  1172. HvReleaseCell(Hive, Parent);
  1173. Type = HvGetCellType(Child);
  1174. if (pcell->SubKeyCounts[Type] == 0) {
  1175. ULONG Signature;
  1176. //
  1177. // we must allocate a leaf
  1178. //
  1179. WorkCell = HvAllocateCell(Hive, sizeof(CM_KEY_FAST_INDEX), Type,(HvGetCellType(Parent)==Type)?Parent:HCELL_NIL);
  1180. if (WorkCell == HCELL_NIL) {
  1181. goto ErrorExit;
  1182. }
  1183. Index = (PCM_KEY_INDEX)HvGetCell(Hive, WorkCell);
  1184. if( Index == NULL ) {
  1185. //
  1186. // we couldn't map the bin containing this cell
  1187. // this shouldn't happen 'cause we just allocated this
  1188. // cell (i.e. bin is PINNED in memory ! )
  1189. //
  1190. ASSERT( FALSE );
  1191. goto ErrorExit;
  1192. }
  1193. // release the cell here; as the registry is locked exclusive (i.e. we don't care)
  1194. HvReleaseCell(Hive, WorkCell);
  1195. if( UseHashIndex(Hive) ) {
  1196. Index->Signature = CM_KEY_HASH_LEAF;
  1197. } else if( UseFastIndex(Hive) ) {
  1198. Index->Signature = CM_KEY_FAST_LEAF;
  1199. } else {
  1200. Index->Signature = CM_KEY_INDEX_LEAF;
  1201. }
  1202. Index->Count = 0;
  1203. pcell->SubKeyLists[Type] = WorkCell;
  1204. cleanup = 1;
  1205. } else {
  1206. Index = (PCM_KEY_INDEX)HvGetCell(Hive, pcell->SubKeyLists[Type]);
  1207. if( Index == NULL ) {
  1208. //
  1209. // we couldn't map the bin containing this cell
  1210. //
  1211. goto ErrorExit;
  1212. }
  1213. // release the cell here; as the registry is locked exclusive (i.e. we don't care)
  1214. HvReleaseCell(Hive, pcell->SubKeyLists[Type]);
  1215. if ( (Index->Signature == CM_KEY_FAST_LEAF) &&
  1216. (Index->Count >= (CM_MAX_FAST_INDEX)) ) {
  1217. //
  1218. // We must change fast index to a slow index to accomodate
  1219. // growth.
  1220. //
  1221. FastIndex = (PCM_KEY_FAST_INDEX)Index;
  1222. for (i=0; i<Index->Count; i++) {
  1223. Index->List[i] = FastIndex->List[i].Cell;
  1224. }
  1225. Index->Signature = CM_KEY_INDEX_LEAF;
  1226. } else if (((Index->Signature == CM_KEY_INDEX_LEAF) ||
  1227. (Index->Signature == CM_KEY_HASH_LEAF)) &&
  1228. (Index->Count >= (CM_MAX_INDEX - 1) )) {
  1229. //
  1230. // We must change flat entry to a root/leaf tree
  1231. //
  1232. WorkCell = HvAllocateCell(
  1233. Hive,
  1234. sizeof(CM_KEY_INDEX) + sizeof(HCELL_INDEX), // allow for 2
  1235. Type,
  1236. (HvGetCellType(Parent)==Type)?Parent:HCELL_NIL
  1237. );
  1238. if (WorkCell == HCELL_NIL) {
  1239. goto ErrorExit;
  1240. }
  1241. Index = (PCM_KEY_INDEX)HvGetCell(Hive, WorkCell);
  1242. if( Index == NULL ) {
  1243. //
  1244. // we couldn't map the bin containing this cell
  1245. // this shouldn't happen 'cause we just allocated this
  1246. // cell (i.e. bin is PINNED in memory
  1247. ASSERT( FALSE );
  1248. goto ErrorExit;
  1249. }
  1250. // release the cell here; as the registry is locked exclusive (i.e. we don't care)
  1251. HvReleaseCell(Hive, WorkCell);
  1252. Index->Signature = CM_KEY_INDEX_ROOT;
  1253. Index->Count = 1;
  1254. Index->List[0] = pcell->SubKeyLists[Type];
  1255. pcell->SubKeyLists[Type] = WorkCell;
  1256. cleanup = 2;
  1257. }
  1258. }
  1259. LeafCell = pcell->SubKeyLists[Type];
  1260. //
  1261. // LeafCell is target for add, or perhaps root
  1262. // Index is pointer to fast leaf, slow Leaf or Root, whichever applies
  1263. //
  1264. if (Index->Signature == CM_KEY_INDEX_ROOT) {
  1265. LeafCell = CmpSelectLeaf(Hive, pcell, &NewName, Type, &RootPointer);
  1266. if (LeafCell == HCELL_NIL) {
  1267. goto ErrorExit;
  1268. }
  1269. }
  1270. #if 0
  1271. //
  1272. // Validation code. manually search for the key and break when found
  1273. //
  1274. if(Index->Signature == CM_KEY_INDEX_ROOT) {
  1275. LONG Result;
  1276. PCM_KEY_INDEX Leaf;
  1277. HCELL_INDEX Cell;
  1278. ULONG iCnt;
  1279. PCM_KEY_INDEX PrevLeaf;
  1280. Leaf = (PCM_KEY_INDEX)HvGetCell(Hive, LeafCell);
  1281. HvReleaseCell(Hive, LeafCell);
  1282. if( Leaf->Count ) {
  1283. Result = CmpCompareInIndex( Hive,
  1284. &NewName,
  1285. 0,
  1286. Leaf,
  1287. &Cell);
  1288. //
  1289. // must be bigger, or the first leaf
  1290. //
  1291. if( (Result < 0) && (RootPointer != &(Index->List[0])) ) {
  1292. for( iCnt=0;iCnt<Index->Count;iCnt++) {
  1293. if( Index->List[iCnt] == LeafCell ) {
  1294. break;
  1295. }
  1296. }
  1297. ASSERT( Index->List[iCnt] == LeafCell );
  1298. ASSERT( iCnt > 0 );
  1299. PrevLeaf = (PCM_KEY_INDEX)HvGetCell(Hive, Index->List[iCnt-1]);
  1300. HvReleaseCell(Hive, Index->List[iCnt-1]);
  1301. if( PrevLeaf->Count ) {
  1302. //
  1303. // must be bigger than last in prev leaf
  1304. //
  1305. Result = CmpCompareInIndex( Hive,
  1306. &NewName,
  1307. PrevLeaf->Count - 1,
  1308. PrevLeaf,
  1309. &Cell);
  1310. if( Result <= 0 ) {
  1311. //
  1312. // Error ==> Debug
  1313. //
  1314. DbgPrint("CmpAddSubKey: Wrong spot selected [1]!!!\n");
  1315. DbgPrint("Hive = %p Parent = %lx Child = %lx , Leaf = %p\n",Hive,Parent,Child,Leaf);
  1316. DbgPrint("RootPointer = %p Index = %p PrevLeaf = %p\n",RootPointer,Index,PrevLeaf);
  1317. DbgBreakPoint();
  1318. }
  1319. }
  1320. }
  1321. }
  1322. Result = CmpCompareInIndex( Hive,
  1323. &NewName,
  1324. Leaf->Count - 1,
  1325. Leaf,
  1326. &Cell);
  1327. if( Result > 0) {
  1328. //
  1329. // must be the last one
  1330. //
  1331. if( (ULONG)(Index->Count - 1) > (ULONG)(((PUCHAR)RootPointer - (PUCHAR)(&(Index->List[0])))/sizeof(HCELL_INDEX)) ) {
  1332. //
  1333. // Error ==> Debug
  1334. //
  1335. DbgPrint("CmpAddSubKey: Wrong spot selected [2]!!!\n");
  1336. DbgPrint("Hive = %p Parent = %lx Child = %lx , Leaf = %p\n",Hive,Parent,Child,Leaf);
  1337. DbgPrint("RootPointer = %p Index = %p\n",RootPointer,Index);
  1338. DbgBreakPoint();
  1339. }
  1340. }
  1341. }
  1342. #endif //0
  1343. //
  1344. // Add new cell to Leaf, update pointers
  1345. //
  1346. LeafCell = CmpAddToLeaf(Hive, LeafCell, Child, &NewName);
  1347. if (LeafCell == HCELL_NIL) {
  1348. goto ErrorExit;
  1349. }
  1350. pcell->SubKeyCounts[Type] += 1;
  1351. if (RootPointer != NULL) {
  1352. *RootPointer = LeafCell;
  1353. } else {
  1354. pcell->SubKeyLists[Type] = LeafCell;
  1355. }
  1356. if (IsCompressed) {
  1357. (Hive->Free)(NewName.Buffer, NewName.Length);
  1358. }
  1359. return TRUE;
  1360. ErrorExit:
  1361. if (IsCompressed) {
  1362. (Hive->Free)(NewName.Buffer, NewName.Length);
  1363. }
  1364. switch (cleanup) {
  1365. case 1:
  1366. HvFreeCell(Hive, pcell->SubKeyLists[Type]);
  1367. pcell->SubKeyLists[Type] = HCELL_NIL;
  1368. break;
  1369. case 2:
  1370. Index = (PCM_KEY_INDEX)HvGetCell(Hive, pcell->SubKeyLists[Type]);
  1371. if( Index == NULL ) {
  1372. //
  1373. // we couldn't map the bin containing this cell
  1374. // this shouldn't happen 'cause we just allocated this
  1375. // cell (i.e. bin is PINNED in memory).
  1376. // But ... better safe than sorry
  1377. //
  1378. ASSERT( FALSE );
  1379. return FALSE;
  1380. }
  1381. // release the cell here; as the registry is locked exclusive (i.e. we don't care)
  1382. HvReleaseCell(Hive, pcell->SubKeyLists[Type]);
  1383. WorkCell = Index->List[0];
  1384. HvFreeCell(Hive, pcell->SubKeyLists[Type]);
  1385. pcell->SubKeyLists[Type] = WorkCell;
  1386. break;
  1387. }
  1388. return FALSE;
  1389. }
  1390. HCELL_INDEX
  1391. CmpAddToLeaf(
  1392. PHHIVE Hive,
  1393. HCELL_INDEX LeafCell,
  1394. HCELL_INDEX NewKey,
  1395. PUNICODE_STRING NewName
  1396. )
  1397. /*++
  1398. Routine Description:
  1399. Insert a new subkey into a Leaf index. Supports both fast and slow
  1400. leaf indexes and will determine which sort of index the given leaf is.
  1401. NOTE: We expect Root to already be marked dirty by caller if non NULL.
  1402. We expect Leaf to always be marked dirty by caller.
  1403. Arguments:
  1404. Hive - pointer to hive control structure for hive of interest
  1405. LeafCell - cell of index leaf node we are to add entry too
  1406. NewKey - cell of KEY_NODE we are to add
  1407. NewName - pointer to unicode string with name to we are to add
  1408. Return Value:
  1409. HCELL_NIL - some resource problem
  1410. Else - cell of Leaf index when are done, caller is expected to
  1411. set this into Root index or Key body.
  1412. --*/
  1413. {
  1414. PCM_KEY_INDEX Leaf;
  1415. PCM_KEY_FAST_INDEX FastLeaf;
  1416. ULONG Size;
  1417. ULONG OldSize;
  1418. ULONG freecount;
  1419. HCELL_INDEX NewCell;
  1420. HCELL_INDEX Child;
  1421. ULONG Select;
  1422. LONG Result;
  1423. ULONG EntrySize;
  1424. ULONG i;
  1425. CmKdPrintEx((DPFLTR_CONFIG_ID,CML_INDEX,"CmpAddToLeaf:\n\t"));
  1426. CmKdPrintEx((DPFLTR_CONFIG_ID,CML_INDEX,"Hive=%p LeafCell=%08lx NewKey=%08lx\n",Hive,LeafCell,NewKey));
  1427. //
  1428. // we have the lock exclusive or nobody is operating inside this hive
  1429. //
  1430. //ASSERT_CM_LOCK_OWNED_EXCLUSIVE();
  1431. ASSERT_CM_EXCLUSIVE_HIVE_ACCESS(Hive);
  1432. if (!HvMarkCellDirty(Hive, LeafCell)) {
  1433. return HCELL_NIL;
  1434. }
  1435. //
  1436. // compute number free slots left in the leaf
  1437. //
  1438. Leaf = (PCM_KEY_INDEX)HvGetCell(Hive, LeafCell);
  1439. if( Leaf == NULL ) {
  1440. //
  1441. // we couldn't map the bin containing this cell
  1442. // this shouldn't happen as marking dirty means
  1443. // PINNING the view into memory
  1444. //
  1445. ASSERT( FALSE );
  1446. return HCELL_NIL;
  1447. }
  1448. // release the cell here; as the registry is locked exclusive (i.e. we don't care)
  1449. HvReleaseCell(Hive, LeafCell);
  1450. if (Leaf->Signature == CM_KEY_INDEX_LEAF) {
  1451. FastLeaf = NULL;
  1452. EntrySize = sizeof(HCELL_INDEX);
  1453. } else {
  1454. ASSERT( (Leaf->Signature == CM_KEY_FAST_LEAF) ||
  1455. (Leaf->Signature == CM_KEY_HASH_LEAF)
  1456. );
  1457. FastLeaf = (PCM_KEY_FAST_INDEX)Leaf;
  1458. EntrySize = sizeof(CM_INDEX);
  1459. }
  1460. OldSize = HvGetCellSize(Hive, Leaf);
  1461. Size = OldSize - ((EntrySize * Leaf->Count) +
  1462. FIELD_OFFSET(CM_KEY_INDEX, List));
  1463. freecount = Size / EntrySize;
  1464. //
  1465. // grow the leaf if it isn't big enough
  1466. //
  1467. NewCell = LeafCell;
  1468. if (freecount < 1) {
  1469. Size = OldSize + OldSize / 2;
  1470. if (Size < (OldSize + EntrySize)) {
  1471. Size = OldSize + EntrySize;
  1472. }
  1473. NewCell = HvReallocateCell(Hive, LeafCell, Size);
  1474. if (NewCell == HCELL_NIL) {
  1475. return HCELL_NIL;
  1476. }
  1477. Leaf = (PCM_KEY_INDEX)HvGetCell(Hive, NewCell);
  1478. if( Leaf == NULL ) {
  1479. //
  1480. // we couldn't map the bin containing this cell
  1481. // this shouldn't happen 'cause we just allocated this
  1482. // cell (i.e. bin is PINNED in memory)
  1483. //
  1484. ASSERT( FALSE );
  1485. return HCELL_NIL;
  1486. }
  1487. // release the cell here; as the registry is locked exclusive (i.e. we don't care)
  1488. HvReleaseCell(Hive, NewCell);
  1489. if (FastLeaf != NULL) {
  1490. FastLeaf = (PCM_KEY_FAST_INDEX)Leaf;
  1491. }
  1492. }
  1493. //
  1494. // Find where to put the new entry
  1495. //
  1496. Select = CmpFindSubKeyInLeaf(Hive, Leaf, NewName, &Child);
  1497. if( INVALID_INDEX & Select ) {
  1498. //
  1499. // couldn't map view
  1500. //
  1501. return HCELL_NIL;
  1502. }
  1503. ASSERT(Child == HCELL_NIL);
  1504. //
  1505. // Select is the index in List of the entry nearest where the
  1506. // new entry should go.
  1507. // Decide wether the new entry goes before or after Offset entry,
  1508. // and then ripple copy and set.
  1509. // If Select == Count, then the leaf is empty, so simply set our entry
  1510. //
  1511. if (Select != Leaf->Count) {
  1512. Result = CmpCompareInIndex(Hive,
  1513. NewName,
  1514. Select,
  1515. Leaf,
  1516. &Child);
  1517. if( Result == 2 ) {
  1518. //
  1519. // couldn't map view inside; bail out
  1520. //
  1521. return HCELL_NIL;
  1522. }
  1523. ASSERT(Result != 0);
  1524. //
  1525. // Result -1 - NewName/NewKey less than selected key, insert before
  1526. // +1 - NewName/NewKey greater than selected key, insert after
  1527. //
  1528. if (Result > 0) {
  1529. ASSERT( Result == 1 );
  1530. Select++;
  1531. }
  1532. if (Select != Leaf->Count) {
  1533. //
  1534. // ripple copy to make space and insert
  1535. //
  1536. if (FastLeaf != NULL) {
  1537. RtlMoveMemory((PVOID)&(FastLeaf->List[Select+1]),
  1538. (PVOID)&(FastLeaf->List[Select]),
  1539. sizeof(CM_INDEX)*(FastLeaf->Count - Select));
  1540. } else {
  1541. RtlMoveMemory((PVOID)&(Leaf->List[Select+1]),
  1542. (PVOID)&(Leaf->List[Select]),
  1543. sizeof(HCELL_INDEX)*(Leaf->Count - Select));
  1544. }
  1545. }
  1546. }
  1547. if (FastLeaf != NULL) {
  1548. FastLeaf->List[Select].Cell = NewKey;
  1549. if( FastLeaf->Signature == CM_KEY_HASH_LEAF ) {
  1550. //
  1551. // Hash leaf; store the HashKey
  1552. //
  1553. FastLeaf->List[Select].HashKey = CmpComputeHashKey(NewName);
  1554. } else {
  1555. FastLeaf->List[Select].NameHint[0] = 0;
  1556. FastLeaf->List[Select].NameHint[1] = 0;
  1557. FastLeaf->List[Select].NameHint[2] = 0;
  1558. FastLeaf->List[Select].NameHint[3] = 0;
  1559. if (NewName->Length/sizeof(WCHAR) < 4) {
  1560. i = NewName->Length/sizeof(WCHAR);
  1561. } else {
  1562. i = 4;
  1563. }
  1564. do {
  1565. if ((USHORT)NewName->Buffer[i-1] > (UCHAR)-1) {
  1566. //
  1567. // Can't compress this name. Leave NameHint[0]==0
  1568. // to force the name to be looked up in the key.
  1569. //
  1570. break;
  1571. }
  1572. FastLeaf->List[Select].NameHint[i-1] = (UCHAR)NewName->Buffer[i-1];
  1573. i--;
  1574. } while ( i>0 );
  1575. }
  1576. } else {
  1577. Leaf->List[Select] = NewKey;
  1578. }
  1579. Leaf->Count += 1;
  1580. return NewCell;
  1581. }
  1582. HCELL_INDEX
  1583. CmpSelectLeaf(
  1584. PHHIVE Hive,
  1585. PCM_KEY_NODE ParentKey,
  1586. PUNICODE_STRING NewName,
  1587. HSTORAGE_TYPE Type,
  1588. PHCELL_INDEX *RootPointer
  1589. )
  1590. /*++
  1591. Routine Description:
  1592. This routine is only called if the subkey index for a cell is NOT
  1593. simply a single Leaf index block.
  1594. It selects the Leaf index block to which a new entry is to be
  1595. added. It may create this block by splitting an existing Leaf
  1596. block.
  1597. Arguments:
  1598. Hive - pointer to hive control structure for hive of interest
  1599. ParentKey - mapped pointer to parent key
  1600. NewName - pointer to unicode string naming entry to add
  1601. Type - Stable or Volatile, describes Child's storage
  1602. RootPointer - pointer to variable to receive address of HCELL_INDEX
  1603. that points to Leaf block returned as function argument.
  1604. Used for updates.
  1605. Return Value:
  1606. HCELL_NIL - resource problem
  1607. Else, cell index of Leaf index block to add entry to
  1608. --*/
  1609. {
  1610. HCELL_INDEX LeafCell;
  1611. HCELL_INDEX WorkCell;
  1612. PCM_KEY_INDEX Index;
  1613. PCM_KEY_INDEX Leaf;
  1614. PCM_KEY_FAST_INDEX FastLeaf;
  1615. ULONG RootSelect;
  1616. LONG Result;
  1617. CmKdPrintEx((DPFLTR_CONFIG_ID,CML_INDEX,"CmpSelectLeaf:\n\t"));
  1618. CmKdPrintEx((DPFLTR_CONFIG_ID,CML_INDEX,"Hive=%p ParentKey=%p\n", Hive, ParentKey));
  1619. //
  1620. // we have the lock exclusive or nobody is operating inside this hive
  1621. //
  1622. //ASSERT_CM_LOCK_OWNED_EXCLUSIVE();
  1623. ASSERT_CM_EXCLUSIVE_HIVE_ACCESS(Hive);
  1624. //
  1625. // Force root to always be dirty, since we'll either grow it or edit it,
  1626. // and it needs to be marked dirty for BOTH cases. (Edit may not
  1627. // occur until after we leave
  1628. //
  1629. if (! HvMarkCellDirty(Hive, ParentKey->SubKeyLists[Type])) {
  1630. return HCELL_NIL;
  1631. }
  1632. //
  1633. // must find the proper leaf
  1634. //
  1635. Index = (PCM_KEY_INDEX)HvGetCell(Hive, ParentKey->SubKeyLists[Type]);
  1636. if( Index == NULL ) {
  1637. //
  1638. // we couldn't map the bin containing this cell
  1639. // this shouldn't happen as marking dirty means
  1640. // PINNING the view into memory
  1641. //
  1642. ASSERT( FALSE );
  1643. return HCELL_NIL;
  1644. }
  1645. ASSERT(Index->Signature == CM_KEY_INDEX_ROOT);
  1646. // release the cell here; as the registry is locked exclusive (i.e. we don't care)
  1647. HvReleaseCell(Hive, ParentKey->SubKeyLists[Type]);
  1648. while (TRUE) {
  1649. RootSelect = CmpFindSubKeyInRoot(Hive, Index, NewName, &LeafCell);
  1650. if( INVALID_INDEX & RootSelect ) {
  1651. //
  1652. // couldn't map view inside; bail out
  1653. //
  1654. return HCELL_NIL;
  1655. }
  1656. if (LeafCell == HCELL_NIL) {
  1657. //
  1658. // Leaf of interest is somewhere near RootSelect
  1659. //
  1660. // . Always use lowest order leaf we can get away with
  1661. // . Never split a leaf if there's one with space we can use
  1662. // . When we split a leaf, we have to repeat search
  1663. //
  1664. // If (NewKey is below lowest key in selected)
  1665. // If there's a Leaf below selected with space
  1666. // use the leaf below
  1667. // else
  1668. // use the leaf (split it if not enough space)
  1669. // Else
  1670. // must be above highest key in selected, less than
  1671. // lowest key in Leaf to right of selected
  1672. // if space in selected
  1673. // use selected
  1674. // else if space in leaf above selected
  1675. // use leaf above
  1676. // else
  1677. // split selected
  1678. //
  1679. LeafCell = Index->List[RootSelect];
  1680. Leaf = (PCM_KEY_INDEX)HvGetCell(Hive, LeafCell);
  1681. if( Leaf == NULL ) {
  1682. //
  1683. // we couldn't map the bin containing this cell
  1684. //
  1685. return HCELL_NIL;
  1686. }
  1687. // release the cell here; as the registry is locked exclusive (i.e. we don't care)
  1688. HvReleaseCell(Hive, LeafCell);
  1689. if( (Leaf->Signature == CM_KEY_FAST_LEAF) ||
  1690. (Leaf->Signature == CM_KEY_HASH_LEAF) ) {
  1691. FastLeaf = (PCM_KEY_FAST_INDEX)Leaf;
  1692. WorkCell = FastLeaf->List[0].Cell;
  1693. } else {
  1694. ASSERT( Leaf->Signature == CM_KEY_INDEX_LEAF );
  1695. WorkCell = Leaf->List[0];
  1696. }
  1697. Result = CmpDoCompareKeyName(Hive, NewName, WorkCell);
  1698. if( Result == 2 ) {
  1699. //
  1700. // couldn't map view inside; bail out
  1701. //
  1702. return HCELL_NIL;
  1703. }
  1704. ASSERT(Result != 0);
  1705. if (Result < 0) {
  1706. //
  1707. // new is off the left end of Selected
  1708. //
  1709. if (RootSelect > 0) {
  1710. //
  1711. // there's a Leaf to the left, try to use it
  1712. //
  1713. LeafCell = Index->List[RootSelect-1];
  1714. Leaf = (PCM_KEY_INDEX)HvGetCell(Hive, LeafCell);
  1715. if( Leaf == NULL ) {
  1716. //
  1717. // we couldn't map the bin containing this cell
  1718. //
  1719. return HCELL_NIL;
  1720. }
  1721. // release the cell here; as the registry is locked exclusive (i.e. we don't care)
  1722. HvReleaseCell(Hive, LeafCell);
  1723. if (Leaf->Count < (CM_MAX_INDEX - 1)) {
  1724. RootSelect--;
  1725. *RootPointer = &(Index->List[RootSelect]);
  1726. break;
  1727. }
  1728. } else {
  1729. //
  1730. // new key is off the left end of the leftmost leaf.
  1731. // Use the leftmost leaf, if there's enough room
  1732. //
  1733. LeafCell = Index->List[0];
  1734. Leaf = (PCM_KEY_INDEX)HvGetCell(Hive, LeafCell);
  1735. if( Leaf == NULL ) {
  1736. //
  1737. // we couldn't map the bin containing this cell
  1738. //
  1739. return HCELL_NIL;
  1740. }
  1741. // release the cell here; as the registry is locked exclusive (i.e. we don't care)
  1742. HvReleaseCell(Hive, LeafCell);
  1743. if (Leaf->Count < (CM_MAX_INDEX - 1)) {
  1744. *RootPointer = &(Index->List[0]);
  1745. break;
  1746. }
  1747. }
  1748. //
  1749. // else fall to split case
  1750. //
  1751. } else {
  1752. //
  1753. // since new key is not in a Leaf, and is not off
  1754. // the left end of the ResultSelect Leaf, it must
  1755. // be off the right end.
  1756. //
  1757. LeafCell = Index->List[RootSelect];
  1758. Leaf = (PCM_KEY_INDEX)HvGetCell(Hive, LeafCell);
  1759. if( Leaf == NULL ) {
  1760. //
  1761. // we couldn't map the bin containing this cell
  1762. //
  1763. return HCELL_NIL;
  1764. }
  1765. // release the cell here; as the registry is locked exclusive (i.e. we don't care)
  1766. HvReleaseCell(Hive, LeafCell);
  1767. if (Leaf->Count < (CM_MAX_INDEX - 1)) {
  1768. *RootPointer = &(Index->List[RootSelect]);
  1769. break;
  1770. }
  1771. //
  1772. // No space, see if there's a leaf to the rigth
  1773. // and if it has space
  1774. //
  1775. if (RootSelect < (ULONG)(Index->Count - 1)) {
  1776. LeafCell = Index->List[RootSelect+1];
  1777. Leaf = (PCM_KEY_INDEX)HvGetCell(Hive, LeafCell);
  1778. if( Leaf == NULL ) {
  1779. //
  1780. // we couldn't map the bin containing this cell
  1781. //
  1782. return HCELL_NIL;
  1783. }
  1784. // release the cell here; as the registry is locked exclusive (i.e. we don't care)
  1785. HvReleaseCell(Hive, LeafCell);
  1786. if (Leaf->Count < (CM_MAX_INDEX - 1)) {
  1787. *RootPointer = &(Index->List[RootSelect+1]);
  1788. break;
  1789. }
  1790. }
  1791. //
  1792. // fall to split case
  1793. //
  1794. }
  1795. } else { // LeafCell != HCELL_NIL
  1796. //
  1797. // Since newkey cannot already be in tree, it must be
  1798. // greater than the bottom of Leaf and less than the top,
  1799. // therefore it must go in Leaf. If no space, split it.
  1800. //
  1801. Leaf = (PCM_KEY_INDEX)HvGetCell(Hive, LeafCell);
  1802. if( Leaf == NULL ) {
  1803. //
  1804. // we couldn't map the bin containing this cell
  1805. //
  1806. return HCELL_NIL;
  1807. }
  1808. // release the cell here; as the registry is locked exclusive (i.e. we don't care)
  1809. HvReleaseCell(Hive, LeafCell);
  1810. if (Leaf->Count < (CM_MAX_INDEX - 1)) {
  1811. *RootPointer = &(Index->List[RootSelect]);
  1812. break;
  1813. }
  1814. //
  1815. // fall to split case
  1816. //
  1817. }
  1818. //
  1819. // either no neigbor, or no space in neighbor, so split
  1820. //
  1821. WorkCell = CmpSplitLeaf(
  1822. Hive,
  1823. ParentKey->SubKeyLists[Type], // root cell
  1824. RootSelect,
  1825. Type
  1826. );
  1827. if (WorkCell == HCELL_NIL) {
  1828. return HCELL_NIL;
  1829. }
  1830. ParentKey->SubKeyLists[Type] = WorkCell;
  1831. Index = (PCM_KEY_INDEX)HvGetCell(Hive, WorkCell);
  1832. if( Index == NULL ) {
  1833. //
  1834. // we couldn't map the bin containing this cell
  1835. //
  1836. return HCELL_NIL;
  1837. }
  1838. // release the cell here; as the registry is locked exclusive (i.e. we don't care)
  1839. HvReleaseCell(Hive, WorkCell);
  1840. ASSERT(Index->Signature == CM_KEY_INDEX_ROOT);
  1841. } // while(true)
  1842. return LeafCell;
  1843. }
  1844. HCELL_INDEX
  1845. CmpSplitLeaf(
  1846. PHHIVE Hive,
  1847. HCELL_INDEX RootCell,
  1848. ULONG RootSelect,
  1849. HSTORAGE_TYPE Type
  1850. )
  1851. /*++
  1852. Routine Description:
  1853. Split the Leaf index block specified by RootSelect, causing both
  1854. of the split out Leaf blocks to appear in the Root index block
  1855. specified by RootCell.
  1856. Caller is expected to have marked old root cell dirty.
  1857. Arguments:
  1858. Hive - pointer to hive control structure for hive of interest
  1859. RootCell - cell of the Root index block of index being grown
  1860. RootSelect - indicates which child of Root to split
  1861. Type - Stable or Volatile
  1862. Return Value:
  1863. HCELL_NIL - some resource problem
  1864. Else - cell of new (e.g. reallocated) Root index block
  1865. --*/
  1866. {
  1867. PCM_KEY_INDEX Root;
  1868. HCELL_INDEX LeafCell;
  1869. PCM_KEY_INDEX Leaf;
  1870. HCELL_INDEX NewLeafCell;
  1871. PCM_KEY_INDEX NewLeaf;
  1872. PCM_KEY_FAST_INDEX FastLeaf;
  1873. ULONG Size;
  1874. ULONG freecount;
  1875. USHORT OldCount;
  1876. USHORT KeepCount;
  1877. USHORT NewCount;
  1878. USHORT ElemSize;
  1879. CmKdPrintEx((DPFLTR_CONFIG_ID,CML_INDEX,"CmpSplitLeaf:\n\t"));
  1880. CmKdPrintEx((DPFLTR_CONFIG_ID,CML_INDEX,"Hive=%p RootCell=%08lx RootSelect\n", Hive, RootCell, RootSelect));
  1881. //
  1882. // we have the lock exclusive or nobody is operating inside this hive
  1883. //
  1884. //ASSERT_CM_LOCK_OWNED_EXCLUSIVE();
  1885. ASSERT_CM_EXCLUSIVE_HIVE_ACCESS(Hive);
  1886. //
  1887. // allocate new Leaf index block
  1888. //
  1889. Root = (PCM_KEY_INDEX)HvGetCell(Hive, RootCell);
  1890. if( Root == NULL ) {
  1891. //
  1892. // we couldn't map the bin containing this cell
  1893. //
  1894. return HCELL_NIL;
  1895. }
  1896. // release the cell here; as the registry is locked exclusive (i.e. we don't care)
  1897. HvReleaseCell(Hive, RootCell);
  1898. LeafCell = Root->List[RootSelect];
  1899. Leaf = (PCM_KEY_INDEX)HvGetCell(Hive, LeafCell);
  1900. if( Leaf == NULL ) {
  1901. //
  1902. // we couldn't map the bin containing this cell
  1903. //
  1904. return HCELL_NIL;
  1905. }
  1906. OldCount = Leaf->Count;
  1907. // release the cell here; as the registry is locked exclusive (i.e. we don't care)
  1908. HvReleaseCell(Hive, LeafCell);
  1909. KeepCount = (USHORT)(OldCount / 2); // # of entries to keep in org. Leaf
  1910. NewCount = (OldCount - KeepCount); // # of entries to move
  1911. if( UseHashIndex(Hive) ) {
  1912. ASSERT( Leaf->Signature == CM_KEY_HASH_LEAF );
  1913. ElemSize = sizeof(CM_INDEX);
  1914. } else {
  1915. ElemSize = sizeof(HCELL_INDEX);
  1916. ASSERT( Leaf->Signature == CM_KEY_INDEX_LEAF );
  1917. }
  1918. ASSERT( FIELD_OFFSET(CM_KEY_INDEX, List) == FIELD_OFFSET(CM_KEY_FAST_INDEX, List) );
  1919. Size = (ElemSize * NewCount) +
  1920. FIELD_OFFSET(CM_KEY_INDEX, List) + 1; // +1 to assure room for add
  1921. if (!HvMarkCellDirty(Hive, LeafCell)) {
  1922. return HCELL_NIL;
  1923. }
  1924. //
  1925. //
  1926. //
  1927. ASSERT( (HvGetCellType(LeafCell) == (ULONG)Type) );
  1928. NewLeafCell = HvAllocateCell(Hive, Size, Type,LeafCell);
  1929. if (NewLeafCell == HCELL_NIL) {
  1930. return HCELL_NIL;
  1931. }
  1932. NewLeaf = (PCM_KEY_INDEX)HvGetCell(Hive, NewLeafCell);
  1933. if( NewLeaf == NULL ) {
  1934. //
  1935. // we couldn't map the bin containing this cell
  1936. // this shouldn't happen as we just allocated this cell
  1937. // so it's bin should be PINNED into memory
  1938. //
  1939. ASSERT( FALSE );
  1940. HvFreeCell(Hive, NewLeafCell);
  1941. return HCELL_NIL;
  1942. }
  1943. if( UseHashIndex(Hive) ) {
  1944. NewLeaf->Signature = CM_KEY_HASH_LEAF;
  1945. } else {
  1946. NewLeaf->Signature = CM_KEY_INDEX_LEAF;
  1947. }
  1948. // release the cell here; as the registry is locked exclusive (i.e. we don't care)
  1949. HvReleaseCell(Hive, NewLeafCell);
  1950. //
  1951. // compute number of free slots left in the root
  1952. //
  1953. Size = HvGetCellSize(Hive, Root);
  1954. Size = Size - ((sizeof(HCELL_INDEX) * Root->Count) +
  1955. FIELD_OFFSET(CM_KEY_INDEX, List));
  1956. freecount = Size / sizeof(HCELL_INDEX);
  1957. //
  1958. // grow the root if it isn't big enough
  1959. //
  1960. if (freecount < 1) {
  1961. Size = HvGetCellSize(Hive, Root) + sizeof(HCELL_INDEX);
  1962. RootCell = HvReallocateCell(Hive, RootCell, Size);
  1963. if (RootCell == HCELL_NIL) {
  1964. HvFreeCell(Hive, NewLeafCell);
  1965. return HCELL_NIL;
  1966. }
  1967. Root = (PCM_KEY_INDEX)HvGetCell(Hive, RootCell);
  1968. if( Root == NULL ) {
  1969. //
  1970. // we couldn't map the bin containing this cell
  1971. // this shouldn't happen as we just allocated this cell
  1972. // so it's bin should be PINNED into memory
  1973. //
  1974. ASSERT( FALSE );
  1975. HvFreeCell(Hive, NewLeafCell);
  1976. return HCELL_NIL;
  1977. }
  1978. // release the cell here; as the registry is locked exclusive (i.e. we don't care)
  1979. HvReleaseCell(Hive, RootCell);
  1980. }
  1981. //
  1982. // copy data from one Leaf to the other
  1983. //
  1984. //
  1985. if( UseHashIndex(Hive) ) {
  1986. FastLeaf = (PCM_KEY_FAST_INDEX)Leaf;
  1987. #if 0 //DBG
  1988. {
  1989. HCELL_INDEX PrevCell = HCELL_NIL;
  1990. HCELL_INDEX CurCell;
  1991. ULONG i;
  1992. for( i=0;i<(ULONG)(Leaf->Count);i++) {
  1993. CurCell = FastLeaf->List[i].Cell;
  1994. if( (PrevCell != HCELL_NIL) && (PrevCell == CurCell) ) {
  1995. DbgPrint("CmpSplitLeaf(%p,%lx,%lx) \n",Hive,RootCell,RootSelect);
  1996. DbgPrint("\t Leaf = %p\n",Leaf);
  1997. DbgPrint("\t at index %lx we have duplicate cell - BEFORE\n",i);
  1998. DbgBreakPoint();
  1999. }
  2000. PrevCell = CurCell;
  2001. }
  2002. }
  2003. #endif //DBG
  2004. RtlMoveMemory(
  2005. (PVOID)&(NewLeaf->List[0]),
  2006. (PVOID)&(FastLeaf->List[KeepCount]),
  2007. ElemSize * NewCount
  2008. );
  2009. } else {
  2010. RtlMoveMemory(
  2011. (PVOID)&(NewLeaf->List[0]),
  2012. (PVOID)&(Leaf->List[KeepCount]),
  2013. ElemSize * NewCount
  2014. );
  2015. }
  2016. ASSERT(KeepCount != 0);
  2017. ASSERT(NewCount != 0);
  2018. Leaf->Count = KeepCount;
  2019. NewLeaf->Count = NewCount;
  2020. //
  2021. // make an open slot in the root
  2022. //
  2023. if (RootSelect < (ULONG)(Root->Count-1)) {
  2024. RtlMoveMemory(
  2025. (PVOID)&(Root->List[RootSelect+2]),
  2026. (PVOID)&(Root->List[RootSelect+1]),
  2027. (Root->Count - (RootSelect + 1)) * sizeof(HCELL_INDEX)
  2028. );
  2029. }
  2030. //
  2031. // update the root
  2032. //
  2033. Root->Count += 1;
  2034. Root->List[RootSelect+1] = NewLeafCell;
  2035. return RootCell;
  2036. }
  2037. BOOLEAN
  2038. CmpMarkIndexDirty(
  2039. PHHIVE Hive,
  2040. HCELL_INDEX ParentKey,
  2041. HCELL_INDEX TargetKey
  2042. )
  2043. /*++
  2044. Routine Description:
  2045. Mark as dirty relevent cells of a subkey index. The Leaf that
  2046. points to TargetKey, and the Root index block, if applicable,
  2047. will be marked dirty. This call assumes we are setting up
  2048. for a subkey delete.
  2049. Arguments:
  2050. Hive - pointer to hive control structure for hive of interest
  2051. ParentKey - key from whose subkey list delete is to be performed
  2052. TargetKey - key being deleted
  2053. Return Value:
  2054. TRUE - it worked, FALSE - it didn't, some resource problem
  2055. --*/
  2056. {
  2057. PCM_KEY_NODE pcell;
  2058. ULONG i;
  2059. HCELL_INDEX IndexCell;
  2060. PCM_KEY_INDEX Index;
  2061. HCELL_INDEX Child = HCELL_NIL;
  2062. UNICODE_STRING SearchName;
  2063. BOOLEAN IsCompressed;
  2064. HCELL_INDEX CellToRelease = HCELL_NIL;
  2065. pcell = (PCM_KEY_NODE)HvGetCell(Hive, TargetKey);
  2066. if( pcell == NULL ) {
  2067. //
  2068. // we couldn't map the bin containing this cell
  2069. //
  2070. return FALSE;
  2071. }
  2072. if (pcell->Flags & KEY_COMP_NAME) {
  2073. IsCompressed = TRUE;
  2074. SearchName.Length = CmpCompressedNameSize(pcell->Name, pcell->NameLength);
  2075. SearchName.MaximumLength = SearchName.Length;
  2076. #if defined(_CM_LDR_)
  2077. SearchName.Buffer = (Hive->Allocate)(SearchName.Length, FALSE,CM_FIND_LEAK_TAG9);
  2078. #else
  2079. SearchName.Buffer = ExAllocatePool(PagedPool, SearchName.Length);
  2080. #endif
  2081. if (SearchName.Buffer==NULL) {
  2082. HvReleaseCell(Hive, TargetKey);
  2083. return(FALSE);
  2084. }
  2085. CmpCopyCompressedName(SearchName.Buffer,
  2086. SearchName.MaximumLength,
  2087. pcell->Name,
  2088. pcell->NameLength);
  2089. } else {
  2090. IsCompressed = FALSE;
  2091. SearchName.Length = pcell->NameLength;
  2092. SearchName.MaximumLength = pcell->NameLength;
  2093. SearchName.Buffer = &(pcell->Name[0]);
  2094. }
  2095. HvReleaseCell(Hive, TargetKey);
  2096. pcell = (PCM_KEY_NODE)HvGetCell(Hive, ParentKey);
  2097. if( pcell == NULL ) {
  2098. //
  2099. // we couldn't map the bin containing this cell
  2100. //
  2101. goto ErrorExit;
  2102. }
  2103. for (i = 0; i < Hive->StorageTypeCount; i++) {
  2104. if (pcell->SubKeyCounts[i] != 0) {
  2105. ASSERT(HvIsCellAllocated(Hive, pcell->SubKeyLists[i]));
  2106. IndexCell = pcell->SubKeyLists[i];
  2107. if( CellToRelease != HCELL_NIL ) {
  2108. HvReleaseCell(Hive, CellToRelease);
  2109. CellToRelease = HCELL_NIL;
  2110. }
  2111. Index = (PCM_KEY_INDEX)HvGetCell(Hive, IndexCell);
  2112. if( Index == NULL ) {
  2113. //
  2114. // we couldn't map the bin containing this cell
  2115. //
  2116. goto ErrorExit;
  2117. }
  2118. CellToRelease = IndexCell;
  2119. if (Index->Signature == CM_KEY_INDEX_ROOT) {
  2120. //
  2121. // target even in index?
  2122. //
  2123. if( INVALID_INDEX & CmpFindSubKeyInRoot(Hive, Index, &SearchName, &Child) ) {
  2124. //
  2125. // couldn't map view inside; bail out
  2126. //
  2127. goto ErrorExit;
  2128. }
  2129. if (Child == HCELL_NIL) {
  2130. continue;
  2131. }
  2132. //
  2133. // mark root dirty
  2134. //
  2135. if (! HvMarkCellDirty(Hive, IndexCell)) {
  2136. goto ErrorExit;
  2137. }
  2138. if( CellToRelease != HCELL_NIL ) {
  2139. HvReleaseCell(Hive, CellToRelease);
  2140. CellToRelease = HCELL_NIL;
  2141. }
  2142. IndexCell = Child;
  2143. Index = (PCM_KEY_INDEX)HvGetCell(Hive, Child);
  2144. if( Index == NULL ) {
  2145. //
  2146. // we couldn't map the bin containing this cell
  2147. //
  2148. goto ErrorExit;
  2149. }
  2150. CellToRelease = Child;
  2151. }
  2152. ASSERT((Index->Signature == CM_KEY_INDEX_LEAF) ||
  2153. (Index->Signature == CM_KEY_FAST_LEAF) ||
  2154. (Index->Signature == CM_KEY_HASH_LEAF)
  2155. );
  2156. if( INVALID_INDEX & CmpFindSubKeyInLeaf(Hive, Index, &SearchName, &Child) ) {
  2157. //
  2158. // couldn't map view
  2159. //
  2160. goto ErrorExit;
  2161. }
  2162. if (Child != HCELL_NIL) {
  2163. if (IsCompressed) {
  2164. #if defined(_CM_LDR_)
  2165. (Hive->Free)(SearchName.Buffer, SearchName.Length);
  2166. #else
  2167. ExFreePool(SearchName.Buffer);
  2168. #endif
  2169. }
  2170. // cleanup
  2171. HvReleaseCell(Hive, ParentKey);
  2172. if( CellToRelease != HCELL_NIL ) {
  2173. HvReleaseCell(Hive, CellToRelease);
  2174. }
  2175. return(HvMarkCellDirty(Hive, IndexCell));
  2176. }
  2177. }
  2178. }
  2179. ErrorExit:
  2180. if( pcell!= NULL ) {
  2181. HvReleaseCell(Hive, ParentKey);
  2182. }
  2183. if( CellToRelease != HCELL_NIL ) {
  2184. HvReleaseCell(Hive, CellToRelease);
  2185. }
  2186. if (IsCompressed) {
  2187. #if defined(_CM_LDR_)
  2188. (Hive->Free)(SearchName.Buffer, SearchName.Length);
  2189. #else
  2190. ExFreePool(SearchName.Buffer);
  2191. #endif
  2192. }
  2193. return FALSE;
  2194. }
  2195. BOOLEAN
  2196. CmpRemoveSubKey(
  2197. PHHIVE Hive,
  2198. HCELL_INDEX ParentKey,
  2199. HCELL_INDEX TargetKey
  2200. )
  2201. /*++
  2202. Routine Description:
  2203. Remove the subkey TargetKey refers to from ParentKey's list.
  2204. NOTE: Assumes that caller has marked relevent cells dirty,
  2205. see CmpMarkIndexDirty.
  2206. Arguments:
  2207. Hive - pointer to hive control structure for hive of interest
  2208. ParentKey - key from whose subkey list delete is to be performed
  2209. TargetKey - key being deleted
  2210. Return Value:
  2211. TRUE - it worked, FALSE - it didn't, some resource problem
  2212. --*/
  2213. {
  2214. PCM_KEY_NODE pcell;
  2215. HCELL_INDEX LeafCell;
  2216. PCM_KEY_INDEX Leaf;
  2217. PCM_KEY_FAST_INDEX FastIndex;
  2218. HCELL_INDEX RootCell = HCELL_NIL;
  2219. PCM_KEY_INDEX Root = NULL;
  2220. HCELL_INDEX Child;
  2221. ULONG Type;
  2222. ULONG RootSelect;
  2223. ULONG LeafSelect;
  2224. UNICODE_STRING SearchName;
  2225. BOOLEAN IsCompressed;
  2226. WCHAR CompressedBuffer[50];
  2227. BOOLEAN Result;
  2228. HCELL_INDEX CellToRelease1 = HCELL_NIL,CellToRelease2 = HCELL_NIL;
  2229. pcell = (PCM_KEY_NODE)HvGetCell(Hive, TargetKey);
  2230. if( pcell == NULL ) {
  2231. //
  2232. // we couldn't map the bin containing this cell
  2233. //
  2234. return FALSE;
  2235. }
  2236. ASSERT_CELL_DIRTY(Hive,TargetKey);
  2237. //
  2238. // release the cell here; as key is dirty/pinned
  2239. //
  2240. HvReleaseCell(Hive, TargetKey);
  2241. if (pcell->Flags & KEY_COMP_NAME) {
  2242. IsCompressed = TRUE;
  2243. SearchName.Length = CmpCompressedNameSize(pcell->Name, pcell->NameLength);
  2244. SearchName.MaximumLength = SearchName.Length;
  2245. if (SearchName.MaximumLength > sizeof(CompressedBuffer)) {
  2246. #if defined(_CM_LDR_)
  2247. SearchName.Buffer = (Hive->Allocate)(SearchName.Length, FALSE,CM_FIND_LEAK_TAG40);
  2248. #else
  2249. SearchName.Buffer = ExAllocatePool(PagedPool, SearchName.Length);
  2250. #endif
  2251. if (SearchName.Buffer==NULL) {
  2252. return(FALSE);
  2253. }
  2254. } else {
  2255. SearchName.Buffer = CompressedBuffer;
  2256. }
  2257. CmpCopyCompressedName(SearchName.Buffer,
  2258. SearchName.MaximumLength,
  2259. pcell->Name,
  2260. pcell->NameLength);
  2261. } else {
  2262. IsCompressed = FALSE;
  2263. SearchName.Length = pcell->NameLength;
  2264. SearchName.MaximumLength = pcell->NameLength;
  2265. SearchName.Buffer = &(pcell->Name[0]);
  2266. }
  2267. pcell = (PCM_KEY_NODE)HvGetCell(Hive, ParentKey);
  2268. if( pcell == NULL ) {
  2269. //
  2270. // we couldn't map the bin containing this cell
  2271. //
  2272. Result = FALSE;
  2273. goto Exit;
  2274. }
  2275. ASSERT_CELL_DIRTY(Hive,ParentKey);
  2276. //
  2277. // release the cell here; as key is dirty/pinned
  2278. //
  2279. HvReleaseCell(Hive, ParentKey);
  2280. Type = HvGetCellType(TargetKey);
  2281. ASSERT(pcell->SubKeyCounts[Type] != 0);
  2282. ASSERT(HvIsCellAllocated(Hive, pcell->SubKeyLists[Type]));
  2283. LeafCell = pcell->SubKeyLists[Type];
  2284. Leaf = (PCM_KEY_INDEX)HvGetCell(Hive, LeafCell);
  2285. if( Leaf == NULL ) {
  2286. //
  2287. // we couldn't map the bin containing this cell
  2288. //
  2289. Result = FALSE;
  2290. goto Exit;
  2291. }
  2292. CellToRelease1 = LeafCell;
  2293. if (Leaf->Signature == CM_KEY_INDEX_ROOT) {
  2294. RootSelect = CmpFindSubKeyInRoot(Hive, Leaf, &SearchName, &Child);
  2295. if( INVALID_INDEX & RootSelect ) {
  2296. //
  2297. // couldn't map view inside; bail out
  2298. //
  2299. Result = FALSE;
  2300. goto Exit;
  2301. }
  2302. ASSERT(Child != FALSE);
  2303. Root = Leaf;
  2304. RootCell = LeafCell;
  2305. LeafCell = Child;
  2306. Leaf = (PCM_KEY_INDEX)HvGetCell(Hive, LeafCell);
  2307. if( Leaf == NULL ) {
  2308. //
  2309. // we couldn't map the bin containing this cell
  2310. //
  2311. Result = FALSE;
  2312. goto Exit;
  2313. }
  2314. CellToRelease2 = LeafCell;
  2315. }
  2316. ASSERT((Leaf->Signature == CM_KEY_INDEX_LEAF) ||
  2317. (Leaf->Signature == CM_KEY_FAST_LEAF) ||
  2318. (Leaf->Signature == CM_KEY_HASH_LEAF)
  2319. );
  2320. LeafSelect = CmpFindSubKeyInLeaf(Hive, Leaf, &SearchName, &Child);
  2321. if( INVALID_INDEX & LeafSelect ) {
  2322. //
  2323. // couldn't map view
  2324. //
  2325. Result = FALSE;
  2326. goto Exit;
  2327. }
  2328. ASSERT(Child != HCELL_NIL);
  2329. //
  2330. // Leaf points to Index Leaf block
  2331. // Child is Index Leaf block cell
  2332. // LeafSelect is Index for List[]
  2333. //
  2334. pcell->SubKeyCounts[Type] -= 1;
  2335. Leaf->Count -= 1;
  2336. if (Leaf->Count == 0) {
  2337. //
  2338. // Empty Leaf, drop it.
  2339. //
  2340. HvFreeCell(Hive, LeafCell);
  2341. if (Root != NULL) {
  2342. Root->Count -= 1;
  2343. if (Root->Count == 0) {
  2344. //
  2345. // Root is empty, free it too.
  2346. //
  2347. HvFreeCell(Hive, RootCell);
  2348. pcell->SubKeyLists[Type] = HCELL_NIL;
  2349. } else if (RootSelect < (ULONG)(Root->Count)) {
  2350. //
  2351. // Middle entry, squeeze root
  2352. //
  2353. RtlMoveMemory(
  2354. (PVOID)&(Root->List[RootSelect]),
  2355. (PVOID)&(Root->List[RootSelect+1]),
  2356. (Root->Count - RootSelect) * sizeof(HCELL_INDEX)
  2357. );
  2358. }
  2359. //
  2360. // Else RootSelect == last entry, so decrementing count
  2361. // was all we needed to do
  2362. //
  2363. } else {
  2364. pcell->SubKeyLists[Type] = HCELL_NIL;
  2365. }
  2366. } else if (LeafSelect < (ULONG)(Leaf->Count)) {
  2367. if (Leaf->Signature == CM_KEY_INDEX_LEAF) {
  2368. RtlMoveMemory((PVOID)&(Leaf->List[LeafSelect]),
  2369. (PVOID)&(Leaf->List[LeafSelect+1]),
  2370. (Leaf->Count - LeafSelect) * sizeof(HCELL_INDEX));
  2371. } else {
  2372. FastIndex = (PCM_KEY_FAST_INDEX)Leaf;
  2373. RtlMoveMemory((PVOID)&(FastIndex->List[LeafSelect]),
  2374. (PVOID)&(FastIndex->List[LeafSelect+1]),
  2375. (FastIndex->Count - LeafSelect) * sizeof(CM_INDEX));
  2376. }
  2377. }
  2378. //
  2379. // Else LeafSelect == last entry, so decrementing count was enough
  2380. //
  2381. // things went OK
  2382. Result = TRUE;
  2383. Exit:
  2384. if( CellToRelease1 != HCELL_NIL ) {
  2385. HvReleaseCell(Hive,CellToRelease1);
  2386. }
  2387. if( CellToRelease2 != HCELL_NIL ) {
  2388. HvReleaseCell(Hive,CellToRelease2);
  2389. }
  2390. if ((IsCompressed) &&
  2391. (SearchName.MaximumLength > sizeof(CompressedBuffer))) {
  2392. #if defined(_CM_LDR_)
  2393. (Hive->Free)(SearchName.Buffer, SearchName.Length);
  2394. #else
  2395. ExFreePool(SearchName.Buffer);
  2396. #endif
  2397. }
  2398. return Result;
  2399. }
  2400. #ifdef NT_RENAME_KEY
  2401. HCELL_INDEX
  2402. CmpDuplicateIndex(
  2403. PHHIVE Hive,
  2404. HCELL_INDEX IndexCell,
  2405. ULONG StorageType
  2406. )
  2407. /*++
  2408. Routine Description:
  2409. Duplicate an index, regardless of its type; Needed for NtRenameKey
  2410. Arguments:
  2411. Hive - pointer to hive control structure for hive of interest
  2412. IndexCell - the index to be duplicated
  2413. StorageType - storagetype (Stable or Volatile)
  2414. Return Value:
  2415. cellindex of a duplicate or HCELL_NIL
  2416. --*/
  2417. {
  2418. PCM_KEY_INDEX Index;
  2419. PCM_KEY_INDEX Leaf;
  2420. ULONG i;
  2421. PCM_KEY_INDEX NewIndex = NULL;
  2422. HCELL_INDEX NewIndexCell;
  2423. HCELL_INDEX LeafCell;
  2424. PAGED_CODE();
  2425. //
  2426. // we have the lock exclusive or nobody is operating inside this hive
  2427. //
  2428. //ASSERT_CM_LOCK_OWNED_EXCLUSIVE();
  2429. ASSERT_CM_EXCLUSIVE_HIVE_ACCESS(Hive);
  2430. ASSERT( HvGetCellType(IndexCell) == StorageType );
  2431. Index = (PCM_KEY_INDEX)HvGetCell(Hive, IndexCell);
  2432. if( Index == NULL ) {
  2433. //
  2434. // we couldn't map a view for the bin containing this cell
  2435. //
  2436. return HCELL_NIL;
  2437. }
  2438. // release the cell here; as the registry is locked exclusive (i.e. we don't care)
  2439. HvReleaseCell(Hive, IndexCell);
  2440. if (Index->Signature == CM_KEY_INDEX_ROOT) {
  2441. //
  2442. // first duplicate IndexCell, zeroing out the new content
  2443. //
  2444. NewIndexCell = HvDuplicateCell(Hive,IndexCell,StorageType,FALSE);
  2445. if( NewIndexCell == HCELL_NIL ) {
  2446. return HCELL_NIL;
  2447. }
  2448. NewIndex = (PCM_KEY_INDEX)HvGetCell(Hive, NewIndexCell);
  2449. if( NewIndex == NULL ) {
  2450. //
  2451. // we couldn't map a view for the bin containing this cell
  2452. // this shouldn't happen as we just allocated this cell (i.e. is dirty/pinned into memory)
  2453. //
  2454. ASSERT( FALSE );
  2455. goto ErrorExit;
  2456. }
  2457. // release the cell here; as the registry is locked exclusive (i.e. we don't care)
  2458. HvReleaseCell(Hive, NewIndexCell);
  2459. //
  2460. // we have a root index;
  2461. //
  2462. NewIndex->Signature = CM_KEY_INDEX_ROOT;
  2463. NewIndex->Count = 0;
  2464. //
  2465. // copy first level.
  2466. //
  2467. for( i=0;i<Index->Count;i++) {
  2468. #if DBG
  2469. Leaf = (PCM_KEY_INDEX)HvGetCell(Hive, Index->List[i]);
  2470. if( Leaf == NULL ) {
  2471. //
  2472. // we couldn't map the bin containing this cell
  2473. //
  2474. goto ErrorExit;
  2475. }
  2476. // release the cell here; as the registry is locked exclusive (i.e. we don't care)
  2477. HvReleaseCell(Hive, Index->List[i]);
  2478. ASSERT((Leaf->Signature == CM_KEY_INDEX_LEAF) ||
  2479. (Leaf->Signature == CM_KEY_FAST_LEAF) ||
  2480. (Leaf->Signature == CM_KEY_HASH_LEAF)
  2481. );
  2482. ASSERT(Leaf->Count != 0);
  2483. #endif
  2484. LeafCell = HvDuplicateCell(Hive,Index->List[i],StorageType,TRUE);
  2485. if( LeafCell == HCELL_NIL ) {
  2486. goto ErrorExit;
  2487. }
  2488. NewIndex->List[i] = LeafCell;
  2489. NewIndex->Count++;
  2490. }
  2491. ASSERT( NewIndex->Count == Index->Count );
  2492. } else {
  2493. //
  2494. // leaf index
  2495. //
  2496. ASSERT((Index->Signature == CM_KEY_INDEX_LEAF) ||
  2497. (Index->Signature == CM_KEY_FAST_LEAF) ||
  2498. (Index->Signature == CM_KEY_HASH_LEAF)
  2499. );
  2500. ASSERT(Index->Count != 0);
  2501. //
  2502. // first duplicate IndexCell, copying the old content
  2503. //
  2504. NewIndexCell = HvDuplicateCell(Hive,IndexCell,StorageType,TRUE);
  2505. }
  2506. return NewIndexCell;
  2507. ErrorExit:
  2508. if( NewIndex != NULL ){
  2509. // we can get here only if we are trying to duplicate an index_root
  2510. ASSERT( NewIndex->Signature == CM_KEY_INDEX_ROOT );
  2511. //
  2512. // free the space we already allocated
  2513. //
  2514. for(i=0;i<NewIndex->Count;i++) {
  2515. ASSERT(NewIndex->List[i] != 0 );
  2516. HvFreeCell(Hive, NewIndex->List[i]);
  2517. }
  2518. }
  2519. HvFreeCell(Hive, NewIndexCell);
  2520. return HCELL_NIL;
  2521. }
  2522. BOOLEAN
  2523. CmpUpdateParentForEachSon(
  2524. PHHIVE Hive,
  2525. HCELL_INDEX Parent
  2526. )
  2527. /*++
  2528. Routine Description:
  2529. Walks the child's list (both stable and volatile and marks updates
  2530. the parent link to Parent.
  2531. First step is to mark all children dirty, and then to update the link.
  2532. This way, if we fail part through, we leave everything in good order
  2533. Arguments:
  2534. Hive - pointer to hive control structure for hive of interest
  2535. Parent - cell index of the cell who's son's to be updated.
  2536. Return Value:
  2537. TRUE - successfully updated
  2538. --*/
  2539. {
  2540. PCM_KEY_NODE ParentNode;
  2541. PCM_KEY_NODE CurrentSon;
  2542. HCELL_INDEX Child;
  2543. ULONG Count;
  2544. ULONG i;
  2545. PAGED_CODE();
  2546. //
  2547. // we have the lock exclusive or nobody is operating inside this hive
  2548. //
  2549. //ASSERT_CM_LOCK_OWNED_EXCLUSIVE();
  2550. ASSERT_CM_EXCLUSIVE_HIVE_ACCESS(Hive);
  2551. //
  2552. // grab the parent node; this was already marked as dirty, we shouldn't
  2553. // have any problem here;
  2554. //
  2555. ParentNode = (PCM_KEY_NODE)HvGetCell(Hive,Parent);
  2556. if( ParentNode == NULL ) {
  2557. //
  2558. // cannot map view; this shouldn't happen as we just allocated
  2559. // this cell (i.e. it should be dirty/pinned into memory)
  2560. //
  2561. ASSERT( FALSE );
  2562. return FALSE;
  2563. }
  2564. // release the cell here; as the registry is locked exclusive (i.e. we don't care)
  2565. HvReleaseCell(Hive, Parent);
  2566. //
  2567. // iterate through the child list (both stable and volatile), marking every
  2568. // child dirty; this will pin the cell into memory and we will have no problems
  2569. // changine the parent later on
  2570. //
  2571. Count = ParentNode->SubKeyCounts[Stable] + ParentNode->SubKeyCounts[Volatile];
  2572. for( i=0;i<Count;i++) {
  2573. Child = CmpFindSubKeyByNumber(Hive,ParentNode,i);
  2574. if( Child == HCELL_NIL ) {
  2575. return FALSE;
  2576. }
  2577. if(!HvMarkCellDirty(Hive,Child)) {
  2578. return FALSE;
  2579. }
  2580. }
  2581. //
  2582. // second iteration, change the parent for each and every son
  2583. //
  2584. for( i=0;i<Count;i++) {
  2585. Child = CmpFindSubKeyByNumber(Hive,ParentNode,i);
  2586. //
  2587. // sanity test: we marked this dirty few lines above!
  2588. //
  2589. ASSERT( Child != HCELL_NIL );
  2590. CurrentSon = (PCM_KEY_NODE)HvGetCell(Hive,Child);
  2591. // release the cell here; as the registry is locked exclusive (i.e. we don't care)
  2592. HvReleaseCell(Hive, Child);
  2593. //
  2594. // sanity test: this cell should be pinned in memory by now
  2595. //
  2596. ASSERT( CurrentSon != NULL );
  2597. //
  2598. // change the parent
  2599. //
  2600. CurrentSon->Parent = Parent;
  2601. }
  2602. return TRUE;
  2603. }
  2604. #endif //NT_RENAME_KEY
  2605. ULONG
  2606. CmpComputeHashKey(
  2607. PUNICODE_STRING Name
  2608. )
  2609. {
  2610. ULONG ConvKey = 0;
  2611. ULONG Cnt;
  2612. WCHAR *Cp;
  2613. ASSERT( (Name->Buffer[0] != OBJ_NAME_PATH_SEPARATOR) || (Name->Length == 0));
  2614. //
  2615. // Manually compute the hash to use.
  2616. //
  2617. Cp = Name->Buffer;
  2618. for (Cnt=0; Cnt<Name->Length; Cnt += sizeof(WCHAR)) {
  2619. ASSERT( *Cp != OBJ_NAME_PATH_SEPARATOR );
  2620. ConvKey = 37 * ConvKey + (ULONG)RtlUpcaseUnicodeChar(*Cp);
  2621. ++Cp;
  2622. }
  2623. return ConvKey;
  2624. }
  2625. ULONG
  2626. CmpComputeHashKeyForCompressedName(
  2627. IN PWCHAR Source,
  2628. IN ULONG SourceLength
  2629. )
  2630. {
  2631. ULONG ConvKey = 0;
  2632. ULONG i;
  2633. for (i=0;i<SourceLength;i++) {
  2634. ConvKey = 37*ConvKey + (ULONG)RtlUpcaseUnicodeChar((WCHAR)(((PUCHAR)Source)[i]));
  2635. }
  2636. return ConvKey;
  2637. }
  2638. //
  2639. // HashIndex routines
  2640. //
  2641. HCELL_INDEX
  2642. CmpFindSubKeyByHash(
  2643. PHHIVE Hive,
  2644. PCM_KEY_FAST_INDEX FastIndex,
  2645. PUNICODE_STRING SearchName
  2646. )
  2647. /*++
  2648. Routine Description:
  2649. Find the child cell (either subkey or value) specified by name.
  2650. It searched in the index table ordered by the hash
  2651. Arguments:
  2652. Hive - pointer to hive control structure for hive of interest
  2653. Index -
  2654. SearchName - name of child of interest
  2655. Return Value:
  2656. Cell of matching child key, or HCELL_NIL if none.
  2657. --*/
  2658. {
  2659. USHORT Current;
  2660. ULONG HashKey;
  2661. LONG Result;
  2662. #ifndef _CM_LDR_
  2663. PAGED_CODE();
  2664. #endif //_CM_LDR_
  2665. ASSERT( FastIndex->Signature == CM_KEY_HASH_LEAF );
  2666. HashKey = CmpComputeHashKey(SearchName);
  2667. for(Current = 0; Current < FastIndex->Count; Current++ ) {
  2668. if( HashKey == FastIndex->List[Current].HashKey ) {
  2669. //
  2670. // HashKey matches; see if this is a real hit
  2671. //
  2672. Result = CmpDoCompareKeyName(Hive,SearchName,FastIndex->List[Current].Cell);
  2673. if (Result == 0) {
  2674. return FastIndex->List[Current].Cell;
  2675. }
  2676. }
  2677. }
  2678. return HCELL_NIL;
  2679. }