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.

189 lines
5.2 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. cmapi2.c
  5. Abstract:
  6. This module contains CM level entry points for the registry,
  7. particularly those which we don't want to link into tools,
  8. setup, the boot loader, etc.
  9. Author:
  10. Bryan M. Willman (bryanwi) 26-Jan-1993
  11. Revision History:
  12. --*/
  13. #include "cmp.h"
  14. #ifdef ALLOC_PRAGMA
  15. #pragma alloc_text(PAGE,CmDeleteKey)
  16. #endif
  17. NTSTATUS
  18. CmDeleteKey(
  19. IN PCM_KEY_BODY KeyBody
  20. )
  21. /*++
  22. Routine Description:
  23. Delete a registry key, clean up Notify block.
  24. Arguments:
  25. KeyBody - pointer to key handle object
  26. Return Value:
  27. NTSTATUS
  28. --*/
  29. {
  30. NTSTATUS status;
  31. PCM_KEY_NODE ptarget;
  32. PHHIVE Hive;
  33. HCELL_INDEX Cell;
  34. HCELL_INDEX Parent;
  35. PCM_KEY_CONTROL_BLOCK KeyControlBlock;
  36. LARGE_INTEGER TimeStamp;
  37. CmKdPrintEx((DPFLTR_CONFIG_ID,CML_CM,"CmDeleteKey\n"));
  38. CmpLockRegistryExclusive();
  39. #ifdef CHECK_REGISTRY_USECOUNT
  40. CmpCheckRegistryUseCount();
  41. #endif //CHECK_REGISTRY_USECOUNT
  42. //
  43. // If already marked for deletion, storage is gone, so
  44. // do nothing and return success.
  45. //
  46. KeyControlBlock = KeyBody->KeyControlBlock;
  47. PERFINFO_REG_DELETE_KEY(KeyControlBlock);
  48. if (KeyControlBlock->Delete == TRUE) {
  49. status = STATUS_SUCCESS;
  50. goto Exit;
  51. }
  52. // Mark the hive as read only
  53. CmpMarkAllBinsReadOnly(KeyControlBlock->KeyHive);
  54. ptarget = (PCM_KEY_NODE)HvGetCell(KeyControlBlock->KeyHive, KeyControlBlock->KeyCell);
  55. if( ptarget == NULL ) {
  56. //
  57. // we couldn't map a view for the bin containing this cell
  58. //
  59. status = STATUS_INSUFFICIENT_RESOURCES;
  60. goto Exit;
  61. }
  62. // release the cell right here, as the registry is locked exclusively, so we don't care
  63. HvReleaseCell(KeyControlBlock->KeyHive, KeyControlBlock->KeyCell);
  64. ASSERT( ptarget->Flags == KeyControlBlock->Flags );
  65. if ( ((ptarget->SubKeyCounts[Stable] + ptarget->SubKeyCounts[Volatile]) == 0) &&
  66. ((ptarget->Flags & KEY_NO_DELETE) == 0))
  67. {
  68. //
  69. // Cell is NOT marked NO_DELETE and does NOT have children
  70. // Send Notification while key still present, if delete fails,
  71. // we'll have sent a spurious notify, that doesn't matter
  72. // Delete the actual storage
  73. //
  74. Hive = KeyControlBlock->KeyHive;
  75. Cell = KeyControlBlock->KeyCell;
  76. Parent = ptarget->Parent;
  77. CmpReportNotify(
  78. KeyControlBlock,
  79. Hive,
  80. Cell,
  81. REG_NOTIFY_CHANGE_NAME
  82. );
  83. status = CmpFreeKeyByCell(Hive, Cell, TRUE);
  84. if (NT_SUCCESS(status)) {
  85. //
  86. // post any waiting notifies
  87. //
  88. CmpFlushNotifiesOnKeyBodyList(KeyControlBlock);
  89. //
  90. // Remove kcb out of cache, but do NOT
  91. // free its storage, CmDelete will do that when
  92. // the RefCount becomes zero.
  93. //
  94. // There are two things that can hold the RefCount non-zero.
  95. //
  96. // 1. open handles for this key
  97. // 2. Fake subKeys that are still in DelayClose.
  98. //
  99. // At this point, we have no way of deleting the fake subkeys from cache
  100. // unless we do a search for the whole cache, which is too expensive.
  101. // Thus, we decide to either let the fake keys age out of cache or when
  102. // someone is doing the lookup for the fake key, then we delete it at that point.
  103. // See routine CmpCacheLookup in cmparse.c for more details.
  104. //
  105. // If the parent has the subkey info or hint cached, free it.
  106. // Again, registry is locked exclusively, no need to lock KCB.
  107. //
  108. ASSERT_CM_LOCK_OWNED_EXCLUSIVE();
  109. CmpCleanUpSubKeyInfo(KeyControlBlock->ParentKcb);
  110. ptarget = (PCM_KEY_NODE)HvGetCell(Hive, Parent);
  111. if( ptarget != NULL ) {
  112. // release the cell right here, as the registry is locked exclusively, so we don't care
  113. HvReleaseCell(Hive, Parent);
  114. //
  115. // this should always be true as CmpFreeKeyByCell always marks the parent dirty on success
  116. //
  117. KeyControlBlock->ParentKcb->KcbMaxNameLen = (USHORT)ptarget->MaxNameLen;
  118. // sanity
  119. ASSERT_CELL_DIRTY(Hive,Parent);
  120. //
  121. // update the LastWriteTime on parent and kcb too
  122. //
  123. KeQuerySystemTime(&TimeStamp);
  124. ptarget->LastWriteTime = TimeStamp;
  125. KeyBody->KeyControlBlock->ParentKcb->KcbLastWriteTime = TimeStamp;
  126. }
  127. KeyControlBlock->Delete = TRUE;
  128. CmpRemoveKeyControlBlock(KeyControlBlock);
  129. KeyControlBlock->KeyCell = HCELL_NIL;
  130. }
  131. } else {
  132. status = STATUS_CANNOT_DELETE;
  133. }
  134. Exit:
  135. #ifdef CHECK_REGISTRY_USECOUNT
  136. CmpCheckRegistryUseCount();
  137. #endif //CHECK_REGISTRY_USECOUNT
  138. CmpUnlockRegistry();
  139. // Mark the hive as read only
  140. CmpMarkAllBinsReadOnly(KeyControlBlock->KeyHive);
  141. return status;
  142. }