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.

2557 lines
79 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 = CmpCopyStackTop - 1;
  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. // Sync up the MaxNameLen field in the parent
  513. //
  514. {
  515. PCM_KEY_NODE TargetNodeParent, TargetNodeSon;
  516. USHORT NameLength;
  517. TargetNodeParent = (PCM_KEY_NODE)HvGetCell(CmpTargetHive,Frame->TargetCell);
  518. if( TargetNodeParent == NULL ) {
  519. goto CopyEnd;
  520. }
  521. //
  522. // make sure it's dirty as we are going to alter it.
  523. //
  524. if (! HvMarkCellDirty(CmpTargetHive,Frame->TargetCell)) {
  525. HvReleaseCell(CmpTargetHive,Frame->TargetCell);
  526. goto CopyEnd;
  527. }
  528. TargetNodeSon = (PCM_KEY_NODE)HvGetCell(CmpTargetHive,NewSubKey);
  529. if( TargetNodeSon == NULL ) {
  530. HvReleaseCell(CmpTargetHive,Frame->TargetCell);
  531. goto CopyEnd;
  532. }
  533. NameLength = TargetNodeSon->NameLength;
  534. if( TargetNodeSon->Flags & KEY_COMP_NAME ) {
  535. NameLength *= sizeof(WCHAR);
  536. }
  537. if (TargetNodeParent->MaxNameLen < NameLength) {
  538. TargetNodeParent->MaxNameLen = NameLength;
  539. }
  540. HvReleaseCell(CmpTargetHive,NewSubKey);
  541. HvReleaseCell(CmpTargetHive,Frame->TargetCell);
  542. }
  543. //
  544. // Check if the sync operation determined that this
  545. // subtree should be copied
  546. //
  547. if(TreeSync && SyncNeedsTreeCopy) {
  548. //
  549. // We have just created a new key in the target tree
  550. // with the above code. However, since this is a sync,
  551. // the parent of that new key has not been created by our
  552. // code and thus may not have been modified at all before
  553. // the creation of the new key. But this parent now
  554. // has a new child, and must therefore be marked as dirty.
  555. //
  556. if (! CmpMarkKeyParentDirty(CmpTargetHive, NewSubKey)) {
  557. goto CopyEnd;
  558. }
  559. //
  560. // Record the stack level where we start the copy
  561. // (and temporarily abandon the sync)
  562. // so that we can return to the sync operation when this
  563. // stack level is reached again (i.e. when the tree
  564. // under the current subkey is fully copied)
  565. //
  566. SyncTreeCopyStackStart = CmpCopyStackTop;
  567. //
  568. // Pretend that this is not a sync in order
  569. // to simply start copying
  570. //
  571. TreeSync = FALSE;
  572. }
  573. NewKeyCreated:
  574. //
  575. // We succeeded in copying/syncing the subkey, apply
  576. // ourselves to it
  577. //
  578. CmpCopyStackTop++;
  579. if (CmpCopyStackTop >= CmpCopyStackSize) {
  580. //
  581. // if we're here, it means that the tree
  582. // we're trying to copy is more than 1024
  583. // COMPONENTS deep (from 2048 to 256k bytes)
  584. // we could grow the stack, but this is pretty
  585. // severe, so return FALSE and fail the copy
  586. //
  587. goto CopyEnd;
  588. }
  589. CmpCopyStack[CmpCopyStackTop].SourceCell =
  590. SourceChild;
  591. CmpCopyStack[CmpCopyStackTop].TargetCell =
  592. NewSubKey;
  593. goto Outer;
  594. } // Inner: while
  595. if (CmpCopyStackTop == 0) {
  596. Ret = TRUE;
  597. goto CopyEnd;
  598. }
  599. CmpCopyStackTop--;
  600. Frame = &(CmpCopyStack[CmpCopyStackTop]);
  601. //
  602. // We have just completed working at a certain stack level.
  603. // This is a good time to check if we need to resume a temporarily
  604. // suspended sync operation.
  605. //
  606. if(SyncNeedsTreeCopy && (CmpCopyStackTop == SyncTreeCopyStackStart))
  607. {
  608. //
  609. // We've been copying a tree for a sync. But now, that tree is fully
  610. // copied. So, let's resume the sync once again.
  611. //
  612. TreeSync = TRUE;
  613. SyncNeedsTreeCopy = FALSE;
  614. }
  615. goto Inner;
  616. } // Outer: while
  617. CopyEnd:
  618. if (NameBuffer) ExFreePool(NameBuffer);
  619. return Ret;
  620. }
  621. HCELL_INDEX
  622. CmpCopyKeyPartial(
  623. PHHIVE SourceHive,
  624. HCELL_INDEX SourceKeyCell,
  625. PHHIVE TargetHive,
  626. HCELL_INDEX Parent,
  627. BOOLEAN CopyValues
  628. )
  629. /*++
  630. Routine Description:
  631. Copy a key body and all of its values, but NOT its subkeylist or
  632. subkey entries. SubKeyList.Count will be set to 0.
  633. Arguments:
  634. SourceHive - pointer to hive control structure for source
  635. SourceKeyCell - value entry being copied
  636. TargetHive - pointer to hive control structure for target
  637. Parent - parent value to set into newly created key body
  638. CopyValues - if FALSE value entries will not be copied, if TRUE, they will
  639. Return Value:
  640. HCELL_INDEX - Cell of body of new key entry, or HCELL_NIL
  641. if some error.
  642. --*/
  643. {
  644. NTSTATUS status;
  645. HCELL_INDEX newkey = HCELL_NIL;
  646. HCELL_INDEX newclass = HCELL_NIL;
  647. HCELL_INDEX newsecurity = HCELL_NIL;
  648. HCELL_INDEX newlist = HCELL_NIL;
  649. HCELL_INDEX newvalue;
  650. BOOLEAN success = FALSE;
  651. ULONG i,Index;
  652. PCELL_DATA psrckey = NULL;
  653. PCM_KEY_NODE ptarkey = NULL;
  654. PCELL_DATA psrclist = NULL;
  655. PCELL_DATA ptarlist;
  656. HCELL_INDEX security;
  657. HCELL_INDEX class;
  658. ULONG classlength;
  659. ULONG count;
  660. ULONG Type;
  661. PCM_KEY_VALUE pvalue;
  662. #if DBG
  663. WCHAR *NameBuffer = NULL;
  664. UNICODE_STRING ValueName;
  665. HCELL_INDEX child;
  666. #endif
  667. PSECURITY_DESCRIPTOR SrcSecurityDescriptor;
  668. CmKdPrintEx((DPFLTR_CONFIG_ID,CML_SAVRES,"CmpCopyKeyPartial:\n"));
  669. CmKdPrintEx((DPFLTR_CONFIG_ID,CML_SAVRES,"\tSHive=%p SCell=%08lx\n",SourceHive,SourceKeyCell));
  670. CmKdPrintEx((DPFLTR_CONFIG_ID,CML_SAVRES,"\tTHive=%p\n",TargetHive));
  671. #if DBG
  672. NameBuffer = ExAllocatePool(PagedPool, REG_MAX_KEY_VALUE_NAME_LENGTH);
  673. if(!NameBuffer) {
  674. return HCELL_NIL;
  675. }
  676. #endif //DBG
  677. //
  678. // get description of source
  679. //
  680. if (Parent == HCELL_NIL) {
  681. //
  682. // This is a root node we are creating, so don't make it volatile.
  683. //
  684. Type = Stable;
  685. } else {
  686. Type = HvGetCellType(Parent);
  687. }
  688. psrckey = HvGetCell(SourceHive, SourceKeyCell);
  689. if( psrckey == NULL ) {
  690. //
  691. // we couldn't map the bin containing this cell
  692. //
  693. goto DoFinally;
  694. }
  695. security = psrckey->u.KeyNode.Security;
  696. class = psrckey->u.KeyNode.Class;
  697. classlength = psrckey->u.KeyNode.ClassLength;
  698. //
  699. // Allocate and copy the body
  700. //
  701. newkey = CmpCopyCell(SourceHive, SourceKeyCell, TargetHive, Type);
  702. if (newkey == HCELL_NIL) {
  703. goto DoFinally;
  704. }
  705. //
  706. // this cell was just allocated so it should be pinned; it's OK to release it here
  707. // as the view is not going anywhere
  708. //
  709. ASSERT_CELL_DIRTY(TargetHive, newkey);
  710. //
  711. // Allocate and copy class
  712. //
  713. if (classlength > 0) {
  714. newclass = CmpCopyCell(SourceHive, class, TargetHive, Type);
  715. if (newclass == HCELL_NIL) {
  716. goto DoFinally;
  717. }
  718. }
  719. //
  720. // Fill in the target body
  721. //
  722. ptarkey = (PCM_KEY_NODE)HvGetCell(TargetHive, newkey);
  723. if( ptarkey == NULL ) {
  724. //
  725. // we couldn't map the bin containing this cell
  726. //
  727. goto DoFinally;
  728. }
  729. ptarkey->Class = newclass;
  730. ptarkey->Security = HCELL_NIL;
  731. ptarkey->SubKeyLists[Stable] = HCELL_NIL;
  732. ptarkey->SubKeyCounts[Stable] = 0;
  733. ptarkey->SubKeyCounts[Volatile] = 0;
  734. ptarkey->SubKeyLists[Volatile] = HCELL_NIL;
  735. ptarkey->Parent = Parent;
  736. ptarkey->Flags = (psrckey->u.KeyNode.Flags & KEY_COMP_NAME);
  737. if (Parent == HCELL_NIL) {
  738. ptarkey->Flags |= KEY_HIVE_ENTRY + KEY_NO_DELETE;
  739. }
  740. //
  741. // Allocate and copy security
  742. //
  743. // Use the hash Luke !!!
  744. //
  745. if( CmpFindSecurityCellCacheIndex ((PCMHIVE)SourceHive,security,&Index) == FALSE ) {
  746. goto DoFinally;
  747. }
  748. SrcSecurityDescriptor = &(((PCMHIVE)SourceHive)->SecurityCache[Index].CachedSecurity->Descriptor);
  749. status = CmpAssignSecurityDescriptor(TargetHive,
  750. newkey,
  751. ptarkey,
  752. SrcSecurityDescriptor);
  753. if (!NT_SUCCESS(status)) {
  754. goto DoFinally;
  755. }
  756. //
  757. // Set up the value list
  758. //
  759. count = psrckey->u.KeyNode.ValueList.Count;
  760. //
  761. // initialize an Empty ValueList
  762. //
  763. ptarkey->ValueList.List = HCELL_NIL;
  764. ptarkey->ValueList.Count = 0;
  765. if ((count == 0) || (CopyValues == FALSE)) {
  766. success = TRUE;
  767. } else {
  768. psrclist = HvGetCell(SourceHive, psrckey->u.KeyNode.ValueList.List);
  769. if( psrclist == NULL ) {
  770. //
  771. // we couldn't map the bin containing this cell
  772. //
  773. goto DoFinally;
  774. }
  775. //
  776. // Copy the values
  777. //
  778. for (i = 0; i < count; i++) {
  779. newvalue = CmpCopyValue(
  780. SourceHive,
  781. psrclist->u.KeyList[i],
  782. TargetHive,
  783. Type
  784. );
  785. if (newvalue == HCELL_NIL) {
  786. //
  787. // for cleanup purposes
  788. //
  789. newlist = ptarkey->ValueList.List;
  790. goto DoFinally;
  791. }
  792. pvalue = (PCM_KEY_VALUE)HvGetCell(TargetHive, newvalue);
  793. if( pvalue == NULL ) {
  794. //
  795. // we couldn't map the bin containing this cell
  796. // this shouldn't happen as we just allocated the cell
  797. // (i.e. the bin containing it should be PINNED into memory by now )
  798. //
  799. ASSERT( FALSE );
  800. //
  801. // for cleanup purposes
  802. //
  803. newlist = ptarkey->ValueList.List;
  804. goto DoFinally;
  805. }
  806. //
  807. // this cell was just allocated so it should be pinned; it's OK to release it here
  808. // as the view is not going anywhere
  809. //
  810. ASSERT_CELL_DIRTY(TargetHive, newvalue);
  811. HvReleaseCell(TargetHive, newvalue);
  812. #if DBG
  813. //
  814. // get the name
  815. //
  816. CmpInitializeValueNameString(pvalue,&ValueName,NameBuffer);
  817. //
  818. // find out the index where we should insert this
  819. // this is a special treatment for the case when we copy form and old hive (not sorted)
  820. // into a new format one (sorted)
  821. //
  822. if( CmpFindNameInList(TargetHive,&(ptarkey->ValueList),&ValueName,&Index,&child) == FALSE ) {
  823. //
  824. // we couldn't map a view inside the above call
  825. //
  826. //
  827. // for cleanup purposes
  828. //
  829. newlist = ptarkey->ValueList.List;
  830. goto DoFinally;
  831. }
  832. //
  833. // the value is not present in the list; we're about to add it!
  834. //
  835. ASSERT( child == HCELL_NIL );
  836. //
  837. // sanity validation : insert at the end
  838. //
  839. ASSERT( Index == i );
  840. #endif //DBG
  841. if( !NT_SUCCESS( CmpAddValueToList(TargetHive,newvalue,i,Type,&(ptarkey->ValueList)) ) ) {
  842. //
  843. // for cleanup purposes
  844. //
  845. newlist = ptarkey->ValueList.List;
  846. if( newlist != HCELL_NIL ) {
  847. ASSERT( i > 0 );
  848. //
  849. // free already copied values
  850. //
  851. ptarlist = HvGetCell(TargetHive, newlist);
  852. if( ptarlist == NULL ) {
  853. //
  854. // we couldn't map the bin containing this cell
  855. // this shouldn't fail as we just allocated this cell
  856. // (i.e. the bin should be PINNED into memory at this point)
  857. //
  858. ASSERT( FALSE );
  859. goto DoFinally;
  860. }
  861. //
  862. // this cell was just allocated so it should be pinned; it's OK to release it here
  863. // as the view is not going anywhere
  864. //
  865. ASSERT_CELL_DIRTY(TargetHive, newlist);
  866. HvReleaseCell(TargetHive, newlist);
  867. for (; i > 0; i--) {
  868. HvFreeCell(
  869. TargetHive,
  870. ptarlist->u.KeyList[i - 1]
  871. );
  872. }
  873. } else {
  874. ASSERT( i == 0 );
  875. }
  876. goto DoFinally;
  877. }
  878. }
  879. success = TRUE;
  880. }
  881. DoFinally:
  882. #if DBG
  883. ASSERT( NameBuffer != NULL );
  884. ExFreePool(NameBuffer);
  885. #endif //DBG
  886. if( psrclist != NULL ) {
  887. ASSERT(psrckey!= NULL );
  888. HvReleaseCell(SourceHive, psrckey->u.KeyNode.ValueList.List);
  889. }
  890. if( psrckey != NULL ) {
  891. HvReleaseCell(SourceHive, SourceKeyCell);
  892. }
  893. if( ptarkey != NULL ) {
  894. ASSERT( newkey != HCELL_NIL );
  895. HvReleaseCell(TargetHive, newkey);
  896. }
  897. if (success == FALSE) {
  898. if (newlist != HCELL_NIL) {
  899. HvFreeCell(TargetHive, newlist);
  900. }
  901. if (newsecurity != HCELL_NIL) {
  902. HvFreeCell(TargetHive, newsecurity);
  903. }
  904. if (newclass != HCELL_NIL) {
  905. HvFreeCell(TargetHive, newclass);
  906. }
  907. if (newkey != HCELL_NIL) {
  908. HvFreeCell(TargetHive, newkey);
  909. }
  910. return HCELL_NIL;
  911. } else {
  912. return newkey;
  913. }
  914. }
  915. HCELL_INDEX
  916. CmpCopyValue(
  917. PHHIVE SourceHive,
  918. HCELL_INDEX SourceValueCell,
  919. PHHIVE TargetHive,
  920. HSTORAGE_TYPE Type
  921. )
  922. /*++
  923. Routine Description:
  924. Copy a value entry. Copies the body of a value entry and the
  925. data. Returns cell of new value entry.
  926. Arguments:
  927. SourceHive - pointer to hive control structure for source
  928. SourceValueCell - value entry being copied
  929. TargetHive - pointer to hive control structure for target
  930. Type - storage type to allocate for target (stable or volatile)
  931. Return Value:
  932. HCELL_INDEX - Cell of body of new value entry, or HCELL_NIL
  933. if some error.
  934. --*/
  935. {
  936. HCELL_INDEX newvalue;
  937. HCELL_INDEX newdata;
  938. PCELL_DATA pvalue;
  939. ULONG datalength;
  940. HCELL_INDEX olddata;
  941. ULONG tempdata;
  942. BOOLEAN small;
  943. HCELL_INDEX CellToRelease = HCELL_NIL;
  944. CmKdPrintEx((DPFLTR_CONFIG_ID,CML_SAVRES,"CmpCopyValue:\n"));
  945. CmKdPrintEx((DPFLTR_CONFIG_ID,CML_SAVRES,"\tSHive=%p SCell=%08lx\n",SourceHive,SourceValueCell));
  946. CmKdPrintEx((DPFLTR_CONFIG_ID,CML_SAVRES,"\tTargetHive=%p\n",TargetHive));
  947. ASSERT( TargetHive->ReleaseCellRoutine == NULL );
  948. //
  949. // get source data
  950. //
  951. pvalue = HvGetCell(SourceHive, SourceValueCell);
  952. if( pvalue == NULL ) {
  953. //
  954. // we couldn't map the bin containing this cell
  955. //
  956. return HCELL_NIL;
  957. }
  958. small = CmpIsHKeyValueSmall(datalength, pvalue->u.KeyValue.DataLength);
  959. olddata = pvalue->u.KeyValue.Data;
  960. //
  961. // Copy body
  962. //
  963. newvalue = CmpCopyCell(SourceHive, SourceValueCell, TargetHive, Type);
  964. if (newvalue == HCELL_NIL) {
  965. HvReleaseCell(SourceHive, SourceValueCell);
  966. return HCELL_NIL;
  967. }
  968. //
  969. // Copy data (if any)
  970. //
  971. if (datalength > 0) {
  972. if (datalength > CM_KEY_VALUE_SMALL) {
  973. if( (CmpIsHKeyValueBig(SourceHive,datalength) == TRUE) ||
  974. (CmpIsHKeyValueBig(TargetHive,datalength) == TRUE)
  975. ) {
  976. PCELL_DATA Buffer;
  977. BOOLEAN BufferAllocated;
  978. HCELL_INDEX CellToRelease2 = HCELL_NIL;
  979. //
  980. // get the data from source, regardless of the size
  981. //
  982. if( CmpGetValueData(SourceHive,&(pvalue->u.KeyValue),&datalength,&Buffer,&BufferAllocated,&CellToRelease2) == FALSE ) {
  983. //
  984. // insufficient resources; return NULL
  985. //
  986. ASSERT( BufferAllocated == FALSE );
  987. ASSERT( Buffer == NULL );
  988. HvFreeCell(TargetHive, newvalue);
  989. HvReleaseCell(SourceHive, SourceValueCell);
  990. return HCELL_NIL;
  991. }
  992. //
  993. // we ignore celltorelease because we have specifically set the releae routine to NULL
  994. //
  995. //
  996. // allocate a new value data in the target hive (regardless of the size)
  997. // and copy the data onto it.
  998. //
  999. if( !NT_SUCCESS(CmpSetValueDataNew(TargetHive,Buffer,datalength,Type,newvalue,&newdata)) ) {
  1000. //
  1001. // We have bombed out loading user data, clean up and exit.
  1002. //
  1003. if( BufferAllocated == TRUE ) {
  1004. ExFreePool( Buffer );
  1005. }
  1006. HvFreeCell(TargetHive, newvalue);
  1007. HvReleaseCell(SourceHive, SourceValueCell);
  1008. if( CellToRelease2 != HCELL_NIL ) {
  1009. HvReleaseCell(SourceHive, CellToRelease2);
  1010. }
  1011. return HCELL_NIL;
  1012. }
  1013. //
  1014. // free the source buffer
  1015. //
  1016. if( BufferAllocated == TRUE ) {
  1017. ExFreePool( Buffer );
  1018. }
  1019. if( CellToRelease2 != HCELL_NIL ) {
  1020. HvReleaseCell(SourceHive, CellToRelease2);
  1021. }
  1022. } else {
  1023. //
  1024. // there's data, normal size, or none of the hives support
  1025. // bigdata cells, so do standard copy
  1026. //
  1027. newdata = CmpCopyCell(SourceHive, olddata, TargetHive, Type);
  1028. }
  1029. if (newdata == HCELL_NIL) {
  1030. HvFreeCell(TargetHive, newvalue);
  1031. HvReleaseCell(SourceHive, SourceValueCell);
  1032. return HCELL_NIL;
  1033. }
  1034. pvalue = HvGetCell(TargetHive, newvalue);
  1035. if( pvalue == NULL ) {
  1036. //
  1037. // we couldn't map the bin containing this cell
  1038. // this shouldn't happen as we just allocated the cell
  1039. // (i.e. it should be PINNED into memory at this point)
  1040. //
  1041. ASSERT( FALSE );
  1042. HvFreeCell(TargetHive, newvalue);
  1043. HvReleaseCell(SourceHive, SourceValueCell);
  1044. CmpFreeValueData(TargetHive,newdata,datalength);
  1045. return HCELL_NIL;
  1046. }
  1047. pvalue->u.KeyValue.Data = newdata;
  1048. pvalue->u.KeyValue.DataLength = datalength;
  1049. } else {
  1050. //
  1051. // the data is small, but may be stored in either large or
  1052. // small format for historical reasons
  1053. //
  1054. if (small) {
  1055. //
  1056. // data is already small, so just do a body to body copy
  1057. //
  1058. tempdata = pvalue->u.KeyValue.Data;
  1059. } else {
  1060. //
  1061. // data is stored externally in old cell, will be internal in new
  1062. //
  1063. CellToRelease = pvalue->u.KeyValue.Data;
  1064. pvalue = HvGetCell(SourceHive, pvalue->u.KeyValue.Data);
  1065. if( pvalue == NULL ) {
  1066. //
  1067. // we couldn't map the bin containing this cell
  1068. //
  1069. HvFreeCell(TargetHive, newvalue);
  1070. HvReleaseCell(SourceHive, SourceValueCell);
  1071. return HCELL_NIL;
  1072. }
  1073. tempdata = *((PULONG)pvalue);
  1074. }
  1075. pvalue = HvGetCell(TargetHive, newvalue);
  1076. if( pvalue == NULL ) {
  1077. //
  1078. // we couldn't map the bin containing this cell
  1079. // this shouldn't happen as we just allocated the cell
  1080. // (i.e. it should be PINNED into memory at this point)
  1081. //
  1082. ASSERT( FALSE );
  1083. HvFreeCell(TargetHive, newvalue);
  1084. HvReleaseCell(SourceHive, SourceValueCell);
  1085. if( CellToRelease != HCELL_NIL ) {
  1086. HvReleaseCell(SourceHive, CellToRelease);
  1087. }
  1088. return HCELL_NIL;
  1089. }
  1090. pvalue->u.KeyValue.Data = tempdata;
  1091. pvalue->u.KeyValue.DataLength =
  1092. datalength + CM_KEY_VALUE_SPECIAL_SIZE;
  1093. if( CellToRelease != HCELL_NIL ) {
  1094. HvReleaseCell(SourceHive, CellToRelease);
  1095. }
  1096. }
  1097. }
  1098. HvReleaseCell(SourceHive, SourceValueCell);
  1099. return newvalue;
  1100. }
  1101. HCELL_INDEX
  1102. CmpCopyCell(
  1103. PHHIVE SourceHive,
  1104. HCELL_INDEX SourceCell,
  1105. PHHIVE TargetHive,
  1106. HSTORAGE_TYPE Type
  1107. )
  1108. /*++
  1109. Routine Description:
  1110. Copy SourceHive.SourceCell to TargetHive.TargetCell.
  1111. Arguments:
  1112. SourceHive - pointer to hive control structure for source
  1113. SourceCell - index of cell to copy from
  1114. TargetHive - pointer to hive control structure for target
  1115. Type - storage type (stable or volatile) of new cell
  1116. Return Value:
  1117. HCELL_INDEX of new cell, or HCELL_NIL if failure.
  1118. --*/
  1119. {
  1120. PVOID psource;
  1121. PVOID ptarget;
  1122. ULONG size;
  1123. HCELL_INDEX newcell;
  1124. CmKdPrintEx((DPFLTR_CONFIG_ID,CML_SAVRES,"CmpCopyCell:\n"));
  1125. CmKdPrintEx((DPFLTR_CONFIG_ID,CML_SAVRES,"\tSourceHive=%p SourceCell=%08lx\n",SourceHive,SourceCell));
  1126. CmKdPrintEx((DPFLTR_CONFIG_ID,CML_SAVRES,"\tTargetHive=%p\n",TargetHive));
  1127. psource = HvGetCell(SourceHive, SourceCell);
  1128. if( psource == NULL ) {
  1129. //
  1130. // we couldn't map the bin containing this cell
  1131. //
  1132. return HCELL_NIL;
  1133. }
  1134. size = HvGetCellSize(SourceHive, psource);
  1135. newcell = HvAllocateCell(TargetHive, size, Type,HCELL_NIL);
  1136. if (newcell == HCELL_NIL) {
  1137. HvReleaseCell(SourceHive, SourceCell);
  1138. return HCELL_NIL;
  1139. }
  1140. ptarget = HvGetCell(TargetHive, newcell);
  1141. if( ptarget == NULL ) {
  1142. //
  1143. // we couldn't map the bin containing this cell
  1144. // this shouldn't happen as we just allocated the cell
  1145. // (i.e. it should be PINNED into memory at this point)
  1146. //
  1147. ASSERT( FALSE );
  1148. HvFreeCell(TargetHive, newcell);
  1149. HvReleaseCell(SourceHive, SourceCell);
  1150. return HCELL_NIL;
  1151. }
  1152. RtlCopyMemory(ptarget, psource, size);
  1153. HvReleaseCell(SourceHive, SourceCell);
  1154. HvReleaseCell(TargetHive, newcell);
  1155. return newcell;
  1156. }
  1157. BOOLEAN
  1158. CmpFreeKeyValues(
  1159. PHHIVE Hive,
  1160. HCELL_INDEX Cell,
  1161. PCM_KEY_NODE Node
  1162. )
  1163. /*++
  1164. Routine Description:
  1165. Free the cells associated with the value entries, the security descriptor,
  1166. and the class of a particular key.
  1167. Arguments:
  1168. Hive - The hive of the key in question
  1169. Cell - The cell of the key in question
  1170. Node - The key body of the key in question
  1171. Return Value:
  1172. TRUE if successful, FALSE otherwise.
  1173. --*/
  1174. {
  1175. PCELL_DATA plist;
  1176. ULONG i;
  1177. ASSERT( Hive->ReleaseCellRoutine == NULL );
  1178. //
  1179. // Mark all the value-related cells dirty
  1180. //
  1181. if (! CmpMarkKeyValuesDirty(Hive, Cell, Node)) {
  1182. return FALSE;
  1183. }
  1184. //
  1185. // Link nodes don't have things that we need to free
  1186. //
  1187. if (!(Node->Flags & KEY_HIVE_EXIT)) {
  1188. //
  1189. // First, free the value entries
  1190. //
  1191. if (Node->ValueList.Count > 0) {
  1192. // Get value list
  1193. plist = HvGetCell(Hive, Node->ValueList.List);
  1194. if( plist == NULL ) {
  1195. //
  1196. // we couldn't map the bin containing this cell
  1197. // this shouldn't happen as we just marked the cell dirty
  1198. // (i.e. it should be PINNED into memory at this point)
  1199. //
  1200. ASSERT( FALSE );
  1201. return FALSE;
  1202. }
  1203. // Free each value
  1204. for (i = 0; i < Node->ValueList.Count; i++) {
  1205. if( CmpFreeValue(Hive, plist->u.KeyList[i]) == FALSE ) {
  1206. //
  1207. // we couldn't map view inside call above
  1208. // this shouldn't happen as we just marked the values dirty
  1209. // (i.e. they should be PINNED into memory at this point)
  1210. //
  1211. ASSERT( FALSE );
  1212. return FALSE;
  1213. }
  1214. }
  1215. // Free the value list
  1216. HvFreeCell(Hive, Node->ValueList.List);
  1217. }
  1218. //
  1219. // Make this key value-less
  1220. //
  1221. Node->ValueList.List = HCELL_NIL;
  1222. Node->ValueList.Count = 0;
  1223. //
  1224. // Free the security descriptor
  1225. //
  1226. // we need to postpone that until we are sure we got the new one
  1227. //CmpFreeSecurityDescriptor(Hive, Cell);
  1228. //
  1229. // Free the Class information
  1230. //
  1231. if (Node->ClassLength > 0) {
  1232. HvFreeCell(Hive, Node->Class);
  1233. Node->Class = HCELL_NIL;
  1234. Node->ClassLength = 0;
  1235. }
  1236. }
  1237. return TRUE;
  1238. }
  1239. BOOLEAN
  1240. CmpMergeKeyValues(
  1241. PHHIVE SourceHive,
  1242. HCELL_INDEX SourceKeyCell,
  1243. PCM_KEY_NODE SourceKeyNode,
  1244. PHHIVE TargetHive,
  1245. HCELL_INDEX TargetKeyCell,
  1246. PCM_KEY_NODE TargetKeyNode
  1247. )
  1248. /*++
  1249. Routine Description:
  1250. Merges the values from the two key-nodes provided.
  1251. Rules for the merge:
  1252. 1. The target values are not touched!
  1253. 2. Only values from the source that are not present in the
  1254. target are taken into account by this routine. They are added
  1255. to the target node value list "as they are".
  1256. Arguments:
  1257. SourceHive - Hive of the source key
  1258. SourceKeyCell - The source key's cell
  1259. SourceKeyNode - The source key's body
  1260. TargetHive - Hive of the target key
  1261. TargetKeyCell - The target key's cell
  1262. TargetKeyNode - The target key's body
  1263. Return Value:
  1264. TRUE of successful, FALSE otherwise.
  1265. --*/
  1266. {
  1267. BOOLEAN success = FALSE;
  1268. PCELL_DATA psrclist;
  1269. HCELL_INDEX newvalue, newlist = HCELL_NIL,child;
  1270. ULONG i, count, Type, ChildIndex;
  1271. PCM_KEY_VALUE poldvalue;
  1272. WCHAR *NameBuffer = NULL;
  1273. UNICODE_STRING ValueName;
  1274. ASSERT_CM_LOCK_OWNED_EXCLUSIVE();
  1275. ASSERT( SourceHive->ReleaseCellRoutine == NULL );
  1276. ASSERT( TargetHive->ReleaseCellRoutine == NULL );
  1277. if(TargetKeyNode->MaxValueNameLen < SourceKeyNode->MaxValueNameLen) {
  1278. TargetKeyNode->MaxValueNameLen = SourceKeyNode->MaxValueNameLen;
  1279. }
  1280. if(TargetKeyNode->MaxValueDataLen < SourceKeyNode->MaxValueDataLen) {
  1281. TargetKeyNode->MaxValueDataLen = SourceKeyNode->MaxValueDataLen;
  1282. }
  1283. if(TargetKeyNode->ValueList.Count == 0) {
  1284. //
  1285. // No Values in Target, do a sync
  1286. //
  1287. return CmpSyncKeyValues(SourceHive, SourceKeyCell, SourceKeyNode, TargetHive, TargetKeyCell, TargetKeyNode);
  1288. }
  1289. //
  1290. // Set up the value list
  1291. //
  1292. count = SourceKeyNode->ValueList.Count;
  1293. if (count == 0) {
  1294. // No values in source, no update to the list needed.
  1295. success = TRUE;
  1296. } else {
  1297. NameBuffer = ExAllocatePool(PagedPool, REG_MAX_KEY_VALUE_NAME_LENGTH);
  1298. if(!NameBuffer) return FALSE;
  1299. //
  1300. // The type of the new cells will be the same as that
  1301. // of the target cell.
  1302. //
  1303. Type = HvGetCellType(TargetKeyCell);
  1304. //
  1305. // Reallocate the value list for target to fit the new size
  1306. // Worst case: all values from the source node will be added
  1307. // to the target node
  1308. //
  1309. psrclist = HvGetCell(SourceHive, SourceKeyNode->ValueList.List);
  1310. if( psrclist == NULL ) {
  1311. //
  1312. // we couldn't map the bin containing this cell
  1313. //
  1314. newlist = HCELL_NIL;
  1315. goto EndValueMerge;
  1316. }
  1317. //
  1318. // Copy the values
  1319. //
  1320. for (i = 0; i < count; i++) {
  1321. poldvalue = (PCM_KEY_VALUE)HvGetCell(SourceHive, psrclist->u.KeyList[i]);
  1322. if( poldvalue == NULL ) {
  1323. //
  1324. // we couldn't map the bin containing this cell
  1325. //
  1326. //
  1327. // for cleanup purposes
  1328. //
  1329. newlist = TargetKeyNode->ValueList.List;
  1330. goto EndValueMerge;
  1331. }
  1332. //
  1333. // get the name
  1334. //
  1335. CmpInitializeValueNameString(poldvalue,&ValueName,NameBuffer);
  1336. //
  1337. // check if this particular values doesn't exist in the target node already
  1338. //
  1339. if( CmpFindNameInList(TargetHive,&(TargetKeyNode->ValueList),&ValueName,&ChildIndex,&child) == FALSE ) {
  1340. //
  1341. // we couldn't map a view inside the above call
  1342. //
  1343. //
  1344. // for cleanup purposes
  1345. //
  1346. newlist = TargetKeyNode->ValueList.List;
  1347. goto EndValueMerge;
  1348. }
  1349. if( child == HCELL_NIL ) {
  1350. //
  1351. // sanity validation : insert at the end
  1352. //
  1353. ASSERT( ChildIndex == TargetKeyNode->ValueList.Count );
  1354. //
  1355. // No, it doesn't, so add it
  1356. //
  1357. newvalue = CmpCopyValue(
  1358. SourceHive,
  1359. psrclist->u.KeyList[i],
  1360. TargetHive,
  1361. Type
  1362. );
  1363. if (newvalue == HCELL_NIL) {
  1364. //
  1365. // for cleanup purposes
  1366. //
  1367. newlist = TargetKeyNode->ValueList.List;
  1368. goto EndValueMerge;
  1369. }
  1370. if( !NT_SUCCESS( CmpAddValueToList(TargetHive,newvalue,ChildIndex,Type,&(TargetKeyNode->ValueList)) ) ) {
  1371. //
  1372. // for cleanup purposes
  1373. //
  1374. newlist = TargetKeyNode->ValueList.List;
  1375. goto EndValueMerge;
  1376. }
  1377. }
  1378. }
  1379. success = TRUE;
  1380. }
  1381. EndValueMerge:
  1382. if (NameBuffer) ExFreePool(NameBuffer);
  1383. if (success == FALSE) {
  1384. // Clean-up on failure
  1385. // Revert to the original size
  1386. //
  1387. // unfortunatelly we cannot do that anymore as we have sorted the list
  1388. //
  1389. }
  1390. return success;
  1391. }
  1392. BOOLEAN
  1393. CmpSyncKeyValues(
  1394. PHHIVE SourceHive,
  1395. HCELL_INDEX SourceKeyCell,
  1396. PCM_KEY_NODE SourceKeyNode,
  1397. PHHIVE TargetHive,
  1398. HCELL_INDEX TargetKeyCell,
  1399. PCM_KEY_NODE TargetKeyNode
  1400. )
  1401. /*++
  1402. Routine Description:
  1403. Synchronizes the value entries, security descriptor, and class of a
  1404. target key with that of a source key - ensuring that the keys are
  1405. identical with respect to the synchronized information.
  1406. Arguments:
  1407. SourceHive - Hive of the source key
  1408. SourceKeyCell - The source key's cell
  1409. SourceKeyNode - The source key's body
  1410. TargetHive - Hive of the target key
  1411. TargetKeyCell - The target key's cell
  1412. TargetKeyNode - The target key's body
  1413. Return Value:
  1414. TRUE of successful, FALSE otherwise.
  1415. --*/
  1416. {
  1417. NTSTATUS status;
  1418. BOOLEAN success = FALSE;
  1419. PCELL_DATA psrclist = NULL, ptarlist;
  1420. HCELL_INDEX newvalue, newlist = HCELL_NIL, newclass = HCELL_NIL;
  1421. ULONG i, count, Type, Index;
  1422. PCM_KEY_VALUE pvalue;
  1423. #if DBG
  1424. WCHAR *NameBuffer = NULL;
  1425. UNICODE_STRING ValueName;
  1426. HCELL_INDEX child;
  1427. #endif //DBG
  1428. PSECURITY_DESCRIPTOR SrcSecurityDescriptor;
  1429. HCELL_INDEX OldSecurity,NewSecurity;
  1430. UNREFERENCED_PARAMETER (SourceKeyCell);
  1431. //
  1432. // nobody is operating on the target hive
  1433. //
  1434. ASSERT( TargetHive->ReleaseCellRoutine == NULL );
  1435. //
  1436. // First, free the target key's values, sd, and class info.
  1437. //
  1438. if(!CmpFreeKeyValues(TargetHive, TargetKeyCell, TargetKeyNode))
  1439. return FALSE;
  1440. #if DBG
  1441. NameBuffer = ExAllocatePool(PagedPool, REG_MAX_KEY_VALUE_NAME_LENGTH);
  1442. if(!NameBuffer) {
  1443. return FALSE;
  1444. }
  1445. #endif //DBG
  1446. //
  1447. // Now, copy the values, class, & sd from the source cell
  1448. //
  1449. //
  1450. // The type of the new cells will be the same as that
  1451. // of the target cell.
  1452. //
  1453. Type = HvGetCellType(TargetKeyCell);
  1454. //
  1455. // Allocate and copy class
  1456. //
  1457. if ((SourceKeyNode->ClassLength > 0) && (SourceKeyNode->Class != HCELL_NIL)) {
  1458. newclass = CmpCopyCell(SourceHive, SourceKeyNode->Class, TargetHive, Type);
  1459. if (newclass == HCELL_NIL) {
  1460. goto EndValueSync;
  1461. }
  1462. // only if class is valid. Otherwise remains 0 (set by CmpFreeKeyValues)
  1463. TargetKeyNode->ClassLength = SourceKeyNode->ClassLength;
  1464. }
  1465. //
  1466. // Associate the new class with the target key
  1467. // and prepare and security descriptor assignment.
  1468. //
  1469. TargetKeyNode->Class = newclass;
  1470. //
  1471. // Allocate and assign security
  1472. //
  1473. //
  1474. // Use the hash Luke !!!
  1475. //
  1476. if( CmpFindSecurityCellCacheIndex ((PCMHIVE)SourceHive,SourceKeyNode->Security,&Index) == FALSE ) {
  1477. goto EndValueSync;
  1478. }
  1479. SrcSecurityDescriptor = &(((PCMHIVE)SourceHive)->SecurityCache[Index].CachedSecurity->Descriptor);
  1480. //
  1481. // store it for later in case of error recovery
  1482. //
  1483. OldSecurity = TargetKeyNode->Security;
  1484. TargetKeyNode->Security = HCELL_NIL;
  1485. status = CmpAssignSecurityDescriptor(TargetHive,
  1486. TargetKeyCell,
  1487. TargetKeyNode,
  1488. SrcSecurityDescriptor);
  1489. if (!NT_SUCCESS(status)) {
  1490. TargetKeyNode->Security = OldSecurity;
  1491. goto EndValueSync;
  1492. }
  1493. NewSecurity = TargetKeyNode->Security;
  1494. TargetKeyNode->Security = OldSecurity;
  1495. if ((TargetKeyNode->Flags & KEY_HIVE_ENTRY) && ( NewSecurity != OldSecurity) ) {
  1496. //
  1497. // we need to play it safe here so we don't blow away the security list for entire hive.
  1498. //
  1499. PCM_KEY_SECURITY NewSec;
  1500. PCM_KEY_SECURITY OldSec;
  1501. PCM_KEY_SECURITY LastSec;
  1502. HCELL_INDEX LastSecCell;
  1503. NewSec = (PCM_KEY_SECURITY)HvGetCell(TargetHive,NewSecurity);
  1504. if( NewSec == NULL ) {
  1505. //
  1506. // could not map view
  1507. //
  1508. goto EndValueSync;
  1509. }
  1510. OldSec = (PCM_KEY_SECURITY)HvGetCell(TargetHive,OldSecurity);
  1511. if( OldSec == NULL ) {
  1512. //
  1513. // could not map view
  1514. //
  1515. HvReleaseCell(TargetHive,NewSecurity);
  1516. goto EndValueSync;
  1517. }
  1518. LastSecCell = OldSec->Blink;
  1519. LastSec = (PCM_KEY_SECURITY)HvGetCell(TargetHive,LastSecCell);
  1520. if( LastSec == NULL ) {
  1521. //
  1522. // could not map view
  1523. //
  1524. HvReleaseCell(TargetHive,OldSecurity);
  1525. HvReleaseCell(TargetHive,NewSecurity);
  1526. goto EndValueSync;
  1527. }
  1528. if( !HvMarkCellDirty(TargetHive,OldSecurity) ||
  1529. !HvMarkCellDirty(TargetHive,LastSecCell) ) {
  1530. //
  1531. // no log space
  1532. //
  1533. HvReleaseCell(TargetHive,LastSecCell);
  1534. HvReleaseCell(TargetHive,OldSecurity);
  1535. HvReleaseCell(TargetHive,NewSecurity);
  1536. goto EndValueSync;
  1537. }
  1538. //
  1539. // link old list to new security
  1540. //
  1541. NewSec->Flink = OldSecurity;
  1542. NewSec->Blink = LastSecCell;
  1543. OldSec->Blink = NewSecurity;
  1544. LastSec->Flink = NewSecurity;
  1545. HvReleaseCell(TargetHive,LastSecCell);
  1546. HvReleaseCell(TargetHive,OldSecurity);
  1547. HvReleaseCell(TargetHive,NewSecurity);
  1548. }
  1549. //
  1550. // we need to play it safe here, to make sure we never end up having a key
  1551. // with a NIL security cell
  1552. //
  1553. CmpFreeSecurityDescriptor(TargetHive, TargetKeyCell);
  1554. TargetKeyNode->Security = NewSecurity;
  1555. //
  1556. // Set up the value list
  1557. //
  1558. count = SourceKeyNode->ValueList.Count;
  1559. //
  1560. // target ValueList is an emptylist; we shall add values to it.
  1561. //
  1562. TargetKeyNode->ValueList.List = HCELL_NIL;
  1563. TargetKeyNode->ValueList.Count = 0;
  1564. //
  1565. // after sync we'll have the values from source
  1566. //
  1567. TargetKeyNode->MaxValueNameLen = SourceKeyNode->MaxValueNameLen;
  1568. TargetKeyNode->MaxValueDataLen = SourceKeyNode->MaxValueDataLen;
  1569. if (count == 0) {
  1570. // No values in source, no list needed.
  1571. success = TRUE;
  1572. } else {
  1573. //
  1574. // Do not allocate space for ValueList; CmpAddValueToList will do it
  1575. //
  1576. psrclist = HvGetCell(SourceHive, SourceKeyNode->ValueList.List);
  1577. if( psrclist == NULL ) {
  1578. //
  1579. // we couldn't map the bin containing this cell
  1580. //
  1581. goto EndValueSync;
  1582. }
  1583. //
  1584. // Copy the values
  1585. //
  1586. for (i = 0; i < count; i++) {
  1587. newvalue = CmpCopyValue(
  1588. SourceHive,
  1589. psrclist->u.KeyList[i],
  1590. TargetHive,
  1591. Type
  1592. );
  1593. if (newvalue == HCELL_NIL) {
  1594. //
  1595. // for cleanup purposes
  1596. //
  1597. newlist = TargetKeyNode->ValueList.List;
  1598. goto EndValueSync;
  1599. }
  1600. pvalue = (PCM_KEY_VALUE)HvGetCell(TargetHive, newvalue);
  1601. if( pvalue == NULL ) {
  1602. //
  1603. // we couldn't map the bin containing this cell
  1604. // this shouldn't happen as we just allocated the cell
  1605. // (i.e. the bin containing it should be PINNED into memory by now )
  1606. //
  1607. ASSERT( FALSE );
  1608. //
  1609. // for cleanup purposes
  1610. //
  1611. newlist = TargetKeyNode->ValueList.List;
  1612. goto EndValueSync;
  1613. }
  1614. #if DBG
  1615. //
  1616. // get the name
  1617. //
  1618. CmpInitializeValueNameString(pvalue,&ValueName,NameBuffer);
  1619. //
  1620. // find out the index where we should insert this
  1621. // this is a special treatment for the case when we copy form and old hive (not sorted)
  1622. // into a new format one (sorted)
  1623. //
  1624. if( CmpFindNameInList(TargetHive,&(TargetKeyNode->ValueList),&ValueName,&Index,&child) == FALSE ) {
  1625. //
  1626. // we couldn't map a view inside the above call
  1627. //
  1628. //
  1629. // for cleanup purposes
  1630. //
  1631. newlist = TargetKeyNode->ValueList.List;
  1632. goto EndValueSync;
  1633. }
  1634. //
  1635. // the value is not present in the list; we're about to add it!
  1636. //
  1637. ASSERT( child == HCELL_NIL );
  1638. //
  1639. // sanity validation : insert at the end
  1640. //
  1641. ASSERT( Index == i );
  1642. #endif //DBG
  1643. if( !NT_SUCCESS( CmpAddValueToList(TargetHive,newvalue,i,Type,&(TargetKeyNode->ValueList)) ) ) {
  1644. //
  1645. // for cleanup purposes
  1646. //
  1647. newlist = TargetKeyNode->ValueList.List;
  1648. if( newlist != HCELL_NIL ) {
  1649. //
  1650. // Delete all the copied values on an error.
  1651. //
  1652. ptarlist = HvGetCell(TargetHive, newlist);
  1653. if( ptarlist == NULL ) {
  1654. //
  1655. // we couldn't map the bin containing this cell
  1656. // this shouldn't fail as we just allocated this cell
  1657. // (i.e. the bin should be PINNED into memory at this point)
  1658. //
  1659. ASSERT( FALSE );
  1660. goto EndValueSync;
  1661. }
  1662. for (; i > 0; i--) {
  1663. HvFreeCell(
  1664. TargetHive,
  1665. ptarlist->u.KeyList[i - 1]
  1666. );
  1667. }
  1668. }
  1669. goto EndValueSync;
  1670. }
  1671. }
  1672. success = TRUE;
  1673. }
  1674. EndValueSync:
  1675. #if DBG
  1676. ASSERT( NameBuffer != NULL );
  1677. ExFreePool(NameBuffer);
  1678. #endif //DBG
  1679. if( psrclist != NULL ) {
  1680. HvReleaseCell(SourceHive, SourceKeyNode->ValueList.List);
  1681. }
  1682. if (success == FALSE) {
  1683. // Clean-up on failure
  1684. if (newlist != HCELL_NIL) {
  1685. HvFreeCell(TargetHive, newlist);
  1686. }
  1687. if (newclass != HCELL_NIL) {
  1688. HvFreeCell(TargetHive, newclass);
  1689. }
  1690. }
  1691. return success;
  1692. }
  1693. VOID
  1694. CmpInitializeKeyNameString(PCM_KEY_NODE Cell,
  1695. PUNICODE_STRING KeyName,
  1696. WCHAR *NameBuffer
  1697. )
  1698. /*++
  1699. Routine Description:
  1700. Initializes a UNICODE_STRING with the name of a given key.
  1701. N.B. The initialized string's buffer is not meant
  1702. to be modified.
  1703. Arguments:
  1704. Cell - The body of the key in question
  1705. KeyName - The UNICODE_STRING to initialize
  1706. NameBuffer - A buffer REG_MAX_KEY_NAME_LENGTH bytes in size
  1707. that will possibly be used as the UNICODE_STRING's
  1708. buffer.
  1709. Return Value:
  1710. NONE.
  1711. --*/
  1712. {
  1713. // is the name stored in compressed form?
  1714. if(Cell->Flags & KEY_COMP_NAME) {
  1715. // Name is compressed.
  1716. // Get the uncompressed length.
  1717. KeyName->Length = CmpCompressedNameSize(Cell->Name,
  1718. Cell->NameLength);
  1719. // Decompress the name into a buffer.
  1720. CmpCopyCompressedName(NameBuffer,
  1721. REG_MAX_KEY_NAME_LENGTH,
  1722. Cell->Name,
  1723. Cell->NameLength);
  1724. //
  1725. // Use the decompression buffer as the string buffer
  1726. //
  1727. KeyName->Buffer = NameBuffer;
  1728. KeyName->MaximumLength = REG_MAX_KEY_NAME_LENGTH;
  1729. } else {
  1730. //
  1731. // Name is not compressed. Just use the name string
  1732. // from the key buffer as the string buffer.
  1733. //
  1734. KeyName->Length = Cell->NameLength;
  1735. KeyName->Buffer = Cell->Name;
  1736. KeyName->MaximumLength = (USHORT)Cell->MaxNameLen;
  1737. }
  1738. }
  1739. VOID
  1740. CmpInitializeValueNameString(PCM_KEY_VALUE Cell,
  1741. PUNICODE_STRING ValueName,
  1742. WCHAR *NameBuffer
  1743. )
  1744. /*
  1745. Routine Description:
  1746. Initializes a UNICODE_STRING with the name of a given value key.
  1747. N.B. The initialized string's buffer is not meant
  1748. to be modified.
  1749. Arguments:
  1750. Cell - The value key in question
  1751. ValueName - The UNICODE_STRING to initialize
  1752. NameBuffer - A buffer REG_MAX_KEY_NAME_LENGTH bytes in size
  1753. that will possibly be used as the UNICODE_STRING's
  1754. buffer.
  1755. Return Value:
  1756. NONE.
  1757. */
  1758. {
  1759. // is the name stored in compressed form?
  1760. if(Cell->Flags & VALUE_COMP_NAME) {
  1761. // Name is compressed.
  1762. // Get the uncompressed length.
  1763. ValueName->Length = CmpCompressedNameSize(Cell->Name,
  1764. Cell->NameLength);
  1765. // Decompress the name into a buffer.
  1766. CmpCopyCompressedName(NameBuffer,
  1767. REG_MAX_KEY_VALUE_NAME_LENGTH,
  1768. Cell->Name,
  1769. Cell->NameLength);
  1770. //
  1771. // Use the decompression buffer as the string buffer
  1772. //
  1773. ValueName->Buffer = NameBuffer;
  1774. ValueName->MaximumLength = REG_MAX_KEY_VALUE_NAME_LENGTH;
  1775. } else {
  1776. //
  1777. // Name is not compressed. Just use the name string
  1778. // from the ValueName buffer as the string buffer.
  1779. //
  1780. ValueName->Length = Cell->NameLength;
  1781. ValueName->Buffer = Cell->Name;
  1782. ValueName->MaximumLength = ValueName->Length;
  1783. }
  1784. }
  1785. BOOLEAN
  1786. CmpSyncSubKeysAfterDelete(PHHIVE SourceHive,
  1787. PCM_KEY_NODE SourceCell,
  1788. PHHIVE TargetHive,
  1789. PCM_KEY_NODE TargetCell,
  1790. WCHAR *NameBuffer)
  1791. /*++
  1792. Routine Description:
  1793. This routine makes sure that any subkeys present in the target key
  1794. but not present in the source key are deleted from the target key
  1795. along with any trees under those subkeys.
  1796. This routine is useful for synchronizing key deletion changes
  1797. in a source cell with a target cell. It is used in this way
  1798. from CmpCopySyncTree.
  1799. NOTE: It is assumed that no open handles are held for the keys
  1800. being deleted. If this is not so, registry in-memory
  1801. data structures may become corrupted.
  1802. Arguments:
  1803. SourceHive - The hive of the source key
  1804. SourceCell - The body of the source key
  1805. TargetHive - The hive of the target key
  1806. TargetCell - The body of the target key
  1807. NameBuffer - A buffer REG_MAX_KEY_NAME_LENGTH bytes in size
  1808. Return Value:
  1809. TRUE if successful, FALSE otherwise.
  1810. --*/
  1811. {
  1812. HCELL_INDEX TargetSubKey, SourceSubKey;
  1813. ULONG i = 0;
  1814. PCM_KEY_NODE SubKeyCell;
  1815. UNICODE_STRING SubKeyName;
  1816. //
  1817. // Run through all of the target cell's subkeys
  1818. //
  1819. while((TargetSubKey = CmpFindSubKeyByNumber(
  1820. TargetHive,
  1821. TargetCell,
  1822. i)) != HCELL_NIL)
  1823. {
  1824. //
  1825. // Check if the current subkey has a counterpart
  1826. // subkey of the source cell.
  1827. // (Note that we use similar techniques as in the code
  1828. // of CmpCopySyncTree2)
  1829. //
  1830. SubKeyCell = (PCM_KEY_NODE)HvGetCell(TargetHive, TargetSubKey);
  1831. if( SubKeyCell == NULL ) {
  1832. //
  1833. // we couldn't map the bin containing this cell
  1834. //
  1835. return FALSE;
  1836. }
  1837. CmpInitializeKeyNameString(SubKeyCell,
  1838. &SubKeyName,
  1839. NameBuffer);
  1840. SourceSubKey = CmpFindSubKeyByName(SourceHive,
  1841. SourceCell,
  1842. &SubKeyName);
  1843. if(SourceSubKey == HCELL_NIL)
  1844. {
  1845. //
  1846. // The current subkey has no counterpart,
  1847. // it must therefore be deleted from the target cell.
  1848. //
  1849. #if DEBUG_TREE_SYNC
  1850. CmKdPrintEx((DPFLTR_CONFIG_ID,DPFLTR_TRACE_LEVEL,"CONFIG: SubKey Deletion of %.*S\n",
  1851. SubKeyName.Length / sizeof(WCHAR),
  1852. SubKeyName.Buffer));
  1853. #endif
  1854. if(SubKeyCell->SubKeyCounts[Stable] + SubKeyCell->SubKeyCounts[Volatile])
  1855. {
  1856. // The subkey we are deleting has subkeys - use delete tree to get rid of them
  1857. CmpDeleteTree(TargetHive, TargetSubKey);
  1858. #if DEBUG_TREE_SYNC
  1859. CmKdPrintEx((DPFLTR_CONFIG_ID,DPFLTR_TRACE_LEVEL,"CONFIG: Delete TREE performed.\n"));
  1860. #endif
  1861. }
  1862. //
  1863. // release this cell as we don't need it anymore
  1864. //
  1865. HvReleaseCell(TargetHive, TargetSubKey);
  1866. // The subkey we are deleting is now a leaf (or has always been one),
  1867. // just delete it.
  1868. if(!NT_SUCCESS(CmpFreeKeyByCell(TargetHive, TargetSubKey, TRUE)))
  1869. {
  1870. return FALSE;
  1871. }
  1872. //
  1873. // We have deleted a subkey, so *i* does not need to get incremented
  1874. // here because it now refers to the next subkey.
  1875. //
  1876. }
  1877. else
  1878. {
  1879. //
  1880. // Counterpart found. No deletion necessary. Move on to the next subkey
  1881. //
  1882. i++;
  1883. //
  1884. // release this cell as we don't need it anymore
  1885. //
  1886. HvReleaseCell(TargetHive, TargetSubKey);
  1887. }
  1888. }
  1889. return TRUE;
  1890. }
  1891. BOOLEAN
  1892. CmpMarkKeyValuesDirty(
  1893. PHHIVE Hive,
  1894. HCELL_INDEX Cell,
  1895. PCM_KEY_NODE Node
  1896. )
  1897. /*++
  1898. Routine Description:
  1899. Marks the cells associated with a key's value entries, security descriptor,
  1900. and class information as dirty.
  1901. Arguments:
  1902. Hive - The hive of the key in question
  1903. Cell - The cell of the key in question
  1904. Node - The body of the key in question
  1905. Return Value:
  1906. TRUE if successful, FALSE otherwise.
  1907. A failure probably indicates that no log space was available.
  1908. --*/
  1909. {
  1910. PCELL_DATA plist, security, pvalue;
  1911. ULONG i;
  1912. ASSERT( Hive->ReleaseCellRoutine == NULL );
  1913. if (Node->Flags & KEY_HIVE_EXIT) {
  1914. //
  1915. // If this is a link node, we are done. Link nodes never have
  1916. // classes, values, subkeys, or security descriptors. Since
  1917. // they always reside in the master hive, they're always volatile.
  1918. //
  1919. return(TRUE);
  1920. }
  1921. //
  1922. // mark cell itself
  1923. //
  1924. if (! HvMarkCellDirty(Hive, Cell)) {
  1925. return FALSE;
  1926. }
  1927. //
  1928. // Mark the class
  1929. //
  1930. if (Node->Class != HCELL_NIL) {
  1931. if (! HvMarkCellDirty(Hive, Node->Class)) {
  1932. return FALSE;
  1933. }
  1934. }
  1935. //
  1936. // Mark security
  1937. //
  1938. if (Node->Security != HCELL_NIL) {
  1939. if (! HvMarkCellDirty(Hive, Node->Security)) {
  1940. return FALSE;
  1941. }
  1942. security = HvGetCell(Hive, Node->Security);
  1943. if( security == NULL ) {
  1944. //
  1945. // we couldn't map the bin containing this cell
  1946. // this shouldn't happen as we just marked the cell dirty
  1947. // (dirty == PINNED in memory).
  1948. //
  1949. ASSERT( FALSE );
  1950. return FALSE;
  1951. }
  1952. if (! (HvMarkCellDirty(Hive, security->u.KeySecurity.Flink) &&
  1953. HvMarkCellDirty(Hive, security->u.KeySecurity.Blink)))
  1954. {
  1955. return FALSE;
  1956. }
  1957. }
  1958. //
  1959. // Mark the value entries and their data
  1960. //
  1961. if (Node->ValueList.Count > 0) {
  1962. // Value list
  1963. if (! HvMarkCellDirty(Hive, Node->ValueList.List)) {
  1964. return FALSE;
  1965. }
  1966. plist = HvGetCell(Hive, Node->ValueList.List);
  1967. if( plist == NULL ) {
  1968. //
  1969. // we couldn't map the bin containing this cell
  1970. // this shouldn't happen as we just marked the cell dirty
  1971. // (dirty == PINNED in memory).
  1972. //
  1973. ASSERT( FALSE );
  1974. return FALSE;
  1975. }
  1976. for (i = 0; i < Node->ValueList.Count; i++) {
  1977. if (! HvMarkCellDirty(Hive, plist->u.KeyList[i])) {
  1978. return FALSE;
  1979. }
  1980. pvalue = HvGetCell(Hive, plist->u.KeyList[i]);
  1981. if( pvalue == NULL ) {
  1982. //
  1983. // we couldn't map the bin containing this cell
  1984. // this shouldn't happen as we just marked the cell dirty
  1985. // (dirty == PINNED in memory).
  1986. //
  1987. ASSERT( FALSE );
  1988. return FALSE;
  1989. }
  1990. if( !CmpMarkValueDataDirty(Hive,&(pvalue->u.KeyValue)) ) {
  1991. return FALSE;
  1992. }
  1993. }
  1994. }
  1995. return TRUE;
  1996. }
  1997. BOOLEAN
  1998. CmpMarkKeyParentDirty(
  1999. PHHIVE Hive,
  2000. HCELL_INDEX Cell
  2001. )
  2002. /*++
  2003. Routine Description:
  2004. Marks the parent of a given key and the parent's subkey list as dirty.
  2005. Arguments:
  2006. Hive - The hive of the key in question.
  2007. Cell - The cell of the key in question.
  2008. Return Value:
  2009. TRUE if successful, FALSE otherwise.
  2010. A failure probably indicates that no log space was available.
  2011. --*/
  2012. {
  2013. PCELL_DATA ptarget;
  2014. ASSERT_CM_EXCLUSIVE_HIVE_ACCESS(Hive);
  2015. //
  2016. // Map in the target
  2017. //
  2018. ptarget = HvGetCell(Hive, Cell);
  2019. if( ptarget == NULL ) {
  2020. //
  2021. // we couldn't map the bin containing this cell
  2022. //
  2023. return FALSE;
  2024. }
  2025. if (ptarget->u.KeyNode.Flags & KEY_HIVE_ENTRY) {
  2026. //
  2027. // if this is an entry node, we are done. our parent will
  2028. // be in the master hive (and thus volatile)
  2029. //
  2030. return TRUE;
  2031. }
  2032. //
  2033. // Mark the parent's Subkey list
  2034. //
  2035. if (! CmpMarkIndexDirty(Hive, ptarget->u.KeyNode.Parent, Cell)) {
  2036. return FALSE;
  2037. }
  2038. //
  2039. // Mark the parent
  2040. //
  2041. if (! HvMarkCellDirty(Hive, ptarget->u.KeyNode.Parent)) {
  2042. return FALSE;
  2043. }
  2044. return TRUE;
  2045. }