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.

246 lines
7.5 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1999.
  5. //
  6. // File: R E M O V E . C P P
  7. //
  8. // Contents: Implements actions related to removing components.
  9. //
  10. // Notes:
  11. //
  12. // Author: shaunco 15 Jan 1999
  13. //
  14. //----------------------------------------------------------------------------
  15. #include <pch.h>
  16. #pragma hdrstop
  17. #include "ncreg.h"
  18. #include "netcfg.h"
  19. VOID
  20. CModifyContext::NotifyAndRemoveComponent (
  21. IN CComponent* pComponent)
  22. {
  23. CNetConfig* pNetConfig;
  24. UINT cPreviousDeletedBindPaths;
  25. Assert (this);
  26. Assert (S_OK == m_hr);
  27. Assert (pComponent);
  28. pNetConfig = PNetConfig();
  29. // Note the number of bindpaths currently in m_DeletedBindPaths.
  30. // We need this so that when we add to the set, we only notify
  31. // for the ones we add.
  32. //
  33. cPreviousDeletedBindPaths = m_DeletedBindPaths.CountBindPaths ();
  34. // Get the bindpaths that involve the component we are removing.
  35. // Add these to the deleted bindpaths we are keeping track of.
  36. //
  37. m_hr = pNetConfig->Core.HrGetBindingsInvolvingComponent (
  38. pComponent,
  39. GBF_ADD_TO_BINDSET | GBF_ONLY_WHICH_CONTAIN_COMPONENT,
  40. &m_DeletedBindPaths);
  41. if (S_OK != m_hr)
  42. {
  43. Assert(FAILED(m_hr));
  44. return;
  45. }
  46. // Remove the component from the core.
  47. //
  48. pNetConfig->Core.RemoveComponentFromCore (pComponent);
  49. // Notify that these bindpaths are being removed. We only need to do
  50. // so if we added any new ones to the set. Existing ones in the set
  51. // have already been notified.
  52. //
  53. // THIS MAY CAUSE RECURSION
  54. //
  55. if (m_DeletedBindPaths.CountBindPaths() > cPreviousDeletedBindPaths)
  56. {
  57. m_hr = pNetConfig->Notify.NotifyRemovedBindPaths (
  58. &m_DeletedBindPaths,
  59. cPreviousDeletedBindPaths);
  60. if (S_OK != m_hr)
  61. {
  62. Assert(FAILED(m_hr));
  63. return;
  64. }
  65. }
  66. // Notify the component's notify object it is being removed.
  67. // This also sends global notifications to other notify objects
  68. // who may be interested.
  69. //
  70. // THIS MAY CAUSE RECURSION
  71. //
  72. m_hr = pNetConfig->Notify.ComponentRemoved (pComponent);
  73. if (S_OK != m_hr)
  74. {
  75. Assert(FAILED(m_hr));
  76. return;
  77. }
  78. // If we have a cached INetCfgComponent interface, we need to tell it
  79. // that the component it represents is no longer valid.
  80. //
  81. pComponent->ReleaseINetCfgComponentInterface ();
  82. // Remove (if not referenced) any components that this component
  83. // required.
  84. //
  85. // THIS MAY CAUSE RECURSION
  86. //
  87. InstallOrRemoveRequiredComponents (pComponent, IOR_REMOVE);
  88. if (S_OK != m_hr)
  89. {
  90. Assert(FAILED(m_hr));
  91. return;
  92. }
  93. // Now that we've given a chance to notify objects to remove references
  94. // to the component being removed, we need to ensure it is not
  95. // referenced by anyone else.
  96. // Check to see if the component we just removed is still
  97. // referencing other components. If it is, it means it forgot
  98. // to remove those components. We'll print what they are and
  99. // remove the bogus reference (but not the components themselves)
  100. // so that when we save the configuration binary we don't
  101. // barf trying to lookup the index of this component we just
  102. // removed.)
  103. //
  104. pNetConfig->Core.EnsureComponentNotReferencedByOthers (pComponent);
  105. }
  106. HRESULT
  107. CModifyContext::HrRemoveComponentIfNotReferenced (
  108. IN CComponent* pComponent,
  109. IN OBO_TOKEN* pOboToken OPTIONAL,
  110. OUT PWSTR* ppmszwRefs OPTIONAL)
  111. {
  112. CNetConfig* pNetConfig;
  113. BOOL fStillReferenced;
  114. Assert (this);
  115. Assert (S_OK == m_hr);
  116. Assert (pComponent);
  117. // If the caller is requesting removal on behalf of an obo token,
  118. // (and its not obo the user) make sure the component is actually
  119. // referenced by that obo token. If it is not, consider it an
  120. // invalid argument.
  121. //
  122. // The reason we don't consider the obo user case is because the UI
  123. // will show anything that is installed and allow the user to try to
  124. // remove them. If the user hasn't actually installed it, we don't
  125. // want to treat this as an invalid argument, rather, we want to let
  126. // the code fall through to the case where we will return the multi-sz
  127. // of descriptions of components still referencing the component.
  128. //
  129. // However, if there are no references (which can happen if we delete
  130. // the configuration binary and then re-create it) we'll go ahead and
  131. // allow removals by anyone). This is a safety-net.
  132. //
  133. // The overall purpose of the following 'if' is to catch programatic
  134. // removals that are on behalf of other components or software that
  135. // have previously installed the component being removed.
  136. //
  137. if (pOboToken &&
  138. (OBO_USER != pOboToken->Type) &&
  139. !pComponent->Refs.FIsReferencedByOboToken (pOboToken) &&
  140. (pComponent->Refs.CountTotalReferencedBy() > 0))
  141. {
  142. return E_INVALIDARG;
  143. }
  144. pNetConfig = PNetConfig();
  145. fStillReferenced = TRUE;
  146. // Now that we actually are going to modify something, push a new
  147. // recursion depth.
  148. //
  149. PushRecursionDepth ();
  150. Assert (S_OK == m_hr);
  151. // If the component is NOT in the list of components we started with,
  152. // it means someone had previously installed it during this modify
  153. // context and now wants to remove it. This is tricky and should
  154. // probably be implemented later. For now, return an error and throw
  155. // up an assert so we can see who needs to do this.
  156. //
  157. if (!m_CoreStartedWith.Components.FComponentInList (pComponent))
  158. {
  159. AssertSz (FALSE, "Whoa. Someone is trying to remove a "
  160. "component that was previously installed during this same "
  161. "modify context. We need to decide if we can support this.");
  162. m_hr = E_UNEXPECTED;
  163. }
  164. if (pOboToken && (S_OK == m_hr))
  165. {
  166. m_hr = pComponent->Refs.HrRemoveReferenceByOboToken (pOboToken);
  167. }
  168. // If no obo token, or we removed the reference from it, actually
  169. // remove it if it is not still referenced by anything else.
  170. //
  171. if (S_OK == m_hr)
  172. {
  173. if (0 == pComponent->Refs.CountTotalReferencedBy())
  174. {
  175. fStillReferenced = FALSE;
  176. NotifyAndRemoveComponent (pComponent);
  177. }
  178. else if (ppmszwRefs)
  179. {
  180. ULONG cb;
  181. // Need to return the multi-sz of descriptions still referencing
  182. // the component the caller tried to remove.
  183. //
  184. // Size the data first.
  185. //
  186. cb = 0;
  187. pComponent->Refs.GetReferenceDescriptionsAsMultiSz (
  188. NULL, &cb);
  189. Assert (cb);
  190. // Allocate room to return the multi-sz.
  191. //
  192. Assert (S_OK == m_hr);
  193. m_hr = HrCoTaskMemAlloc (cb, (VOID**)ppmszwRefs);
  194. if (S_OK == m_hr)
  195. {
  196. // Now get the multi-sz.
  197. //
  198. pComponent->Refs.GetReferenceDescriptionsAsMultiSz (
  199. (BYTE*)(*ppmszwRefs), &cb);
  200. Assert (fStillReferenced);
  201. }
  202. }
  203. }
  204. HRESULT hr;
  205. hr = HrPopRecursionDepth ();
  206. if (fStillReferenced && SUCCEEDED(hr))
  207. {
  208. // Still reference return code overrides other success codes like
  209. // need reboot.
  210. //
  211. hr = NETCFG_S_STILL_REFERENCED;
  212. }
  213. return hr;
  214. }