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.

1013 lines
29 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1999.
  5. //
  6. // File: N E T C F G . C P P
  7. //
  8. // Contents: The main set of routines for dealing with the network
  9. // binding engine.
  10. //
  11. // Notes:
  12. //
  13. // Author: shaunco 15 Jan 1999
  14. //
  15. //----------------------------------------------------------------------------
  16. #include <pch.h>
  17. #pragma hdrstop
  18. #include "diagctx.h"
  19. #include "inetcfg.h"
  20. #include "persist.h"
  21. #include "netcfg.h"
  22. #include "util.h"
  23. // Called after a component has been removed. In case this component
  24. // is still listed in any other component's references, we remove those
  25. // references. This can happen if a notify object installs something
  26. // on behalf of its component, but forgets to remove it.
  27. //
  28. VOID
  29. CNetConfigCore::EnsureComponentNotReferencedByOthers (
  30. IN const CComponent* pComponent)
  31. {
  32. TraceFileFunc(ttidNetcfgBase);
  33. CComponentList::iterator iter;
  34. CComponent* pScan;
  35. for (iter = Components.begin();
  36. iter != Components.end();
  37. iter++)
  38. {
  39. pScan = *iter;
  40. Assert (pScan);
  41. if (pScan->Refs.FIsReferencedByComponent (pComponent))
  42. {
  43. g_pDiagCtx->Printf (ttidBeDiag, " %S is still referenced by %S. "
  44. "Removing the refernce.\n",
  45. pScan->PszGetPnpIdOrInfId(),
  46. pComponent->PszGetPnpIdOrInfId());
  47. pScan->Refs.RemoveReferenceByComponent (pComponent);
  48. }
  49. }
  50. }
  51. HRESULT
  52. CNetConfigCore::HrCopyCore (
  53. IN const CNetConfigCore* pSourceCore)
  54. {
  55. TraceFileFunc(ttidNetcfgBase);
  56. HRESULT hr;
  57. hr = Components.HrCopyComponentList (&pSourceCore->Components);
  58. if (S_OK != hr)
  59. {
  60. goto finished;
  61. }
  62. hr = StackTable.HrCopyStackTable (&pSourceCore->StackTable);
  63. if (S_OK != hr)
  64. {
  65. goto finished;
  66. }
  67. hr = DisabledBindings.HrCopyBindingSet (&pSourceCore->DisabledBindings);
  68. if (S_OK != hr)
  69. {
  70. goto finished;
  71. }
  72. finished:
  73. if (S_OK != hr)
  74. {
  75. Clear ();
  76. }
  77. TraceHr (ttidError, FAL, hr, FALSE, "CNetConfigCore::HrCopyCore");
  78. return hr;
  79. }
  80. VOID
  81. CNetConfigCore::Clear ()
  82. {
  83. TraceFileFunc(ttidNetcfgBase);
  84. Assert (this);
  85. DisabledBindings.Clear();
  86. StackTable.Clear();
  87. Components.Clear();
  88. }
  89. VOID
  90. CNetConfigCore::Free ()
  91. {
  92. TraceFileFunc(ttidNetcfgBase);
  93. Assert (this);
  94. FreeCollectionAndItem (Components);
  95. }
  96. BOOL
  97. CNetConfigCore::FIsEmpty () const
  98. {
  99. TraceFileFunc(ttidNetcfgBase);
  100. return Components.FIsEmpty () &&
  101. StackTable.FIsEmpty () &&
  102. DisabledBindings.FIsEmpty ();
  103. }
  104. BOOL
  105. CNetConfigCore::FContainsFilterComponent () const
  106. {
  107. TraceFileFunc(ttidNetcfgBase);
  108. CComponentList::const_iterator iter;
  109. const CComponent* pComponent;
  110. for (iter = Components.begin();
  111. iter != Components.end();
  112. iter++)
  113. {
  114. pComponent = *iter;
  115. Assert (pComponent);
  116. if (pComponent->FIsFilter())
  117. {
  118. return TRUE;
  119. }
  120. }
  121. return FALSE;
  122. }
  123. BOOL
  124. CNetConfigCore::FIsBindPathDisabled (
  125. IN const CBindPath* pBindPath,
  126. IN DWORD dwFlags /* IBD_FLAGS */) const
  127. {
  128. TraceFileFunc(ttidNetcfgBase);
  129. const CBindPath* pScan;
  130. Assert (this);
  131. Assert (pBindPath);
  132. Assert ((dwFlags & IBD_EXACT_MATCH_ONLY) ||
  133. (dwFlags & IBD_MATCH_SUBPATHS_TOO));
  134. DbgVerifyBindingSet (&DisabledBindings);
  135. // The bindpath is disabled if it matches one of the bindpaths in
  136. // the disabled set or if one of the bindpaths in the disabled set
  137. // is a subpath of it.
  138. //
  139. // IBD_EXACT_MATCH_ONLY is used when writing bindings to the registry.
  140. // We only neglect writing a disabled binding for the components
  141. // which directly have the disabled binding. i.e. if
  142. // netbt>-tcpip->adapter is disabled, we only negect to write the
  143. // binding for netbt. We still write binding for components above
  144. // netbt (server, client) as if they were bound. We do this because
  145. // 1) it doesn't matter that the upper components have these written
  146. // 2) it means we don't have to involve these upper components in
  147. // PnP notifications when then binding is enabled/disabled.
  148. //
  149. // IBD_MATCH_SUBPATHS_TOO is used when reporting bindpaths as enabled
  150. // or disabled through the INetCfg interface. To clients, a binding
  151. // is disabled if any of its subpaths are disabled. It has to be
  152. // because there is no way that connectivity along the entire path
  153. // will happen if any of the subpaths are cut-off (disabled).
  154. //
  155. for (pScan = DisabledBindings.begin();
  156. pScan != DisabledBindings.end();
  157. pScan++)
  158. {
  159. if (pScan->FIsSameBindPathAs (pBindPath))
  160. {
  161. return TRUE;
  162. }
  163. if (dwFlags & IBD_MATCH_SUBPATHS_TOO)
  164. {
  165. if (pScan->FIsSubPathOf (pBindPath))
  166. {
  167. return TRUE;
  168. }
  169. }
  170. }
  171. return FALSE;
  172. }
  173. // An alternate way to check if a bindpath is disabled when you have
  174. // just the two components in question and you know that they are expected
  175. // to be bound to one another. Using this method as opposed to
  176. // FIsBindPathDisabled is better when you don't have the binpath allocated
  177. // and don't want to allocate one just to check it. Thus, this method
  178. // allocates no memory and doesn't need to check subpaths because a bindpath
  179. // of length 2 can have no subpaths. This method is used primarily when
  180. // seeing if a filter is bound to an adapter.
  181. //
  182. BOOL
  183. CNetConfigCore::FIsLength2BindPathDisabled (
  184. IN const CComponent* pUpper,
  185. IN const CComponent* pLower) const
  186. {
  187. TraceFileFunc(ttidNetcfgBase);
  188. const CBindPath* pScan;
  189. Assert (this);
  190. Assert (pUpper);
  191. Assert (pLower);
  192. DbgVerifyBindingSet (&DisabledBindings);
  193. for (pScan = DisabledBindings.begin();
  194. pScan != DisabledBindings.end();
  195. pScan++)
  196. {
  197. if (pScan->CountComponents() != 2)
  198. {
  199. continue;
  200. }
  201. if ((pScan->POwner() == pUpper) &&
  202. (pScan->PLastComponent() == pLower))
  203. {
  204. return TRUE;
  205. }
  206. }
  207. return FALSE;
  208. }
  209. HRESULT
  210. CNetConfigCore::HrDisableBindPath (
  211. IN const CBindPath* pBindPath)
  212. {
  213. TraceFileFunc(ttidNetcfgBase);
  214. HRESULT hr;
  215. Assert (this);
  216. Assert (pBindPath);
  217. hr = DisabledBindings.HrAddBindPath (
  218. pBindPath, INS_IGNORE_IF_DUP | INS_APPEND);
  219. DbgVerifyBindingSet (&DisabledBindings);
  220. TraceHr (ttidError, FAL, hr, FALSE,
  221. "CNetConfigCore::HrDisableBindPath");
  222. return hr;
  223. }
  224. HRESULT
  225. CNetConfigCore::HrGetComponentBindings (
  226. IN const CComponent* pComponent,
  227. IN DWORD dwFlags /* GB_FLAGS */,
  228. OUT CBindingSet* pBindSet)
  229. {
  230. TraceFileFunc(ttidNetcfgBase);
  231. GBCONTEXT Ctx;
  232. Assert (pComponent);
  233. Assert (pBindSet);
  234. DbgVerifyData();
  235. // Initialize the output parameter.
  236. //
  237. if (!(dwFlags & GBF_ADD_TO_BINDSET))
  238. {
  239. pBindSet->Clear();
  240. }
  241. // Initialize the members of our context structure for recursion.
  242. // We set the append bindpath flags to assert if a duplicate is inserted
  243. // because we know that GetBindingsBelowComponent will not insert
  244. // duplicates under normal conditions.
  245. //
  246. ZeroMemory (&Ctx, sizeof(Ctx));
  247. Ctx.pCore = this;
  248. Ctx.pBindSet = pBindSet;
  249. Ctx.pSourceComponent = pComponent;
  250. Ctx.fPruneDisabledBindings = (dwFlags & GBF_PRUNE_DISABLED_BINDINGS);
  251. Ctx.dwAddBindPathFlags = (dwFlags & GBF_ADD_TO_BINDSET)
  252. ? INS_IGNORE_IF_DUP
  253. : INS_ASSERT_IF_DUP;
  254. GetBindingsBelowComponent (pComponent, &Ctx);
  255. // Verify the bindset we are about to return is valid.
  256. // (Checked builds only.)
  257. //
  258. if (S_OK == Ctx.hr)
  259. {
  260. DbgVerifyBindingSet (pBindSet);
  261. }
  262. TraceHr (ttidError, FAL, Ctx.hr, FALSE,
  263. "CNetConfigCore::HrGetComponentBindings");
  264. return Ctx.hr;
  265. }
  266. HRESULT
  267. CNetConfigCore::HrGetComponentUpperBindings (
  268. IN const CComponent* pComponent,
  269. IN DWORD dwFlags,
  270. OUT CBindingSet* pBindSet)
  271. {
  272. TraceFileFunc(ttidNetcfgBase);
  273. HRESULT hr = S_OK;
  274. CBindPath BindPath;
  275. const CStackEntry* pScan;
  276. DWORD dwAddBindPathFlags;
  277. Assert (pComponent);
  278. Assert (FIsEnumerated(pComponent->Class()));
  279. Assert ((GBF_DEFAULT == dwFlags) ||
  280. (dwFlags & GBF_ADD_TO_BINDSET) ||
  281. (dwFlags & GBF_PRUNE_DISABLED_BINDINGS));
  282. Assert (pBindSet);
  283. DbgVerifyData();
  284. dwAddBindPathFlags = INS_APPEND | INS_IGNORE_IF_DUP;
  285. // Initialize the output parameter.
  286. //
  287. if (!(dwFlags & GBF_ADD_TO_BINDSET))
  288. {
  289. pBindSet->Clear();
  290. dwAddBindPathFlags = INS_APPEND | INS_ASSERT_IF_DUP;
  291. }
  292. hr = BindPath.HrReserveRoomForComponents (2);
  293. if (S_OK == hr)
  294. {
  295. // This won't fail because we've reserved enough room above.
  296. //
  297. hr = BindPath.HrInsertComponent (pComponent);
  298. Assert (S_OK == hr);
  299. Assert (1 == BindPath.CountComponents());
  300. // For all rows in the stack table where the lower component
  301. // is the one passed in...
  302. //
  303. for (pScan = StackTable.begin();
  304. pScan != StackTable.end();
  305. pScan++)
  306. {
  307. if (pComponent != pScan->pLower)
  308. {
  309. continue;
  310. }
  311. // Continue if this length-2 bindpath is disabled.
  312. //
  313. if (dwFlags & GBF_PRUNE_DISABLED_BINDINGS)
  314. {
  315. if (FIsLength2BindPathDisabled (pScan->pUpper, pScan->pLower))
  316. {
  317. continue;
  318. }
  319. }
  320. // This won't fail because we've reserved enough room above.
  321. //
  322. hr = BindPath.HrInsertComponent (pScan->pUpper);
  323. Assert (S_OK == hr);
  324. Assert (2 == BindPath.CountComponents());
  325. hr = pBindSet->HrAddBindPath (&BindPath, dwAddBindPathFlags);
  326. if (S_OK != hr)
  327. {
  328. break;
  329. }
  330. BindPath.RemoveFirstComponent();
  331. }
  332. // Verify the bindset we are about to return is valid.
  333. // (Checked builds only.)
  334. //
  335. DbgVerifyBindingSet (pBindSet);
  336. }
  337. TraceHr (ttidError, FAL, hr, FALSE,
  338. "CNetConfigCore::HrGetComponentUpperBindings");
  339. return hr;
  340. }
  341. HRESULT
  342. CNetConfigCore::HrGetBindingsInvolvingComponent (
  343. IN const CComponent* pComponent,
  344. IN DWORD dwFlags,
  345. IN OUT CBindingSet* pBindSet)
  346. {
  347. TraceFileFunc(ttidNetcfgBase);
  348. GCCONTEXT Ctx;
  349. CComponentList ComponentsAbove;
  350. UINT cExistingBindPaths;
  351. Assert (pComponent);
  352. Assert ((GBF_DEFAULT == dwFlags) ||
  353. (dwFlags & GBF_ADD_TO_BINDSET) ||
  354. (dwFlags & GBF_PRUNE_DISABLED_BINDINGS) ||
  355. (dwFlags & GBF_ONLY_WHICH_CONTAIN_COMPONENT));
  356. Assert (pBindSet);
  357. DbgVerifyData();
  358. // Initialize the output parameter.
  359. //
  360. if (!(dwFlags & GBF_ADD_TO_BINDSET))
  361. {
  362. pBindSet->Clear();
  363. }
  364. // Since we may be adding to the bindset, be sure to exclude the existing
  365. // bindpaths from our scans below.
  366. //
  367. cExistingBindPaths = pBindSet->CountBindPaths();
  368. // Initialize the members of our context structure for recursion.
  369. //
  370. ZeroMemory (&Ctx, sizeof(Ctx));
  371. Ctx.pStackTable = &StackTable;
  372. Ctx.pComponents = &ComponentsAbove;
  373. Ctx.fIgnoreDontExposeLower = TRUE;
  374. GetComponentsAboveComponent (pComponent, &Ctx);
  375. if (S_OK == Ctx.hr)
  376. {
  377. // First get the bindings below the component.
  378. //
  379. Ctx.hr = HrGetComponentBindings (
  380. pComponent,
  381. dwFlags | GBF_ADD_TO_BINDSET,
  382. pBindSet);
  383. if (S_OK == Ctx.hr)
  384. {
  385. CComponentList::const_iterator iter;
  386. const CComponent* pComponentAbove;
  387. // Now get the bindings below each of the components
  388. // above the component and add them to the bindset.
  389. //
  390. for (iter = ComponentsAbove.begin();
  391. iter != ComponentsAbove.end();
  392. iter++)
  393. {
  394. pComponentAbove = *iter;
  395. Assert (pComponentAbove);
  396. Ctx.hr = HrGetComponentBindings (
  397. pComponentAbove,
  398. dwFlags | GBF_ADD_TO_BINDSET,
  399. pBindSet);
  400. if (S_OK != Ctx.hr)
  401. {
  402. break;
  403. }
  404. // Verify the bindset we are about to return is valid.
  405. // (Checked builds only.)
  406. //
  407. DbgVerifyBindingSet (pBindSet);
  408. }
  409. }
  410. // Now remove any bindings that don't involve the component.
  411. // If the component is enumerated, leave bindings that end in
  412. // NCF_DONTEXPOSELOWER components, because they are indirectly
  413. // involved in the bindings associated with the adapter.
  414. //
  415. if (S_OK == Ctx.hr)
  416. {
  417. CBindPath* pScan;
  418. BOOL fIsEnumerated;
  419. fIsEnumerated = FIsEnumerated(pComponent->Class());
  420. if (fIsEnumerated || !(dwFlags & GBF_ONLY_WHICH_CONTAIN_COMPONENT))
  421. {
  422. // fDelBoundToComponent means "is there a NCF_DONTEXPOSELOWER
  423. // component bound to pComponent". If there is not, we will
  424. // be setting GBF_ONLY_WHICH_CONTAIN_COMPONENT to force the
  425. // removal of any NCF_DONTEXPOSELOWER components from
  426. // the bind set below.
  427. //
  428. BOOL fDelBoundToComponent = FALSE;
  429. for (pScan = pBindSet->PGetBindPathAtIndex (cExistingBindPaths);
  430. pScan != pBindSet->end();
  431. pScan++)
  432. {
  433. if ((pScan->PLastComponent() == pComponent) &&
  434. (pScan->POwner()->m_dwCharacter & NCF_DONTEXPOSELOWER))
  435. {
  436. fDelBoundToComponent = TRUE;
  437. break;
  438. }
  439. }
  440. if (!fDelBoundToComponent)
  441. {
  442. dwFlags |= GBF_ONLY_WHICH_CONTAIN_COMPONENT;
  443. }
  444. }
  445. pScan = pBindSet->PGetBindPathAtIndex (cExistingBindPaths);
  446. while (pScan != pBindSet->end())
  447. {
  448. if (pScan->FContainsComponent (pComponent))
  449. {
  450. pScan++;
  451. continue;
  452. }
  453. // At this point, we know that the bindpath does not
  454. // contain pComponent. See if we should erase it or keep it.
  455. //
  456. // If the component is not an adpater or if the caller wants
  457. // only bindpaths which contain the adapter, erase it.
  458. //
  459. if (!fIsEnumerated ||
  460. (dwFlags & GBF_ONLY_WHICH_CONTAIN_COMPONENT))
  461. {
  462. pBindSet->erase (pScan);
  463. continue;
  464. }
  465. // Otherwise, (pComponent is an adpater and the caller wants
  466. // indirect bindings involved with that adpater) we'll
  467. // erase the bindpath only if the last component is not an
  468. // NCF_DONTEXPOSELOWER component. We need to keep these
  469. // bindpaths so that the LAN UI (which shows components
  470. // involved in bindpaths that involve an adapter) can
  471. // display these NCF_DONTEXPOSELOWER components too.
  472. //
  473. else
  474. {
  475. CComponent* pLast = pScan->PLastComponent();
  476. if (!(pLast->m_dwCharacter & NCF_DONTEXPOSELOWER))
  477. {
  478. pBindSet->erase (pScan);
  479. continue;
  480. }
  481. }
  482. pScan++;
  483. }
  484. }
  485. }
  486. TraceHr (ttidError, FAL, Ctx.hr, FALSE,
  487. "CNetConfigCore::HrGetBindingsInvolvingComponent");
  488. return Ctx.hr;
  489. }
  490. HRESULT
  491. CNetConfigCore::HrGetFiltersEnabledForAdapter (
  492. IN const CComponent* pAdapter,
  493. OUT CComponentList* pFilters)
  494. {
  495. TraceFileFunc(ttidNetcfgBase);
  496. HRESULT hr;
  497. const CStackEntry* pScan;
  498. Assert (this);
  499. Assert (pAdapter);
  500. Assert (FIsEnumerated(pAdapter->Class()));
  501. Assert (pFilters);
  502. // Initialize the output parameter.
  503. //
  504. pFilters->Clear();
  505. // Scan the stack table looking for lower component matches to pAdapter.
  506. // When found, and if the upper component is a filter, and if the
  507. // direct bindpath is not disabled, add the filter to the output list.
  508. //
  509. for (pScan = StackTable.begin(); pScan != StackTable.end(); pScan++)
  510. {
  511. // Looking for lower component matches to the adapter where
  512. // the upper component is a filter. Ignore all others.
  513. //
  514. if ((pScan->pLower != pAdapter) || !pScan->pUpper->FIsFilter())
  515. {
  516. continue;
  517. }
  518. Assert (pScan->pUpper->FIsFilter());
  519. Assert (pScan->pLower == pAdapter);
  520. // If the bindpath is not disabled, add the filter to the list.
  521. //
  522. if (!FIsLength2BindPathDisabled (pScan->pUpper, pScan->pLower))
  523. {
  524. // Assert if a duplicate because the same filter can't be bound
  525. // to the same adapter more than once.
  526. // No need to sort when we insert because the class of all of
  527. // the components in this list will be the same.
  528. //
  529. hr = pFilters->HrInsertComponent (pScan->pUpper,
  530. INS_ASSERT_IF_DUP | INS_NON_SORTED);
  531. if (S_OK != hr)
  532. {
  533. return hr;
  534. }
  535. }
  536. }
  537. return S_OK;
  538. }
  539. // (Takes ownership of pComponent)
  540. //
  541. HRESULT
  542. CNetConfigCore::HrAddComponentToCore (
  543. IN CComponent* pComponent,
  544. IN DWORD dwFlags /* INS_FLAGS */)
  545. {
  546. TraceFileFunc(ttidNetcfgBase);
  547. HRESULT hr;
  548. Assert (pComponent);
  549. Assert ((INS_SORTED == dwFlags) || (INS_NON_SORTED == dwFlags));
  550. DbgVerifyExternalDataLoadedForAllComponents ();
  551. pComponent->Ext.DbgVerifyExternalDataLoaded ();
  552. // Make sure we are not trying to insert a component with a PnpId that
  553. // is the same as one already in the core. Note that we do not perform
  554. // this check inside of CComponentList::HrInsertComponent because it is
  555. // not appropriate for all component lists. Specifically, the dirty
  556. // component list may end up having two different components with the
  557. // same PnpId for the case when we are asked to install an adapter that
  558. // is pending removal. In this case the new adapter will get the same
  559. // PnpId as the one that was removed. We'll remove the old one from
  560. // core to insert the new one so the dirty component list will have
  561. // both components with the same PnpId.
  562. //
  563. if (FIsEnumerated(pComponent->Class()) &&
  564. Components.PFindComponentByPnpId (pComponent->m_pszPnpId))
  565. {
  566. AssertSz (FALSE, "Asked to add a component with a duplicate PnpId!");
  567. return E_INVALIDARG;
  568. }
  569. // Insert the component into the list. This should only fail if we
  570. // are out of memory.
  571. //
  572. hr = Components.HrInsertComponent (
  573. pComponent, dwFlags | INS_ASSERT_IF_DUP);
  574. if (S_OK == hr)
  575. {
  576. // Insert the appropriate stack entries for pComponent based on
  577. // how it binds with the other components.
  578. //
  579. hr = StackTable.HrInsertStackEntriesForComponent (
  580. pComponent, &Components, dwFlags);
  581. // If we failed to insert the stack entries, undo the insertion
  582. // into the component list.
  583. //
  584. if (S_OK != hr)
  585. {
  586. Components.RemoveComponent (pComponent);
  587. }
  588. }
  589. // Error or not, we should still have a valid core.
  590. //
  591. DbgVerifyData();
  592. TraceHr (ttidError, FAL, hr, FALSE,
  593. "CNetConfigCore::HrAddComponentToCore");
  594. return hr;
  595. }
  596. VOID
  597. CNetConfigCore::RemoveComponentFromCore (
  598. IN const CComponent* pComponent)
  599. {
  600. TraceFileFunc(ttidNetcfgBase);
  601. Assert (this);
  602. Assert (pComponent);
  603. Components.RemoveComponent (pComponent);
  604. StackTable.RemoveEntriesWithComponent (pComponent);
  605. DisabledBindings.RemoveBindPathsWithComponent (pComponent);
  606. #if DBG
  607. // We set m_fRemovedAComponent so that when subsequent
  608. // DbgVerifyBindingSet calls are made, we don't assert on components
  609. // that are in the binding set but not in the core. This is a natural
  610. // occurance for the m_DeletedBindings we build up during removal of
  611. // components.
  612. //
  613. m_fRemovedAComponent = TRUE;
  614. // Note: need to find a convenient time during Apply where
  615. // we set this flag back to FALSE.
  616. #endif
  617. }
  618. // static
  619. HRESULT
  620. CNetConfig::HrCreateInstance (
  621. IN class CImplINetCfg* pINetCfg,
  622. OUT CNetConfig** ppNetConfig)
  623. {
  624. TraceFileFunc(ttidNetcfgBase);
  625. Assert (pINetCfg);
  626. HRESULT hr = E_OUTOFMEMORY;
  627. CNetConfig* pObj;
  628. pObj = new CNetConfig;
  629. if (pObj)
  630. {
  631. // Load the configuration binary. If we have have the write lock,
  632. // request write access, otherwise, request read access.
  633. // Requesting write access means this will only succeed if the
  634. // volatile key indicating we need a reboot does not exist.
  635. //
  636. hr = HrLoadNetworkConfigurationFromRegistry (
  637. (pINetCfg->m_WriteLock.FIsOwnedByMe ())
  638. ? KEY_WRITE : KEY_READ,
  639. pObj);
  640. if (S_OK == hr)
  641. {
  642. pObj->Core.DbgVerifyData();
  643. pObj->Notify.HoldINetCfg (pINetCfg);
  644. *ppNetConfig = pObj;
  645. }
  646. else
  647. {
  648. delete pObj;
  649. }
  650. }
  651. TraceHr (ttidError, FAL, hr, FALSE, "CNetConfig::HrCreateInstance");
  652. return hr;
  653. }
  654. CNetConfig::~CNetConfig ()
  655. {
  656. TraceFileFunc(ttidNetcfgBase);
  657. Core.Free ();
  658. }
  659. HRESULT
  660. CNetConfig::HrEnsureExternalDataLoadedForAllComponents ()
  661. {
  662. TraceFileFunc(ttidNetcfgBase);
  663. HRESULT hr;
  664. HRESULT hrRet;
  665. CComponentList::iterator iter;
  666. CComponent* pComponent;
  667. hrRet = S_OK;
  668. // This is a while loop instead of a for loop because of the
  669. // potential for conditional advancement of the iterator. If we
  670. // remove a component from the core while looping, we don't increment
  671. // the iterator for the next iteration.
  672. //
  673. iter = Core.Components.begin();
  674. while (iter != Core.Components.end())
  675. {
  676. pComponent = *iter;
  677. Assert (pComponent);
  678. hr = pComponent->Ext.HrEnsureExternalDataLoaded ();
  679. if ((SPAPI_E_NO_SUCH_DEVINST == hr) ||
  680. (SPAPI_E_KEY_DOES_NOT_EXIST == hr))
  681. {
  682. g_pDiagCtx->Printf (ttidBeDiag,
  683. "Removing %s from the core because its external data is missing\n",
  684. pComponent->PszGetPnpIdOrInfId());
  685. Core.RemoveComponentFromCore (pComponent);
  686. delete pComponent;
  687. hr = S_OK;
  688. // Because we removed this component from the core, the
  689. // list has been adjusted and the next component is now this
  690. // iter. Therefore, just continue without incrementing iter.
  691. //
  692. continue;
  693. }
  694. // Remember the first error as our return code, but keep going.
  695. // Like the name says, we are to load data for all components so
  696. // don't stop just because one fails.
  697. //
  698. if ((S_OK != hr) && (S_OK == hrRet))
  699. {
  700. hrRet = hr;
  701. }
  702. iter++;
  703. }
  704. TraceHr (ttidError, FAL, hrRet, FALSE,
  705. "CNetConfig::HrEnsureExternalDataLoadedForAllComponents");
  706. return hrRet;
  707. }
  708. #if DBG
  709. VOID
  710. CNetConfigCore::DbgVerifyData () const
  711. {
  712. TraceFileFunc(ttidNetcfgBase);
  713. HRESULT hr;
  714. CComponentList::const_iterator iter;
  715. const CComponent* pComponent;
  716. const CStackEntry* pStackEntry;
  717. const CComponent* pUpper;
  718. const CComponent* pLower;
  719. CHAR szBuffer [512];
  720. for (pStackEntry = StackTable.begin();
  721. pStackEntry != StackTable.end();
  722. pStackEntry++)
  723. {
  724. pUpper = pStackEntry->pUpper;
  725. pLower = pStackEntry->pLower;
  726. Assert (pUpper);
  727. Assert (pLower);
  728. Assert (pUpper != pLower);
  729. // Can't access upper and lower range if the external data isn't
  730. // loaded.
  731. //
  732. if (pUpper->Ext.DbgIsExternalDataLoaded() &&
  733. pLower->Ext.DbgIsExternalDataLoaded())
  734. {
  735. if (!pUpper->FCanDirectlyBindTo (pLower, NULL, NULL))
  736. {
  737. wsprintfA (szBuffer, "%S should not bind to %S. They are in the "
  738. "stack table as if they do. (Likely upgrade problem.)",
  739. pUpper->PszGetPnpIdOrInfId(),
  740. pLower->PszGetPnpIdOrInfId());
  741. AssertSzFn (szBuffer, FAL);
  742. }
  743. }
  744. if (!FIsEnumerated (pUpper->Class()))
  745. {
  746. if (pUpper != Components.PFindComponentByInfId (
  747. pUpper->m_pszInfId, NULL))
  748. {
  749. wsprintfA (szBuffer, "%S is an upper component in the stack "
  750. "table, but was not found in the component list.",
  751. pUpper->m_pszInfId);
  752. AssertSzFn (szBuffer, FAL);
  753. }
  754. }
  755. else
  756. {
  757. if (pUpper != Components.PFindComponentByPnpId (
  758. pUpper->m_pszPnpId))
  759. {
  760. wsprintfA (szBuffer, "%S is an upper component in the stack "
  761. "table, but was not found in the component list.",
  762. pUpper->m_pszInfId);
  763. AssertSzFn (szBuffer, FAL);
  764. }
  765. }
  766. if (!FIsEnumerated (pLower->Class()))
  767. {
  768. if (pLower != Components.PFindComponentByInfId (
  769. pLower->m_pszInfId, NULL))
  770. {
  771. wsprintfA (szBuffer, "%S is a lower component in the stack "
  772. "table, but was not found in the component list.",
  773. pLower->m_pszInfId);
  774. AssertSzFn (szBuffer, FAL);
  775. }
  776. }
  777. else
  778. {
  779. if (pLower != Components.PFindComponentByPnpId (
  780. pLower->m_pszPnpId))
  781. {
  782. wsprintfA (szBuffer, "%S is a lower component in the stack "
  783. "table, but was not found in the component list.",
  784. pLower->m_pszInfId);
  785. AssertSzFn (szBuffer, FAL);
  786. }
  787. }
  788. if (pUpper != Components.PFindComponentByInstanceGuid (&pUpper->m_InstanceGuid))
  789. {
  790. wsprintfA (szBuffer, "%S is an upper component in the stack "
  791. "table, but was not found in the component list by GUID.",
  792. pUpper->PszGetPnpIdOrInfId());
  793. AssertSzFn (szBuffer, FAL);
  794. }
  795. if (pLower != Components.PFindComponentByInstanceGuid (&pLower->m_InstanceGuid))
  796. {
  797. wsprintfA (szBuffer, "%S is a lower component in the stack "
  798. "table, but was not found in the component list by GUID.",
  799. pLower->PszGetPnpIdOrInfId());
  800. AssertSzFn (szBuffer, FAL);
  801. }
  802. }
  803. }
  804. VOID
  805. CNetConfigCore::DbgVerifyExternalDataLoadedForAllComponents () const
  806. {
  807. TraceFileFunc(ttidNetcfgBase);
  808. CComponentList::const_iterator iter;
  809. const CComponent* pComponent;
  810. for (iter = Components.begin();
  811. iter != Components.end();
  812. iter++)
  813. {
  814. pComponent = *iter;
  815. Assert (pComponent);
  816. pComponent->Ext.DbgVerifyExternalDataLoaded();
  817. }
  818. }
  819. VOID
  820. CNetConfigCore::DbgVerifyBindingSet (
  821. const CBindingSet* pBindSet) const
  822. {
  823. TraceFileFunc(ttidNetcfgBase);
  824. const CBindPath* pPath;
  825. const CBindPath* pOtherPath;
  826. CBindPath::const_iterator iter;
  827. const CComponent* pComponent;
  828. Assert (pBindSet);
  829. // First make sure every component in the set is in our component
  830. // list. We only do this if we're not in the state where a component
  831. // has been removed from the core. For this case, its okay if those
  832. // components still exist in binding sets.
  833. //
  834. if (!m_fRemovedAComponent)
  835. {
  836. for (pPath = pBindSet->begin();
  837. pPath != pBindSet->end();
  838. pPath++)
  839. {
  840. for (iter = pPath->begin();
  841. iter != pPath->end();
  842. iter++)
  843. {
  844. pComponent = *iter;
  845. Assert (Components.FComponentInList (pComponent));
  846. }
  847. }
  848. }
  849. // Make sure there are no duplicate bindpaths in the set.
  850. //
  851. for (pPath = pBindSet->begin();
  852. pPath != pBindSet->end();
  853. pPath++)
  854. {
  855. Assert (!pPath->FIsEmpty());
  856. for (pOtherPath = pBindSet->begin();
  857. pOtherPath != pBindSet->end();
  858. pOtherPath++)
  859. {
  860. if (pPath == pOtherPath)
  861. {
  862. continue;
  863. }
  864. Assert (!pPath->FIsSameBindPathAs (pOtherPath));
  865. }
  866. }
  867. }
  868. #endif // DBG