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.

394 lines
12 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1999.
  5. //
  6. // File: I N S T A L L . C P P
  7. //
  8. // Contents: Implements actions related to installing components.
  9. //
  10. // Notes:
  11. //
  12. // Author: shaunco 15 Jan 1999
  13. //
  14. //----------------------------------------------------------------------------
  15. #include <pch.h>
  16. #pragma hdrstop
  17. #include "classinst.h"
  18. #include "lockdown.h"
  19. #include "netcfg.h"
  20. #include "obotoken.h"
  21. #include "util.h"
  22. #if DBG
  23. VOID
  24. DbgVerifyComponentInstallParams (
  25. IN const COMPONENT_INSTALL_PARAMS& Params)
  26. {
  27. if (!Params.pComponent)
  28. {
  29. Assert (FIsValidNetClass (Params.Class));
  30. Assert (Params.pszInfId && *Params.pszInfId);
  31. Assert (FOboTokenValidForClass (Params.pOboToken, Params.Class));
  32. }
  33. }
  34. #else
  35. #define DbgVerifyComponentInstallParams NOP_FUNCTION
  36. #endif
  37. VOID
  38. CModifyContext::InstallAndAddAndNotifyComponent(
  39. IN const COMPONENT_INSTALL_PARAMS& Params,
  40. OUT CComponent** ppComponent)
  41. {
  42. CNetConfig* pNetConfig;
  43. CComponent* pComponent;
  44. UINT cPreviousAddedBindPaths;
  45. Assert (this);
  46. Assert (S_OK == m_hr);
  47. DbgVerifyComponentInstallParams (Params);
  48. Assert (ppComponent);
  49. pNetConfig = PNetConfig();
  50. // Call the class installer to do the grunt work of finding the
  51. // INF, processing it, creating the instance key, etc. If this
  52. // all succeeds, we are returned an allocated CComponent.
  53. //
  54. //$REVIEW: Think about having HrCiInstallComponent return the
  55. // list of required components. This will keep us from having to
  56. // reopen the instance key and ndi key.
  57. //
  58. if (!Params.pComponent)
  59. {
  60. // error test only
  61. //if (0 == _wcsicmp(L"ms_nwipx", Params.pszInfId))
  62. //{
  63. // TraceTag (ttidBeDiag, "Simulating failure for: %S", Params.pszInfId);
  64. // m_hr = E_FAIL;
  65. // return;
  66. //}
  67. m_hr = HrCiInstallComponent (Params, &pComponent, NULL);
  68. if (S_OK != m_hr)
  69. {
  70. Assert(FAILED(m_hr));
  71. return;
  72. }
  73. }
  74. else
  75. {
  76. pComponent = Params.pComponent;
  77. }
  78. Assert (pComponent);
  79. // Install all of the components required by this component.
  80. //
  81. // THIS MAY CAUSE RECURSION
  82. //
  83. InstallOrRemoveRequiredComponents (pComponent, IOR_INSTALL);
  84. if (S_OK != m_hr)
  85. {
  86. Assert(FAILED(m_hr));
  87. return;
  88. }
  89. // If this is an enumerated component, and it has the same PnpId as
  90. // a component already in our core, we will remove the existing component.
  91. // This can happen if an adapter is removed and reinstalled and the
  92. // binding engine could not be notified of both because the write
  93. // lock was held at the time of remove.
  94. //
  95. if (FIsEnumerated(pComponent->Class()))
  96. {
  97. CComponent* pDup;
  98. while (NULL != (pDup = pNetConfig->Core.Components.PFindComponentByPnpId (
  99. pComponent->m_pszPnpId)))
  100. {
  101. TraceTag (ttidBeDiag, "Removing duplicate PnpId: %S",
  102. pComponent->m_pszPnpId);
  103. pDup->Refs.RemoveAllReferences();
  104. (VOID) HrRemoveComponentIfNotReferenced (pDup, NULL, NULL);
  105. }
  106. }
  107. // We only insert the component and its stack table entries into our
  108. // list after all of its required components have been installed.
  109. // This is just the concept of "don't consider a component installed
  110. // until all of its requirements are also installed".
  111. // i.e. Atomicity of component installation.
  112. //
  113. m_hr = pNetConfig->Core.HrAddComponentToCore (pComponent, INS_SORTED);
  114. if (S_OK != m_hr)
  115. {
  116. Assert(FAILED(m_hr));
  117. return;
  118. }
  119. // Notify the component's notify object it is being installed.
  120. // This also sends global notifications to other notify objects
  121. // who may be interested.
  122. //
  123. // THIS MAY CAUSE RECURSION
  124. //
  125. m_hr = pNetConfig->Notify.ComponentAdded (pComponent, Params.pnip);
  126. if (S_OK != m_hr)
  127. {
  128. Assert(FAILED(m_hr));
  129. return;
  130. }
  131. // Note the number of bindpaths currently in m_AddedBindPaths.
  132. // We need this so that when we add to the set, we only notify
  133. // for the ones we add.
  134. //
  135. cPreviousAddedBindPaths = m_AddedBindPaths.CountBindPaths ();
  136. // Get the bindpaths that involve the component we are adding.
  137. // Add these to the added bindpaths we are keeping track of.
  138. //
  139. m_hr = pNetConfig->Core.HrGetBindingsInvolvingComponent (
  140. pComponent,
  141. GBF_ADD_TO_BINDSET | GBF_ONLY_WHICH_CONTAIN_COMPONENT,
  142. &m_AddedBindPaths);
  143. if (S_OK != m_hr)
  144. {
  145. Assert(FAILED(m_hr));
  146. return;
  147. }
  148. // Query and notify for these added bindpaths.
  149. //
  150. // THIS MAY CAUSE RECURSION
  151. //
  152. if (m_AddedBindPaths.CountBindPaths() > cPreviousAddedBindPaths)
  153. {
  154. m_hr = pNetConfig->Notify.QueryAndNotifyForAddedBindPaths (
  155. &m_AddedBindPaths,
  156. cPreviousAddedBindPaths);
  157. if (S_OK != m_hr)
  158. {
  159. Assert(FAILED(m_hr));
  160. return;
  161. }
  162. }
  163. // Install any components as a convenience to the user
  164. // depending on the component we just installed component.
  165. //
  166. // THIS MAY CAUSE RECURSION
  167. //
  168. InstallConvenienceComponentsForUser (pComponent);
  169. if (S_OK != m_hr)
  170. {
  171. Assert(FAILED(m_hr));
  172. return;
  173. }
  174. // Assign the output pointer.
  175. //
  176. Assert (S_OK == m_hr);
  177. Assert (pComponent);
  178. *ppComponent = pComponent;
  179. }
  180. //+---------------------------------------------------------------------------
  181. // Install components on behalf of the user
  182. //
  183. // Assumptions:
  184. //
  185. VOID
  186. CModifyContext::InstallConvenienceComponentsForUser (
  187. IN const CComponent* pComponent)
  188. {
  189. COMPONENT_INSTALL_PARAMS Params;
  190. OBO_TOKEN UserOboToken;
  191. CComponent* pNewComponent;
  192. Assert (this);
  193. Assert (S_OK == m_hr);
  194. Assert (pComponent);
  195. ZeroMemory (&UserOboToken, sizeof(UserOboToken));
  196. UserOboToken.Type = OBO_USER;
  197. // If the component is an ATM adapter, make sure ATMUNI and ATMLANE are
  198. // installed.
  199. //
  200. if (FSubstringMatch (L"ndisatm", pComponent->Ext.PszUpperRange(),
  201. NULL, NULL))
  202. {
  203. ZeroMemory (&Params, sizeof(Params));
  204. Params.pOboToken = &UserOboToken;
  205. Params.Class = NC_NETTRANS;
  206. Params.pszInfId = L"ms_atmuni";
  207. HrInstallNewOrReferenceExistingComponent (Params, &pNewComponent);
  208. Params.pszInfId = L"ms_atmlane";
  209. HrInstallNewOrReferenceExistingComponent (Params, &pNewComponent);
  210. }
  211. }
  212. HRESULT
  213. CModifyContext::HrInstallNewOrReferenceExistingComponent (
  214. IN const COMPONENT_INSTALL_PARAMS& Params,
  215. OUT CComponent** ppComponent)
  216. {
  217. HRESULT hr;
  218. BOOL fInstallNew;
  219. CNetConfig* pNetConfig;
  220. CComponent* pComponent;
  221. Assert (this);
  222. Assert (S_OK == m_hr);
  223. DbgVerifyComponentInstallParams (Params);
  224. Assert (ppComponent);
  225. // Initialize the output parameter.
  226. //
  227. *ppComponent = NULL;
  228. // Assume, for now, that we will be installing a new component.
  229. //
  230. hr = S_OK;
  231. fInstallNew = TRUE;
  232. pNetConfig = PNetConfig();
  233. pComponent = NULL;
  234. // If the user wishes to add a reference if the component is already
  235. // installed...
  236. //
  237. if (Params.pOboToken)
  238. {
  239. // ...then look to see if the component is installed...
  240. //
  241. pComponent = pNetConfig->Core.Components.
  242. PFindComponentByInfId (Params.pszInfId, NULL);
  243. // ...if it is, we won't be installing a new one.
  244. //
  245. if (pComponent)
  246. {
  247. fInstallNew = FALSE;
  248. if (pComponent->m_dwCharacter & NCF_SINGLE_INSTANCE)
  249. {
  250. *ppComponent = NULL;
  251. return HRESULT_FROM_SETUPAPI(ERROR_DEVINST_ALREADY_EXISTS);
  252. }
  253. // If the existing component is already referenced by
  254. // the specified obo token, we can return.
  255. //
  256. if (pComponent->Refs.FIsReferencedByOboToken (Params.pOboToken))
  257. {
  258. *ppComponent = pComponent;
  259. return S_OK;
  260. }
  261. }
  262. // ...otherwise, (it is not in the current core) but if it IS
  263. // in the core we started with, it means someone had previously
  264. // removed it during this modify context and now wants to add it
  265. // back. This is tricky and should probably be implemented later.
  266. // For now, return an error and throw up an assert so we can see
  267. // who needs to do this.
  268. //
  269. else if (m_CoreStartedWith.Components.
  270. PFindComponentByInfId (Params.pszInfId, NULL))
  271. {
  272. AssertSz (FALSE, "Whoa. Someone is trying to install a "
  273. "component that was previously removed during this same "
  274. "modify context. We need to decide if we can support this.");
  275. return E_UNEXPECTED;
  276. }
  277. }
  278. // If we've decided to install a new component, (which can happen
  279. // if an obo token was not specified OR if an obo token was specified
  280. // but the component was not already present) then do the work.
  281. //
  282. if (fInstallNew)
  283. {
  284. // If the component to be installed is locked down, bail out.
  285. // Note we don't put the modify context into error if this situation
  286. // occurs.
  287. // Note too that we only do this if Params.pComponent is not present
  288. // which would indicate the class installer calling us to install an
  289. // enumerated component.
  290. //
  291. if (!Params.pComponent)
  292. {
  293. if (FIsComponentLockedDown (Params.pszInfId))
  294. {
  295. TraceTag (ttidBeDiag, "%S is locked down and cannot be installed "
  296. "until the next reboot.",
  297. Params.pszInfId);
  298. return NETCFG_E_NEED_REBOOT;
  299. }
  300. }
  301. // Make sure the modify context is setup and keep track of our
  302. // recursion depth.
  303. //
  304. PushRecursionDepth ();
  305. Assert (S_OK == m_hr);
  306. InstallAndAddAndNotifyComponent (Params, ppComponent);
  307. hr = HrPopRecursionDepth ();
  308. // If the component to be installed was not found, the return code
  309. // will be SPAPI_E_NO_DRIVER_SELECTED. We want to return this to the
  310. // caller, but we don't need the context to remain with this error.
  311. // This will allow subsequent calls to install other componetns to
  312. // proceed.
  313. //
  314. if (SPAPI_E_NO_DRIVER_SELECTED == m_hr)
  315. {
  316. m_hr = S_OK;
  317. Assert (SPAPI_E_NO_DRIVER_SELECTED == hr);
  318. }
  319. }
  320. else
  321. {
  322. // Referencing pComponent on behalf of the obo token.
  323. //
  324. Assert (pComponent);
  325. Assert (Params.pOboToken);
  326. // Make sure the modify context is setup and keep track of our
  327. // recursion depth.
  328. //
  329. PushRecursionDepth ();
  330. Assert (S_OK == m_hr);
  331. m_hr = pComponent->Refs.HrAddReferenceByOboToken (Params.pOboToken);
  332. if (S_OK == m_hr)
  333. {
  334. *ppComponent = pComponent;
  335. }
  336. hr = HrPopRecursionDepth ();
  337. }
  338. // If we are returning success, we'd better have our ouput parameter set.
  339. //
  340. Assert (FImplies(SUCCEEDED(hr), *ppComponent));
  341. return hr;
  342. }