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.

866 lines
24 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1999.
  5. //
  6. // File: F I L T D E V S . C P P
  7. //
  8. // Contents: Implements the basic datatype for a collection of filter
  9. // devices.
  10. //
  11. // Notes:
  12. //
  13. // Author: shaunco 15 Jan 1999
  14. //
  15. //----------------------------------------------------------------------------
  16. #include <pch.h>
  17. #pragma hdrstop
  18. #include "classinst.h"
  19. #include "filtdevs.h"
  20. #include "nceh.h"
  21. #include "ncreg.h"
  22. #include "ncstl.h"
  23. #include "ncsetup.h"
  24. CFilterDevices::CFilterDevices (
  25. IN CNetConfigCore* pCore)
  26. {
  27. Assert (pCore);
  28. ZeroMemory (this, sizeof(*this));
  29. m_pCore = pCore;
  30. }
  31. CFilterDevices::~CFilterDevices ()
  32. {
  33. // Free had better have been called before this.
  34. //
  35. Assert (this);
  36. Assert (!m_hdi);
  37. Assert (!m_pmszFilterClasses);
  38. Assert (empty());
  39. }
  40. HRESULT
  41. CFilterDevices::HrInsertFilterDevice (
  42. IN CFilterDevice* pDevice)
  43. {
  44. HRESULT hr;
  45. Assert (this);
  46. Assert (pDevice);
  47. // Assert there is not already a device in the list with the
  48. // same instance guid.
  49. //
  50. Assert (!PFindFilterDeviceByInstanceGuid (pDevice->m_szInstanceGuid));
  51. // Assert there is not already a device in the list with the
  52. // same parent filter AND the same filtered adapter.
  53. //
  54. Assert (!PFindFilterDeviceByAdapterAndFilter (
  55. pDevice->m_pAdapter,
  56. pDevice->m_pFilter));
  57. NC_TRY
  58. {
  59. push_back (pDevice);
  60. hr = S_OK;
  61. }
  62. NC_CATCH_ALL
  63. {
  64. hr = E_OUTOFMEMORY;
  65. }
  66. TraceHr (ttidError, FAL, hr, FALSE, "CFilterDevices::HrInsertFilterDevice");
  67. return hr;
  68. }
  69. HRESULT
  70. CFilterDevices::HrPrepare ()
  71. {
  72. HRESULT hr;
  73. HKEY hkeyNetwork;
  74. // Reserve room for 8 different filters in our internal member.
  75. // We use this component list at various times as "scratch space" when
  76. // figuring out which filters are enabled for an adapter.
  77. //
  78. hr = m_Filters.HrReserveRoomForComponents (8);
  79. if (S_OK != hr)
  80. {
  81. goto finished;
  82. }
  83. hr = m_BindPathsToRebind.HrReserveRoomForBindPaths (8);
  84. if (S_OK != hr)
  85. {
  86. goto finished;
  87. }
  88. // Load the FilterClasses multi-sz.
  89. //
  90. hr = HrOpenNetworkKey (KEY_READ, &hkeyNetwork);
  91. if (S_OK == hr)
  92. {
  93. hr = HrRegQueryMultiSzWithAlloc (
  94. hkeyNetwork,
  95. L"FilterClasses",
  96. &m_pmszFilterClasses);
  97. if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr)
  98. {
  99. Assert (!m_pmszFilterClasses);
  100. hr = S_OK;
  101. }
  102. RegCloseKey (hkeyNetwork);
  103. }
  104. finished:
  105. TraceHr (ttidError, FAL, hr, FALSE, "CFilterDevices::HrPrepare");
  106. return hr;
  107. }
  108. CFilterDevice*
  109. CFilterDevices::PFindFilterDeviceByAdapterAndFilter (
  110. IN const CComponent* pAdapter,
  111. IN const CComponent* pFilter) const
  112. {
  113. const_iterator iter;
  114. CFilterDevice* pDevice;
  115. Assert (this);
  116. Assert (pAdapter);
  117. Assert (pFilter);
  118. Assert (FIsEnumerated(pAdapter->Class()));
  119. Assert (NC_NETSERVICE == pFilter->Class());
  120. Assert (pFilter->FIsFilter());
  121. for (iter = begin(); iter != end(); iter++)
  122. {
  123. pDevice = *iter;
  124. Assert (pDevice);
  125. if ((pAdapter == pDevice->m_pAdapter) &&
  126. (pFilter == pDevice->m_pFilter))
  127. {
  128. return pDevice;
  129. }
  130. }
  131. return NULL;
  132. }
  133. DWORD
  134. CFilterDevices::MapFilterClassToOrdinal (
  135. IN PCWSTR pszFilterClass)
  136. {
  137. DWORD Ordinal;
  138. DWORD dwIndex;
  139. DWORD cStrings;
  140. Assert (pszFilterClass);
  141. #if DBG
  142. Ordinal = 0;
  143. #endif
  144. // If the class is found in the list, return its position.
  145. //
  146. if (FGetSzPositionInMultiSzSafe (
  147. pszFilterClass,
  148. m_pmszFilterClasses,
  149. &dwIndex,
  150. NULL,
  151. &cStrings))
  152. {
  153. Ordinal = dwIndex + 1;
  154. }
  155. else
  156. {
  157. HRESULT hr;
  158. PWSTR pmszNew;
  159. BOOL fChanged;
  160. // We're adding another string, so compute the new ordinal value
  161. // for return.
  162. //
  163. Ordinal = cStrings + 1;
  164. // String was not found, so we append it at the end.
  165. // It is important to insert at the end so we don't have to
  166. // change the ordinals of any existing filters that already
  167. // had their ordinal computed.
  168. //
  169. hr = HrAddSzToMultiSz (pszFilterClass, m_pmszFilterClasses,
  170. STRING_FLAG_ENSURE_AT_END, 0, &pmszNew, &fChanged);
  171. if (S_OK == hr)
  172. {
  173. HKEY hkeyNetwork;
  174. // It better have changed because we didn't find the string
  175. // above.
  176. //
  177. Assert (fChanged);
  178. // Out with the old. In with the new.
  179. //
  180. MemFree (m_pmszFilterClasses);
  181. m_pmszFilterClasses = pmszNew;
  182. // Save it back to the registry.
  183. //
  184. hr = HrOpenNetworkKey (KEY_WRITE, &hkeyNetwork);
  185. if (S_OK == hr)
  186. {
  187. hr = HrRegSetMultiSz (
  188. hkeyNetwork,
  189. L"FilterClasses",
  190. m_pmszFilterClasses);
  191. Assert (S_OK == hr);
  192. RegCloseKey (hkeyNetwork);
  193. }
  194. }
  195. }
  196. // By definition, Ordinal is 1-based. This is so that when stored
  197. // in CComponent, we know we have to load the filter class and get
  198. // its ordinal if CComponent::FilterClassOrdinal is zero. i.e. zero
  199. // is a sentinel value that means we need to do work and when non-zero
  200. // means we don't have to do that work again.
  201. //
  202. Assert (Ordinal != 0);
  203. return Ordinal;
  204. }
  205. CFilterDevice*
  206. CFilterDevices::PFindFilterDeviceByInstanceGuid (
  207. IN PCWSTR pszInstanceGuid) const
  208. {
  209. const_iterator iter;
  210. CFilterDevice* pDevice;
  211. Assert (this);
  212. Assert (pszInstanceGuid && *pszInstanceGuid);
  213. for (iter = begin(); iter != end(); iter++)
  214. {
  215. pDevice = *iter;
  216. Assert (pDevice);
  217. if (0 == wcscmp(pszInstanceGuid, pDevice->m_szInstanceGuid))
  218. {
  219. return pDevice;
  220. }
  221. }
  222. return NULL;
  223. }
  224. HRESULT
  225. CFilterDevices::HrLoadFilterDevice (
  226. IN SP_DEVINFO_DATA* pdeid,
  227. IN HKEY hkeyInstance,
  228. IN PCWSTR pszFilterInfId,
  229. OUT BOOL* pfRemove)
  230. {
  231. HRESULT hr;
  232. CComponent* pAdapter;
  233. CComponent* pFilter;
  234. WCHAR szInstanceGuid [c_cchGuidWithTerm];
  235. DWORD cbBuffer;
  236. Assert (pszFilterInfId && *pszFilterInfId);
  237. Assert (pfRemove);
  238. *pfRemove = FALSE;
  239. // Initialize these to NULL. If we don't find them below, they will
  240. // remain NULL and this will tell us something.
  241. //
  242. pAdapter = NULL;
  243. pFilter = NULL;
  244. cbBuffer = sizeof(szInstanceGuid);
  245. hr = HrRegQuerySzBuffer (
  246. hkeyInstance,
  247. L"NetCfgInstanceId",
  248. szInstanceGuid, &cbBuffer);
  249. if (S_OK == hr)
  250. {
  251. HKEY hkeyLinkage;
  252. // Read the RootDevice registry value for this filter device. The
  253. // last entry in that multi-sz will be the bindname of the adapter
  254. // being filtered.
  255. //
  256. hr = HrRegOpenKeyEx (
  257. hkeyInstance,
  258. L"Linkage",
  259. KEY_READ,
  260. &hkeyLinkage);
  261. if (S_OK == hr)
  262. {
  263. PWSTR pmszRootDevice;
  264. hr = HrRegQueryMultiSzWithAlloc (
  265. hkeyLinkage,
  266. L"RootDevice",
  267. &pmszRootDevice);
  268. if (S_OK == hr)
  269. {
  270. PCWSTR pszScan;
  271. PCWSTR pszLastDevice = NULL;
  272. // Scan to the last string in the multi-sz and note it.
  273. //
  274. for (pszScan = pmszRootDevice;
  275. *pszScan;
  276. pszScan += wcslen(pszScan) + 1)
  277. {
  278. pszLastDevice = pszScan;
  279. }
  280. // The last string in the multi-sz is the bindname of the
  281. // adapter being filtered.
  282. //
  283. if (pszLastDevice)
  284. {
  285. pAdapter = m_pCore->Components.PFindComponentByBindName (
  286. NC_NET, pszLastDevice);
  287. if (!pAdapter)
  288. {
  289. hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
  290. }
  291. }
  292. MemFree (pmszRootDevice);
  293. }
  294. RegCloseKey (hkeyLinkage);
  295. }
  296. if (S_OK == hr)
  297. {
  298. // Should have the adapter if no error.
  299. //
  300. Assert (pAdapter);
  301. // Get the enabled filters for the adapter.
  302. //
  303. hr = m_pCore->HrGetFiltersEnabledForAdapter (pAdapter, &m_Filters);
  304. if (S_OK == hr)
  305. {
  306. // Use pszFilterInfId to find the parent filter component for
  307. // this filter device. If it is not found, it probably means
  308. // the entire filter is in the process of being removed.
  309. // (Or the registry was messed with.)
  310. //
  311. pFilter = m_pCore->Components.PFindComponentByInfId (
  312. pszFilterInfId, NULL);
  313. // If the filter corresponding to this device is still
  314. // installed and is enabled over the adapter, then we'll
  315. // insert the device into our list. Otherwise, we're going
  316. // to remove it.
  317. //
  318. if (pFilter && m_Filters.FComponentInList (pFilter))
  319. {
  320. CFilterDevice* pFilterDevice;
  321. // Create an instance of the filter device class to
  322. // represent this filter device.
  323. //
  324. hr = CFilterDevice::HrCreateInstance (
  325. pAdapter,
  326. pFilter,
  327. pdeid,
  328. szInstanceGuid,
  329. &pFilterDevice);
  330. if (S_OK == hr)
  331. {
  332. // Add the filter device to our list of filter devices.
  333. //
  334. hr = HrInsertFilterDevice (pFilterDevice);
  335. if (S_OK != hr)
  336. {
  337. delete pFilterDevice;
  338. }
  339. }
  340. }
  341. else
  342. {
  343. *pfRemove = TRUE;
  344. Assert (pszFilterInfId && *pszFilterInfId);
  345. Assert (pAdapter);
  346. g_pDiagCtx->Printf (ttidBeDiag,
  347. " Removing filter device for %S over %S adapter\n",
  348. pszFilterInfId,
  349. pAdapter->m_pszPnpId);
  350. // Since we will be removing a filter device from the
  351. // chain, we need to rebind the protocols above the
  352. // adapter we are removing the filter device for.
  353. //
  354. // So, get the upper bindings of the adapter (bindpaths
  355. // are only 2 levels deep) and add them to the bind set
  356. // that we will rebind later on.
  357. //
  358. hr = m_pCore->HrGetComponentUpperBindings (
  359. pAdapter,
  360. GBF_ADD_TO_BINDSET | GBF_PRUNE_DISABLED_BINDINGS,
  361. &m_BindPathsToRebind);
  362. }
  363. }
  364. }
  365. }
  366. TraceHr (ttidError, FAL, hr,
  367. HRESULT_FROM_WIN32(ERROR_NOT_FOUND) == hr,
  368. "CFilterDevices::HrLoadFilterDevice");
  369. return hr;
  370. }
  371. VOID
  372. CFilterDevices::LoadAndRemoveFilterDevicesIfNeeded ()
  373. {
  374. HRESULT hr;
  375. SP_DEVINFO_DATA deid;
  376. DWORD dwIndex;
  377. DWORD cbBuffer;
  378. WCHAR szFilterInfId [_MAX_PATH];
  379. Assert (this);
  380. Assert (m_pCore);
  381. Assert (!m_hdi);
  382. Assert (empty());
  383. // Filter devices can only be of net class.
  384. //
  385. hr = HrSetupDiGetClassDevs (&GUID_DEVCLASS_NET, NULL, NULL,
  386. DIGCF_PROFILE, &m_hdi);
  387. if (S_OK != hr)
  388. {
  389. return;
  390. }
  391. Assert (m_hdi);
  392. // Enumerate all net class devices from setupapi.
  393. //
  394. for (dwIndex = 0; S_OK == hr; dwIndex++)
  395. {
  396. hr = HrSetupDiEnumDeviceInfo (m_hdi, dwIndex, &deid);
  397. if (S_OK == hr)
  398. {
  399. HKEY hkeyInstance;
  400. hr = HrSetupDiOpenDevRegKey (
  401. m_hdi, &deid,
  402. DICS_FLAG_GLOBAL, 0, DIREG_DRV,
  403. KEY_READ, &hkeyInstance);
  404. if (S_OK == hr)
  405. {
  406. // If the device has a "FilterInfId" value under its
  407. // instance key, its one of ours.
  408. //
  409. cbBuffer = sizeof(szFilterInfId);
  410. hr = HrRegQuerySzBuffer (
  411. hkeyInstance,
  412. L"FilterInfId",
  413. szFilterInfId,
  414. &cbBuffer);
  415. if (S_OK == hr)
  416. {
  417. BOOL fRemove;
  418. // Load the rest of the filter device, and add it to
  419. // our list. If this fails for any reason, remove the
  420. // filter device because its of no use to us anymore.
  421. //
  422. hr = HrLoadFilterDevice (
  423. &deid,
  424. hkeyInstance,
  425. szFilterInfId,
  426. &fRemove);
  427. if ((S_OK != hr) || fRemove)
  428. {
  429. if (S_OK != hr)
  430. {
  431. g_pDiagCtx->Printf (ttidBeDiag,
  432. " Removing filter device for %S\n",
  433. szFilterInfId);
  434. }
  435. (VOID) HrCiRemoveFilterDevice (m_hdi, &deid);
  436. hr = S_OK;
  437. }
  438. }
  439. //else if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr)
  440. //{
  441. // Not a filter device. Skip it.
  442. //}
  443. RegCloseKey (hkeyInstance);
  444. }
  445. // Allow the loop to continue;
  446. //
  447. hr = S_OK;
  448. }
  449. }
  450. if (HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS) == hr)
  451. {
  452. hr = S_OK;
  453. }
  454. g_pDiagCtx->Printf (ttidBeDiag, " Loaded %d filter devices\n", size());
  455. }
  456. VOID
  457. CFilterDevices::InstallFilterDevicesIfNeeded ()
  458. {
  459. HRESULT hr;
  460. CComponentList::iterator iterAdapter;
  461. CComponentList::iterator iterFilter;
  462. CComponent* pAdapter;
  463. CComponent* pFilter;
  464. HKEY hkeyInstance;
  465. HKEY hkeyNdi;
  466. DWORD cbBuffer;
  467. BOOL fAddDevice;
  468. BOOL fAddedDeviceForAdapter;
  469. WCHAR szFilterDeviceInfId [_MAX_PATH];
  470. WCHAR szFilterClass [_MAX_PATH];
  471. Assert (this);
  472. Assert (m_pCore);
  473. // If, for some reason, we couldn't get m_hdi up in
  474. // RemoveFilterDevicesIfNeeded, we can't proceed.
  475. //
  476. if (!m_hdi)
  477. {
  478. return;
  479. }
  480. // For all adapters (because filters possibly bind to any adapter)
  481. // we get the filters enabled for each. For each on of these filters
  482. // that don't already have an associated filter device for the adapter,
  483. // we create a new one and associated it.
  484. //
  485. for (iterAdapter = m_pCore->Components.begin();
  486. iterAdapter != m_pCore->Components.end();
  487. iterAdapter++)
  488. {
  489. pAdapter = *iterAdapter;
  490. Assert (pAdapter);
  491. // Skip components that are not network adapters.
  492. //
  493. if (NC_NET != pAdapter->Class())
  494. {
  495. continue;
  496. }
  497. hr = m_pCore->HrGetFiltersEnabledForAdapter (pAdapter, &m_Filters);
  498. if (S_OK != hr)
  499. {
  500. // More than likely, we are out of memory.
  501. //
  502. TraceHr (ttidError, FAL, hr, FALSE,
  503. "HrGetFiltersEnabledForAdapter failed in "
  504. "InstallFilterDevicesIfNeeded. Adapter=%S",
  505. pAdapter->m_pszPnpId);
  506. break;
  507. }
  508. // We haven't yet added any devices for this adapter.
  509. //
  510. fAddedDeviceForAdapter = FALSE;
  511. // For each of the filters enabled for this adapter, install
  512. // a filter device if needed and make sure the filter has its
  513. // ordinal position with respect other filters read from the
  514. // registry. We need m_dwFilterClassOrdinal to be valid (non-zero)
  515. // before we sort the filter devices when writing their bindings.
  516. //
  517. for (iterFilter = m_Filters.begin();
  518. iterFilter != m_Filters.end();
  519. iterFilter++)
  520. {
  521. pFilter = *iterFilter;
  522. Assert (pFilter);
  523. // If there isn't a filter device for the current adapter
  524. // and filter, we need to install one.
  525. //
  526. fAddDevice = !PFindFilterDeviceByAdapterAndFilter (
  527. pAdapter, pFilter);
  528. // If we don't need to add a filter device and we already
  529. // have the ordinal position of the filter, we can continue with
  530. // the next filter for this adapter.
  531. //
  532. if (!fAddDevice && (0 != pFilter->m_dwFilterClassOrdinal))
  533. {
  534. continue;
  535. }
  536. *szFilterDeviceInfId = 0;
  537. // Open the instance key of the filter so we can read
  538. // a few values.
  539. //
  540. hr = pFilter->HrOpenInstanceKey (KEY_READ, &hkeyInstance,
  541. NULL, NULL);
  542. if (S_OK == hr)
  543. {
  544. // Open the Ndi key.
  545. //
  546. hr = HrRegOpenKeyEx (hkeyInstance, L"Ndi",
  547. KEY_READ, &hkeyNdi);
  548. if (S_OK == hr)
  549. {
  550. if (0 == pFilter->m_dwFilterClassOrdinal)
  551. {
  552. // Read the filter class and convert it to an
  553. // ordinal based on its position in the
  554. // filter classes list.
  555. //
  556. cbBuffer = sizeof(szFilterClass);
  557. hr = HrRegQuerySzBuffer (hkeyNdi,
  558. L"FilterClass",
  559. szFilterClass,
  560. &cbBuffer);
  561. if (S_OK == hr)
  562. {
  563. pFilter->m_dwFilterClassOrdinal =
  564. MapFilterClassToOrdinal (szFilterClass);
  565. }
  566. }
  567. if (fAddDevice)
  568. {
  569. // Read the ind id of the filter device.
  570. //
  571. cbBuffer = sizeof(szFilterDeviceInfId);
  572. hr = HrRegQuerySzBuffer (
  573. hkeyNdi, L"FilterDeviceInfId",
  574. szFilterDeviceInfId, &cbBuffer);
  575. }
  576. RegCloseKey (hkeyNdi);
  577. }
  578. RegCloseKey (hkeyInstance);
  579. }
  580. if ((S_OK == hr) && fAddDevice)
  581. {
  582. CFilterDevice* pFilterDevice;
  583. Assert (*szFilterDeviceInfId);
  584. g_pDiagCtx->Printf (ttidBeDiag,
  585. " Installing filter device for %S over %S adapter\n",
  586. pFilter->m_pszInfId,
  587. pAdapter->m_pszPnpId);
  588. hr = HrCiInstallFilterDevice (m_hdi,
  589. szFilterDeviceInfId,
  590. pAdapter,
  591. pFilter,
  592. &pFilterDevice);
  593. if (S_OK == hr)
  594. {
  595. hr = HrInsertFilterDevice (pFilterDevice);
  596. if (S_OK == hr)
  597. {
  598. fAddedDeviceForAdapter = TRUE;
  599. }
  600. else
  601. {
  602. delete pFilterDevice;
  603. }
  604. }
  605. }
  606. }
  607. // If we added at least one filter device in the chain for this
  608. // adapter, we'll need to unbind the adapter from whatever it is
  609. // currently bound to before we start the filter device.
  610. //
  611. if (fAddedDeviceForAdapter)
  612. {
  613. // So, get the upper bindings of the adapter (bindpaths
  614. // are only 2 levels deep) and add them to the bind set
  615. // that we will rebind later on.
  616. //
  617. hr = m_pCore->HrGetComponentUpperBindings (
  618. pAdapter,
  619. GBF_ADD_TO_BINDSET | GBF_PRUNE_DISABLED_BINDINGS,
  620. &m_BindPathsToRebind);
  621. }
  622. }
  623. }
  624. INT
  625. __cdecl
  626. CompareFilterDevices (
  627. const VOID* pv1,
  628. const VOID* pv2)
  629. {
  630. CFilterDevice* pDevice1 = *((CFilterDevice**)pv1);
  631. CFilterDevice* pDevice2 = *((CFilterDevice**)pv2);
  632. if (pDevice1->m_pAdapter == pDevice2->m_pAdapter)
  633. {
  634. Assert (pDevice1->m_pFilter != pDevice2->m_pFilter);
  635. if (pDevice1->m_pFilter->m_dwFilterClassOrdinal ==
  636. pDevice2->m_pFilter->m_dwFilterClassOrdinal)
  637. {
  638. AssertSz (0, "We have two filters of the same class installed.");
  639. return 0;
  640. }
  641. return (pDevice1->m_pFilter->m_dwFilterClassOrdinal <
  642. pDevice2->m_pFilter->m_dwFilterClassOrdinal)
  643. ? -1 : 1;
  644. }
  645. return (pDevice1->m_pAdapter < pDevice2->m_pAdapter) ? -1 : 1;
  646. /*
  647. if (pDevice1->m_pFilter == pDevice2->m_pFilter)
  648. {
  649. Assert (pDevice1->m_pAdapter != pDevice2->m_pAdapter);
  650. return (pDevice1->m_pAdapter < pDevice2->m_pAdapter) ? -1 : 1;
  651. }
  652. if (pDevice1->m_pFilter->m_dwFilterClassOrdinal ==
  653. pDevice2->m_pFilter->m_dwFilterClassOrdinal)
  654. {
  655. AssertSz (0, "We have two filters of the same class installed.");
  656. return 0;
  657. }
  658. return (pDevice1->m_pFilter->m_dwFilterClassOrdinal <
  659. pDevice2->m_pFilter->m_dwFilterClassOrdinal)
  660. ? -1 : 1;
  661. */
  662. }
  663. VOID
  664. CFilterDevices::SortForWritingBindings ()
  665. {
  666. Assert (this);
  667. // If we're empty, there is nothing to do.
  668. //
  669. if (empty())
  670. {
  671. return;
  672. }
  673. qsort (begin(), size(), sizeof(CFilterDevice*), CompareFilterDevices);
  674. }
  675. VOID
  676. CFilterDevices::StartFilterDevices ()
  677. {
  678. HRESULT hr;
  679. CFilterDevices::reverse_iterator iter;
  680. CFilterDevice* pDevice;
  681. Assert (this);
  682. Assert (m_pCore);
  683. // If we're empty, there is nothing to do.
  684. //
  685. if (empty())
  686. {
  687. return;
  688. }
  689. // If we're not empty, we must have had m_hdi to insert something.
  690. //
  691. Assert (m_hdi);
  692. for (iter = rbegin(); iter != rend(); iter++)
  693. {
  694. pDevice = *iter;
  695. Assert (pDevice);
  696. g_pDiagCtx->Printf (ttidBeDiag, " %S filter over %S adapter\n",
  697. pDevice->m_pFilter->m_pszInfId,
  698. pDevice->m_pAdapter->m_pszPnpId);
  699. hr = HrSetupDiSendPropertyChangeNotification (
  700. m_hdi,
  701. &pDevice->m_deid,
  702. DICS_START,
  703. DICS_FLAG_CONFIGSPECIFIC,
  704. 0);
  705. if (S_OK != hr)
  706. {
  707. g_pDiagCtx->Printf (ttidBeDiag, " Failed to start filter device for "
  708. "%S over %S adapter\n",
  709. pDevice->m_pFilter->m_pszInfId,
  710. pDevice->m_pAdapter->m_pszPnpId);
  711. }
  712. }
  713. }
  714. VOID
  715. CFilterDevices::Free ()
  716. {
  717. Assert (this);
  718. MemFree (m_pmszFilterClasses);
  719. m_pmszFilterClasses = NULL;
  720. SetupDiDestroyDeviceInfoListSafe (m_hdi);
  721. m_hdi = NULL;
  722. FreeCollectionAndItem (*this);
  723. // Do NOT free m_BindPathsToRebind. This is used even after ApplyChanges
  724. // calls Free.
  725. //
  726. }