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.

2520 lines
75 KiB

  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. cmtrecpy.c
  5. Abstract:
  6. This file contains code for CmpCopyTree, misc copy utility routines.
  7. Author:
  8. Bryan M. Willman (bryanwi) 15-Jan-92
  9. Revision History:
  10. Elliot Shmukler (t-ellios) 24-Aug-1998
  11. Added support for synchronizing two trees.
  12. --*/
  13. #include "cmp.h"
  14. //
  15. // Set this to true to enable tree sync debug outputs
  16. //
  17. #define DEBUG_TREE_SYNC FALSE
  18. //
  19. // stack used for directing nesting of tree copy. gets us off
  20. // the kernel stack and thus allows for VERY deep nesting
  21. //
  22. #define CMP_INITIAL_STACK_SIZE 1024 // ENTRIES
  23. typedef struct {
  24. HCELL_INDEX SourceCell;
  25. HCELL_INDEX TargetCell;
  26. ULONG i;
  27. } CMP_COPY_STACK_ENTRY, *PCMP_COPY_STACK_ENTRY;
  28. BOOLEAN
  29. CmpCopySyncTree2(
  30. PCMP_COPY_STACK_ENTRY CmpCopyStack,
  31. ULONG CmpCopyStackSize,
  32. ULONG CmpCopyStackTop,
  33. PHHIVE CmpSourceHive,
  34. PHHIVE CmpTargetHive,
  35. BOOLEAN CopyVolatile,
  36. CMP_COPY_TYPE CopyType
  37. );
  38. BOOLEAN
  39. CmpFreeKeyValues(
  40. PHHIVE Hive,
  41. HCELL_INDEX Cell,
  42. PCM_KEY_NODE Node
  43. );
  44. BOOLEAN
  45. CmpSyncKeyValues(
  46. PHHIVE SourceHive,
  47. HCELL_INDEX SourceKeyCell,
  48. PCM_KEY_NODE SourceKeyNode,
  49. PHHIVE TargetHive,
  50. HCELL_INDEX TargetKeyCell,
  51. PCM_KEY_NODE TargetKeyNode
  52. );
  53. BOOLEAN
  54. CmpMergeKeyValues(
  55. PHHIVE SourceHive,
  56. HCELL_INDEX SourceKeyCell,
  57. PCM_KEY_NODE SourceKeyNode,
  58. PHHIVE TargetHive,
  59. HCELL_INDEX TargetKeyCell,
  60. PCM_KEY_NODE TargetKeyNode
  61. );
  62. BOOLEAN
  63. CmpSyncSubKeysAfterDelete(
  64. PHHIVE SourceHive,
  65. PCM_KEY_NODE SourceCell,
  66. PHHIVE TargetHive,
  67. PCM_KEY_NODE TargetCell,
  68. WCHAR *NameBuffer);
  69. BOOLEAN
  70. CmpMarkKeyValuesDirty(
  71. PHHIVE Hive,
  72. HCELL_INDEX Cell,
  73. PCM_KEY_NODE Node
  74. );
  75. BOOLEAN
  76. CmpMarkKeyParentDirty(
  77. PHHIVE Hive,
  78. HCELL_INDEX Cell
  79. );
  80. #ifdef ALLOC_PRAGMA
  81. #pragma alloc_text(PAGE,CmpCopySyncTree)
  82. #pragma alloc_text(PAGE,CmpCopySyncTree2)
  83. #pragma alloc_text(PAGE,CmpCopyKeyPartial)
  84. #pragma alloc_text(PAGE,CmpCopyValue)
  85. #pragma alloc_text(PAGE,CmpCopyCell)
  86. #pragma alloc_text(PAGE,CmpFreeKeyValues)
  87. #pragma alloc_text(PAGE,CmpSyncKeyValues)
  88. #pragma alloc_text(PAGE,CmpMergeKeyValues)
  89. #pragma alloc_text(PAGE,CmpInitializeKeyNameString)
  90. #pragma alloc_text(PAGE,CmpInitializeValueNameString)
  91. #pragma alloc_text(PAGE,CmpSyncSubKeysAfterDelete)
  92. #pragma alloc_text(PAGE,CmpMarkKeyValuesDirty)
  93. #pragma alloc_text(PAGE,CmpMarkKeyParentDirty)
  94. #endif
  95. //
  96. // Routine to actually call to do a tree copy (or sync)
  97. //
  98. BOOLEAN
  99. CmpCopySyncTree(
  100. PHHIVE SourceHive,
  101. HCELL_INDEX SourceCell,
  102. PHHIVE TargetHive,
  103. HCELL_INDEX TargetCell,
  104. BOOLEAN CopyVolatile,
  105. CMP_COPY_TYPE CopyType
  106. )
  107. /*++
  108. Routine Description:
  109. This routine can perform two distinct (yet similar) tasks:
  110. a tree copy or a tree synchronization (sync). Which task
  111. is performed is determined by the TreeSync parameter.
  112. For both operations:
  113. --------------------
  114. The source root key and target root key must exist in advance.
  115. These root nodes and their value entries will NOT be copied/synced.
  116. NOTE: Volatile keys are only copied/synced if the CopyVolatile
  117. parameter is set to true.
  118. For a tree copy:
  119. ----------------
  120. A tree is copied from source to destination. The subkeys
  121. of the source root key and the full trees under those
  122. subkeys will be copied to a new tree at target root key.
  123. NOTE: If this call fails part way through, it will NOT undo
  124. any successfully completed key copies, thus a partial
  125. tree copy CAN occur.
  126. For a tree sync:
  127. ----------------
  128. The target tree is synchronized with the source tree. It is
  129. assumed that for a certain period of the time the target tree
  130. has remained unmodified while modifications may have been made
  131. to the source tree. During a sync, any such modifications
  132. to the source tree are made to the target tree. Thus, at the
  133. end of a successful sync, the target tree is identical to the
  134. source tree.
  135. Since only things that have changed in the source tree
  136. are modified in the target tree, a sync operation is far
  137. more efficient than the delete/copy operations necessary
  138. to accomplish the same results.
  139. NOTE: It is assumed that no open handles are held
  140. on any target tree keys. Registry in-memory data
  141. structures may be corrupted if this is not true.
  142. Arguments:
  143. SourceHive - pointer to hive control structure for source
  144. SourceCell - index of cell at root of tree to copy/sync
  145. TargetHive - pointer to hive control structure for target
  146. TargetCell - pointer to cell at root of target tree
  147. CopyVolatile - indicates whether volatile keys should be
  148. copied/synced.
  149. CopyType - indicates the type of the copy operation:
  150. Copy - A copy is requested
  151. Sync - A sync is requested
  152. Merge - A merge is requested i.e.:
  153. 1. the target nodes that are not present on the source tree are not
  154. deleted.
  155. 2. the target nodes that are present in the source tree gets overrided
  156. no matter what the LastWriteTime value is.
  157. Return Value:
  158. BOOLEAN - Result code from call, among the following:
  159. TRUE - it worked
  160. FALSE - the tree copy/sync was not completed (though more than 0
  161. keys may have been copied/synced)
  162. --*/
  163. {
  164. BOOLEAN result;
  165. PCMP_COPY_STACK_ENTRY CmpCopyStack;
  166. PRELEASE_CELL_ROUTINE TargetReleaseCellRoutine;
  167. CmKdPrintEx((DPFLTR_CONFIG_ID,CML_SAVRES,"CmpCopyTree:\n"));
  168. CmpCopyStack = ExAllocatePool(
  169. PagedPool,
  170. sizeof(CMP_COPY_STACK_ENTRY)*CMP_INITIAL_STACK_SIZE
  171. );
  172. if (CmpCopyStack == NULL) {
  173. return FALSE;
  174. }
  175. CmpCopyStack[0].SourceCell = SourceCell;
  176. CmpCopyStack[0].TargetCell = TargetCell;
  177. //ASSERT_CM_LOCK_OWNED_EXCLUSIVE();
  178. //
  179. // since the registry is locked exclusively here, we don't need to lock/release cells
  180. // while copying the trees; So, we just set the release routines to NULL and restore after
  181. // the copy is complete; this saves some pain
  182. //
  183. TargetReleaseCellRoutine = TargetHive->ReleaseCellRoutine;
  184. TargetHive->ReleaseCellRoutine = NULL;
  185. result = CmpCopySyncTree2(
  186. CmpCopyStack,
  187. CMP_INITIAL_STACK_SIZE,
  188. 0,
  189. SourceHive,
  190. TargetHive,
  191. CopyVolatile,
  192. CopyType
  193. );
  194. TargetHive->ReleaseCellRoutine = TargetReleaseCellRoutine;
  195. ExFreePool(CmpCopyStack);
  196. return result;
  197. }
  198. //
  199. // Helper
  200. //
  201. BOOLEAN
  202. CmpCopySyncTree2(
  203. PCMP_COPY_STACK_ENTRY CmpCopyStack,
  204. ULONG CmpCopyStackSize,
  205. ULONG CmpCopyStackTop,
  206. PHHIVE CmpSourceHive,
  207. PHHIVE CmpTargetHive,
  208. BOOLEAN CopyVolatile,
  209. CMP_COPY_TYPE CopyType
  210. )
  211. /*++
  212. Routine Description:
  213. This is a helper routine for CmpCopySyncTree. It accomplishes
  214. the functionality described by that routine in a "virtually"
  215. recursive manner which frees this routine from the limitations
  216. of the Kernel stack.
  217. This routine should not be called directly. Use CmpCopySyncTree!.
  218. Arguments:
  219. (All of these are "virtual globals")
  220. CmpCopyStack - "global" pointer to stack for frames
  221. CmpCopyStackSize - alloced size of stack
  222. CmpCopyStackTop - current top
  223. CmpSourceHive, CmpTargetHive - source and target hives
  224. CopyVolatile, CopyType - same as CmpCopySyncTree.
  225. Return Value:
  226. BOOLEAN - Result code from call, among the following:
  227. TRUE - it worked
  228. FALSE - the tree copy/sync was not completed (though more than 0
  229. keys may have been copied/synced)
  230. --*/
  231. {
  232. PCMP_COPY_STACK_ENTRY Frame;
  233. HCELL_INDEX SourceChild;
  234. HCELL_INDEX NewSubKey;
  235. BOOLEAN Ret = FALSE, SyncNeedsTreeCopy = FALSE;
  236. UNICODE_STRING KeyName;
  237. PCM_KEY_NODE SourceChildCell, TargetChildCell;
  238. PCM_KEY_NODE SourceCell, TargetCell, TempNode;
  239. ULONG SyncTreeCopyStackStart;
  240. WCHAR *NameBuffer = NULL;
  241. // A merge is a particular case of a sync !!!
  242. BOOLEAN TreeSync = (CopyType == Sync || CopyType == Merge)?TRUE:FALSE;
  243. CmKdPrintEx((DPFLTR_CONFIG_ID,CML_SAVRES,"CmpCopyTree2:\n"));
  244. if (TreeSync) {
  245. //
  246. // The sync operation involves some work with key names,
  247. // so we must allocate a buffer used for key name decompression.
  248. //
  249. NameBuffer = ExAllocatePool(PagedPool, REG_MAX_KEY_NAME_LENGTH);
  250. if(!NameBuffer) return FALSE;
  251. }
  252. //
  253. // outer loop, apply to entire tree, emulate recursion here
  254. // jump to here is a virtual call
  255. //
  256. Outer: while (TRUE) {
  257. Frame = &(CmpCopyStack[CmpCopyStackTop]);
  258. Frame->i = 0;
  259. //
  260. // inner loop, applies to one key
  261. // jump to here is a virtual return
  262. //
  263. Inner: while (TRUE) {
  264. SourceCell = (PCM_KEY_NODE)HvGetCell(CmpSourceHive, Frame->SourceCell);
  265. if( SourceCell == NULL ) {
  266. //
  267. // we couldn't map the bin containing this cell
  268. //
  269. goto CopyEnd;
  270. }
  271. SourceChild = CmpFindSubKeyByNumber(CmpSourceHive,
  272. SourceCell,
  273. Frame->i);
  274. (Frame->i)++;
  275. if ((SourceChild == HCELL_NIL) || (!CopyVolatile &&
  276. (HvGetCellType(SourceChild) == Volatile))) {
  277. //
  278. // we've stepped through all the children (or we are only
  279. // interested in stable children and have just stepped through
  280. // the stable children and into the volatile ones)
  281. //
  282. if(TreeSync && (CopyType != Merge))
  283. {
  284. //
  285. // If we are here during a sync, that means most of sync operations
  286. // applied to the current SourceCell have been completed.
  287. // That is, we have:
  288. // 1) Synchronized SourceCell's values with its counterpart in the
  289. // target tree.
  290. // 2) Synchronized any new SourceCell subkeys (subkeys present
  291. // in SourceCell but not its counterpart) by creating
  292. // and copying them to the proper place in the target tree.
  293. //
  294. // What this means is that SourceCell's counterpart in the target tree
  295. // (TargetCell) now has at least as many subkeys as SourceCell.
  296. //
  297. // This implies that if TargetCell now has more subkeys that SourceCell
  298. // than some subkeys of TargetCell are not present in the source tree
  299. // (probably because those keys were deleted from the source tree
  300. // during the period between the previous sync and now).
  301. //
  302. // If such keys exist, then they must be delete them from TargetCell
  303. // in order to complete the sync. We do this below.
  304. //
  305. TargetCell = (PCM_KEY_NODE)HvGetCell(CmpTargetHive, Frame->TargetCell);
  306. if( TargetCell == NULL ) {
  307. //
  308. // we couldn't map the bin containing this cell
  309. //
  310. HvReleaseCell(CmpSourceHive, Frame->SourceCell);
  311. goto CopyEnd;
  312. }
  313. //
  314. // Does TargetCell have more subkeys than SourceCell?
  315. //
  316. if((TargetCell->SubKeyCounts[Stable] +
  317. TargetCell->SubKeyCounts[Volatile]) >
  318. (SourceCell->SubKeyCounts[Stable] +
  319. // We only count the volatile keys if we are actually
  320. // syncing them. Note, however, that we always use
  321. // the volatile counts in TargetCell since we may
  322. // be syncing to a volatile tree where all keys are volatile.
  323. (CopyVolatile ? SourceCell->SubKeyCounts[Volatile] : 0)))
  324. {
  325. #if DEBUG_TREE_SYNC
  326. CmKdPrintEx((DPFLTR_CONFIG_ID,DPFLTR_TRACE_LEVEL,"CONFIG: SubKey Deletion from Source Cell #%lu.\n",
  327. Frame->SourceCell));
  328. #endif
  329. //
  330. // Delete what should be deleted from TargetCell
  331. //
  332. CmpSyncSubKeysAfterDelete(CmpSourceHive,
  333. SourceCell,
  334. CmpTargetHive,
  335. TargetCell,
  336. NameBuffer);
  337. }
  338. //
  339. // release target cell as we don't need it anymore
  340. //
  341. HvReleaseCell(CmpTargetHive, Frame->TargetCell);
  342. }
  343. //
  344. // release the source cell
  345. //
  346. HvReleaseCell(CmpSourceHive, Frame->SourceCell);
  347. break;
  348. } else {
  349. //
  350. // release the source cell
  351. //
  352. HvReleaseCell(CmpSourceHive, Frame->SourceCell);
  353. }
  354. if (TreeSync) {
  355. //
  356. // For a sync, we want to check if the current child (subkey)
  357. // of SourceCell is also a child of TargetCell - i.e. if
  358. // the subkey in question has a counterpart in the target tree.
  359. //
  360. // There is no guarantee that the counterpart's index number
  361. // will be the same so we must perform this check using
  362. // the subkey name.
  363. //
  364. //
  365. // Get the name of the current child
  366. //
  367. SourceChildCell = (PCM_KEY_NODE)HvGetCell(CmpSourceHive,
  368. SourceChild);
  369. if( SourceChildCell == NULL ) {
  370. //
  371. // we couldn't map the bin containing this cell
  372. //
  373. goto CopyEnd;
  374. }
  375. CmpInitializeKeyNameString(SourceChildCell,
  376. &KeyName,
  377. NameBuffer);
  378. //
  379. // Try to find the current child's counterpart in
  380. // in the target tree using the child's name.
  381. //
  382. TempNode = (PCM_KEY_NODE)HvGetCell(CmpTargetHive,Frame->TargetCell);
  383. if( TempNode == NULL ) {
  384. //
  385. // we couldn't map the bin containing this cell
  386. //
  387. HvReleaseCell(CmpSourceHive,SourceChild);
  388. goto CopyEnd;
  389. }
  390. NewSubKey = CmpFindSubKeyByName(CmpTargetHive,
  391. TempNode,
  392. &KeyName);
  393. // release the temporary node
  394. HvReleaseCell(CmpTargetHive,Frame->TargetCell);
  395. if (NewSubKey != HCELL_NIL) {
  396. //
  397. // Found it, the current child (subkey) has a counterpart
  398. // in the target tree. Thus, we just need to check if
  399. // the counterpart's values are out of date and should
  400. // be updated.
  401. //
  402. TargetChildCell = (PCM_KEY_NODE)HvGetCell(CmpTargetHive,
  403. NewSubKey);
  404. if( TargetChildCell == NULL ) {
  405. //
  406. // we couldn't map the bin containing this cell
  407. //
  408. HvReleaseCell(CmpSourceHive,SourceChild);
  409. goto CopyEnd;
  410. }
  411. //
  412. // Check if the current subkey has been modified
  413. // more recently than its target tree counterpart.
  414. // When we are doing a tree merge, always override the target.
  415. //
  416. if ( (CopyType == Merge) ||
  417. ((TargetChildCell->LastWriteTime.QuadPart) <
  418. (SourceChildCell->LastWriteTime.QuadPart))) {
  419. //
  420. // The counterpart is out of date. Its values
  421. // must be synchronized with the current subkey.
  422. //
  423. #if DEBUG_TREE_SYNC
  424. CmKdPrintEx((DPFLTR_CONFIG_ID,DPFLTR_TRACE_LEVEL,"CONFIG: Target Refresh.\n"));
  425. CmKdPrintEx((DPFLTR_CONFIG_ID,DPFLTR_TRACE_LEVEL,"CONFIG: Source Cell %lu = %.*S\n",
  426. SourceChild,
  427. KeyName.Length / sizeof(WCHAR),
  428. KeyName.Buffer));
  429. #endif
  430. //
  431. // Sync up the key's values, sd, & class
  432. //
  433. if(CopyType == Merge) {
  434. if(!CmpMergeKeyValues(CmpSourceHive, SourceChild, SourceChildCell,
  435. CmpTargetHive, NewSubKey, TargetChildCell)) {
  436. HvReleaseCell(CmpSourceHive,SourceChild);
  437. HvReleaseCell(CmpTargetHive,NewSubKey);
  438. goto CopyEnd;
  439. }
  440. } else {
  441. if(!CmpSyncKeyValues(CmpSourceHive, SourceChild, SourceChildCell,
  442. CmpTargetHive, NewSubKey, TargetChildCell)) {
  443. HvReleaseCell(CmpSourceHive,SourceChild);
  444. HvReleaseCell(CmpTargetHive,NewSubKey);
  445. goto CopyEnd;
  446. }
  447. }
  448. //
  449. // Sync the timestamps so that we don't do this again.
  450. //
  451. TargetChildCell->LastWriteTime.QuadPart =
  452. SourceChildCell->LastWriteTime.QuadPart;
  453. }
  454. //
  455. // If we are here, then the current subkey's target
  456. // tree counterpart has been synchronized (or did not need
  457. // to be). Transfer control to the code that will apply
  458. // this function "recursively" to the current subkey in order
  459. // to continue the sync.
  460. //
  461. HvReleaseCell(CmpSourceHive,SourceChild);
  462. HvReleaseCell(CmpTargetHive,NewSubKey);
  463. goto NewKeyCreated;
  464. }
  465. //
  466. // If we are here, it means that the current child (subkey)
  467. // does not have a counterpart in the target tree. This means
  468. // we have encountered a new subkey in the source tree and must
  469. // create it in the target tree.
  470. //
  471. // The standard copy code below will create this subkey. However,
  472. // we must also make sure that the tree under this subkey is properly
  473. // copied from source to target. The most efficient way of doing
  474. // this is to temporarily forget that we are in a sync operation
  475. // and merely perform a copy until the desired result is achieved.
  476. //
  477. #if DEBUG_TREE_SYNC
  478. CmKdPrintEx((DPFLTR_CONFIG_ID,DPFLTR_TRACE_LEVEL,"CONFIG: New SubKey.\n"));
  479. CmKdPrintEx((DPFLTR_CONFIG_ID,DPFLTR_TRACE_LEVEL,"CONFIG: Source Cell %lu = %.*S\n",
  480. SourceChild,
  481. KeyName.Length / sizeof(WCHAR),
  482. KeyName.Buffer));
  483. #endif
  484. //
  485. // Indicate that we will just copy and not sync for a while
  486. //
  487. SyncNeedsTreeCopy = TRUE;
  488. //
  489. // release this cell as we don't need it anymore
  490. //
  491. HvReleaseCell(CmpSourceHive,SourceChild);
  492. }
  493. NewSubKey = CmpCopyKeyPartial(
  494. CmpSourceHive,
  495. SourceChild,
  496. CmpTargetHive,
  497. Frame->TargetCell,
  498. TRUE
  499. );
  500. if (NewSubKey == HCELL_NIL) {
  501. goto CopyEnd;
  502. }
  503. if ( ! CmpAddSubKey(
  504. CmpTargetHive,
  505. Frame->TargetCell,
  506. NewSubKey
  507. )
  508. ) {
  509. goto CopyEnd;
  510. }
  511. //
  512. // Check if the sync operation determined that this
  513. // subtree should be copied
  514. //
  515. if(TreeSync && SyncNeedsTreeCopy) {
  516. //
  517. // We have just created a new key in the target tree
  518. // with the above code. However, since this is a sync,
  519. // the parent of that new key has not been created by our
  520. // code and thus may not have been modified at all before
  521. // the creation of the new key. But this parent now
  522. // has a new child, and must therefore be marked as dirty.
  523. //
  524. if (! CmpMarkKeyParentDirty(CmpTargetHive, NewSubKey)) {
  525. goto CopyEnd;
  526. }
  527. //
  528. // Record the stack level where we start the copy
  529. // (and temporarily abandon the sync)
  530. // so that we can return to the sync operation when this
  531. // stack level is reached again (i.e. when the tree
  532. // under the current subkey is fully copied)
  533. //
  534. SyncTreeCopyStackStart = CmpCopyStackTop;
  535. //
  536. // Pretend that this is not a sync in order
  537. // to simply start copying
  538. //
  539. TreeSync = FALSE;
  540. }
  541. NewKeyCreated:
  542. //
  543. // We succeeded in copying/syncing the subkey, apply
  544. // ourselves to it
  545. //
  546. CmpCopyStackTop++;
  547. if (CmpCopyStackTop >= CmpCopyStackSize) {
  548. //
  549. // if we're here, it means that the tree
  550. // we're trying to copy is more than 1024
  551. // COMPONENTS deep (from 2048 to 256k bytes)
  552. // we could grow the stack, but this is pretty
  553. // severe, so return FALSE and fail the copy
  554. //
  555. goto CopyEnd;
  556. }
  557. CmpCopyStack[CmpCopyStackTop].SourceCell =
  558. SourceChild;
  559. CmpCopyStack[CmpCopyStackTop].TargetCell =
  560. NewSubKey;
  561. goto Outer;
  562. } // Inner: while
  563. if (CmpCopyStackTop == 0) {
  564. Ret = TRUE;
  565. goto CopyEnd;
  566. }
  567. CmpCopyStackTop--;
  568. Frame = &(CmpCopyStack[CmpCopyStackTop]);
  569. //
  570. // We have just completed working at a certain stack level.
  571. // This is a good time to check if we need to resume a temporarily
  572. // suspended sync operation.
  573. //
  574. if(SyncNeedsTreeCopy && (CmpCopyStackTop == SyncTreeCopyStackStart))
  575. {
  576. //
  577. // We've been copying a tree for a sync. But now, that tree is fully
  578. // copied. So, let's resume the sync once again.
  579. //
  580. TreeSync = TRUE;
  581. SyncNeedsTreeCopy = FALSE;
  582. }
  583. goto Inner;
  584. } // Outer: while
  585. CopyEnd:
  586. if (NameBuffer) ExFreePool(NameBuffer);
  587. return Ret;
  588. }
  589. HCELL_INDEX
  590. CmpCopyKeyPartial(
  591. PHHIVE SourceHive,
  592. HCELL_INDEX SourceKeyCell,
  593. PHHIVE TargetHive,
  594. HCELL_INDEX Parent,
  595. BOOLEAN CopyValues
  596. )
  597. /*++
  598. Routine Description:
  599. Copy a key body and all of its values, but NOT its subkeylist or
  600. subkey entries. SubKeyList.Count will be set to 0.
  601. Arguments:
  602. SourceHive - pointer to hive control structure for source
  603. SourceKeyCell - value entry being copied
  604. TargetHive - pointer to hive control structure for target
  605. Parent - parent value to set into newly created key body
  606. CopyValues - if FALSE value entries will not be copied, if TRUE, they will
  607. Return Value:
  608. HCELL_INDEX - Cell of body of new key entry, or HCELL_NIL
  609. if some error.
  610. --*/
  611. {
  612. NTSTATUS status;
  613. HCELL_INDEX newkey = HCELL_NIL;
  614. HCELL_INDEX newclass = HCELL_NIL;
  615. HCELL_INDEX newsecurity = HCELL_NIL;
  616. HCELL_INDEX newlist = HCELL_NIL;
  617. HCELL_INDEX newvalue;
  618. BOOLEAN success = FALSE;
  619. ULONG i,Index;
  620. PCELL_DATA psrckey = NULL;
  621. PCM_KEY_NODE ptarkey = NULL;
  622. PCELL_DATA psrclist = NULL;
  623. PCELL_DATA ptarlist;
  624. HCELL_INDEX security;
  625. HCELL_INDEX class;
  626. ULONG classlength;
  627. ULONG count;
  628. ULONG Type;
  629. PCM_KEY_VALUE pvalue;
  630. #if DBG
  631. WCHAR *NameBuffer = NULL;
  632. UNICODE_STRING ValueName;
  633. HCELL_INDEX child;
  634. #endif
  635. PSECURITY_DESCRIPTOR SrcSecurityDescriptor;
  636. CmKdPrintEx((DPFLTR_CONFIG_ID,CML_SAVRES,"CmpCopyKeyPartial:\n"));
  637. CmKdPrintEx((DPFLTR_CONFIG_ID,CML_SAVRES,"\tSHive=%p SCell=%08lx\n",SourceHive,SourceKeyCell));
  638. CmKdPrintEx((DPFLTR_CONFIG_ID,CML_SAVRES,"\tTHive=%p\n",TargetHive));
  639. #if DBG
  640. NameBuffer = ExAllocatePool(PagedPool, REG_MAX_KEY_VALUE_NAME_LENGTH);
  641. if(!NameBuffer) {
  642. return HCELL_NIL;
  643. }
  644. #endif //DBG
  645. //
  646. // get description of source
  647. //
  648. if (Parent == HCELL_NIL) {
  649. //
  650. // This is a root node we are creating, so don't make it volatile.
  651. //
  652. Type = Stable;
  653. } else {
  654. Type = HvGetCellType(Parent);
  655. }
  656. psrckey = HvGetCell(SourceHive, SourceKeyCell);
  657. if( psrckey == NULL ) {
  658. //
  659. // we couldn't map the bin containing this cell
  660. //
  661. goto DoFinally;
  662. }
  663. security = psrckey->u.KeyNode.Security;
  664. class = psrckey->u.KeyNode.Class;
  665. classlength = psrckey->u.KeyNode.ClassLength;
  666. //
  667. // Allocate and copy the body
  668. //
  669. newkey = CmpCopyCell(SourceHive, SourceKeyCell, TargetHive, Type);
  670. if (newkey == HCELL_NIL) {
  671. goto DoFinally;
  672. }
  673. //
  674. // this cell was just allocated so it should be pinned; it's OK to release it here
  675. // as the view is not going anywhere
  676. //
  677. ASSERT_CELL_DIRTY(TargetHive, newkey);
  678. //
  679. // Allocate and copy class
  680. //
  681. if (classlength > 0) {
  682. newclass = CmpCopyCell(SourceHive, class, TargetHive, Type);
  683. if (newclass == HCELL_NIL) {
  684. goto DoFinally;
  685. }
  686. }
  687. //
  688. // Fill in the target body
  689. //
  690. ptarkey = (PCM_KEY_NODE)HvGetCell(TargetHive, newkey);
  691. if( ptarkey == NULL ) {
  692. //
  693. // we couldn't map the bin containing this cell
  694. //
  695. goto DoFinally;
  696. }
  697. ptarkey->Class = newclass;
  698. ptarkey->Security = HCELL_NIL;
  699. ptarkey->SubKeyLists[Stable] = HCELL_NIL;
  700. ptarkey->SubKeyCounts[Stable] = 0;
  701. ptarkey->SubKeyCounts[Volatile] = 0;
  702. ptarkey->SubKeyLists[Volatile] = HCELL_NIL;
  703. ptarkey->Parent = Parent;
  704. ptarkey->Flags = (psrckey->u.KeyNode.Flags & KEY_COMP_NAME);
  705. if (Parent == HCELL_NIL) {
  706. ptarkey->Flags |= KEY_HIVE_ENTRY + KEY_NO_DELETE;
  707. }
  708. //
  709. // Allocate and copy security
  710. //
  711. // Use the hash Luke !!!
  712. //
  713. if( CmpFindSecurityCellCacheIndex ((PCMHIVE)SourceHive,security,&Index) == FALSE ) {
  714. goto DoFinally;
  715. }
  716. SrcSecurityDescriptor = &(((PCMHIVE)SourceHive)->SecurityCache[Index].CachedSecurity->Descriptor);
  717. status = CmpAssignSecurityDescriptor(TargetHive,
  718. newkey,
  719. ptarkey,
  720. SrcSecurityDescriptor);
  721. if (!NT_SUCCESS(status)) {
  722. goto DoFinally;
  723. }
  724. //
  725. // Set up the value list
  726. //
  727. count = psrckey->u.KeyNode.ValueList.Count;
  728. //
  729. // initialize an Empty ValueList
  730. //
  731. ptarkey->ValueList.List = HCELL_NIL;
  732. ptarkey->ValueList.Count = 0;
  733. if ((count == 0) || (CopyValues == FALSE)) {
  734. success = TRUE;
  735. } else {
  736. psrclist = HvGetCell(SourceHive, psrckey->u.KeyNode.ValueList.List);
  737. if( psrclist == NULL ) {
  738. //
  739. // we couldn't map the bin containing this cell
  740. //
  741. goto DoFinally;
  742. }
  743. //
  744. // Copy the values
  745. //
  746. for (i = 0; i < count; i++) {
  747. newvalue = CmpCopyValue(
  748. SourceHive,
  749. psrclist->u.KeyList[i],
  750. TargetHive,
  751. Type
  752. );
  753. if (newvalue == HCELL_NIL) {
  754. //
  755. // for cleanup purposes
  756. //
  757. newlist = ptarkey->ValueList.List;
  758. goto DoFinally;
  759. }
  760. pvalue = (PCM_KEY_VALUE)HvGetCell(TargetHive, newvalue);
  761. if( pvalue == NULL ) {
  762. //
  763. // we couldn't map the bin containing this cell
  764. // this shouldn't happen as we just allocated the cell
  765. // (i.e. the bin containing it should be PINNED into memory by now )
  766. //
  767. ASSERT( FALSE );
  768. //
  769. // for cleanup purposes
  770. //
  771. newlist = ptarkey->ValueList.List;
  772. goto DoFinally;
  773. }
  774. //
  775. // this cell was just allocated so it should be pinned; it's OK to release it here
  776. // as the view is not going anywhere
  777. //
  778. ASSERT_CELL_DIRTY(TargetHive, newvalue);
  779. HvReleaseCell(TargetHive, newvalue);
  780. #if DBG
  781. //
  782. // get the name
  783. //
  784. CmpInitializeValueNameString(pvalue,&ValueName,NameBuffer);
  785. //
  786. // find out the index where we should insert this
  787. // this is a special treatment for the case when we copy form and old hive (not sorted)
  788. // into a new format one (sorted)
  789. //
  790. if( CmpFindNameInList(TargetHive,&(ptarkey->ValueList),&ValueName,&Index,&child) == FALSE ) {
  791. //
  792. // we couldn't map a view inside the above call
  793. //
  794. //
  795. // for cleanup purposes
  796. //
  797. newlist = ptarkey->ValueList.List;
  798. goto DoFinally;
  799. }
  800. //
  801. // the value is not present in the list; we're about to add it!
  802. //
  803. ASSERT( child == HCELL_NIL );
  804. //
  805. // sanity validation : insert at the end
  806. //
  807. ASSERT( Index == i );
  808. #endif //DBG
  809. if( !NT_SUCCESS( CmpAddValueToList(TargetHive,newvalue,i,Type,&(ptarkey->ValueList)) ) ) {
  810. //
  811. // for cleanup purposes
  812. //
  813. newlist = ptarkey->ValueList.List;
  814. if( newlist != HCELL_NIL ) {
  815. ASSERT( i > 0 );
  816. //
  817. // free already copied values
  818. //
  819. ptarlist = HvGetCell(TargetHive, newlist);
  820. if( ptarlist == NULL ) {
  821. //
  822. // we couldn't map the bin containing this cell
  823. // this shouldn't fail as we just allocated this cell
  824. // (i.e. the bin should be PINNED into memory at this point)
  825. //
  826. ASSERT( FALSE );
  827. goto DoFinally;
  828. }
  829. //
  830. // this cell was just allocated so it should be pinned; it's OK to release it here
  831. // as the view is not going anywhere
  832. //
  833. ASSERT_CELL_DIRTY(TargetHive, newlist);
  834. HvReleaseCell(TargetHive, newlist);
  835. for (; i > 0; i--) {
  836. HvFreeCell(
  837. TargetHive,
  838. ptarlist->u.KeyList[i - 1]
  839. );
  840. }
  841. } else {
  842. ASSERT( i == 0 );
  843. }
  844. goto DoFinally;
  845. }
  846. }
  847. success = TRUE;
  848. }
  849. DoFinally:
  850. #if DBG
  851. ASSERT( NameBuffer != NULL );
  852. ExFreePool(NameBuffer);
  853. #endif //DBG
  854. if( psrclist != NULL ) {
  855. ASSERT(psrckey!= NULL );
  856. HvReleaseCell(SourceHive, psrckey->u.KeyNode.ValueList.List);
  857. }
  858. if( psrckey != NULL ) {
  859. HvReleaseCell(SourceHive, SourceKeyCell);
  860. }
  861. if( ptarkey != NULL ) {
  862. ASSERT( newkey != HCELL_NIL );
  863. HvReleaseCell(TargetHive, newkey);
  864. }
  865. if (success == FALSE) {
  866. if (newlist != HCELL_NIL) {
  867. HvFreeCell(TargetHive, newlist);
  868. }
  869. if (newsecurity != HCELL_NIL) {
  870. HvFreeCell(TargetHive, newsecurity);
  871. }
  872. if (newclass != HCELL_NIL) {
  873. HvFreeCell(TargetHive, newclass);
  874. }
  875. if (newkey != HCELL_NIL) {
  876. HvFreeCell(TargetHive, newkey);
  877. }
  878. return HCELL_NIL;
  879. } else {
  880. return newkey;
  881. }
  882. }
  883. HCELL_INDEX
  884. CmpCopyValue(
  885. PHHIVE SourceHive,
  886. HCELL_INDEX SourceValueCell,
  887. PHHIVE TargetHive,
  888. HSTORAGE_TYPE Type
  889. )
  890. /*++
  891. Routine Description:
  892. Copy a value entry. Copies the body of a value entry and the
  893. data. Returns cell of new value entry.
  894. Arguments:
  895. SourceHive - pointer to hive control structure for source
  896. SourceValueCell - value entry being copied
  897. TargetHive - pointer to hive control structure for target
  898. Type - storage type to allocate for target (stable or volatile)
  899. Return Value:
  900. HCELL_INDEX - Cell of body of new value entry, or HCELL_NIL
  901. if some error.
  902. --*/
  903. {
  904. HCELL_INDEX newvalue;
  905. HCELL_INDEX newdata;
  906. PCELL_DATA pvalue;
  907. ULONG datalength;
  908. HCELL_INDEX olddata;
  909. ULONG tempdata;
  910. BOOLEAN small;
  911. HCELL_INDEX CellToRelease = HCELL_NIL;
  912. CmKdPrintEx((DPFLTR_CONFIG_ID,CML_SAVRES,"CmpCopyValue:\n"));
  913. CmKdPrintEx((DPFLTR_CONFIG_ID,CML_SAVRES,"\tSHive=%p SCell=%08lx\n",SourceHive,SourceValueCell));
  914. CmKdPrintEx((DPFLTR_CONFIG_ID,CML_SAVRES,"\tTargetHive=%p\n",TargetHive));
  915. ASSERT( TargetHive->ReleaseCellRoutine == NULL );
  916. //
  917. // get source data
  918. //
  919. pvalue = HvGetCell(SourceHive, SourceValueCell);
  920. if( pvalue == NULL ) {
  921. //
  922. // we couldn't map the bin containing this cell
  923. //
  924. return HCELL_NIL;
  925. }
  926. small = CmpIsHKeyValueSmall(datalength, pvalue->u.KeyValue.DataLength);
  927. olddata = pvalue->u.KeyValue.Data;
  928. //
  929. // Copy body
  930. //
  931. newvalue = CmpCopyCell(SourceHive, SourceValueCell, TargetHive, Type);
  932. if (newvalue == HCELL_NIL) {
  933. HvReleaseCell(SourceHive, SourceValueCell);
  934. return HCELL_NIL;
  935. }
  936. //
  937. // Copy data (if any)
  938. //
  939. if (datalength > 0) {
  940. if (datalength > CM_KEY_VALUE_SMALL) {
  941. if( (CmpIsHKeyValueBig(SourceHive,datalength) == TRUE) ||
  942. (CmpIsHKeyValueBig(TargetHive,datalength) == TRUE)
  943. ) {
  944. PCELL_DATA Buffer;
  945. BOOLEAN BufferAllocated;
  946. HCELL_INDEX CellToRelease2 = HCELL_NIL;
  947. //
  948. // get the data from source, regardless of the size
  949. //
  950. if( CmpGetValueData(SourceHive,&(pvalue->u.KeyValue),&datalength,&Buffer,&BufferAllocated,&CellToRelease2) == FALSE ) {
  951. //
  952. // insufficient resources; return NULL
  953. //
  954. ASSERT( BufferAllocated == FALSE );
  955. ASSERT( Buffer == NULL );
  956. HvFreeCell(TargetHive, newvalue);
  957. HvReleaseCell(SourceHive, SourceValueCell);
  958. return HCELL_NIL;
  959. }
  960. //
  961. // we ignore celltorelease because we have specifically set the releae routine to NULL
  962. //
  963. //
  964. // allocate a new value data in the target hive (regardless of the size)
  965. // and copy the data onto it.
  966. //
  967. if( !NT_SUCCESS(CmpSetValueDataNew(TargetHive,Buffer,datalength,Type,newvalue,&newdata)) ) {
  968. //
  969. // We have bombed out loading user data, clean up and exit.
  970. //
  971. if( BufferAllocated == TRUE ) {
  972. ExFreePool( Buffer );
  973. }
  974. HvFreeCell(TargetHive, newvalue);
  975. HvReleaseCell(SourceHive, SourceValueCell);
  976. if( CellToRelease2 != HCELL_NIL ) {
  977. HvReleaseCell(SourceHive, CellToRelease2);
  978. }
  979. return HCELL_NIL;
  980. }
  981. //
  982. // free the source buffer
  983. //
  984. if( BufferAllocated == TRUE ) {
  985. ExFreePool( Buffer );
  986. }
  987. if( CellToRelease2 != HCELL_NIL ) {
  988. HvReleaseCell(SourceHive, CellToRelease2);
  989. }
  990. } else {
  991. //
  992. // there's data, normal size, or none of the hives support
  993. // bigdata cells, so do standard copy
  994. //
  995. newdata = CmpCopyCell(SourceHive, olddata, TargetHive, Type);
  996. }
  997. if (newdata == HCELL_NIL) {
  998. HvFreeCell(TargetHive, newvalue);
  999. HvReleaseCell(SourceHive, SourceValueCell);
  1000. return HCELL_NIL;
  1001. }
  1002. pvalue = HvGetCell(TargetHive, newvalue);
  1003. if( pvalue == NULL ) {
  1004. //
  1005. // we couldn't map the bin containing this cell
  1006. // this shouldn't happen as we just allocated the cell
  1007. // (i.e. it should be PINNED into memory at this point)
  1008. //
  1009. ASSERT( FALSE );
  1010. HvFreeCell(TargetHive, newvalue);
  1011. HvReleaseCell(SourceHive, SourceValueCell);
  1012. CmpFreeValueData(TargetHive,newdata,datalength);
  1013. return HCELL_NIL;
  1014. }
  1015. pvalue->u.KeyValue.Data = newdata;
  1016. pvalue->u.KeyValue.DataLength = datalength;
  1017. } else {
  1018. //
  1019. // the data is small, but may be stored in either large or
  1020. // small format for historical reasons
  1021. //
  1022. if (small) {
  1023. //
  1024. // data is already small, so just do a body to body copy
  1025. //
  1026. tempdata = pvalue->u.KeyValue.Data;
  1027. } else {
  1028. //
  1029. // data is stored externally in old cell, will be internal in new
  1030. //
  1031. CellToRelease = pvalue->u.KeyValue.Data;
  1032. pvalue = HvGetCell(SourceHive, pvalue->u.KeyValue.Data);
  1033. if( pvalue == NULL ) {
  1034. //
  1035. // we couldn't map the bin containing this cell
  1036. //
  1037. HvFreeCell(TargetHive, newvalue);
  1038. HvReleaseCell(SourceHive, SourceValueCell);
  1039. return HCELL_NIL;
  1040. }
  1041. tempdata = *((PULONG)pvalue);
  1042. }
  1043. pvalue = HvGetCell(TargetHive, newvalue);
  1044. if( pvalue == NULL ) {
  1045. //
  1046. // we couldn't map the bin containing this cell
  1047. // this shouldn't happen as we just allocated the cell
  1048. // (i.e. it should be PINNED into memory at this point)
  1049. //
  1050. ASSERT( FALSE );
  1051. HvFreeCell(TargetHive, newvalue);
  1052. HvReleaseCell(SourceHive, SourceValueCell);
  1053. if( CellToRelease != HCELL_NIL ) {
  1054. HvReleaseCell(SourceHive, CellToRelease);
  1055. }
  1056. return HCELL_NIL;
  1057. }
  1058. pvalue->u.KeyValue.Data = tempdata;
  1059. pvalue->u.KeyValue.DataLength =
  1060. datalength + CM_KEY_VALUE_SPECIAL_SIZE;
  1061. if( CellToRelease != HCELL_NIL ) {
  1062. HvReleaseCell(SourceHive, CellToRelease);
  1063. }
  1064. }
  1065. }
  1066. HvReleaseCell(SourceHive, SourceValueCell);
  1067. return newvalue;
  1068. }
  1069. HCELL_INDEX
  1070. CmpCopyCell(
  1071. PHHIVE SourceHive,
  1072. HCELL_INDEX SourceCell,
  1073. PHHIVE TargetHive,
  1074. HSTORAGE_TYPE Type
  1075. )
  1076. /*++
  1077. Routine Description:
  1078. Copy SourceHive.SourceCell to TargetHive.TargetCell.
  1079. Arguments:
  1080. SourceHive - pointer to hive control structure for source
  1081. SourceCell - index of cell to copy from
  1082. TargetHive - pointer to hive control structure for target
  1083. Type - storage type (stable or volatile) of new cell
  1084. Return Value:
  1085. HCELL_INDEX of new cell, or HCELL_NIL if failure.
  1086. --*/
  1087. {
  1088. PVOID psource;
  1089. PVOID ptarget;
  1090. ULONG size;
  1091. HCELL_INDEX newcell;
  1092. CmKdPrintEx((DPFLTR_CONFIG_ID,CML_SAVRES,"CmpCopyCell:\n"));
  1093. CmKdPrintEx((DPFLTR_CONFIG_ID,CML_SAVRES,"\tSourceHive=%p SourceCell=%08lx\n",SourceHive,SourceCell));
  1094. CmKdPrintEx((DPFLTR_CONFIG_ID,CML_SAVRES,"\tTargetHive=%p\n",TargetHive));
  1095. psource = HvGetCell(SourceHive, SourceCell);
  1096. if( psource == NULL ) {
  1097. //
  1098. // we couldn't map the bin containing this cell
  1099. //
  1100. return HCELL_NIL;
  1101. }
  1102. size = HvGetCellSize(SourceHive, psource);
  1103. newcell = HvAllocateCell(TargetHive, size, Type,HCELL_NIL);
  1104. if (newcell == HCELL_NIL) {
  1105. HvReleaseCell(SourceHive, SourceCell);
  1106. return HCELL_NIL;
  1107. }
  1108. ptarget = HvGetCell(TargetHive, newcell);
  1109. if( ptarget == NULL ) {
  1110. //
  1111. // we couldn't map the bin containing this cell
  1112. // this shouldn't happen as we just allocated the cell
  1113. // (i.e. it should be PINNED into memory at this point)
  1114. //
  1115. ASSERT( FALSE );
  1116. HvFreeCell(TargetHive, newcell);
  1117. HvReleaseCell(SourceHive, SourceCell);
  1118. return HCELL_NIL;
  1119. }
  1120. RtlCopyMemory(ptarget, psource, size);
  1121. HvReleaseCell(SourceHive, SourceCell);
  1122. HvReleaseCell(TargetHive, newcell);
  1123. return newcell;
  1124. }
  1125. BOOLEAN
  1126. CmpFreeKeyValues(
  1127. PHHIVE Hive,
  1128. HCELL_INDEX Cell,
  1129. PCM_KEY_NODE Node
  1130. )
  1131. /*++
  1132. Routine Description:
  1133. Free the cells associated with the value entries, the security descriptor,
  1134. and the class of a particular key.
  1135. Arguments:
  1136. Hive - The hive of the key in question
  1137. Cell - The cell of the key in question
  1138. Node - The key body of the key in question
  1139. Return Value:
  1140. TRUE if successful, FALSE otherwise.
  1141. --*/
  1142. {
  1143. PCELL_DATA plist;
  1144. ULONG i;
  1145. ASSERT( Hive->ReleaseCellRoutine == NULL );
  1146. //
  1147. // Mark all the value-related cells dirty
  1148. //
  1149. if (! CmpMarkKeyValuesDirty(Hive, Cell, Node)) {
  1150. return FALSE;
  1151. }
  1152. //
  1153. // Link nodes don't have things that we need to free
  1154. //
  1155. if (!(Node->Flags & KEY_HIVE_EXIT)) {
  1156. //
  1157. // First, free the value entries
  1158. //
  1159. if (Node->ValueList.Count > 0) {
  1160. // Get value list
  1161. plist = HvGetCell(Hive, Node->ValueList.List);
  1162. if( plist == NULL ) {
  1163. //
  1164. // we couldn't map the bin containing this cell
  1165. // this shouldn't happen as we just marked the cell dirty
  1166. // (i.e. it should be PINNED into memory at this point)
  1167. //
  1168. ASSERT( FALSE );
  1169. return FALSE;
  1170. }
  1171. // Free each value
  1172. for (i = 0; i < Node->ValueList.Count; i++) {
  1173. if( CmpFreeValue(Hive, plist->u.KeyList[i]) == FALSE ) {
  1174. //
  1175. // we couldn't map view inside call above
  1176. // this shouldn't happen as we just marked the values dirty
  1177. // (i.e. they should be PINNED into memory at this point)
  1178. //
  1179. ASSERT( FALSE );
  1180. return FALSE;
  1181. }
  1182. }
  1183. // Free the value list
  1184. HvFreeCell(Hive, Node->ValueList.List);
  1185. }
  1186. //
  1187. // Make this key value-less
  1188. //
  1189. Node->ValueList.List = HCELL_NIL;
  1190. Node->ValueList.Count = 0;
  1191. //
  1192. // Free the security descriptor
  1193. //
  1194. // we need to postpone that until we are sure we got the new one
  1195. //CmpFreeSecurityDescriptor(Hive, Cell);
  1196. //
  1197. // Free the Class information
  1198. //
  1199. if (Node->ClassLength > 0) {
  1200. HvFreeCell(Hive, Node->Class);
  1201. Node->Class = HCELL_NIL;
  1202. Node->ClassLength = 0;
  1203. }
  1204. }
  1205. return TRUE;
  1206. }
  1207. BOOLEAN
  1208. CmpMergeKeyValues(
  1209. PHHIVE SourceHive,
  1210. HCELL_INDEX SourceKeyCell,
  1211. PCM_KEY_NODE SourceKeyNode,
  1212. PHHIVE TargetHive,
  1213. HCELL_INDEX TargetKeyCell,
  1214. PCM_KEY_NODE TargetKeyNode
  1215. )
  1216. /*++
  1217. Routine Description:
  1218. Merges the values from the two key-nodes provided.
  1219. Rules for the merge:
  1220. 1. The target values are not touched!
  1221. 2. Only values from the source that are not present in the
  1222. target are taken into account by this routine. They are added
  1223. to the target node value list "as they are".
  1224. Arguments:
  1225. SourceHive - Hive of the source key
  1226. SourceKeyCell - The source key's cell
  1227. SourceKeyNode - The source key's body
  1228. TargetHive - Hive of the target key
  1229. TargetKeyCell - The target key's cell
  1230. TargetKeyNode - The target key's body
  1231. Return Value:
  1232. TRUE of successful, FALSE otherwise.
  1233. --*/
  1234. {
  1235. NTSTATUS status;
  1236. BOOLEAN success = FALSE;
  1237. PCELL_DATA psrclist;
  1238. HCELL_INDEX newvalue, newlist = HCELL_NIL,child;
  1239. ULONG i, count, Type, ChildIndex;
  1240. PCM_KEY_VALUE poldvalue;
  1241. WCHAR *NameBuffer = NULL;
  1242. UNICODE_STRING ValueName;
  1243. ASSERT_CM_LOCK_OWNED_EXCLUSIVE();
  1244. ASSERT( SourceHive->ReleaseCellRoutine == NULL );
  1245. ASSERT( TargetHive->ReleaseCellRoutine == NULL );
  1246. if(TargetKeyNode->MaxValueNameLen < SourceKeyNode->MaxValueNameLen) {
  1247. TargetKeyNode->MaxValueNameLen = SourceKeyNode->MaxValueNameLen;
  1248. }
  1249. if(TargetKeyNode->MaxValueDataLen < SourceKeyNode->MaxValueDataLen) {
  1250. TargetKeyNode->MaxValueDataLen = SourceKeyNode->MaxValueDataLen;
  1251. }
  1252. if(TargetKeyNode->ValueList.Count == 0) {
  1253. //
  1254. // No Values in Target, do a sync
  1255. //
  1256. return CmpSyncKeyValues(SourceHive, SourceKeyCell, SourceKeyNode, TargetHive, TargetKeyCell, TargetKeyNode);
  1257. }
  1258. //
  1259. // Set up the value list
  1260. //
  1261. count = SourceKeyNode->ValueList.Count;
  1262. if (count == 0) {
  1263. // No values in source, no update to the list needed.
  1264. success = TRUE;
  1265. } else {
  1266. NameBuffer = ExAllocatePool(PagedPool, REG_MAX_KEY_VALUE_NAME_LENGTH);
  1267. if(!NameBuffer) return FALSE;
  1268. //
  1269. // The type of the new cells will be the same as that
  1270. // of the target cell.
  1271. //
  1272. Type = HvGetCellType(TargetKeyCell);
  1273. //
  1274. // Reallocate the value list for target to fit the new size
  1275. // Worst case: all values from the source node will be added
  1276. // to the target node
  1277. //
  1278. psrclist = HvGetCell(SourceHive, SourceKeyNode->ValueList.List);
  1279. if( psrclist == NULL ) {
  1280. //
  1281. // we couldn't map the bin containing this cell
  1282. //
  1283. newlist = HCELL_NIL;
  1284. goto EndValueMerge;
  1285. }
  1286. //
  1287. // Copy the values
  1288. //
  1289. for (i = 0; i < count; i++) {
  1290. poldvalue = (PCM_KEY_VALUE)HvGetCell(SourceHive, psrclist->u.KeyList[i]);
  1291. if( poldvalue == NULL ) {
  1292. //
  1293. // we couldn't map the bin containing this cell
  1294. //
  1295. //
  1296. // for cleanup purposes
  1297. //
  1298. newlist = TargetKeyNode->ValueList.List;
  1299. goto EndValueMerge;
  1300. }
  1301. //
  1302. // get the name
  1303. //
  1304. CmpInitializeValueNameString(poldvalue,&ValueName,NameBuffer);
  1305. //
  1306. // check if this particular values doesn't exist in the target node already
  1307. //
  1308. if( CmpFindNameInList(TargetHive,&(TargetKeyNode->ValueList),&ValueName,&ChildIndex,&child) == FALSE ) {
  1309. //
  1310. // we couldn't map a view inside the above call
  1311. //
  1312. //
  1313. // for cleanup purposes
  1314. //
  1315. newlist = TargetKeyNode->ValueList.List;
  1316. goto EndValueMerge;
  1317. }
  1318. if( child == HCELL_NIL ) {
  1319. //
  1320. // sanity validation : insert at the end
  1321. //
  1322. ASSERT( ChildIndex == TargetKeyNode->ValueList.Count );
  1323. //
  1324. // No, it doesn't, so add it
  1325. //
  1326. newvalue = CmpCopyValue(
  1327. SourceHive,
  1328. psrclist->u.KeyList[i],
  1329. TargetHive,
  1330. Type
  1331. );
  1332. if (newvalue == HCELL_NIL) {
  1333. //
  1334. // for cleanup purposes
  1335. //
  1336. newlist = TargetKeyNode->ValueList.List;
  1337. goto EndValueMerge;
  1338. }
  1339. if( !NT_SUCCESS( CmpAddValueToList(TargetHive,newvalue,ChildIndex,Type,&(TargetKeyNode->ValueList)) ) ) {
  1340. //
  1341. // for cleanup purposes
  1342. //
  1343. newlist = TargetKeyNode->ValueList.List;
  1344. goto EndValueMerge;
  1345. }
  1346. }
  1347. }
  1348. success = TRUE;
  1349. }
  1350. EndValueMerge:
  1351. if (NameBuffer) ExFreePool(NameBuffer);
  1352. if (success == FALSE) {
  1353. // Clean-up on failure
  1354. // Revert to the original size
  1355. //
  1356. // unfortunatelly we cannot do that anymore as we have sorted the list
  1357. //
  1358. }
  1359. return success;
  1360. }
  1361. BOOLEAN
  1362. CmpSyncKeyValues(
  1363. PHHIVE SourceHive,
  1364. HCELL_INDEX SourceKeyCell,
  1365. PCM_KEY_NODE SourceKeyNode,
  1366. PHHIVE TargetHive,
  1367. HCELL_INDEX TargetKeyCell,
  1368. PCM_KEY_NODE TargetKeyNode
  1369. )
  1370. /*++
  1371. Routine Description:
  1372. Synchronizes the value entries, security descriptor, and class of a
  1373. target key with that of a source key - ensuring that the keys are
  1374. identical with respect to the synchronized information.
  1375. Arguments:
  1376. SourceHive - Hive of the source key
  1377. SourceKeyCell - The source key's cell
  1378. SourceKeyNode - The source key's body
  1379. TargetHive - Hive of the target key
  1380. TargetKeyCell - The target key's cell
  1381. TargetKeyNode - The target key's body
  1382. Return Value:
  1383. TRUE of successful, FALSE otherwise.
  1384. --*/
  1385. {
  1386. NTSTATUS status;
  1387. BOOLEAN success = FALSE;
  1388. PCELL_DATA psrclist = NULL, ptarlist, psrcsecurity;
  1389. HCELL_INDEX newvalue, newlist = HCELL_NIL, newclass = HCELL_NIL;
  1390. ULONG i, count, Type, Index;
  1391. PCM_KEY_VALUE pvalue;
  1392. #if DBG
  1393. WCHAR *NameBuffer = NULL;
  1394. UNICODE_STRING ValueName;
  1395. HCELL_INDEX child;
  1396. #endif //DBG
  1397. PSECURITY_DESCRIPTOR SrcSecurityDescriptor;
  1398. HCELL_INDEX OldSecurity,NewSecurity;
  1399. //
  1400. // nobody is operating on the target hive
  1401. //
  1402. ASSERT( TargetHive->ReleaseCellRoutine == NULL );
  1403. //
  1404. // First, free the target key's values, sd, and class info.
  1405. //
  1406. if(!CmpFreeKeyValues(TargetHive, TargetKeyCell, TargetKeyNode))
  1407. return FALSE;
  1408. #if DBG
  1409. NameBuffer = ExAllocatePool(PagedPool, REG_MAX_KEY_VALUE_NAME_LENGTH);
  1410. if(!NameBuffer) {
  1411. return FALSE;
  1412. }
  1413. #endif //DBG
  1414. //
  1415. // Now, copy the values, class, & sd from the source cell
  1416. //
  1417. //
  1418. // The type of the new cells will be the same as that
  1419. // of the target cell.
  1420. //
  1421. Type = HvGetCellType(TargetKeyCell);
  1422. //
  1423. // Allocate and copy class
  1424. //
  1425. if ((SourceKeyNode->ClassLength > 0) && (SourceKeyNode->Class != HCELL_NIL)) {
  1426. newclass = CmpCopyCell(SourceHive, SourceKeyNode->Class, TargetHive, Type);
  1427. if (newclass == HCELL_NIL) {
  1428. goto EndValueSync;
  1429. }
  1430. // only if class is valid. Otherwise remains 0 (set by CmpFreeKeyValues)
  1431. TargetKeyNode->ClassLength = SourceKeyNode->ClassLength;
  1432. }
  1433. //
  1434. // Associate the new class with the target key
  1435. // and prepare and security descriptor assignment.
  1436. //
  1437. TargetKeyNode->Class = newclass;
  1438. //
  1439. // Allocate and assign security
  1440. //
  1441. //
  1442. // Use the hash Luke !!!
  1443. //
  1444. if( CmpFindSecurityCellCacheIndex ((PCMHIVE)SourceHive,SourceKeyNode->Security,&Index) == FALSE ) {
  1445. goto EndValueSync;
  1446. }
  1447. SrcSecurityDescriptor = &(((PCMHIVE)SourceHive)->SecurityCache[Index].CachedSecurity->Descriptor);
  1448. //
  1449. // store it for later in case of error recovery
  1450. //
  1451. OldSecurity = TargetKeyNode->Security;
  1452. TargetKeyNode->Security = HCELL_NIL;
  1453. status = CmpAssignSecurityDescriptor(TargetHive,
  1454. TargetKeyCell,
  1455. TargetKeyNode,
  1456. SrcSecurityDescriptor);
  1457. if (!NT_SUCCESS(status)) {
  1458. TargetKeyNode->Security = OldSecurity;
  1459. goto EndValueSync;
  1460. }
  1461. NewSecurity = TargetKeyNode->Security;
  1462. TargetKeyNode->Security = OldSecurity;
  1463. if ((TargetKeyNode->Flags & KEY_HIVE_ENTRY) && ( NewSecurity != OldSecurity) ) {
  1464. //
  1465. // we need to play it safe here so we don't blow away the security list for entire hive.
  1466. //
  1467. PCM_KEY_SECURITY NewSec;
  1468. PCM_KEY_SECURITY OldSec;
  1469. PCM_KEY_SECURITY LastSec;
  1470. HCELL_INDEX LastSecCell;
  1471. NewSec = (PCM_KEY_SECURITY)HvGetCell(TargetHive,NewSecurity);
  1472. if( NewSec == NULL ) {
  1473. //
  1474. // could not map view
  1475. //
  1476. goto EndValueSync;
  1477. }
  1478. OldSec = (PCM_KEY_SECURITY)HvGetCell(TargetHive,OldSecurity);
  1479. if( OldSec == NULL ) {
  1480. //
  1481. // could not map view
  1482. //
  1483. HvReleaseCell(TargetHive,NewSecurity);
  1484. goto EndValueSync;
  1485. }
  1486. LastSecCell = OldSec->Blink;
  1487. LastSec = (PCM_KEY_SECURITY)HvGetCell(TargetHive,LastSecCell);
  1488. if( LastSec == NULL ) {
  1489. //
  1490. // could not map view
  1491. //
  1492. HvReleaseCell(TargetHive,OldSecurity);
  1493. HvReleaseCell(TargetHive,NewSecurity);
  1494. goto EndValueSync;
  1495. }
  1496. if( !HvMarkCellDirty(TargetHive,OldSecurity) ||
  1497. !HvMarkCellDirty(TargetHive,LastSecCell) ) {
  1498. //
  1499. // no log space
  1500. //
  1501. HvReleaseCell(TargetHive,LastSecCell);
  1502. HvReleaseCell(TargetHive,OldSecurity);
  1503. HvReleaseCell(TargetHive,NewSecurity);
  1504. goto EndValueSync;
  1505. }
  1506. //
  1507. // link old list to new security
  1508. //
  1509. NewSec->Flink = OldSecurity;
  1510. NewSec->Blink = LastSecCell;
  1511. OldSec->Blink = NewSecurity;
  1512. LastSec->Flink = NewSecurity;
  1513. HvReleaseCell(TargetHive,LastSecCell);
  1514. HvReleaseCell(TargetHive,OldSecurity);
  1515. HvReleaseCell(TargetHive,NewSecurity);
  1516. }
  1517. //
  1518. // we need to play it safe here, to make sure we never end up having a key
  1519. // with a NIL security cell
  1520. //
  1521. CmpFreeSecurityDescriptor(TargetHive, TargetKeyCell);
  1522. TargetKeyNode->Security = NewSecurity;
  1523. //
  1524. // Set up the value list
  1525. //
  1526. count = SourceKeyNode->ValueList.Count;
  1527. //
  1528. // target ValueList is an emptylist; we shall add values to it.
  1529. //
  1530. TargetKeyNode->ValueList.List = HCELL_NIL;
  1531. TargetKeyNode->ValueList.Count = 0;
  1532. //
  1533. // after sync we'll have the values from source
  1534. //
  1535. TargetKeyNode->MaxValueNameLen = SourceKeyNode->MaxValueNameLen;
  1536. TargetKeyNode->MaxValueDataLen = SourceKeyNode->MaxValueDataLen;
  1537. if (count == 0) {
  1538. // No values in source, no list needed.
  1539. success = TRUE;
  1540. } else {
  1541. //
  1542. // Do not allocate space for ValueList; CmpAddValueToList will do it
  1543. //
  1544. psrclist = HvGetCell(SourceHive, SourceKeyNode->ValueList.List);
  1545. if( psrclist == NULL ) {
  1546. //
  1547. // we couldn't map the bin containing this cell
  1548. //
  1549. goto EndValueSync;
  1550. }
  1551. //
  1552. // Copy the values
  1553. //
  1554. for (i = 0; i < count; i++) {
  1555. newvalue = CmpCopyValue(
  1556. SourceHive,
  1557. psrclist->u.KeyList[i],
  1558. TargetHive,
  1559. Type
  1560. );
  1561. if (newvalue == HCELL_NIL) {
  1562. //
  1563. // for cleanup purposes
  1564. //
  1565. newlist = TargetKeyNode->ValueList.List;
  1566. goto EndValueSync;
  1567. }
  1568. pvalue = (PCM_KEY_VALUE)HvGetCell(TargetHive, newvalue);
  1569. if( pvalue == NULL ) {
  1570. //
  1571. // we couldn't map the bin containing this cell
  1572. // this shouldn't happen as we just allocated the cell
  1573. // (i.e. the bin containing it should be PINNED into memory by now )
  1574. //
  1575. ASSERT( FALSE );
  1576. //
  1577. // for cleanup purposes
  1578. //
  1579. newlist = TargetKeyNode->ValueList.List;
  1580. goto EndValueSync;
  1581. }
  1582. #if DBG
  1583. //
  1584. // get the name
  1585. //
  1586. CmpInitializeValueNameString(pvalue,&ValueName,NameBuffer);
  1587. //
  1588. // find out the index where we should insert this
  1589. // this is a special treatment for the case when we copy form and old hive (not sorted)
  1590. // into a new format one (sorted)
  1591. //
  1592. if( CmpFindNameInList(TargetHive,&(TargetKeyNode->ValueList),&ValueName,&Index,&child) == FALSE ) {
  1593. //
  1594. // we couldn't map a view inside the above call
  1595. //
  1596. //
  1597. // for cleanup purposes
  1598. //
  1599. newlist = TargetKeyNode->ValueList.List;
  1600. goto EndValueSync;
  1601. }
  1602. //
  1603. // the value is not present in the list; we're about to add it!
  1604. //
  1605. ASSERT( child == HCELL_NIL );
  1606. //
  1607. // sanity validation : insert at the end
  1608. //
  1609. ASSERT( Index == i );
  1610. #endif //DBG
  1611. if( !NT_SUCCESS( CmpAddValueToList(TargetHive,newvalue,i,Type,&(TargetKeyNode->ValueList)) ) ) {
  1612. //
  1613. // for cleanup purposes
  1614. //
  1615. newlist = TargetKeyNode->ValueList.List;
  1616. if( newlist != HCELL_NIL ) {
  1617. //
  1618. // Delete all the copied values on an error.
  1619. //
  1620. ptarlist = HvGetCell(TargetHive, newlist);
  1621. if( ptarlist == NULL ) {
  1622. //
  1623. // we couldn't map the bin containing this cell
  1624. // this shouldn't fail as we just allocated this cell
  1625. // (i.e. the bin should be PINNED into memory at this point)
  1626. //
  1627. ASSERT( FALSE );
  1628. goto EndValueSync;
  1629. }
  1630. for (; i > 0; i--) {
  1631. HvFreeCell(
  1632. TargetHive,
  1633. ptarlist->u.KeyList[i - 1]
  1634. );
  1635. }
  1636. }
  1637. goto EndValueSync;
  1638. }
  1639. }
  1640. success = TRUE;
  1641. }
  1642. EndValueSync:
  1643. #if DBG
  1644. ASSERT( NameBuffer != NULL );
  1645. ExFreePool(NameBuffer);
  1646. #endif //DBG
  1647. if( psrclist != NULL ) {
  1648. HvReleaseCell(SourceHive, SourceKeyNode->ValueList.List);
  1649. }
  1650. if (success == FALSE) {
  1651. // Clean-up on failure
  1652. if (newlist != HCELL_NIL) {
  1653. HvFreeCell(TargetHive, newlist);
  1654. }
  1655. if (newclass != HCELL_NIL) {
  1656. HvFreeCell(TargetHive, newclass);
  1657. }
  1658. }
  1659. return success;
  1660. }
  1661. VOID
  1662. CmpInitializeKeyNameString(PCM_KEY_NODE Cell,
  1663. PUNICODE_STRING KeyName,
  1664. WCHAR *NameBuffer
  1665. )
  1666. /*++
  1667. Routine Description:
  1668. Initializes a UNICODE_STRING with the name of a given key.
  1669. N.B. The initialized string's buffer is not meant
  1670. to be modified.
  1671. Arguments:
  1672. Cell - The body of the key in question
  1673. KeyName - The UNICODE_STRING to initialize
  1674. NameBuffer - A buffer REG_MAX_KEY_NAME_LENGTH bytes in size
  1675. that will possibly be used as the UNICODE_STRING's
  1676. buffer.
  1677. Return Value:
  1678. NONE.
  1679. --*/
  1680. {
  1681. // is the name stored in compressed form?
  1682. if(Cell->Flags & KEY_COMP_NAME) {
  1683. // Name is compressed.
  1684. // Get the uncompressed length.
  1685. KeyName->Length = CmpCompressedNameSize(Cell->Name,
  1686. Cell->NameLength);
  1687. // Decompress the name into a buffer.
  1688. CmpCopyCompressedName(NameBuffer,
  1689. REG_MAX_KEY_NAME_LENGTH,
  1690. Cell->Name,
  1691. Cell->NameLength);
  1692. //
  1693. // Use the decompression buffer as the string buffer
  1694. //
  1695. KeyName->Buffer = NameBuffer;
  1696. KeyName->MaximumLength = REG_MAX_KEY_NAME_LENGTH;
  1697. } else {
  1698. //
  1699. // Name is not compressed. Just use the name string
  1700. // from the key buffer as the string buffer.
  1701. //
  1702. KeyName->Length = Cell->NameLength;
  1703. KeyName->Buffer = Cell->Name;
  1704. KeyName->MaximumLength = (USHORT)Cell->MaxNameLen;
  1705. }
  1706. }
  1707. VOID
  1708. CmpInitializeValueNameString(PCM_KEY_VALUE Cell,
  1709. PUNICODE_STRING ValueName,
  1710. WCHAR *NameBuffer
  1711. )
  1712. /*
  1713. Routine Description:
  1714. Initializes a UNICODE_STRING with the name of a given value key.
  1715. N.B. The initialized string's buffer is not meant
  1716. to be modified.
  1717. Arguments:
  1718. Cell - The value key in question
  1719. ValueName - The UNICODE_STRING to initialize
  1720. NameBuffer - A buffer REG_MAX_KEY_NAME_LENGTH bytes in size
  1721. that will possibly be used as the UNICODE_STRING's
  1722. buffer.
  1723. Return Value:
  1724. NONE.
  1725. */
  1726. {
  1727. // is the name stored in compressed form?
  1728. if(Cell->Flags & VALUE_COMP_NAME) {
  1729. // Name is compressed.
  1730. // Get the uncompressed length.
  1731. ValueName->Length = CmpCompressedNameSize(Cell->Name,
  1732. Cell->NameLength);
  1733. // Decompress the name into a buffer.
  1734. CmpCopyCompressedName(NameBuffer,
  1735. REG_MAX_KEY_VALUE_NAME_LENGTH,
  1736. Cell->Name,
  1737. Cell->NameLength);
  1738. //
  1739. // Use the decompression buffer as the string buffer
  1740. //
  1741. ValueName->Buffer = NameBuffer;
  1742. ValueName->MaximumLength = REG_MAX_KEY_VALUE_NAME_LENGTH;
  1743. } else {
  1744. //
  1745. // Name is not compressed. Just use the name string
  1746. // from the ValueName buffer as the string buffer.
  1747. //
  1748. ValueName->Length = Cell->NameLength;
  1749. ValueName->Buffer = Cell->Name;
  1750. ValueName->MaximumLength = ValueName->Length;
  1751. }
  1752. }
  1753. BOOLEAN
  1754. CmpSyncSubKeysAfterDelete(PHHIVE SourceHive,
  1755. PCM_KEY_NODE SourceCell,
  1756. PHHIVE TargetHive,
  1757. PCM_KEY_NODE TargetCell,
  1758. WCHAR *NameBuffer)
  1759. /*++
  1760. Routine Description:
  1761. This routine makes sure that any subkeys present in the target key
  1762. but not present in the source key are deleted from the target key
  1763. along with any trees under those subkeys.
  1764. This routine is useful for synchronizing key deletion changes
  1765. in a source cell with a target cell. It is used in this way
  1766. from CmpCopySyncTree.
  1767. NOTE: It is assumed that no open handles are held for the keys
  1768. being deleted. If this is not so, registry in-memory
  1769. data structures may become corrupted.
  1770. Arguments:
  1771. SourceHive - The hive of the source key
  1772. SourceCell - The body of the source key
  1773. TargetHive - The hive of the target key
  1774. TargetCell - The body of the target key
  1775. NameBuffer - A buffer REG_MAX_KEY_NAME_LENGTH bytes in size
  1776. Return Value:
  1777. TRUE if successful, FALSE otherwise.
  1778. --*/
  1779. {
  1780. HCELL_INDEX TargetSubKey, SourceSubKey;
  1781. ULONG i = 0;
  1782. PCM_KEY_NODE SubKeyCell;
  1783. UNICODE_STRING SubKeyName;
  1784. //
  1785. // Run through all of the target cell's subkeys
  1786. //
  1787. while((TargetSubKey = CmpFindSubKeyByNumber(
  1788. TargetHive,
  1789. TargetCell,
  1790. i)) != HCELL_NIL)
  1791. {
  1792. //
  1793. // Check if the current subkey has a counterpart
  1794. // subkey of the source cell.
  1795. // (Note that we use similar techniques as in the code
  1796. // of CmpCopySyncTree2)
  1797. //
  1798. SubKeyCell = (PCM_KEY_NODE)HvGetCell(TargetHive, TargetSubKey);
  1799. if( SubKeyCell == NULL ) {
  1800. //
  1801. // we couldn't map the bin containing this cell
  1802. //
  1803. return FALSE;
  1804. }
  1805. CmpInitializeKeyNameString(SubKeyCell,
  1806. &SubKeyName,
  1807. NameBuffer);
  1808. SourceSubKey = CmpFindSubKeyByName(SourceHive,
  1809. SourceCell,
  1810. &SubKeyName);
  1811. if(SourceSubKey == HCELL_NIL)
  1812. {
  1813. //
  1814. // The current subkey has no counterpart,
  1815. // it must therefore be deleted from the target cell.
  1816. //
  1817. #if DEBUG_TREE_SYNC
  1818. CmKdPrintEx((DPFLTR_CONFIG_ID,DPFLTR_TRACE_LEVEL,"CONFIG: SubKey Deletion of %.*S\n",
  1819. SubKeyName.Length / sizeof(WCHAR),
  1820. SubKeyName.Buffer));
  1821. #endif
  1822. if(SubKeyCell->SubKeyCounts[Stable] + SubKeyCell->SubKeyCounts[Volatile])
  1823. {
  1824. // The subkey we are deleting has subkeys - use delete tree to get rid of them
  1825. CmpDeleteTree(TargetHive, TargetSubKey);
  1826. #if DEBUG_TREE_SYNC
  1827. CmKdPrintEx((DPFLTR_CONFIG_ID,DPFLTR_TRACE_LEVEL,"CONFIG: Delete TREE performed.\n"));
  1828. #endif
  1829. }
  1830. //
  1831. // release this cell as we don't need it anymore
  1832. //
  1833. HvReleaseCell(TargetHive, TargetSubKey);
  1834. // The subkey we are deleting is now a leaf (or has always been one),
  1835. // just delete it.
  1836. if(!NT_SUCCESS(CmpFreeKeyByCell(TargetHive, TargetSubKey, TRUE)))
  1837. {
  1838. return FALSE;
  1839. }
  1840. //
  1841. // We have deleted a subkey, so *i* does not need to get incremented
  1842. // here because it now refers to the next subkey.
  1843. //
  1844. }
  1845. else
  1846. {
  1847. //
  1848. // Counterpart found. No deletion necessary. Move on to the next subkey
  1849. //
  1850. i++;
  1851. //
  1852. // release this cell as we don't need it anymore
  1853. //
  1854. HvReleaseCell(TargetHive, TargetSubKey);
  1855. }
  1856. }
  1857. return TRUE;
  1858. }
  1859. BOOLEAN
  1860. CmpMarkKeyValuesDirty(
  1861. PHHIVE Hive,
  1862. HCELL_INDEX Cell,
  1863. PCM_KEY_NODE Node
  1864. )
  1865. /*++
  1866. Routine Description:
  1867. Marks the cells associated with a key's value entries, security descriptor,
  1868. and class information as dirty.
  1869. Arguments:
  1870. Hive - The hive of the key in question
  1871. Cell - The cell of the key in question
  1872. Node - The body of the key in question
  1873. Return Value:
  1874. TRUE if successful, FALSE otherwise.
  1875. A failure probably indicates that no log space was available.
  1876. --*/
  1877. {
  1878. PCELL_DATA plist, security, pvalue;
  1879. ULONG i, realsize;
  1880. ASSERT( Hive->ReleaseCellRoutine == NULL );
  1881. if (Node->Flags & KEY_HIVE_EXIT) {
  1882. //
  1883. // If this is a link node, we are done. Link nodes never have
  1884. // classes, values, subkeys, or security descriptors. Since
  1885. // they always reside in the master hive, they're always volatile.
  1886. //
  1887. return(TRUE);
  1888. }
  1889. //
  1890. // mark cell itself
  1891. //
  1892. if (! HvMarkCellDirty(Hive, Cell)) {
  1893. return FALSE;
  1894. }
  1895. //
  1896. // Mark the class
  1897. //
  1898. if (Node->Class != HCELL_NIL) {
  1899. if (! HvMarkCellDirty(Hive, Node->Class)) {
  1900. return FALSE;
  1901. }
  1902. }
  1903. //
  1904. // Mark security
  1905. //
  1906. if (Node->Security != HCELL_NIL) {
  1907. if (! HvMarkCellDirty(Hive, Node->Security)) {
  1908. return FALSE;
  1909. }
  1910. security = HvGetCell(Hive, Node->Security);
  1911. if( security == NULL ) {
  1912. //
  1913. // we couldn't map the bin containing this cell
  1914. // this shouldn't happen as we just marked the cell dirty
  1915. // (dirty == PINNED in memory).
  1916. //
  1917. ASSERT( FALSE );
  1918. return FALSE;
  1919. }
  1920. if (! (HvMarkCellDirty(Hive, security->u.KeySecurity.Flink) &&
  1921. HvMarkCellDirty(Hive, security->u.KeySecurity.Blink)))
  1922. {
  1923. return FALSE;
  1924. }
  1925. }
  1926. //
  1927. // Mark the value entries and their data
  1928. //
  1929. if (Node->ValueList.Count > 0) {
  1930. // Value list
  1931. if (! HvMarkCellDirty(Hive, Node->ValueList.List)) {
  1932. return FALSE;
  1933. }
  1934. plist = HvGetCell(Hive, Node->ValueList.List);
  1935. if( plist == NULL ) {
  1936. //
  1937. // we couldn't map the bin containing this cell
  1938. // this shouldn't happen as we just marked the cell dirty
  1939. // (dirty == PINNED in memory).
  1940. //
  1941. ASSERT( FALSE );
  1942. return FALSE;
  1943. }
  1944. for (i = 0; i < Node->ValueList.Count; i++) {
  1945. if (! HvMarkCellDirty(Hive, plist->u.KeyList[i])) {
  1946. return FALSE;
  1947. }
  1948. pvalue = HvGetCell(Hive, plist->u.KeyList[i]);
  1949. if( pvalue == NULL ) {
  1950. //
  1951. // we couldn't map the bin containing this cell
  1952. // this shouldn't happen as we just marked the cell dirty
  1953. // (dirty == PINNED in memory).
  1954. //
  1955. ASSERT( FALSE );
  1956. return FALSE;
  1957. }
  1958. if( !CmpMarkValueDataDirty(Hive,&(pvalue->u.KeyValue)) ) {
  1959. return FALSE;
  1960. }
  1961. }
  1962. }
  1963. return TRUE;
  1964. }
  1965. BOOLEAN
  1966. CmpMarkKeyParentDirty(
  1967. PHHIVE Hive,
  1968. HCELL_INDEX Cell
  1969. )
  1970. /*++
  1971. Routine Description:
  1972. Marks the parent of a given key and the parent's subkey list as dirty.
  1973. Arguments:
  1974. Hive - The hive of the key in question.
  1975. Cell - The cell of the key in question.
  1976. Return Value:
  1977. TRUE if successful, FALSE otherwise.
  1978. A failure probably indicates that no log space was available.
  1979. --*/
  1980. {
  1981. PCELL_DATA ptarget;
  1982. ASSERT_CM_EXCLUSIVE_HIVE_ACCESS(Hive);
  1983. //
  1984. // Map in the target
  1985. //
  1986. ptarget = HvGetCell(Hive, Cell);
  1987. if( ptarget == NULL ) {
  1988. //
  1989. // we couldn't map the bin containing this cell
  1990. //
  1991. return FALSE;
  1992. }
  1993. if (ptarget->u.KeyNode.Flags & KEY_HIVE_ENTRY) {
  1994. //
  1995. // if this is an entry node, we are done. our parent will
  1996. // be in the master hive (and thus volatile)
  1997. //
  1998. return TRUE;
  1999. }
  2000. //
  2001. // Mark the parent's Subkey list
  2002. //
  2003. if (! CmpMarkIndexDirty(Hive, ptarget->u.KeyNode.Parent, Cell)) {
  2004. return FALSE;
  2005. }
  2006. //
  2007. // Mark the parent
  2008. //
  2009. if (! HvMarkCellDirty(Hive, ptarget->u.KeyNode.Parent)) {
  2010. return FALSE;
  2011. }
  2012. return TRUE;
  2013. }