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.

3243 lines
89 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)CmUpcaseUnicodeChar(c1) -
  738. (LONG)CmUpcaseUnicodeChar(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 = 0;
  910. PCM_KEY_INDEX Leaf = NULL;
  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 DirtyParent;
  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 DirtyParent;
  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. HvMarkCellDirty(Hive,Node->SubKeyLists[Stable]);
  1058. Index->Count--;
  1059. goto DirtyParent;
  1060. }
  1061. } else {
  1062. if( Index->List[j] == Child ) {
  1063. //
  1064. // found it!
  1065. //
  1066. RtlMoveMemory((PVOID)&(Index->List[j]),
  1067. (PVOID)&(Index->List[j+1]),
  1068. (Index->Count - j) * sizeof(HCELL_INDEX));
  1069. HvMarkCellDirty(Hive,Node->SubKeyLists[Stable]);
  1070. Index->Count--;
  1071. goto DirtyParent;
  1072. }
  1073. }
  1074. }
  1075. }
  1076. ASSERT( FALSE );
  1077. DirtyParent:
  1078. //
  1079. // mark parent and index dirty and decrement index count.
  1080. //
  1081. HvMarkCellDirty(Hive,Parent);
  1082. Node->SubKeyCounts[Stable]--;
  1083. Exit:
  1084. if( Index ) {
  1085. ASSERT( Node );
  1086. HvReleaseCell(Hive,Node->SubKeyLists[Stable]);
  1087. }
  1088. if( Node ) {
  1089. HvReleaseCell(Hive,Parent);
  1090. }
  1091. return Result;
  1092. }
  1093. BOOLEAN
  1094. CmpAddSubKey(
  1095. PHHIVE Hive,
  1096. HCELL_INDEX Parent,
  1097. HCELL_INDEX Child
  1098. )
  1099. /*++
  1100. Routine Description:
  1101. Add a new child subkey to the subkey index for a cell. The
  1102. child MUST NOT already be present (bugcheck if so.)
  1103. NOTE: We expect Parent to already be marked dirty.
  1104. We will mark stuff in Index dirty
  1105. Arguments:
  1106. Hive - pointer to hive control structure for hive of interest
  1107. Parent - cell of key that will be parent of new key
  1108. Child - new key to put in Paren't sub key list
  1109. Return Value:
  1110. TRUE - it worked
  1111. FALSE - resource problem
  1112. --*/
  1113. {
  1114. PCM_KEY_NODE pcell;
  1115. HCELL_INDEX WorkCell;
  1116. PCM_KEY_INDEX Index;
  1117. PCM_KEY_FAST_INDEX FastIndex;
  1118. UNICODE_STRING NewName;
  1119. HCELL_INDEX LeafCell;
  1120. PHCELL_INDEX RootPointer = NULL;
  1121. ULONG cleanup = 0;
  1122. ULONG Type = 0;
  1123. BOOLEAN IsCompressed;
  1124. ULONG i;
  1125. #ifndef _CM_LDR_
  1126. PAGED_CODE();
  1127. #endif //_CM_LDR_
  1128. CmKdPrintEx((DPFLTR_CONFIG_ID,CML_INDEX,"CmpAddSubKey:\n\t"));
  1129. CmKdPrintEx((DPFLTR_CONFIG_ID,CML_INDEX,"Hive=%p Parent=%08lx Child=%08lx\n",Hive,Parent,Child));
  1130. //
  1131. // we have the lock exclusive or nobody is operating inside this hive
  1132. //
  1133. //ASSERT_CM_LOCK_OWNED_EXCLUSIVE();
  1134. ASSERT_CM_EXCLUSIVE_HIVE_ACCESS(Hive);
  1135. //
  1136. // build a name string
  1137. //
  1138. pcell = (PCM_KEY_NODE)HvGetCell(Hive, Child);
  1139. if( pcell == NULL ) {
  1140. //
  1141. // we couldn't map the bin containing this cell
  1142. //
  1143. return FALSE;
  1144. }
  1145. // release the cell here; as the registry is locked exclusive (i.e. we don't care)
  1146. HvReleaseCell(Hive, Child);
  1147. if (pcell->Flags & KEY_COMP_NAME) {
  1148. IsCompressed = TRUE;
  1149. NewName.Length = CmpCompressedNameSize(pcell->Name, pcell->NameLength);
  1150. NewName.MaximumLength = NewName.Length;
  1151. NewName.Buffer = (Hive->Allocate)(NewName.Length, FALSE,CM_FIND_LEAK_TAG8);
  1152. if (NewName.Buffer==NULL) {
  1153. return(FALSE);
  1154. }
  1155. CmpCopyCompressedName(NewName.Buffer,
  1156. NewName.MaximumLength,
  1157. pcell->Name,
  1158. pcell->NameLength);
  1159. } else {
  1160. IsCompressed = FALSE;
  1161. NewName.Length = pcell->NameLength;
  1162. NewName.MaximumLength = pcell->NameLength;
  1163. NewName.Buffer = &(pcell->Name[0]);
  1164. }
  1165. pcell = (PCM_KEY_NODE)HvGetCell(Hive, Parent);
  1166. if( pcell == NULL ) {
  1167. //
  1168. // we couldn't map the bin containing this cell
  1169. //
  1170. goto ErrorExit;
  1171. }
  1172. //ASSERT_CELL_DIRTY(Hive,Parent);
  1173. // release the cell here; as the registry is locked exclusive (i.e. we don't care)
  1174. HvReleaseCell(Hive, Parent);
  1175. Type = HvGetCellType(Child);
  1176. if (pcell->SubKeyCounts[Type] == 0) {
  1177. //
  1178. // we must allocate a leaf
  1179. //
  1180. WorkCell = HvAllocateCell(Hive, sizeof(CM_KEY_FAST_INDEX), Type,(HvGetCellType(Parent)==Type)?Parent:HCELL_NIL);
  1181. if (WorkCell == HCELL_NIL) {
  1182. goto ErrorExit;
  1183. }
  1184. Index = (PCM_KEY_INDEX)HvGetCell(Hive, WorkCell);
  1185. if( Index == NULL ) {
  1186. //
  1187. // we couldn't map the bin containing this cell
  1188. // this shouldn't happen 'cause we just allocated this
  1189. // cell (i.e. bin is PINNED in memory ! )
  1190. //
  1191. ASSERT( FALSE );
  1192. goto ErrorExit;
  1193. }
  1194. // release the cell here; as the registry is locked exclusive (i.e. we don't care)
  1195. HvReleaseCell(Hive, WorkCell);
  1196. if( UseHashIndex(Hive) ) {
  1197. Index->Signature = CM_KEY_HASH_LEAF;
  1198. } else if( UseFastIndex(Hive) ) {
  1199. Index->Signature = CM_KEY_FAST_LEAF;
  1200. } else {
  1201. Index->Signature = CM_KEY_INDEX_LEAF;
  1202. }
  1203. Index->Count = 0;
  1204. pcell->SubKeyLists[Type] = WorkCell;
  1205. cleanup = 1;
  1206. } else {
  1207. Index = (PCM_KEY_INDEX)HvGetCell(Hive, pcell->SubKeyLists[Type]);
  1208. if( Index == NULL ) {
  1209. //
  1210. // we couldn't map the bin containing this cell
  1211. //
  1212. goto ErrorExit;
  1213. }
  1214. // release the cell here; as the registry is locked exclusive (i.e. we don't care)
  1215. HvReleaseCell(Hive, pcell->SubKeyLists[Type]);
  1216. if ( (Index->Signature == CM_KEY_FAST_LEAF) &&
  1217. (Index->Count >= (CM_MAX_FAST_INDEX)) ) {
  1218. //
  1219. // We must change fast index to a slow index to accomodate
  1220. // growth.
  1221. //
  1222. FastIndex = (PCM_KEY_FAST_INDEX)Index;
  1223. for (i=0; i<Index->Count; i++) {
  1224. Index->List[i] = FastIndex->List[i].Cell;
  1225. }
  1226. Index->Signature = CM_KEY_INDEX_LEAF;
  1227. } else if (((Index->Signature == CM_KEY_INDEX_LEAF) ||
  1228. (Index->Signature == CM_KEY_HASH_LEAF)) &&
  1229. (Index->Count >= (CM_MAX_INDEX - 1) )) {
  1230. //
  1231. // We must change flat entry to a root/leaf tree
  1232. //
  1233. WorkCell = HvAllocateCell(
  1234. Hive,
  1235. sizeof(CM_KEY_INDEX) + sizeof(HCELL_INDEX), // allow for 2
  1236. Type,
  1237. (HvGetCellType(Parent)==Type)?Parent:HCELL_NIL
  1238. );
  1239. if (WorkCell == HCELL_NIL) {
  1240. goto ErrorExit;
  1241. }
  1242. Index = (PCM_KEY_INDEX)HvGetCell(Hive, WorkCell);
  1243. if( Index == NULL ) {
  1244. //
  1245. // we couldn't map the bin containing this cell
  1246. // this shouldn't happen 'cause we just allocated this
  1247. // cell (i.e. bin is PINNED in memory
  1248. ASSERT( FALSE );
  1249. goto ErrorExit;
  1250. }
  1251. // release the cell here; as the registry is locked exclusive (i.e. we don't care)
  1252. HvReleaseCell(Hive, WorkCell);
  1253. Index->Signature = CM_KEY_INDEX_ROOT;
  1254. Index->Count = 1;
  1255. Index->List[0] = pcell->SubKeyLists[Type];
  1256. pcell->SubKeyLists[Type] = WorkCell;
  1257. cleanup = 2;
  1258. }
  1259. }
  1260. LeafCell = pcell->SubKeyLists[Type];
  1261. //
  1262. // LeafCell is target for add, or perhaps root
  1263. // Index is pointer to fast leaf, slow Leaf or Root, whichever applies
  1264. //
  1265. if (Index->Signature == CM_KEY_INDEX_ROOT) {
  1266. LeafCell = CmpSelectLeaf(Hive, pcell, &NewName, Type, &RootPointer);
  1267. if (LeafCell == HCELL_NIL) {
  1268. goto ErrorExit;
  1269. }
  1270. }
  1271. #if 0
  1272. //
  1273. // Validation code. manually search for the key and break when found
  1274. //
  1275. if(Index->Signature == CM_KEY_INDEX_ROOT) {
  1276. LONG Result;
  1277. PCM_KEY_INDEX Leaf;
  1278. HCELL_INDEX Cell;
  1279. ULONG iCnt;
  1280. PCM_KEY_INDEX PrevLeaf;
  1281. Leaf = (PCM_KEY_INDEX)HvGetCell(Hive, LeafCell);
  1282. HvReleaseCell(Hive, LeafCell);
  1283. if( Leaf->Count ) {
  1284. Result = CmpCompareInIndex( Hive,
  1285. &NewName,
  1286. 0,
  1287. Leaf,
  1288. &Cell);
  1289. //
  1290. // must be bigger, or the first leaf
  1291. //
  1292. if( (Result < 0) && (RootPointer != &(Index->List[0])) ) {
  1293. for( iCnt=0;iCnt<Index->Count;iCnt++) {
  1294. if( Index->List[iCnt] == LeafCell ) {
  1295. break;
  1296. }
  1297. }
  1298. ASSERT( Index->List[iCnt] == LeafCell );
  1299. ASSERT( iCnt > 0 );
  1300. PrevLeaf = (PCM_KEY_INDEX)HvGetCell(Hive, Index->List[iCnt-1]);
  1301. HvReleaseCell(Hive, Index->List[iCnt-1]);
  1302. if( PrevLeaf->Count ) {
  1303. //
  1304. // must be bigger than last in prev leaf
  1305. //
  1306. Result = CmpCompareInIndex( Hive,
  1307. &NewName,
  1308. PrevLeaf->Count - 1,
  1309. PrevLeaf,
  1310. &Cell);
  1311. if( Result <= 0 ) {
  1312. //
  1313. // Error ==> Debug
  1314. //
  1315. DbgPrint("CmpAddSubKey: Wrong spot selected [1]!!!\n");
  1316. DbgPrint("Hive = %p Parent = %lx Child = %lx , Leaf = %p\n",Hive,Parent,Child,Leaf);
  1317. DbgPrint("RootPointer = %p Index = %p PrevLeaf = %p\n",RootPointer,Index,PrevLeaf);
  1318. DbgBreakPoint();
  1319. }
  1320. }
  1321. }
  1322. }
  1323. Result = CmpCompareInIndex( Hive,
  1324. &NewName,
  1325. Leaf->Count - 1,
  1326. Leaf,
  1327. &Cell);
  1328. if( Result > 0) {
  1329. //
  1330. // must be the last one
  1331. //
  1332. if( (ULONG)(Index->Count - 1) > (ULONG)(((PUCHAR)RootPointer - (PUCHAR)(&(Index->List[0])))/sizeof(HCELL_INDEX)) ) {
  1333. //
  1334. // Error ==> Debug
  1335. //
  1336. DbgPrint("CmpAddSubKey: Wrong spot selected [2]!!!\n");
  1337. DbgPrint("Hive = %p Parent = %lx Child = %lx , Leaf = %p\n",Hive,Parent,Child,Leaf);
  1338. DbgPrint("RootPointer = %p Index = %p\n",RootPointer,Index);
  1339. DbgBreakPoint();
  1340. }
  1341. }
  1342. }
  1343. #endif //0
  1344. //
  1345. // Add new cell to Leaf, update pointers
  1346. //
  1347. LeafCell = CmpAddToLeaf(Hive, LeafCell, Child, &NewName);
  1348. if (LeafCell == HCELL_NIL) {
  1349. goto ErrorExit;
  1350. }
  1351. pcell->SubKeyCounts[Type] += 1;
  1352. if (RootPointer != NULL) {
  1353. *RootPointer = LeafCell;
  1354. } else {
  1355. pcell->SubKeyLists[Type] = LeafCell;
  1356. }
  1357. if (IsCompressed) {
  1358. (Hive->Free)(NewName.Buffer, NewName.Length);
  1359. }
  1360. return TRUE;
  1361. ErrorExit:
  1362. if (IsCompressed) {
  1363. (Hive->Free)(NewName.Buffer, NewName.Length);
  1364. }
  1365. switch (cleanup) {
  1366. case 1:
  1367. HvFreeCell(Hive, pcell->SubKeyLists[Type]);
  1368. pcell->SubKeyLists[Type] = HCELL_NIL;
  1369. break;
  1370. case 2:
  1371. Index = (PCM_KEY_INDEX)HvGetCell(Hive, pcell->SubKeyLists[Type]);
  1372. if( Index == NULL ) {
  1373. //
  1374. // we couldn't map the bin containing this cell
  1375. // this shouldn't happen 'cause we just allocated this
  1376. // cell (i.e. bin is PINNED in memory).
  1377. // But ... better safe than sorry
  1378. //
  1379. ASSERT( FALSE );
  1380. return FALSE;
  1381. }
  1382. // release the cell here; as the registry is locked exclusive (i.e. we don't care)
  1383. HvReleaseCell(Hive, pcell->SubKeyLists[Type]);
  1384. WorkCell = Index->List[0];
  1385. HvFreeCell(Hive, pcell->SubKeyLists[Type]);
  1386. pcell->SubKeyLists[Type] = WorkCell;
  1387. break;
  1388. }
  1389. return FALSE;
  1390. }
  1391. HCELL_INDEX
  1392. CmpAddToLeaf(
  1393. PHHIVE Hive,
  1394. HCELL_INDEX LeafCell,
  1395. HCELL_INDEX NewKey,
  1396. PUNICODE_STRING NewName
  1397. )
  1398. /*++
  1399. Routine Description:
  1400. Insert a new subkey into a Leaf index. Supports both fast and slow
  1401. leaf indexes and will determine which sort of index the given leaf is.
  1402. NOTE: We expect Root to already be marked dirty by caller if non NULL.
  1403. We expect Leaf to always be marked dirty by caller.
  1404. Arguments:
  1405. Hive - pointer to hive control structure for hive of interest
  1406. LeafCell - cell of index leaf node we are to add entry too
  1407. NewKey - cell of KEY_NODE we are to add
  1408. NewName - pointer to unicode string with name to we are to add
  1409. Return Value:
  1410. HCELL_NIL - some resource problem
  1411. Else - cell of Leaf index when are done, caller is expected to
  1412. set this into Root index or Key body.
  1413. --*/
  1414. {
  1415. PCM_KEY_INDEX Leaf;
  1416. PCM_KEY_FAST_INDEX FastLeaf;
  1417. ULONG Size;
  1418. ULONG OldSize;
  1419. ULONG freecount;
  1420. HCELL_INDEX NewCell;
  1421. HCELL_INDEX Child;
  1422. ULONG Select;
  1423. LONG Result;
  1424. ULONG EntrySize;
  1425. ULONG i;
  1426. CmKdPrintEx((DPFLTR_CONFIG_ID,CML_INDEX,"CmpAddToLeaf:\n\t"));
  1427. CmKdPrintEx((DPFLTR_CONFIG_ID,CML_INDEX,"Hive=%p LeafCell=%08lx NewKey=%08lx\n",Hive,LeafCell,NewKey));
  1428. //
  1429. // we have the lock exclusive or nobody is operating inside this hive
  1430. //
  1431. //ASSERT_CM_LOCK_OWNED_EXCLUSIVE();
  1432. ASSERT_CM_EXCLUSIVE_HIVE_ACCESS(Hive);
  1433. if (!HvMarkCellDirty(Hive, LeafCell)) {
  1434. return HCELL_NIL;
  1435. }
  1436. //
  1437. // compute number free slots left in the leaf
  1438. //
  1439. Leaf = (PCM_KEY_INDEX)HvGetCell(Hive, LeafCell);
  1440. if( Leaf == NULL ) {
  1441. //
  1442. // we couldn't map the bin containing this cell
  1443. // this shouldn't happen as marking dirty means
  1444. // PINNING the view into memory
  1445. //
  1446. ASSERT( FALSE );
  1447. return HCELL_NIL;
  1448. }
  1449. // release the cell here; as the registry is locked exclusive (i.e. we don't care)
  1450. HvReleaseCell(Hive, LeafCell);
  1451. if (Leaf->Signature == CM_KEY_INDEX_LEAF) {
  1452. FastLeaf = NULL;
  1453. EntrySize = sizeof(HCELL_INDEX);
  1454. } else {
  1455. ASSERT( (Leaf->Signature == CM_KEY_FAST_LEAF) ||
  1456. (Leaf->Signature == CM_KEY_HASH_LEAF)
  1457. );
  1458. FastLeaf = (PCM_KEY_FAST_INDEX)Leaf;
  1459. EntrySize = sizeof(CM_INDEX);
  1460. }
  1461. OldSize = HvGetCellSize(Hive, Leaf);
  1462. Size = OldSize - ((EntrySize * Leaf->Count) +
  1463. FIELD_OFFSET(CM_KEY_INDEX, List));
  1464. freecount = Size / EntrySize;
  1465. //
  1466. // grow the leaf if it isn't big enough
  1467. //
  1468. NewCell = LeafCell;
  1469. if (freecount < 1) {
  1470. Size = OldSize + OldSize / 2;
  1471. if (Size < (OldSize + EntrySize)) {
  1472. Size = OldSize + EntrySize;
  1473. }
  1474. NewCell = HvReallocateCell(Hive, LeafCell, Size);
  1475. if (NewCell == HCELL_NIL) {
  1476. return HCELL_NIL;
  1477. }
  1478. Leaf = (PCM_KEY_INDEX)HvGetCell(Hive, NewCell);
  1479. if( Leaf == NULL ) {
  1480. //
  1481. // we couldn't map the bin containing this cell
  1482. // this shouldn't happen 'cause we just allocated this
  1483. // cell (i.e. bin is PINNED in memory)
  1484. //
  1485. ASSERT( FALSE );
  1486. return HCELL_NIL;
  1487. }
  1488. // release the cell here; as the registry is locked exclusive (i.e. we don't care)
  1489. HvReleaseCell(Hive, NewCell);
  1490. if (FastLeaf != NULL) {
  1491. FastLeaf = (PCM_KEY_FAST_INDEX)Leaf;
  1492. }
  1493. }
  1494. //
  1495. // Find where to put the new entry
  1496. //
  1497. Select = CmpFindSubKeyInLeaf(Hive, Leaf, NewName, &Child);
  1498. if( INVALID_INDEX & Select ) {
  1499. //
  1500. // couldn't map view
  1501. //
  1502. return HCELL_NIL;
  1503. }
  1504. ASSERT(Child == HCELL_NIL);
  1505. //
  1506. // Select is the index in List of the entry nearest where the
  1507. // new entry should go.
  1508. // Decide wether the new entry goes before or after Offset entry,
  1509. // and then ripple copy and set.
  1510. // If Select == Count, then the leaf is empty, so simply set our entry
  1511. //
  1512. if (Select != Leaf->Count) {
  1513. Result = CmpCompareInIndex(Hive,
  1514. NewName,
  1515. Select,
  1516. Leaf,
  1517. &Child);
  1518. if( Result == 2 ) {
  1519. //
  1520. // couldn't map view inside; bail out
  1521. //
  1522. return HCELL_NIL;
  1523. }
  1524. ASSERT(Result != 0);
  1525. //
  1526. // Result -1 - NewName/NewKey less than selected key, insert before
  1527. // +1 - NewName/NewKey greater than selected key, insert after
  1528. //
  1529. if (Result > 0) {
  1530. ASSERT( Result == 1 );
  1531. Select++;
  1532. }
  1533. if (Select != Leaf->Count) {
  1534. //
  1535. // ripple copy to make space and insert
  1536. //
  1537. if (FastLeaf != NULL) {
  1538. RtlMoveMemory((PVOID)&(FastLeaf->List[Select+1]),
  1539. (PVOID)&(FastLeaf->List[Select]),
  1540. sizeof(CM_INDEX)*(FastLeaf->Count - Select));
  1541. } else {
  1542. RtlMoveMemory((PVOID)&(Leaf->List[Select+1]),
  1543. (PVOID)&(Leaf->List[Select]),
  1544. sizeof(HCELL_INDEX)*(Leaf->Count - Select));
  1545. }
  1546. }
  1547. }
  1548. if (FastLeaf != NULL) {
  1549. FastLeaf->List[Select].Cell = NewKey;
  1550. if( FastLeaf->Signature == CM_KEY_HASH_LEAF ) {
  1551. //
  1552. // Hash leaf; store the HashKey
  1553. //
  1554. FastLeaf->List[Select].HashKey = CmpComputeHashKey(NewName);
  1555. } else {
  1556. FastLeaf->List[Select].NameHint[0] = 0;
  1557. FastLeaf->List[Select].NameHint[1] = 0;
  1558. FastLeaf->List[Select].NameHint[2] = 0;
  1559. FastLeaf->List[Select].NameHint[3] = 0;
  1560. if (NewName->Length/sizeof(WCHAR) < 4) {
  1561. i = NewName->Length/sizeof(WCHAR);
  1562. } else {
  1563. i = 4;
  1564. }
  1565. do {
  1566. if ((USHORT)NewName->Buffer[i-1] > (UCHAR)-1) {
  1567. //
  1568. // Can't compress this name. Leave NameHint[0]==0
  1569. // to force the name to be looked up in the key.
  1570. //
  1571. break;
  1572. }
  1573. FastLeaf->List[Select].NameHint[i-1] = (UCHAR)NewName->Buffer[i-1];
  1574. i--;
  1575. } while ( i>0 );
  1576. }
  1577. } else {
  1578. Leaf->List[Select] = NewKey;
  1579. }
  1580. Leaf->Count += 1;
  1581. return NewCell;
  1582. }
  1583. HCELL_INDEX
  1584. CmpSelectLeaf(
  1585. PHHIVE Hive,
  1586. PCM_KEY_NODE ParentKey,
  1587. PUNICODE_STRING NewName,
  1588. HSTORAGE_TYPE Type,
  1589. PHCELL_INDEX *RootPointer
  1590. )
  1591. /*++
  1592. Routine Description:
  1593. This routine is only called if the subkey index for a cell is NOT
  1594. simply a single Leaf index block.
  1595. It selects the Leaf index block to which a new entry is to be
  1596. added. It may create this block by splitting an existing Leaf
  1597. block.
  1598. Arguments:
  1599. Hive - pointer to hive control structure for hive of interest
  1600. ParentKey - mapped pointer to parent key
  1601. NewName - pointer to unicode string naming entry to add
  1602. Type - Stable or Volatile, describes Child's storage
  1603. RootPointer - pointer to variable to receive address of HCELL_INDEX
  1604. that points to Leaf block returned as function argument.
  1605. Used for updates.
  1606. Return Value:
  1607. HCELL_NIL - resource problem
  1608. Else, cell index of Leaf index block to add entry to
  1609. --*/
  1610. {
  1611. HCELL_INDEX LeafCell;
  1612. HCELL_INDEX WorkCell;
  1613. PCM_KEY_INDEX Index;
  1614. PCM_KEY_INDEX Leaf;
  1615. PCM_KEY_FAST_INDEX FastLeaf;
  1616. ULONG RootSelect;
  1617. LONG Result;
  1618. CmKdPrintEx((DPFLTR_CONFIG_ID,CML_INDEX,"CmpSelectLeaf:\n\t"));
  1619. CmKdPrintEx((DPFLTR_CONFIG_ID,CML_INDEX,"Hive=%p ParentKey=%p\n", Hive, ParentKey));
  1620. //
  1621. // we have the lock exclusive or nobody is operating inside this hive
  1622. //
  1623. //ASSERT_CM_LOCK_OWNED_EXCLUSIVE();
  1624. ASSERT_CM_EXCLUSIVE_HIVE_ACCESS(Hive);
  1625. //
  1626. // Force root to always be dirty, since we'll either grow it or edit it,
  1627. // and it needs to be marked dirty for BOTH cases. (Edit may not
  1628. // occur until after we leave
  1629. //
  1630. if (! HvMarkCellDirty(Hive, ParentKey->SubKeyLists[Type])) {
  1631. return HCELL_NIL;
  1632. }
  1633. //
  1634. // must find the proper leaf
  1635. //
  1636. Index = (PCM_KEY_INDEX)HvGetCell(Hive, ParentKey->SubKeyLists[Type]);
  1637. if( Index == NULL ) {
  1638. //
  1639. // we couldn't map the bin containing this cell
  1640. // this shouldn't happen as marking dirty means
  1641. // PINNING the view into memory
  1642. //
  1643. ASSERT( FALSE );
  1644. return HCELL_NIL;
  1645. }
  1646. ASSERT(Index->Signature == CM_KEY_INDEX_ROOT);
  1647. // release the cell here; as the registry is locked exclusive (i.e. we don't care)
  1648. HvReleaseCell(Hive, ParentKey->SubKeyLists[Type]);
  1649. while (TRUE) {
  1650. RootSelect = CmpFindSubKeyInRoot(Hive, Index, NewName, &LeafCell);
  1651. if( INVALID_INDEX & RootSelect ) {
  1652. //
  1653. // couldn't map view inside; bail out
  1654. //
  1655. return HCELL_NIL;
  1656. }
  1657. if (LeafCell == HCELL_NIL) {
  1658. //
  1659. // Leaf of interest is somewhere near RootSelect
  1660. //
  1661. // . Always use lowest order leaf we can get away with
  1662. // . Never split a leaf if there's one with space we can use
  1663. // . When we split a leaf, we have to repeat search
  1664. //
  1665. // If (NewKey is below lowest key in selected)
  1666. // If there's a Leaf below selected with space
  1667. // use the leaf below
  1668. // else
  1669. // use the leaf (split it if not enough space)
  1670. // Else
  1671. // must be above highest key in selected, less than
  1672. // lowest key in Leaf to right of selected
  1673. // if space in selected
  1674. // use selected
  1675. // else if space in leaf above selected
  1676. // use leaf above
  1677. // else
  1678. // split selected
  1679. //
  1680. LeafCell = Index->List[RootSelect];
  1681. Leaf = (PCM_KEY_INDEX)HvGetCell(Hive, LeafCell);
  1682. if( Leaf == NULL ) {
  1683. //
  1684. // we couldn't map the bin containing this cell
  1685. //
  1686. return HCELL_NIL;
  1687. }
  1688. // release the cell here; as the registry is locked exclusive (i.e. we don't care)
  1689. HvReleaseCell(Hive, LeafCell);
  1690. if( (Leaf->Signature == CM_KEY_FAST_LEAF) ||
  1691. (Leaf->Signature == CM_KEY_HASH_LEAF) ) {
  1692. FastLeaf = (PCM_KEY_FAST_INDEX)Leaf;
  1693. WorkCell = FastLeaf->List[0].Cell;
  1694. } else {
  1695. ASSERT( Leaf->Signature == CM_KEY_INDEX_LEAF );
  1696. WorkCell = Leaf->List[0];
  1697. }
  1698. Result = CmpDoCompareKeyName(Hive, NewName, WorkCell);
  1699. if( Result == 2 ) {
  1700. //
  1701. // couldn't map view inside; bail out
  1702. //
  1703. return HCELL_NIL;
  1704. }
  1705. ASSERT(Result != 0);
  1706. if (Result < 0) {
  1707. //
  1708. // new is off the left end of Selected
  1709. //
  1710. if (RootSelect > 0) {
  1711. //
  1712. // there's a Leaf to the left, try to use it
  1713. //
  1714. LeafCell = Index->List[RootSelect-1];
  1715. Leaf = (PCM_KEY_INDEX)HvGetCell(Hive, LeafCell);
  1716. if( Leaf == NULL ) {
  1717. //
  1718. // we couldn't map the bin containing this cell
  1719. //
  1720. return HCELL_NIL;
  1721. }
  1722. // release the cell here; as the registry is locked exclusive (i.e. we don't care)
  1723. HvReleaseCell(Hive, LeafCell);
  1724. if (Leaf->Count < (CM_MAX_INDEX - 1)) {
  1725. RootSelect--;
  1726. *RootPointer = &(Index->List[RootSelect]);
  1727. break;
  1728. }
  1729. } else {
  1730. //
  1731. // new key is off the left end of the leftmost leaf.
  1732. // Use the leftmost leaf, if there's enough room
  1733. //
  1734. LeafCell = Index->List[0];
  1735. Leaf = (PCM_KEY_INDEX)HvGetCell(Hive, LeafCell);
  1736. if( Leaf == NULL ) {
  1737. //
  1738. // we couldn't map the bin containing this cell
  1739. //
  1740. return HCELL_NIL;
  1741. }
  1742. // release the cell here; as the registry is locked exclusive (i.e. we don't care)
  1743. HvReleaseCell(Hive, LeafCell);
  1744. if (Leaf->Count < (CM_MAX_INDEX - 1)) {
  1745. *RootPointer = &(Index->List[0]);
  1746. break;
  1747. }
  1748. }
  1749. //
  1750. // else fall to split case
  1751. //
  1752. } else {
  1753. //
  1754. // since new key is not in a Leaf, and is not off
  1755. // the left end of the ResultSelect Leaf, it must
  1756. // be off the right end.
  1757. //
  1758. LeafCell = Index->List[RootSelect];
  1759. Leaf = (PCM_KEY_INDEX)HvGetCell(Hive, LeafCell);
  1760. if( Leaf == NULL ) {
  1761. //
  1762. // we couldn't map the bin containing this cell
  1763. //
  1764. return HCELL_NIL;
  1765. }
  1766. // release the cell here; as the registry is locked exclusive (i.e. we don't care)
  1767. HvReleaseCell(Hive, LeafCell);
  1768. if (Leaf->Count < (CM_MAX_INDEX - 1)) {
  1769. *RootPointer = &(Index->List[RootSelect]);
  1770. break;
  1771. }
  1772. //
  1773. // No space, see if there's a leaf to the rigth
  1774. // and if it has space
  1775. //
  1776. if (RootSelect < (ULONG)(Index->Count - 1)) {
  1777. LeafCell = Index->List[RootSelect+1];
  1778. Leaf = (PCM_KEY_INDEX)HvGetCell(Hive, LeafCell);
  1779. if( Leaf == NULL ) {
  1780. //
  1781. // we couldn't map the bin containing this cell
  1782. //
  1783. return HCELL_NIL;
  1784. }
  1785. // release the cell here; as the registry is locked exclusive (i.e. we don't care)
  1786. HvReleaseCell(Hive, LeafCell);
  1787. if (Leaf->Count < (CM_MAX_INDEX - 1)) {
  1788. *RootPointer = &(Index->List[RootSelect+1]);
  1789. break;
  1790. }
  1791. }
  1792. //
  1793. // fall to split case
  1794. //
  1795. }
  1796. } else { // LeafCell != HCELL_NIL
  1797. //
  1798. // Since newkey cannot already be in tree, it must be
  1799. // greater than the bottom of Leaf and less than the top,
  1800. // therefore it must go in Leaf. If no space, split it.
  1801. //
  1802. Leaf = (PCM_KEY_INDEX)HvGetCell(Hive, LeafCell);
  1803. if( Leaf == NULL ) {
  1804. //
  1805. // we couldn't map the bin containing this cell
  1806. //
  1807. return HCELL_NIL;
  1808. }
  1809. // release the cell here; as the registry is locked exclusive (i.e. we don't care)
  1810. HvReleaseCell(Hive, LeafCell);
  1811. if (Leaf->Count < (CM_MAX_INDEX - 1)) {
  1812. *RootPointer = &(Index->List[RootSelect]);
  1813. break;
  1814. }
  1815. //
  1816. // fall to split case
  1817. //
  1818. }
  1819. //
  1820. // either no neigbor, or no space in neighbor, so split
  1821. //
  1822. WorkCell = CmpSplitLeaf(
  1823. Hive,
  1824. ParentKey->SubKeyLists[Type], // root cell
  1825. RootSelect,
  1826. Type
  1827. );
  1828. if (WorkCell == HCELL_NIL) {
  1829. return HCELL_NIL;
  1830. }
  1831. ParentKey->SubKeyLists[Type] = WorkCell;
  1832. Index = (PCM_KEY_INDEX)HvGetCell(Hive, WorkCell);
  1833. if( Index == NULL ) {
  1834. //
  1835. // we couldn't map the bin containing this cell
  1836. //
  1837. return HCELL_NIL;
  1838. }
  1839. // release the cell here; as the registry is locked exclusive (i.e. we don't care)
  1840. HvReleaseCell(Hive, WorkCell);
  1841. ASSERT(Index->Signature == CM_KEY_INDEX_ROOT);
  1842. } // while(true)
  1843. return LeafCell;
  1844. }
  1845. HCELL_INDEX
  1846. CmpSplitLeaf(
  1847. PHHIVE Hive,
  1848. HCELL_INDEX RootCell,
  1849. ULONG RootSelect,
  1850. HSTORAGE_TYPE Type
  1851. )
  1852. /*++
  1853. Routine Description:
  1854. Split the Leaf index block specified by RootSelect, causing both
  1855. of the split out Leaf blocks to appear in the Root index block
  1856. specified by RootCell.
  1857. Caller is expected to have marked old root cell dirty.
  1858. Arguments:
  1859. Hive - pointer to hive control structure for hive of interest
  1860. RootCell - cell of the Root index block of index being grown
  1861. RootSelect - indicates which child of Root to split
  1862. Type - Stable or Volatile
  1863. Return Value:
  1864. HCELL_NIL - some resource problem
  1865. Else - cell of new (e.g. reallocated) Root index block
  1866. --*/
  1867. {
  1868. PCM_KEY_INDEX Root;
  1869. HCELL_INDEX LeafCell;
  1870. PCM_KEY_INDEX Leaf;
  1871. HCELL_INDEX NewLeafCell;
  1872. PCM_KEY_INDEX NewLeaf;
  1873. PCM_KEY_FAST_INDEX FastLeaf;
  1874. ULONG Size;
  1875. ULONG freecount;
  1876. USHORT OldCount;
  1877. USHORT KeepCount;
  1878. USHORT NewCount;
  1879. USHORT ElemSize;
  1880. CmKdPrintEx((DPFLTR_CONFIG_ID,CML_INDEX,"CmpSplitLeaf:\n\t"));
  1881. CmKdPrintEx((DPFLTR_CONFIG_ID,CML_INDEX,"Hive=%p RootCell=%08lx RootSelect\n", Hive, RootCell, RootSelect));
  1882. //
  1883. // we have the lock exclusive or nobody is operating inside this hive
  1884. //
  1885. //ASSERT_CM_LOCK_OWNED_EXCLUSIVE();
  1886. ASSERT_CM_EXCLUSIVE_HIVE_ACCESS(Hive);
  1887. //
  1888. // allocate new Leaf index block
  1889. //
  1890. Root = (PCM_KEY_INDEX)HvGetCell(Hive, RootCell);
  1891. if( Root == NULL ) {
  1892. //
  1893. // we couldn't map the bin containing this cell
  1894. //
  1895. return HCELL_NIL;
  1896. }
  1897. // release the cell here; as the registry is locked exclusive (i.e. we don't care)
  1898. HvReleaseCell(Hive, RootCell);
  1899. LeafCell = Root->List[RootSelect];
  1900. Leaf = (PCM_KEY_INDEX)HvGetCell(Hive, LeafCell);
  1901. if( Leaf == NULL ) {
  1902. //
  1903. // we couldn't map the bin containing this cell
  1904. //
  1905. return HCELL_NIL;
  1906. }
  1907. OldCount = Leaf->Count;
  1908. // release the cell here; as the registry is locked exclusive (i.e. we don't care)
  1909. HvReleaseCell(Hive, LeafCell);
  1910. KeepCount = (USHORT)(OldCount / 2); // # of entries to keep in org. Leaf
  1911. NewCount = (OldCount - KeepCount); // # of entries to move
  1912. if( UseHashIndex(Hive) ) {
  1913. ASSERT( Leaf->Signature == CM_KEY_HASH_LEAF );
  1914. ElemSize = sizeof(CM_INDEX);
  1915. } else {
  1916. ElemSize = sizeof(HCELL_INDEX);
  1917. ASSERT( Leaf->Signature == CM_KEY_INDEX_LEAF );
  1918. }
  1919. ASSERT( FIELD_OFFSET(CM_KEY_INDEX, List) == FIELD_OFFSET(CM_KEY_FAST_INDEX, List) );
  1920. Size = (ElemSize * NewCount) +
  1921. FIELD_OFFSET(CM_KEY_INDEX, List) + 1; // +1 to assure room for add
  1922. if (!HvMarkCellDirty(Hive, LeafCell)) {
  1923. return HCELL_NIL;
  1924. }
  1925. //
  1926. //
  1927. //
  1928. ASSERT( (HvGetCellType(LeafCell) == (ULONG)Type) );
  1929. NewLeafCell = HvAllocateCell(Hive, Size, Type,LeafCell);
  1930. if (NewLeafCell == HCELL_NIL) {
  1931. return HCELL_NIL;
  1932. }
  1933. NewLeaf = (PCM_KEY_INDEX)HvGetCell(Hive, NewLeafCell);
  1934. if( NewLeaf == NULL ) {
  1935. //
  1936. // we couldn't map the bin containing this cell
  1937. // this shouldn't happen as we just allocated this cell
  1938. // so it's bin should be PINNED into memory
  1939. //
  1940. ASSERT( FALSE );
  1941. HvFreeCell(Hive, NewLeafCell);
  1942. return HCELL_NIL;
  1943. }
  1944. if( UseHashIndex(Hive) ) {
  1945. NewLeaf->Signature = CM_KEY_HASH_LEAF;
  1946. } else {
  1947. NewLeaf->Signature = CM_KEY_INDEX_LEAF;
  1948. }
  1949. // release the cell here; as the registry is locked exclusive (i.e. we don't care)
  1950. HvReleaseCell(Hive, NewLeafCell);
  1951. //
  1952. // compute number of free slots left in the root
  1953. //
  1954. Size = HvGetCellSize(Hive, Root);
  1955. Size = Size - ((sizeof(HCELL_INDEX) * Root->Count) +
  1956. FIELD_OFFSET(CM_KEY_INDEX, List));
  1957. freecount = Size / sizeof(HCELL_INDEX);
  1958. //
  1959. // grow the root if it isn't big enough
  1960. //
  1961. if (freecount < 1) {
  1962. Size = HvGetCellSize(Hive, Root) + sizeof(HCELL_INDEX);
  1963. RootCell = HvReallocateCell(Hive, RootCell, Size);
  1964. if (RootCell == HCELL_NIL) {
  1965. HvFreeCell(Hive, NewLeafCell);
  1966. return HCELL_NIL;
  1967. }
  1968. Root = (PCM_KEY_INDEX)HvGetCell(Hive, RootCell);
  1969. if( Root == NULL ) {
  1970. //
  1971. // we couldn't map the bin containing this cell
  1972. // this shouldn't happen as we just allocated this cell
  1973. // so it's bin should be PINNED into memory
  1974. //
  1975. ASSERT( FALSE );
  1976. HvFreeCell(Hive, NewLeafCell);
  1977. return HCELL_NIL;
  1978. }
  1979. // release the cell here; as the registry is locked exclusive (i.e. we don't care)
  1980. HvReleaseCell(Hive, RootCell);
  1981. }
  1982. //
  1983. // copy data from one Leaf to the other
  1984. //
  1985. //
  1986. if( UseHashIndex(Hive) ) {
  1987. FastLeaf = (PCM_KEY_FAST_INDEX)Leaf;
  1988. #if 0 //DBG
  1989. {
  1990. HCELL_INDEX PrevCell = HCELL_NIL;
  1991. HCELL_INDEX CurCell;
  1992. ULONG i;
  1993. for( i=0;i<(ULONG)(Leaf->Count);i++) {
  1994. CurCell = FastLeaf->List[i].Cell;
  1995. if( (PrevCell != HCELL_NIL) && (PrevCell == CurCell) ) {
  1996. DbgPrint("CmpSplitLeaf(%p,%lx,%lx) \n",Hive,RootCell,RootSelect);
  1997. DbgPrint("\t Leaf = %p\n",Leaf);
  1998. DbgPrint("\t at index %lx we have duplicate cell - BEFORE\n",i);
  1999. DbgBreakPoint();
  2000. }
  2001. PrevCell = CurCell;
  2002. }
  2003. }
  2004. #endif //DBG
  2005. RtlMoveMemory(
  2006. (PVOID)&(NewLeaf->List[0]),
  2007. (PVOID)&(FastLeaf->List[KeepCount]),
  2008. ElemSize * NewCount
  2009. );
  2010. } else {
  2011. RtlMoveMemory(
  2012. (PVOID)&(NewLeaf->List[0]),
  2013. (PVOID)&(Leaf->List[KeepCount]),
  2014. ElemSize * NewCount
  2015. );
  2016. }
  2017. ASSERT(KeepCount != 0);
  2018. ASSERT(NewCount != 0);
  2019. Leaf->Count = KeepCount;
  2020. NewLeaf->Count = NewCount;
  2021. //
  2022. // make an open slot in the root
  2023. //
  2024. if (RootSelect < (ULONG)(Root->Count-1)) {
  2025. RtlMoveMemory(
  2026. (PVOID)&(Root->List[RootSelect+2]),
  2027. (PVOID)&(Root->List[RootSelect+1]),
  2028. (Root->Count - (RootSelect + 1)) * sizeof(HCELL_INDEX)
  2029. );
  2030. }
  2031. //
  2032. // update the root
  2033. //
  2034. Root->Count += 1;
  2035. Root->List[RootSelect+1] = NewLeafCell;
  2036. return RootCell;
  2037. }
  2038. BOOLEAN
  2039. CmpMarkIndexDirty(
  2040. PHHIVE Hive,
  2041. HCELL_INDEX ParentKey,
  2042. HCELL_INDEX TargetKey
  2043. )
  2044. /*++
  2045. Routine Description:
  2046. Mark as dirty relevent cells of a subkey index. The Leaf that
  2047. points to TargetKey, and the Root index block, if applicable,
  2048. will be marked dirty. This call assumes we are setting up
  2049. for a subkey delete.
  2050. Arguments:
  2051. Hive - pointer to hive control structure for hive of interest
  2052. ParentKey - key from whose subkey list delete is to be performed
  2053. TargetKey - key being deleted
  2054. Return Value:
  2055. TRUE - it worked, FALSE - it didn't, some resource problem
  2056. --*/
  2057. {
  2058. PCM_KEY_NODE pcell;
  2059. ULONG i;
  2060. HCELL_INDEX IndexCell;
  2061. PCM_KEY_INDEX Index;
  2062. HCELL_INDEX Child = HCELL_NIL;
  2063. UNICODE_STRING SearchName;
  2064. BOOLEAN IsCompressed;
  2065. HCELL_INDEX CellToRelease = HCELL_NIL;
  2066. pcell = (PCM_KEY_NODE)HvGetCell(Hive, TargetKey);
  2067. if( pcell == NULL ) {
  2068. //
  2069. // we couldn't map the bin containing this cell
  2070. //
  2071. return FALSE;
  2072. }
  2073. if (pcell->Flags & KEY_COMP_NAME) {
  2074. IsCompressed = TRUE;
  2075. SearchName.Length = CmpCompressedNameSize(pcell->Name, pcell->NameLength);
  2076. SearchName.MaximumLength = SearchName.Length;
  2077. #if defined(_CM_LDR_)
  2078. SearchName.Buffer = (Hive->Allocate)(SearchName.Length, FALSE,CM_FIND_LEAK_TAG9);
  2079. #else
  2080. SearchName.Buffer = ExAllocatePool(PagedPool, SearchName.Length);
  2081. #endif
  2082. if (SearchName.Buffer==NULL) {
  2083. HvReleaseCell(Hive, TargetKey);
  2084. return(FALSE);
  2085. }
  2086. CmpCopyCompressedName(SearchName.Buffer,
  2087. SearchName.MaximumLength,
  2088. pcell->Name,
  2089. pcell->NameLength);
  2090. } else {
  2091. IsCompressed = FALSE;
  2092. SearchName.Length = pcell->NameLength;
  2093. SearchName.MaximumLength = pcell->NameLength;
  2094. SearchName.Buffer = &(pcell->Name[0]);
  2095. }
  2096. HvReleaseCell(Hive, TargetKey);
  2097. pcell = (PCM_KEY_NODE)HvGetCell(Hive, ParentKey);
  2098. if( pcell == NULL ) {
  2099. //
  2100. // we couldn't map the bin containing this cell
  2101. //
  2102. goto ErrorExit;
  2103. }
  2104. for (i = 0; i < Hive->StorageTypeCount; i++) {
  2105. if (pcell->SubKeyCounts[i] != 0) {
  2106. ASSERT(HvIsCellAllocated(Hive, pcell->SubKeyLists[i]));
  2107. IndexCell = pcell->SubKeyLists[i];
  2108. if( CellToRelease != HCELL_NIL ) {
  2109. HvReleaseCell(Hive, CellToRelease);
  2110. CellToRelease = HCELL_NIL;
  2111. }
  2112. Index = (PCM_KEY_INDEX)HvGetCell(Hive, IndexCell);
  2113. if( Index == NULL ) {
  2114. //
  2115. // we couldn't map the bin containing this cell
  2116. //
  2117. goto ErrorExit;
  2118. }
  2119. CellToRelease = IndexCell;
  2120. if (Index->Signature == CM_KEY_INDEX_ROOT) {
  2121. //
  2122. // target even in index?
  2123. //
  2124. if( INVALID_INDEX & CmpFindSubKeyInRoot(Hive, Index, &SearchName, &Child) ) {
  2125. //
  2126. // couldn't map view inside; bail out
  2127. //
  2128. goto ErrorExit;
  2129. }
  2130. if (Child == HCELL_NIL) {
  2131. continue;
  2132. }
  2133. //
  2134. // mark root dirty
  2135. //
  2136. if (! HvMarkCellDirty(Hive, IndexCell)) {
  2137. goto ErrorExit;
  2138. }
  2139. if( CellToRelease != HCELL_NIL ) {
  2140. HvReleaseCell(Hive, CellToRelease);
  2141. CellToRelease = HCELL_NIL;
  2142. }
  2143. IndexCell = Child;
  2144. Index = (PCM_KEY_INDEX)HvGetCell(Hive, Child);
  2145. if( Index == NULL ) {
  2146. //
  2147. // we couldn't map the bin containing this cell
  2148. //
  2149. goto ErrorExit;
  2150. }
  2151. CellToRelease = Child;
  2152. }
  2153. ASSERT((Index->Signature == CM_KEY_INDEX_LEAF) ||
  2154. (Index->Signature == CM_KEY_FAST_LEAF) ||
  2155. (Index->Signature == CM_KEY_HASH_LEAF)
  2156. );
  2157. if( INVALID_INDEX & CmpFindSubKeyInLeaf(Hive, Index, &SearchName, &Child) ) {
  2158. //
  2159. // couldn't map view
  2160. //
  2161. goto ErrorExit;
  2162. }
  2163. if (Child != HCELL_NIL) {
  2164. if (IsCompressed) {
  2165. #if defined(_CM_LDR_)
  2166. (Hive->Free)(SearchName.Buffer, SearchName.Length);
  2167. #else
  2168. ExFreePool(SearchName.Buffer);
  2169. #endif
  2170. }
  2171. // cleanup
  2172. HvReleaseCell(Hive, ParentKey);
  2173. if( CellToRelease != HCELL_NIL ) {
  2174. HvReleaseCell(Hive, CellToRelease);
  2175. }
  2176. return(HvMarkCellDirty(Hive, IndexCell));
  2177. }
  2178. }
  2179. }
  2180. ErrorExit:
  2181. if( pcell!= NULL ) {
  2182. HvReleaseCell(Hive, ParentKey);
  2183. }
  2184. if( CellToRelease != HCELL_NIL ) {
  2185. HvReleaseCell(Hive, CellToRelease);
  2186. }
  2187. if (IsCompressed) {
  2188. #if defined(_CM_LDR_)
  2189. (Hive->Free)(SearchName.Buffer, SearchName.Length);
  2190. #else
  2191. ExFreePool(SearchName.Buffer);
  2192. #endif
  2193. }
  2194. return FALSE;
  2195. }
  2196. BOOLEAN
  2197. CmpRemoveSubKey(
  2198. PHHIVE Hive,
  2199. HCELL_INDEX ParentKey,
  2200. HCELL_INDEX TargetKey
  2201. )
  2202. /*++
  2203. Routine Description:
  2204. Remove the subkey TargetKey refers to from ParentKey's list.
  2205. NOTE: Assumes that caller has marked relevent cells dirty,
  2206. see CmpMarkIndexDirty.
  2207. Arguments:
  2208. Hive - pointer to hive control structure for hive of interest
  2209. ParentKey - key from whose subkey list delete is to be performed
  2210. TargetKey - key being deleted
  2211. Return Value:
  2212. TRUE - it worked, FALSE - it didn't, some resource problem
  2213. --*/
  2214. {
  2215. PCM_KEY_NODE pcell;
  2216. HCELL_INDEX LeafCell;
  2217. PCM_KEY_INDEX Leaf;
  2218. PCM_KEY_FAST_INDEX FastIndex;
  2219. HCELL_INDEX RootCell = HCELL_NIL;
  2220. PCM_KEY_INDEX Root = NULL;
  2221. HCELL_INDEX Child;
  2222. ULONG Type;
  2223. ULONG RootSelect;
  2224. ULONG LeafSelect;
  2225. UNICODE_STRING SearchName;
  2226. BOOLEAN IsCompressed;
  2227. WCHAR CompressedBuffer[50];
  2228. BOOLEAN Result;
  2229. HCELL_INDEX CellToRelease1 = HCELL_NIL,CellToRelease2 = HCELL_NIL;
  2230. pcell = (PCM_KEY_NODE)HvGetCell(Hive, TargetKey);
  2231. if( pcell == NULL ) {
  2232. //
  2233. // we couldn't map the bin containing this cell
  2234. //
  2235. return FALSE;
  2236. }
  2237. ASSERT_CELL_DIRTY(Hive,TargetKey);
  2238. //
  2239. // release the cell here; as key is dirty/pinned
  2240. //
  2241. HvReleaseCell(Hive, TargetKey);
  2242. if (pcell->Flags & KEY_COMP_NAME) {
  2243. IsCompressed = TRUE;
  2244. SearchName.Length = CmpCompressedNameSize(pcell->Name, pcell->NameLength);
  2245. SearchName.MaximumLength = SearchName.Length;
  2246. if (SearchName.MaximumLength > sizeof(CompressedBuffer)) {
  2247. #if defined(_CM_LDR_)
  2248. SearchName.Buffer = (Hive->Allocate)(SearchName.Length, FALSE,CM_FIND_LEAK_TAG40);
  2249. #else
  2250. SearchName.Buffer = ExAllocatePool(PagedPool, SearchName.Length);
  2251. #endif
  2252. if (SearchName.Buffer==NULL) {
  2253. return(FALSE);
  2254. }
  2255. } else {
  2256. SearchName.Buffer = CompressedBuffer;
  2257. }
  2258. CmpCopyCompressedName(SearchName.Buffer,
  2259. SearchName.MaximumLength,
  2260. pcell->Name,
  2261. pcell->NameLength);
  2262. } else {
  2263. IsCompressed = FALSE;
  2264. SearchName.Length = pcell->NameLength;
  2265. SearchName.MaximumLength = pcell->NameLength;
  2266. SearchName.Buffer = &(pcell->Name[0]);
  2267. }
  2268. pcell = (PCM_KEY_NODE)HvGetCell(Hive, ParentKey);
  2269. if( pcell == NULL ) {
  2270. //
  2271. // we couldn't map the bin containing this cell
  2272. //
  2273. Result = FALSE;
  2274. goto Exit;
  2275. }
  2276. ASSERT_CELL_DIRTY(Hive,ParentKey);
  2277. //
  2278. // release the cell here; as key is dirty/pinned
  2279. //
  2280. HvReleaseCell(Hive, ParentKey);
  2281. Type = HvGetCellType(TargetKey);
  2282. ASSERT(pcell->SubKeyCounts[Type] != 0);
  2283. ASSERT(HvIsCellAllocated(Hive, pcell->SubKeyLists[Type]));
  2284. LeafCell = pcell->SubKeyLists[Type];
  2285. Leaf = (PCM_KEY_INDEX)HvGetCell(Hive, LeafCell);
  2286. if( Leaf == NULL ) {
  2287. //
  2288. // we couldn't map the bin containing this cell
  2289. //
  2290. Result = FALSE;
  2291. goto Exit;
  2292. }
  2293. CellToRelease1 = LeafCell;
  2294. RootSelect = INVALID_INDEX; // only needed for the compiler W4 option
  2295. if (Leaf->Signature == CM_KEY_INDEX_ROOT) {
  2296. RootSelect = CmpFindSubKeyInRoot(Hive, Leaf, &SearchName, &Child);
  2297. if( INVALID_INDEX & RootSelect ) {
  2298. //
  2299. // couldn't map view inside; bail out
  2300. //
  2301. Result = FALSE;
  2302. goto Exit;
  2303. }
  2304. ASSERT(Child != FALSE);
  2305. Root = Leaf;
  2306. RootCell = LeafCell;
  2307. LeafCell = Child;
  2308. Leaf = (PCM_KEY_INDEX)HvGetCell(Hive, LeafCell);
  2309. if( Leaf == NULL ) {
  2310. //
  2311. // we couldn't map the bin containing this cell
  2312. //
  2313. Result = FALSE;
  2314. goto Exit;
  2315. }
  2316. CellToRelease2 = LeafCell;
  2317. }
  2318. ASSERT((Leaf->Signature == CM_KEY_INDEX_LEAF) ||
  2319. (Leaf->Signature == CM_KEY_FAST_LEAF) ||
  2320. (Leaf->Signature == CM_KEY_HASH_LEAF)
  2321. );
  2322. LeafSelect = CmpFindSubKeyInLeaf(Hive, Leaf, &SearchName, &Child);
  2323. if( INVALID_INDEX & LeafSelect ) {
  2324. //
  2325. // couldn't map view
  2326. //
  2327. Result = FALSE;
  2328. goto Exit;
  2329. }
  2330. ASSERT(Child != HCELL_NIL);
  2331. //
  2332. // Leaf points to Index Leaf block
  2333. // Child is Index Leaf block cell
  2334. // LeafSelect is Index for List[]
  2335. //
  2336. pcell->SubKeyCounts[Type] -= 1;
  2337. Leaf->Count -= 1;
  2338. if (Leaf->Count == 0) {
  2339. //
  2340. // Empty Leaf, drop it.
  2341. //
  2342. HvFreeCell(Hive, LeafCell);
  2343. if (Root != NULL) {
  2344. Root->Count -= 1;
  2345. if (Root->Count == 0) {
  2346. //
  2347. // Root is empty, free it too.
  2348. //
  2349. HvFreeCell(Hive, RootCell);
  2350. pcell->SubKeyLists[Type] = HCELL_NIL;
  2351. } else if (RootSelect < (ULONG)(Root->Count)) {
  2352. //
  2353. // Middle entry, squeeze root
  2354. //
  2355. RtlMoveMemory(
  2356. (PVOID)&(Root->List[RootSelect]),
  2357. (PVOID)&(Root->List[RootSelect+1]),
  2358. (Root->Count - RootSelect) * sizeof(HCELL_INDEX)
  2359. );
  2360. }
  2361. //
  2362. // Else RootSelect == last entry, so decrementing count
  2363. // was all we needed to do
  2364. //
  2365. } else {
  2366. pcell->SubKeyLists[Type] = HCELL_NIL;
  2367. }
  2368. } else if (LeafSelect < (ULONG)(Leaf->Count)) {
  2369. if (Leaf->Signature == CM_KEY_INDEX_LEAF) {
  2370. RtlMoveMemory((PVOID)&(Leaf->List[LeafSelect]),
  2371. (PVOID)&(Leaf->List[LeafSelect+1]),
  2372. (Leaf->Count - LeafSelect) * sizeof(HCELL_INDEX));
  2373. } else {
  2374. FastIndex = (PCM_KEY_FAST_INDEX)Leaf;
  2375. RtlMoveMemory((PVOID)&(FastIndex->List[LeafSelect]),
  2376. (PVOID)&(FastIndex->List[LeafSelect+1]),
  2377. (FastIndex->Count - LeafSelect) * sizeof(CM_INDEX));
  2378. }
  2379. }
  2380. //
  2381. // Else LeafSelect == last entry, so decrementing count was enough
  2382. //
  2383. // things went OK
  2384. Result = TRUE;
  2385. Exit:
  2386. if( CellToRelease1 != HCELL_NIL ) {
  2387. HvReleaseCell(Hive,CellToRelease1);
  2388. }
  2389. if( CellToRelease2 != HCELL_NIL ) {
  2390. HvReleaseCell(Hive,CellToRelease2);
  2391. }
  2392. if ((IsCompressed) &&
  2393. (SearchName.MaximumLength > sizeof(CompressedBuffer))) {
  2394. #if defined(_CM_LDR_)
  2395. (Hive->Free)(SearchName.Buffer, SearchName.Length);
  2396. #else
  2397. ExFreePool(SearchName.Buffer);
  2398. #endif
  2399. }
  2400. return Result;
  2401. }
  2402. #ifdef NT_RENAME_KEY
  2403. HCELL_INDEX
  2404. CmpDuplicateIndex(
  2405. PHHIVE Hive,
  2406. HCELL_INDEX IndexCell,
  2407. ULONG StorageType
  2408. )
  2409. /*++
  2410. Routine Description:
  2411. Duplicate an index, regardless of its type; Needed for NtRenameKey
  2412. Arguments:
  2413. Hive - pointer to hive control structure for hive of interest
  2414. IndexCell - the index to be duplicated
  2415. StorageType - storagetype (Stable or Volatile)
  2416. Return Value:
  2417. cellindex of a duplicate or HCELL_NIL
  2418. --*/
  2419. {
  2420. PCM_KEY_INDEX Index;
  2421. #if DBG
  2422. PCM_KEY_INDEX Leaf;
  2423. #endif
  2424. ULONG i;
  2425. PCM_KEY_INDEX NewIndex = NULL;
  2426. HCELL_INDEX NewIndexCell;
  2427. HCELL_INDEX LeafCell;
  2428. PAGED_CODE();
  2429. //
  2430. // we have the lock exclusive or nobody is operating inside this hive
  2431. //
  2432. //ASSERT_CM_LOCK_OWNED_EXCLUSIVE();
  2433. ASSERT_CM_EXCLUSIVE_HIVE_ACCESS(Hive);
  2434. ASSERT( HvGetCellType(IndexCell) == StorageType );
  2435. Index = (PCM_KEY_INDEX)HvGetCell(Hive, IndexCell);
  2436. if( Index == NULL ) {
  2437. //
  2438. // we couldn't map a view for the bin containing this cell
  2439. //
  2440. return HCELL_NIL;
  2441. }
  2442. // release the cell here; as the registry is locked exclusive (i.e. we don't care)
  2443. HvReleaseCell(Hive, IndexCell);
  2444. if (Index->Signature == CM_KEY_INDEX_ROOT) {
  2445. //
  2446. // first duplicate IndexCell, zeroing out the new content
  2447. //
  2448. NewIndexCell = HvDuplicateCell(Hive,IndexCell,StorageType,FALSE);
  2449. if( NewIndexCell == HCELL_NIL ) {
  2450. return HCELL_NIL;
  2451. }
  2452. NewIndex = (PCM_KEY_INDEX)HvGetCell(Hive, NewIndexCell);
  2453. if( NewIndex == NULL ) {
  2454. //
  2455. // we couldn't map a view for the bin containing this cell
  2456. // this shouldn't happen as we just allocated this cell (i.e. is dirty/pinned into memory)
  2457. //
  2458. ASSERT( FALSE );
  2459. goto ErrorExit;
  2460. }
  2461. // release the cell here; as the registry is locked exclusive (i.e. we don't care)
  2462. HvReleaseCell(Hive, NewIndexCell);
  2463. //
  2464. // we have a root index;
  2465. //
  2466. NewIndex->Signature = CM_KEY_INDEX_ROOT;
  2467. NewIndex->Count = 0;
  2468. //
  2469. // copy first level.
  2470. //
  2471. for( i=0;i<Index->Count;i++) {
  2472. #if DBG
  2473. Leaf = (PCM_KEY_INDEX)HvGetCell(Hive, Index->List[i]);
  2474. if( Leaf == NULL ) {
  2475. //
  2476. // we couldn't map the bin containing this cell
  2477. //
  2478. goto ErrorExit;
  2479. }
  2480. // release the cell here; as the registry is locked exclusive (i.e. we don't care)
  2481. HvReleaseCell(Hive, Index->List[i]);
  2482. ASSERT((Leaf->Signature == CM_KEY_INDEX_LEAF) ||
  2483. (Leaf->Signature == CM_KEY_FAST_LEAF) ||
  2484. (Leaf->Signature == CM_KEY_HASH_LEAF)
  2485. );
  2486. ASSERT(Leaf->Count != 0);
  2487. #endif
  2488. LeafCell = HvDuplicateCell(Hive,Index->List[i],StorageType,TRUE);
  2489. if( LeafCell == HCELL_NIL ) {
  2490. goto ErrorExit;
  2491. }
  2492. NewIndex->List[i] = LeafCell;
  2493. NewIndex->Count++;
  2494. }
  2495. ASSERT( NewIndex->Count == Index->Count );
  2496. } else {
  2497. //
  2498. // leaf index
  2499. //
  2500. ASSERT((Index->Signature == CM_KEY_INDEX_LEAF) ||
  2501. (Index->Signature == CM_KEY_FAST_LEAF) ||
  2502. (Index->Signature == CM_KEY_HASH_LEAF)
  2503. );
  2504. ASSERT(Index->Count != 0);
  2505. //
  2506. // first duplicate IndexCell, copying the old content
  2507. //
  2508. NewIndexCell = HvDuplicateCell(Hive,IndexCell,StorageType,TRUE);
  2509. }
  2510. return NewIndexCell;
  2511. ErrorExit:
  2512. if( NewIndex != NULL ){
  2513. // we can get here only if we are trying to duplicate an index_root
  2514. ASSERT( NewIndex->Signature == CM_KEY_INDEX_ROOT );
  2515. //
  2516. // free the space we already allocated
  2517. //
  2518. for(i=0;i<NewIndex->Count;i++) {
  2519. ASSERT(NewIndex->List[i] != 0 );
  2520. HvFreeCell(Hive, NewIndex->List[i]);
  2521. }
  2522. }
  2523. HvFreeCell(Hive, NewIndexCell);
  2524. return HCELL_NIL;
  2525. }
  2526. BOOLEAN
  2527. CmpUpdateParentForEachSon(
  2528. PHHIVE Hive,
  2529. HCELL_INDEX Parent
  2530. )
  2531. /*++
  2532. Routine Description:
  2533. Walks the child's list (both stable and volatile and marks updates
  2534. the parent link to Parent.
  2535. First step is to mark all children dirty, and then to update the link.
  2536. This way, if we fail part through, we leave everything in good order
  2537. Arguments:
  2538. Hive - pointer to hive control structure for hive of interest
  2539. Parent - cell index of the cell who's son's to be updated.
  2540. Return Value:
  2541. TRUE - successfully updated
  2542. --*/
  2543. {
  2544. PCM_KEY_NODE ParentNode;
  2545. PCM_KEY_NODE CurrentSon;
  2546. HCELL_INDEX Child;
  2547. ULONG Count;
  2548. ULONG i;
  2549. PAGED_CODE();
  2550. //
  2551. // we have the lock exclusive or nobody is operating inside this hive
  2552. //
  2553. //ASSERT_CM_LOCK_OWNED_EXCLUSIVE();
  2554. ASSERT_CM_EXCLUSIVE_HIVE_ACCESS(Hive);
  2555. //
  2556. // grab the parent node; this was already marked as dirty, we shouldn't
  2557. // have any problem here;
  2558. //
  2559. ParentNode = (PCM_KEY_NODE)HvGetCell(Hive,Parent);
  2560. if( ParentNode == NULL ) {
  2561. //
  2562. // cannot map view; this shouldn't happen as we just allocated
  2563. // this cell (i.e. it should be dirty/pinned into memory)
  2564. //
  2565. ASSERT( FALSE );
  2566. return FALSE;
  2567. }
  2568. // release the cell here; as the registry is locked exclusive (i.e. we don't care)
  2569. HvReleaseCell(Hive, Parent);
  2570. //
  2571. // iterate through the child list (both stable and volatile), marking every
  2572. // child dirty; this will pin the cell into memory and we will have no problems
  2573. // changine the parent later on
  2574. //
  2575. Count = ParentNode->SubKeyCounts[Stable] + ParentNode->SubKeyCounts[Volatile];
  2576. for( i=0;i<Count;i++) {
  2577. Child = CmpFindSubKeyByNumber(Hive,ParentNode,i);
  2578. if( Child == HCELL_NIL ) {
  2579. return FALSE;
  2580. }
  2581. if(!HvMarkCellDirty(Hive,Child)) {
  2582. return FALSE;
  2583. }
  2584. }
  2585. //
  2586. // second iteration, change the parent for each and every son
  2587. //
  2588. for( i=0;i<Count;i++) {
  2589. Child = CmpFindSubKeyByNumber(Hive,ParentNode,i);
  2590. //
  2591. // sanity test: we marked this dirty few lines above!
  2592. //
  2593. ASSERT( Child != HCELL_NIL );
  2594. CurrentSon = (PCM_KEY_NODE)HvGetCell(Hive,Child);
  2595. // release the cell here; as the registry is locked exclusive (i.e. we don't care)
  2596. HvReleaseCell(Hive, Child);
  2597. //
  2598. // sanity test: this cell should be pinned in memory by now
  2599. //
  2600. ASSERT( CurrentSon != NULL );
  2601. //
  2602. // change the parent
  2603. //
  2604. CurrentSon->Parent = Parent;
  2605. }
  2606. return TRUE;
  2607. }
  2608. #endif //NT_RENAME_KEY
  2609. ULONG
  2610. CmpComputeHashKey(
  2611. PUNICODE_STRING Name
  2612. )
  2613. {
  2614. ULONG ConvKey = 0;
  2615. ULONG Cnt;
  2616. WCHAR *Cp;
  2617. ASSERT((Name->Length == 0) || (Name->Buffer[0] != OBJ_NAME_PATH_SEPARATOR));
  2618. //
  2619. // Manually compute the hash to use.
  2620. //
  2621. Cp = Name->Buffer;
  2622. for (Cnt=0; Cnt<Name->Length; Cnt += sizeof(WCHAR)) {
  2623. ASSERT( *Cp != OBJ_NAME_PATH_SEPARATOR );
  2624. ConvKey = 37 * ConvKey + (ULONG)CmUpcaseUnicodeChar(*Cp);
  2625. ++Cp;
  2626. }
  2627. return ConvKey;
  2628. }
  2629. ULONG
  2630. CmpComputeHashKeyForCompressedName(
  2631. IN PWCHAR Source,
  2632. IN ULONG SourceLength
  2633. )
  2634. {
  2635. ULONG ConvKey = 0;
  2636. ULONG i;
  2637. for (i=0;i<SourceLength;i++) {
  2638. ConvKey = 37*ConvKey + (ULONG)CmUpcaseUnicodeChar((WCHAR)(((PUCHAR)Source)[i]));
  2639. }
  2640. return ConvKey;
  2641. }
  2642. //
  2643. // HashIndex routines
  2644. //
  2645. HCELL_INDEX
  2646. CmpFindSubKeyByHash(
  2647. PHHIVE Hive,
  2648. PCM_KEY_FAST_INDEX FastIndex,
  2649. PUNICODE_STRING SearchName
  2650. )
  2651. /*++
  2652. Routine Description:
  2653. Find the child cell (either subkey or value) specified by name.
  2654. It searched in the index table ordered by the hash
  2655. Arguments:
  2656. Hive - pointer to hive control structure for hive of interest
  2657. Index -
  2658. SearchName - name of child of interest
  2659. Return Value:
  2660. Cell of matching child key, or HCELL_NIL if none.
  2661. --*/
  2662. {
  2663. USHORT Current;
  2664. ULONG HashKey;
  2665. LONG Result;
  2666. #ifndef _CM_LDR_
  2667. PAGED_CODE();
  2668. #endif //_CM_LDR_
  2669. ASSERT( FastIndex->Signature == CM_KEY_HASH_LEAF );
  2670. HashKey = CmpComputeHashKey(SearchName);
  2671. for(Current = 0; Current < FastIndex->Count; Current++ ) {
  2672. if( HashKey == FastIndex->List[Current].HashKey ) {
  2673. //
  2674. // HashKey matches; see if this is a real hit
  2675. //
  2676. Result = CmpDoCompareKeyName(Hive,SearchName,FastIndex->List[Current].Cell);
  2677. if (Result == 0) {
  2678. return FastIndex->List[Current].Cell;
  2679. }
  2680. }
  2681. }
  2682. return HCELL_NIL;
  2683. }