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.

551 lines
14 KiB

  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. cmtredel.c
  5. Abstract:
  6. This file contains code for CmpDeleteTree, and support.
  7. Author:
  8. Bryan M. Willman (bryanwi) 24-Jan-92
  9. Revision History:
  10. --*/
  11. #include "cmp.h"
  12. #ifdef ALLOC_PRAGMA
  13. #pragma alloc_text(PAGE,CmpDeleteTree)
  14. #pragma alloc_text(PAGE,CmpFreeKeyByCell)
  15. #pragma alloc_text(PAGE,CmpMarkKeyDirty)
  16. #endif
  17. //
  18. // Routine to actually call to do a tree delete
  19. //
  20. VOID
  21. CmpDeleteTree(
  22. PHHIVE Hive,
  23. HCELL_INDEX Cell
  24. )
  25. /*++
  26. Routine Description:
  27. Delete all child subkeys, recursively, of Hive.Cell. Delete all
  28. value entries of Hive.Cell. Do NOT delete Hive.Cell itself.
  29. NOTE: If this call fails part way through, it will NOT undo
  30. any successfully completed deletes.
  31. NOTE: This algorithm can deal with a hive of any depth, at the
  32. cost of some "redundent" scaning and mapping.
  33. Arguments:
  34. Hive - pointer to hive control structure for hive to delete from
  35. Cell - index of cell at root of tree to delete
  36. Return Value:
  37. BOOLEAN - Result code from call, among the following:
  38. TRUE - it worked
  39. FALSE - the tree delete was not completed (though more than 0
  40. keys may have been deleted)
  41. --*/
  42. {
  43. ULONG count;
  44. HCELL_INDEX ptr1;
  45. HCELL_INDEX ptr2;
  46. HCELL_INDEX parent;
  47. PCM_KEY_NODE Node;
  48. CmKdPrintEx((DPFLTR_CONFIG_ID,CML_SAVRES,"CmpDeleteTree:\n"));
  49. CmKdPrintEx((DPFLTR_CONFIG_ID,CML_SAVRES,"\tHive=%p Cell=%08lx\n",Hive,Cell));
  50. //
  51. // we have the lock exclusive or nobody is operating inside this hive
  52. //
  53. //ASSERT_CM_LOCK_OWNED_EXCLUSIVE();
  54. ASSERT_CM_EXCLUSIVE_HIVE_ACCESS(Hive);
  55. ptr1 = Cell;
  56. while(TRUE) {
  57. Node = (PCM_KEY_NODE)HvGetCell(Hive, ptr1);
  58. if( Node == NULL ) {
  59. //
  60. // we couldn't map the bin containing this cell
  61. // bad luck! we cannot delete this tree
  62. //
  63. return;
  64. }
  65. count = Node->SubKeyCounts[Stable] +
  66. Node->SubKeyCounts[Volatile];
  67. parent = Node->Parent;
  68. if (count > 0) { // ptr1->count > 0?
  69. //
  70. // subkeys exist, find and delete them
  71. //
  72. ptr2 = CmpFindSubKeyByNumber(Hive, Node, 0);
  73. //
  74. // release the cell here as we are overriding node
  75. //
  76. HvReleaseCell(Hive, ptr1);
  77. if( ptr2 == HCELL_NIL ) {
  78. //
  79. // we couldn't map view inside
  80. // bad luck! we cannot delete this tree
  81. //
  82. return;
  83. }
  84. Node = (PCM_KEY_NODE)HvGetCell(Hive, ptr2);
  85. if( Node == NULL ) {
  86. //
  87. // we couldn't map the bin containing this cell
  88. // bad luck! we cannot delete this tree
  89. //
  90. return;
  91. }
  92. count = Node->SubKeyCounts[Stable] +
  93. Node->SubKeyCounts[Volatile];
  94. //
  95. // release the cell here as we don't need it anymore
  96. //
  97. HvReleaseCell(Hive, ptr2);
  98. if (count > 0) { // ptr2->count > 0?
  99. //
  100. // subkey has subkeys, descend to next level
  101. //
  102. ptr1 = ptr2;
  103. continue;
  104. } else {
  105. //
  106. // have found leaf, delete it
  107. //
  108. CmpFreeKeyByCell(Hive, ptr2, TRUE);
  109. continue;
  110. }
  111. } else {
  112. //
  113. // release the cell here as we don't need it anymore
  114. //
  115. HvReleaseCell(Hive, ptr1);
  116. //
  117. // no more subkeys at this level, we are now a leaf.
  118. //
  119. if (ptr1 != Cell) {
  120. //
  121. // we are not at the root cell, so ascend to parent
  122. //
  123. ptr1 = parent; // ptr1 = ptr1->parent
  124. continue;
  125. } else {
  126. //
  127. // we are at the root cell, we are done
  128. //
  129. return;
  130. }
  131. } // outer if
  132. } // while
  133. }
  134. NTSTATUS
  135. CmpFreeKeyByCell(
  136. PHHIVE Hive,
  137. HCELL_INDEX Cell,
  138. BOOLEAN Unlink
  139. )
  140. /*++
  141. Routine Description:
  142. Actually free the storage for the specified cell. We will first
  143. remove it from its parent's child key list, then free all of its
  144. values, then the key body itself.
  145. Arguments:
  146. Hive - pointer to hive control structure for hive of interest
  147. Cell - index for cell to free storage for (the target)
  148. Unlink - if TRUE, target cell will be removed from parent cell's
  149. subkeylist, if FALSE, it will NOT be.
  150. Return Value:
  151. NONE.
  152. --*/
  153. {
  154. PCELL_DATA ptarget;
  155. PCELL_DATA pparent;
  156. PCELL_DATA plist;
  157. ULONG i;
  158. //
  159. // we have the lock exclusive or nobody is operating inside this hive
  160. //
  161. //ASSERT_CM_LOCK_OWNED_EXCLUSIVE();
  162. ASSERT_CM_EXCLUSIVE_HIVE_ACCESS(Hive);
  163. //
  164. // Mark dirty everything that we might touch
  165. //
  166. if (! CmpMarkKeyDirty(Hive, Cell
  167. #if DBG
  168. ,TRUE
  169. #endif //DBG
  170. )) {
  171. return STATUS_NO_LOG_SPACE;
  172. }
  173. //
  174. // Map in the target
  175. //
  176. ptarget = HvGetCell(Hive, Cell);
  177. if( ptarget == NULL ) {
  178. //
  179. // we couldn't map the bin containing this cell
  180. // we shouldn't hit this as we just marked the cell dirty
  181. //
  182. ASSERT( FALSE );
  183. return STATUS_INSUFFICIENT_RESOURCES;
  184. }
  185. //
  186. // release the cell here as it is dirty(pinned); it cannot go anywhere
  187. //
  188. HvReleaseCell(Hive, Cell);
  189. ASSERT((ptarget->u.KeyNode.SubKeyCounts[Stable] +
  190. ptarget->u.KeyNode.SubKeyCounts[Volatile]) == 0);
  191. if (Unlink == TRUE) {
  192. BOOLEAN Success;
  193. Success = CmpRemoveSubKey(Hive, ptarget->u.KeyNode.Parent, Cell);
  194. if (!Success) {
  195. return STATUS_INSUFFICIENT_RESOURCES;
  196. }
  197. pparent = HvGetCell(Hive, ptarget->u.KeyNode.Parent);
  198. if( pparent == NULL ) {
  199. //
  200. // we couldn't map the bin containing this cell
  201. // we shouldn't hit this as we just marked the cell dirty
  202. //
  203. ASSERT( FALSE );
  204. return STATUS_INSUFFICIENT_RESOURCES;
  205. }
  206. //
  207. // release the cell here as it is dirty(pinned); it cannot go anywhere
  208. //
  209. HvReleaseCell(Hive, ptarget->u.KeyNode.Parent);
  210. if ( (pparent->u.KeyNode.SubKeyCounts[Stable] +
  211. pparent->u.KeyNode.SubKeyCounts[Volatile]) == 0)
  212. {
  213. pparent->u.KeyNode.MaxNameLen = 0;
  214. pparent->u.KeyNode.MaxClassLen = 0;
  215. }
  216. }
  217. //
  218. // Target is now an unreferenced key, free it's actual storage
  219. //
  220. //
  221. // Free misc stuff
  222. //
  223. if (!(ptarget->u.KeyNode.Flags & KEY_HIVE_EXIT) &&
  224. !(ptarget->u.KeyNode.Flags & KEY_PREDEF_HANDLE) ) {
  225. //
  226. // First, free the value entries
  227. //
  228. if (ptarget->u.KeyNode.ValueList.Count > 0) {
  229. // target list
  230. plist = HvGetCell(Hive, ptarget->u.KeyNode.ValueList.List);
  231. if( plist == NULL ) {
  232. //
  233. // we couldn't map the bin containing this cell
  234. // we shouldn't hit this as we just marked the cell dirty
  235. //
  236. ASSERT( FALSE );
  237. return STATUS_INSUFFICIENT_RESOURCES;
  238. }
  239. //
  240. // release the cell here as it is dirty(pinned); it cannot go anywhere
  241. //
  242. HvReleaseCell(Hive, ptarget->u.KeyNode.ValueList.List);
  243. for (i = 0; i < ptarget->u.KeyNode.ValueList.Count; i++) {
  244. //
  245. // even if we cannot free the value here, we ignore it.
  246. // nothing bad happens (just some leaks)
  247. //
  248. if( CmpFreeValue(Hive, plist->u.KeyList[i]) == FALSE ) {
  249. //
  250. // we couldn't map view inside call above
  251. // this shouldn't happen as we just marked the values dirty
  252. // (i.e. they should be PINNED into memory by now)
  253. //
  254. ASSERT( FALSE );
  255. }
  256. }
  257. HvFreeCell(Hive, ptarget->u.KeyNode.ValueList.List);
  258. }
  259. //
  260. // Free the security descriptor
  261. //
  262. CmpFreeSecurityDescriptor(Hive, Cell);
  263. }
  264. //
  265. // Free the key body itself, and Class data.
  266. //
  267. if( CmpFreeKeyBody(Hive, Cell) == FALSE ) {
  268. //
  269. // couldn't map view inside
  270. //
  271. return STATUS_INSUFFICIENT_RESOURCES;
  272. }
  273. return STATUS_SUCCESS;
  274. }
  275. BOOLEAN
  276. CmpMarkKeyDirty(
  277. PHHIVE Hive,
  278. HCELL_INDEX Cell
  279. #if DBG
  280. ,
  281. BOOLEAN CheckNoSubkeys
  282. #endif
  283. )
  284. /*++
  285. Routine Description:
  286. Mark all of the cells related to a key being deleted dirty.
  287. Includes the parent, the parent's child list, the key body,
  288. class, security, all value entry bodies, and all of their data cells.
  289. Arguments:
  290. Hive - pointer to hive control structure for hive of interest
  291. Cell - index for cell holding keybody to make dirty
  292. Return Value:
  293. TRUE - it worked
  294. FALSE - some error, most likely cannot get log space
  295. --*/
  296. {
  297. PCELL_DATA ptarget;
  298. PCELL_DATA plist;
  299. PCELL_DATA security;
  300. PCELL_DATA pvalue;
  301. ULONG i;
  302. //
  303. // we have the lock exclusive or nobody is operating inside this hive
  304. //
  305. //ASSERT_CM_LOCK_OWNED_EXCLUSIVE();
  306. ASSERT_CM_EXCLUSIVE_HIVE_ACCESS(Hive);
  307. //
  308. // Map in the target
  309. //
  310. ptarget = HvGetCell(Hive, Cell);
  311. if( ptarget == NULL ) {
  312. //
  313. // we couldn't map the bin containing this cell
  314. //
  315. return FALSE;
  316. }
  317. #if DBG
  318. if(CheckNoSubkeys == TRUE) {
  319. ASSERT(ptarget->u.KeyNode.SubKeyCounts[Stable] == 0);
  320. ASSERT(ptarget->u.KeyNode.SubKeyCounts[Volatile] == 0);
  321. }
  322. #endif //DBG
  323. if (ptarget->u.KeyNode.Flags & KEY_HIVE_EXIT) {
  324. //
  325. // If this is a link node, we are done. Link nodes never have
  326. // classes, values, subkeys, or security descriptors. Since
  327. // they always reside in the master hive, they're always volatile.
  328. //
  329. HvReleaseCell(Hive, Cell);
  330. return(TRUE);
  331. }
  332. //
  333. // mark cell itself
  334. //
  335. if (! HvMarkCellDirty(Hive, Cell)) {
  336. HvReleaseCell(Hive, Cell);
  337. return FALSE;
  338. }
  339. //
  340. // we can safely release it here, as it is now dirty/pinned
  341. //
  342. HvReleaseCell(Hive, Cell);
  343. //
  344. // Mark the class
  345. //
  346. if (ptarget->u.KeyNode.Class != HCELL_NIL) {
  347. if (! HvMarkCellDirty(Hive, ptarget->u.KeyNode.Class)) {
  348. return FALSE;
  349. }
  350. }
  351. //
  352. // Mark security
  353. //
  354. if (ptarget->u.KeyNode.Security != HCELL_NIL) {
  355. if (! HvMarkCellDirty(Hive, ptarget->u.KeyNode.Security)) {
  356. return FALSE;
  357. }
  358. security = HvGetCell(Hive, ptarget->u.KeyNode.Security);
  359. if( security == NULL ) {
  360. //
  361. // we couldn't map the bin containing this cell
  362. // we shouldn't hit this as we just marked the cell dirty
  363. // (i.e. dirty == PINNED in memory)
  364. //
  365. ASSERT( FALSE );
  366. return FALSE;
  367. }
  368. //
  369. // we can safely release it here, as it is now dirty/pinned
  370. //
  371. HvReleaseCell(Hive, ptarget->u.KeyNode.Security);
  372. if (! (HvMarkCellDirty(Hive, security->u.KeySecurity.Flink) &&
  373. HvMarkCellDirty(Hive, security->u.KeySecurity.Blink)))
  374. {
  375. return FALSE;
  376. }
  377. }
  378. //
  379. // Mark the value entries and their data
  380. //
  381. if ( !(ptarget->u.KeyNode.Flags & KEY_PREDEF_HANDLE) &&
  382. (ptarget->u.KeyNode.ValueList.Count > 0)
  383. ) {
  384. // target list
  385. if (! HvMarkCellDirty(Hive, ptarget->u.KeyNode.ValueList.List)) {
  386. return FALSE;
  387. }
  388. plist = HvGetCell(Hive, ptarget->u.KeyNode.ValueList.List);
  389. if( plist == NULL ) {
  390. //
  391. // we couldn't map the bin containing this cell
  392. // we shouldn't hit this as we just marked the cell dirty
  393. // (i.e. dirty == PINNED in memory)
  394. //
  395. ASSERT( FALSE );
  396. return FALSE;
  397. }
  398. //
  399. // we can safely release it here, as it is now dirty/pinned
  400. //
  401. HvReleaseCell(Hive, ptarget->u.KeyNode.ValueList.List);
  402. for (i = 0; i < ptarget->u.KeyNode.ValueList.Count; i++) {
  403. if (! HvMarkCellDirty(Hive, plist->u.KeyList[i])) {
  404. return FALSE;
  405. }
  406. pvalue = HvGetCell(Hive, plist->u.KeyList[i]);
  407. if( pvalue == NULL ) {
  408. //
  409. // we couldn't map the bin containing this cell
  410. // we shouldn't hit this as we just marked the cell dirty
  411. // (i.e. dirty == PINNED in memory)
  412. //
  413. ASSERT( FALSE );
  414. return FALSE;
  415. }
  416. //
  417. // we can safely release it here, as it is now dirty/pinned
  418. //
  419. HvReleaseCell(Hive,plist->u.KeyList[i]);
  420. if( !CmpMarkValueDataDirty(Hive,&(pvalue->u.KeyValue)) ) {
  421. return FALSE;
  422. }
  423. }
  424. }
  425. if (ptarget->u.KeyNode.Flags & KEY_HIVE_ENTRY) {
  426. //
  427. // if this is an entry node, we are done. our parent will
  428. // be in the master hive (and thus volatile)
  429. //
  430. return TRUE;
  431. }
  432. //
  433. // Mark the parent's Subkey list
  434. //
  435. if (! CmpMarkIndexDirty(Hive, ptarget->u.KeyNode.Parent, Cell)) {
  436. return FALSE;
  437. }
  438. //
  439. // Mark the parent
  440. //
  441. if (! HvMarkCellDirty(Hive, ptarget->u.KeyNode.Parent)) {
  442. return FALSE;
  443. }
  444. return TRUE;
  445. }