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.

552 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. ULONG realsize;
  303. //
  304. // we have the lock exclusive or nobody is operating inside this hive
  305. //
  306. //ASSERT_CM_LOCK_OWNED_EXCLUSIVE();
  307. ASSERT_CM_EXCLUSIVE_HIVE_ACCESS(Hive);
  308. //
  309. // Map in the target
  310. //
  311. ptarget = HvGetCell(Hive, Cell);
  312. if( ptarget == NULL ) {
  313. //
  314. // we couldn't map the bin containing this cell
  315. //
  316. return FALSE;
  317. }
  318. #if DBG
  319. if(CheckNoSubkeys == TRUE) {
  320. ASSERT(ptarget->u.KeyNode.SubKeyCounts[Stable] == 0);
  321. ASSERT(ptarget->u.KeyNode.SubKeyCounts[Volatile] == 0);
  322. }
  323. #endif //DBG
  324. if (ptarget->u.KeyNode.Flags & KEY_HIVE_EXIT) {
  325. //
  326. // If this is a link node, we are done. Link nodes never have
  327. // classes, values, subkeys, or security descriptors. Since
  328. // they always reside in the master hive, they're always volatile.
  329. //
  330. HvReleaseCell(Hive, Cell);
  331. return(TRUE);
  332. }
  333. //
  334. // mark cell itself
  335. //
  336. if (! HvMarkCellDirty(Hive, Cell)) {
  337. HvReleaseCell(Hive, Cell);
  338. return FALSE;
  339. }
  340. //
  341. // we can safely release it here, as it is now dirty/pinned
  342. //
  343. HvReleaseCell(Hive, Cell);
  344. //
  345. // Mark the class
  346. //
  347. if (ptarget->u.KeyNode.Class != HCELL_NIL) {
  348. if (! HvMarkCellDirty(Hive, ptarget->u.KeyNode.Class)) {
  349. return FALSE;
  350. }
  351. }
  352. //
  353. // Mark security
  354. //
  355. if (ptarget->u.KeyNode.Security != HCELL_NIL) {
  356. if (! HvMarkCellDirty(Hive, ptarget->u.KeyNode.Security)) {
  357. return FALSE;
  358. }
  359. security = HvGetCell(Hive, ptarget->u.KeyNode.Security);
  360. if( security == NULL ) {
  361. //
  362. // we couldn't map the bin containing this cell
  363. // we shouldn't hit this as we just marked the cell dirty
  364. // (i.e. dirty == PINNED in memory)
  365. //
  366. ASSERT( FALSE );
  367. return FALSE;
  368. }
  369. //
  370. // we can safely release it here, as it is now dirty/pinned
  371. //
  372. HvReleaseCell(Hive, ptarget->u.KeyNode.Security);
  373. if (! (HvMarkCellDirty(Hive, security->u.KeySecurity.Flink) &&
  374. HvMarkCellDirty(Hive, security->u.KeySecurity.Blink)))
  375. {
  376. return FALSE;
  377. }
  378. }
  379. //
  380. // Mark the value entries and their data
  381. //
  382. if ( !(ptarget->u.KeyNode.Flags & KEY_PREDEF_HANDLE) &&
  383. (ptarget->u.KeyNode.ValueList.Count > 0)
  384. ) {
  385. // target list
  386. if (! HvMarkCellDirty(Hive, ptarget->u.KeyNode.ValueList.List)) {
  387. return FALSE;
  388. }
  389. plist = HvGetCell(Hive, ptarget->u.KeyNode.ValueList.List);
  390. if( plist == NULL ) {
  391. //
  392. // we couldn't map the bin containing this cell
  393. // we shouldn't hit this as we just marked the cell dirty
  394. // (i.e. dirty == PINNED in memory)
  395. //
  396. ASSERT( FALSE );
  397. return FALSE;
  398. }
  399. //
  400. // we can safely release it here, as it is now dirty/pinned
  401. //
  402. HvReleaseCell(Hive, ptarget->u.KeyNode.ValueList.List);
  403. for (i = 0; i < ptarget->u.KeyNode.ValueList.Count; i++) {
  404. if (! HvMarkCellDirty(Hive, plist->u.KeyList[i])) {
  405. return FALSE;
  406. }
  407. pvalue = HvGetCell(Hive, plist->u.KeyList[i]);
  408. if( pvalue == NULL ) {
  409. //
  410. // we couldn't map the bin containing this cell
  411. // we shouldn't hit this as we just marked the cell dirty
  412. // (i.e. dirty == PINNED in memory)
  413. //
  414. ASSERT( FALSE );
  415. return FALSE;
  416. }
  417. //
  418. // we can safely release it here, as it is now dirty/pinned
  419. //
  420. HvReleaseCell(Hive,plist->u.KeyList[i]);
  421. if( !CmpMarkValueDataDirty(Hive,&(pvalue->u.KeyValue)) ) {
  422. return FALSE;
  423. }
  424. }
  425. }
  426. if (ptarget->u.KeyNode.Flags & KEY_HIVE_ENTRY) {
  427. //
  428. // if this is an entry node, we are done. our parent will
  429. // be in the master hive (and thus volatile)
  430. //
  431. return TRUE;
  432. }
  433. //
  434. // Mark the parent's Subkey list
  435. //
  436. if (! CmpMarkIndexDirty(Hive, ptarget->u.KeyNode.Parent, Cell)) {
  437. return FALSE;
  438. }
  439. //
  440. // Mark the parent
  441. //
  442. if (! HvMarkCellDirty(Hive, ptarget->u.KeyNode.Parent)) {
  443. return FALSE;
  444. }
  445. return TRUE;
  446. }