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.

800 lines
17 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1999.
  5. //
  6. // File: B I N D I N G S . C P P
  7. //
  8. // Contents: The basic datatypes for binding objects. Bindpaths are
  9. // ordered collections of component pointers. Bindsets
  10. // are a collection of bindpaths. This module implements
  11. // the operations that are valid on binpaths and bindsets.
  12. //
  13. // Notes:
  14. //
  15. // Author: shaunco 15 Jan 1999
  16. //
  17. //----------------------------------------------------------------------------
  18. #include <pch.h>
  19. #pragma hdrstop
  20. #include "bindings.h"
  21. #include "complist.h"
  22. #include "diagctx.h"
  23. #include "nceh.h"
  24. //+---------------------------------------------------------------------------
  25. // CBindPath -
  26. //
  27. bool
  28. CBindPath::operator< (
  29. const CBindPath& OtherPath) const
  30. {
  31. TraceFileFunc(ttidNetCfgBind);
  32. const_iterator iterThis;
  33. const_iterator iterOther;
  34. NETCLASS Class;
  35. NETCLASS OtherClass;
  36. for (iterThis = begin(), iterOther = OtherPath.begin();
  37. (iterThis != end()) && (iterOther != OtherPath.end());
  38. iterThis++, iterOther++)
  39. {
  40. Class = (*iterThis)->Class();
  41. OtherClass = (*iterOther)->Class();
  42. if (Class > OtherClass)
  43. {
  44. return TRUE;
  45. }
  46. else if (Class < OtherClass)
  47. {
  48. return FALSE;
  49. }
  50. }
  51. return size() > OtherPath.size();
  52. }
  53. bool
  54. CBindPath::operator> (
  55. const CBindPath& OtherPath) const
  56. {
  57. TraceFileFunc(ttidNetCfgBind);
  58. const_iterator iterThis;
  59. const_iterator iterOther;
  60. NETCLASS Class;
  61. NETCLASS OtherClass;
  62. for (iterThis = begin(), iterOther = OtherPath.begin();
  63. (iterThis != end()) && (iterOther != OtherPath.end());
  64. iterThis++, iterOther++)
  65. {
  66. Class = (*iterThis)->Class();
  67. OtherClass = (*iterOther)->Class();
  68. if (Class < OtherClass)
  69. {
  70. return TRUE;
  71. }
  72. else if (Class > OtherClass)
  73. {
  74. return FALSE;
  75. }
  76. }
  77. return size() < OtherPath.size();
  78. }
  79. BOOL
  80. CBindPath::FAllComponentsLoadedOkayIfLoadedAtAll () const
  81. {
  82. TraceFileFunc(ttidNetCfgBind);
  83. CBindPath::const_iterator iter;
  84. const CComponent* pComponent;
  85. Assert (this);
  86. for (iter = begin(); iter != end(); iter++)
  87. {
  88. pComponent = *iter;
  89. Assert (pComponent);
  90. if (!pComponent->Ext.FLoadedOkayIfLoadedAtAll())
  91. {
  92. return FALSE;
  93. }
  94. }
  95. return TRUE;
  96. }
  97. BOOL
  98. CBindPath::FGetPathToken (
  99. OUT PWSTR pszToken,
  100. IN OUT ULONG* pcchToken) const
  101. {
  102. TraceFileFunc(ttidNetCfgBind);
  103. const_iterator iter;
  104. const CComponent* pComponent;
  105. ULONG cchIn;
  106. ULONG cch;
  107. BOOL fFirstTime;
  108. Assert (this);
  109. Assert (pcchToken);
  110. if (pszToken)
  111. {
  112. *pszToken = 0;
  113. }
  114. cchIn = *pcchToken;
  115. cch = 0;
  116. for (iter = begin(), fFirstTime = TRUE; iter != end(); iter++)
  117. {
  118. if (!fFirstTime)
  119. {
  120. cch += 2;
  121. if (pszToken && (cch <= cchIn))
  122. {
  123. wcscat (pszToken, L"->");
  124. }
  125. }
  126. else
  127. {
  128. fFirstTime = FALSE;
  129. }
  130. pComponent = *iter;
  131. Assert (pComponent);
  132. cch += wcslen (pComponent->PszGetPnpIdOrInfId());
  133. if (pszToken && (cch <= cchIn))
  134. {
  135. wcscat (pszToken, pComponent->PszGetPnpIdOrInfId());
  136. }
  137. }
  138. *pcchToken = cch;
  139. return cch <= cchIn;
  140. }
  141. BOOL
  142. CBindPath::FIsSameBindPathAs (
  143. IN const CBindPath* pOtherPath) const
  144. {
  145. TraceFileFunc(ttidNetCfgBind);
  146. UINT unThisSize;
  147. UINT unOtherSize;
  148. UINT cb;
  149. Assert (this);
  150. Assert (pOtherPath);
  151. unThisSize = this->size();
  152. unOtherSize = pOtherPath->size();
  153. if ((0 == unThisSize) || (0 == unOtherSize) || (unThisSize != unOtherSize))
  154. {
  155. return FALSE;
  156. }
  157. // Sizes are non-zero and equal. Compare the data.
  158. //
  159. cb = (UINT)((BYTE*)(end()) - (BYTE*)(begin()));
  160. Assert (cb == unThisSize * sizeof(CComponent*));
  161. return (0 == memcmp (
  162. (BYTE*)(this->begin()),
  163. (BYTE*)(pOtherPath->begin()),
  164. cb));
  165. }
  166. BOOL
  167. CBindPath::FIsSubPathOf (
  168. IN const CBindPath* pOtherPath) const
  169. {
  170. TraceFileFunc(ttidNetCfgBind);
  171. UINT unThisSize;
  172. UINT unOtherSize;
  173. UINT unSkipComponents;
  174. UINT cb;
  175. Assert (this);
  176. Assert (pOtherPath);
  177. unThisSize = this->size();
  178. unOtherSize = pOtherPath->size();
  179. if ((0 == unThisSize) || (0 == unOtherSize) || (unThisSize >= unOtherSize))
  180. {
  181. return FALSE;
  182. }
  183. // This size is less than other. Compare the data starting at the
  184. // component pointer in the other path that will have the same depth
  185. // as this path.
  186. //
  187. cb = (UINT)((BYTE*)(end()) - (BYTE*)(begin()));
  188. // The component pointer in the other path that we start comparing at
  189. // is at an offset equal to the difference in path sizes.
  190. //
  191. // e.g. other path: a->b->c->d->e size=5
  192. // this path: c->d->e size=3
  193. // start comparing after skipping 5-3=2 components of the other path
  194. //
  195. Assert (unOtherSize > unThisSize);
  196. unSkipComponents = unOtherSize - unThisSize;
  197. return (0 == memcmp (
  198. (BYTE*)(this->begin()),
  199. (BYTE*)(pOtherPath->begin() + unSkipComponents),
  200. cb));
  201. }
  202. HRESULT
  203. CBindPath::HrAppendBindPath (
  204. IN const CBindPath* pBindPath)
  205. {
  206. TraceFileFunc(ttidNetCfgBind);
  207. HRESULT hr;
  208. Assert (this);
  209. Assert (pBindPath);
  210. NC_TRY
  211. {
  212. insert (end(), pBindPath->begin(), pBindPath->end());
  213. DbgVerifyBindpath ();
  214. hr = S_OK;
  215. }
  216. NC_CATCH_ALL
  217. {
  218. hr = E_OUTOFMEMORY;
  219. }
  220. TraceHr (ttidError, FAL, hr, FALSE, "CBindPath::HrAppendBindPath");
  221. return hr;
  222. }
  223. HRESULT
  224. CBindPath::HrAppendComponent (
  225. IN const CComponent* pComponent)
  226. {
  227. TraceFileFunc(ttidNetCfgBind);
  228. HRESULT hr;
  229. Assert (this);
  230. Assert (pComponent);
  231. Assert (!FContainsComponent (pComponent));
  232. NC_TRY
  233. {
  234. push_back (const_cast<CComponent*>(pComponent));
  235. DbgVerifyBindpath ();
  236. hr = S_OK;
  237. }
  238. NC_CATCH_ALL
  239. {
  240. hr = E_OUTOFMEMORY;
  241. }
  242. TraceHr (ttidError, FAL, hr, FALSE, "CBindPath::HrAppendComponent");
  243. return hr;
  244. }
  245. HRESULT
  246. CBindPath::HrGetComponentsInBindPath (
  247. IN OUT CComponentList* pComponents) const
  248. {
  249. TraceFileFunc(ttidNetCfgBind);
  250. HRESULT hr;
  251. CBindPath::const_iterator iter;
  252. const CComponent* pComponent;
  253. Assert (this);
  254. Assert (pComponents);
  255. for (iter = begin(); iter != end(); iter++)
  256. {
  257. pComponent = *iter;
  258. Assert (pComponent);
  259. hr = pComponents->HrInsertComponent (pComponent,
  260. INS_IGNORE_IF_DUP | INS_SORTED);
  261. if (S_OK != hr)
  262. {
  263. TraceHr (ttidError, FAL, hr, FALSE,
  264. "CBindPath::HrGetComponentsInBindPath");
  265. return hr;
  266. }
  267. }
  268. return S_OK;
  269. }
  270. HRESULT
  271. CBindPath::HrInsertComponent (
  272. IN const CComponent* pComponent)
  273. {
  274. TraceFileFunc(ttidNetCfgBind);
  275. HRESULT hr;
  276. Assert (this);
  277. Assert (pComponent);
  278. Assert (!FContainsComponent (pComponent));
  279. NC_TRY
  280. {
  281. insert (begin(), const_cast<CComponent*>(pComponent));
  282. DbgVerifyBindpath ();
  283. hr = S_OK;
  284. }
  285. NC_CATCH_ALL
  286. {
  287. hr = E_OUTOFMEMORY;
  288. }
  289. TraceHr (ttidError, FAL, hr, FALSE, "CBindPath::HrInsertComponent");
  290. return hr;
  291. }
  292. HRESULT
  293. CBindPath::HrReserveRoomForComponents (
  294. IN UINT cComponents)
  295. {
  296. TraceFileFunc(ttidNetCfgBind);
  297. HRESULT hr;
  298. NC_TRY
  299. {
  300. reserve (cComponents);
  301. hr = S_OK;
  302. }
  303. NC_CATCH_ALL
  304. {
  305. hr = E_OUTOFMEMORY;
  306. }
  307. TraceHr (ttidError, FAL, hr, FALSE,
  308. "CBindPath::HrReserveRoomForComponents");
  309. return hr;
  310. }
  311. #if DBG
  312. VOID
  313. CBindPath::DbgVerifyBindpath ()
  314. {
  315. TraceFileFunc(ttidNetCfgBind);
  316. const_iterator iter;
  317. const_iterator iterOther;
  318. const CComponent* pComponent;
  319. const CComponent* pOtherComponent;
  320. Assert (this);
  321. // Make sure the bindpath does not contain any duplicate component
  322. // pointers.
  323. //
  324. for (iter = begin(); iter != end(); iter++)
  325. {
  326. pComponent = *iter;
  327. Assert (pComponent);
  328. for (iterOther = begin(); iterOther != end(); iterOther++)
  329. {
  330. pOtherComponent = *iterOther;
  331. Assert (pOtherComponent);
  332. if (iter == iterOther)
  333. {
  334. continue;
  335. }
  336. Assert (pComponent != pOtherComponent);
  337. }
  338. }
  339. }
  340. #endif
  341. //+---------------------------------------------------------------------------
  342. // CBindingSet -
  343. //
  344. VOID
  345. CBindingSet::Printf (
  346. TRACETAGID ttid,
  347. PCSTR pszPrefixLine) const
  348. {
  349. TraceFileFunc(ttidNetCfgBind);
  350. WCHAR pszBuf [1024];
  351. WCHAR* pch;
  352. ULONG cch;
  353. Assert (this);
  354. if (pszPrefixLine)
  355. {
  356. g_pDiagCtx->Printf (ttid, pszPrefixLine);
  357. }
  358. const CBindPath* pBindPath;
  359. INT nIndex = 1;
  360. for (pBindPath = begin(); pBindPath != end(); pBindPath++, nIndex++)
  361. {
  362. pch = pszBuf + wsprintfW (pszBuf, L"%2i: ", nIndex);
  363. cch = celems(pszBuf) - wcslen(pszBuf) - 1;
  364. if (pBindPath->FGetPathToken (pch, &cch))
  365. {
  366. g_pDiagCtx->Printf (ttid, "%S\n", pszBuf);
  367. }
  368. }
  369. }
  370. BOOL
  371. CBindingSet::FContainsBindPath (
  372. IN const CBindPath* pBindPathToCheckFor) const
  373. {
  374. TraceFileFunc(ttidNetCfgBind);
  375. const CBindPath* pBindPath;
  376. Assert (this);
  377. Assert (pBindPathToCheckFor);
  378. for (pBindPath = begin(); pBindPath != end(); pBindPath++)
  379. {
  380. if (pBindPath->FIsSameBindPathAs (pBindPathToCheckFor))
  381. {
  382. return TRUE;
  383. }
  384. }
  385. return FALSE;
  386. }
  387. BOOL
  388. CBindingSet::FContainsComponent (
  389. IN const CComponent* pComponent) const
  390. {
  391. TraceFileFunc(ttidNetCfgBind);
  392. const CBindPath* pBindPath;
  393. Assert (this);
  394. Assert (pComponent);
  395. for (pBindPath = begin(); pBindPath != end(); pBindPath++)
  396. {
  397. if (pBindPath->FContainsComponent (pComponent))
  398. {
  399. return TRUE;
  400. }
  401. }
  402. return FALSE;
  403. }
  404. HRESULT
  405. CBindingSet::HrAppendBindingSet (
  406. IN const CBindingSet* pBindSet)
  407. {
  408. TraceFileFunc(ttidNetCfgBind);
  409. HRESULT hr;
  410. const CBindPath* pSrcPath;
  411. Assert (this);
  412. Assert (pBindSet);
  413. hr = S_OK;
  414. NC_TRY
  415. {
  416. for (pSrcPath = pBindSet->begin();
  417. pSrcPath != pBindSet->end();
  418. pSrcPath++)
  419. {
  420. if (!FContainsBindPath (pSrcPath))
  421. {
  422. insert (end(), *pSrcPath);
  423. }
  424. }
  425. }
  426. NC_CATCH_ALL
  427. {
  428. hr = E_OUTOFMEMORY;
  429. }
  430. TraceHr (ttidError, FAL, hr, FALSE, "CBindingSet::HrAppendBindingSet");
  431. return hr;
  432. }
  433. HRESULT
  434. CBindingSet::HrAddBindPath (
  435. IN const CBindPath* pBindPath,
  436. IN DWORD dwFlags)
  437. {
  438. TraceFileFunc(ttidNetCfgBind);
  439. HRESULT hr;
  440. Assert (this);
  441. Assert (pBindPath);
  442. Assert (!pBindPath->FIsEmpty());
  443. Assert ((dwFlags & INS_ASSERT_IF_DUP) || (dwFlags & INS_IGNORE_IF_DUP));
  444. Assert ((dwFlags & INS_APPEND) || (dwFlags & INS_INSERT));
  445. Assert (!(INS_SORTED & dwFlags) && !(INS_NON_SORTED & dwFlags));
  446. if (FContainsBindPath (pBindPath))
  447. {
  448. // If the caller didn't tell us to ignore duplicates, we assert
  449. // if there is one because it is bad, bad, bad to have duplicate
  450. // bindpaths in the set.
  451. //
  452. // If we have a dup, we want the caller to be aware that it
  453. // is possible, and pass us the flag telling us to ignore it.
  454. // Otherwise, we assert to let them know. (And we still ignore
  455. // it.)
  456. Assert (dwFlags & INS_IGNORE_IF_DUP);
  457. return S_OK;
  458. }
  459. NC_TRY
  460. {
  461. // Either insert the bindpath or append it.
  462. //
  463. iterator iter = begin();
  464. if (dwFlags & INS_APPEND)
  465. {
  466. iter = end();
  467. }
  468. insert (iter, *pBindPath);
  469. hr = S_OK;
  470. }
  471. NC_CATCH_ALL
  472. {
  473. hr = E_OUTOFMEMORY;
  474. }
  475. TraceHr (ttidError, FAL, hr, FALSE, "CBindingSet::HrAddBindPath");
  476. return hr;
  477. }
  478. HRESULT
  479. CBindingSet::HrAddBindPathsInSet1ButNotInSet2 (
  480. IN const CBindingSet* pSet1,
  481. IN const CBindingSet* pSet2)
  482. {
  483. TraceFileFunc(ttidNetCfgBind);
  484. HRESULT hr;
  485. const CBindPath* pBindPath;
  486. Assert (this);
  487. Assert (pSet1);
  488. Assert (pSet2);
  489. Assert ((this != pSet1) && (this != pSet2));
  490. hr = S_OK;
  491. for (pBindPath = pSet1->begin();
  492. pBindPath != pSet1->end();
  493. pBindPath++)
  494. {
  495. if (pSet2->FContainsBindPath (pBindPath))
  496. {
  497. continue;
  498. }
  499. hr = HrAddBindPath (pBindPath, INS_IGNORE_IF_DUP | INS_APPEND);
  500. if (S_OK != hr)
  501. {
  502. break;
  503. }
  504. }
  505. TraceHr (ttidError, FAL, hr, FALSE,
  506. "CBindingSet::HrAddBindPathsInSet1ButNotInSet2");
  507. return hr;
  508. }
  509. HRESULT
  510. CBindingSet::HrCopyBindingSet (
  511. IN const CBindingSet* pSourceSet)
  512. {
  513. TraceFileFunc(ttidNetCfgBind);
  514. HRESULT hr;
  515. Assert (this);
  516. Assert (pSourceSet);
  517. NC_TRY
  518. {
  519. *this = *pSourceSet;
  520. hr = S_OK;
  521. }
  522. NC_CATCH_ALL
  523. {
  524. hr = E_OUTOFMEMORY;
  525. }
  526. TraceHr (ttidError, FAL, hr, FALSE, "CBindingSet::HrCopyBindingSet");
  527. return hr;
  528. }
  529. HRESULT
  530. CBindingSet::HrGetAffectedComponentsInBindingSet (
  531. IN OUT CComponentList* pComponents) const
  532. {
  533. TraceFileFunc(ttidNetCfgBind);
  534. HRESULT hr;
  535. const CBindPath* pBindPath;
  536. Assert (this);
  537. Assert (pComponents);
  538. hr = S_OK;
  539. for (pBindPath = begin(); pBindPath != end(); pBindPath++)
  540. {
  541. hr = pComponents->HrInsertComponent (pBindPath->POwner(),
  542. INS_IGNORE_IF_DUP | INS_SORTED);
  543. if (S_OK != hr)
  544. {
  545. break;
  546. }
  547. // For bindpaths from a protocol to an adpater, we want to
  548. // add the adapter to the component list because it will need
  549. // to have its upper bind changed.
  550. //
  551. if (pBindPath->CountComponents() == 2)
  552. {
  553. const CComponent* pAdapter;
  554. pAdapter = pBindPath->PLastComponent();
  555. if (FIsEnumerated (pAdapter->Class()))
  556. {
  557. hr = pComponents->HrInsertComponent (pAdapter,
  558. INS_IGNORE_IF_DUP | INS_SORTED);
  559. if (S_OK != hr)
  560. {
  561. break;
  562. }
  563. }
  564. }
  565. }
  566. TraceHr (ttidError, FAL, hr, FALSE,
  567. "CBindingSet::HrGetAffectedComponentsInBindingSet");
  568. return hr;
  569. }
  570. HRESULT
  571. CBindingSet::HrReserveRoomForBindPaths (
  572. IN UINT cBindPaths)
  573. {
  574. TraceFileFunc(ttidNetCfgBind);
  575. HRESULT hr;
  576. NC_TRY
  577. {
  578. reserve (cBindPaths);
  579. hr = S_OK;
  580. }
  581. NC_CATCH_ALL
  582. {
  583. hr = E_OUTOFMEMORY;
  584. }
  585. TraceHr (ttidError, FAL, hr, FALSE,
  586. "CBindingSet::HrReserveRoomForBindPaths");
  587. return hr;
  588. }
  589. VOID
  590. CBindingSet::RemoveBindPath (
  591. IN const CBindPath* pBindPath)
  592. {
  593. TraceFileFunc(ttidNetCfgBind);
  594. CBindPath* pScan;
  595. for (pScan = begin(); pScan != end(); pScan++)
  596. {
  597. if (pScan->FIsSameBindPathAs (pBindPath))
  598. {
  599. erase (pScan);
  600. return;
  601. }
  602. }
  603. }
  604. VOID
  605. CBindingSet::RemoveBindPathsWithComponent (
  606. IN const CComponent* pComponent)
  607. {
  608. TraceFileFunc(ttidNetCfgBind);
  609. CBindPath* pBindPath;
  610. Assert (this);
  611. Assert (pComponent);
  612. pBindPath = begin();
  613. while (pBindPath != end())
  614. {
  615. if (pBindPath->FContainsComponent(pComponent))
  616. {
  617. erase (pBindPath);
  618. }
  619. else
  620. {
  621. pBindPath++;
  622. }
  623. }
  624. }
  625. VOID
  626. CBindingSet::RemoveSubpaths ()
  627. {
  628. TraceFileFunc(ttidNetCfgBind);
  629. CBindPath* pCandidate;
  630. CBindPath* pBindPath;
  631. Assert (this);
  632. for (pBindPath = begin(); pBindPath != end(); pBindPath++)
  633. {
  634. pCandidate = begin();
  635. while (pCandidate != end())
  636. {
  637. if (pCandidate->FIsSubPathOf (pBindPath))
  638. {
  639. // FIsSubPathOf returns FALSE when asked if a bindpath
  640. // is a subpath of itself. (Set-theorectially, this is
  641. // incorrect, but having it return FALSE for this case
  642. // prevents us from having to make another check.
  643. //
  644. Assert (pCandidate != pBindPath);
  645. erase (pCandidate);
  646. // If erasing a bindpath that occurs before the current
  647. // outer loop enumerator, we need to back it up because
  648. // the erase would move everything up by one, but we still
  649. // want to finish the inner loop for this current outer
  650. // bindpath.
  651. //
  652. if (pCandidate < pBindPath)
  653. {
  654. pBindPath--;
  655. }
  656. }
  657. else
  658. {
  659. pCandidate++;
  660. }
  661. }
  662. }
  663. }
  664. VOID
  665. CBindingSet::SortForPnpBind ()
  666. {
  667. TraceFileFunc(ttidNetCfgBind);
  668. // Sort where bindpaths closes to the adapters come first.
  669. //
  670. sort<iterator> (begin(), end(), greater<CBindPath>());
  671. }
  672. VOID
  673. CBindingSet::SortForPnpUnbind ()
  674. {
  675. TraceFileFunc(ttidNetCfgBind);
  676. // Sort where bindpaths furthest from the adapters come first.
  677. //
  678. sort<iterator> (begin(), end(), less<CBindPath>());
  679. }