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.

1039 lines
32 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1999.
  5. //
  6. // File: R E G B I N D . C P P
  7. //
  8. // Contents: This module is responsible for writing bindings to the
  9. // registry so that they may be consumed by NDIS and TDI.
  10. //
  11. // Notes:
  12. //
  13. // Author: shaunco 1 Feb 1999
  14. //
  15. //----------------------------------------------------------------------------
  16. #include "pch.h"
  17. #pragma hdrstop
  18. #include "filtdevs.h"
  19. #include "lanamap.h"
  20. #include "netcfg.h"
  21. #include "ncreg.h"
  22. #include "ndispnp.h"
  23. HRESULT
  24. HrRegSetMultiSzAndLogDifference (
  25. IN HKEY hkey,
  26. IN PCWSTR pszValueName,
  27. IN PCWSTR pmszValue,
  28. IN const CComponent* pComponent
  29. )
  30. {
  31. // Only log the difference if we're operating under the appropriate
  32. // diagnostic context.
  33. //
  34. if (g_pDiagCtx->Flags() & DF_REPAIR_REGISTRY_BINDINGS)
  35. {
  36. HRESULT hr;
  37. DWORD cbCurrent;
  38. PWSTR pmszCurrent = (PWSTR)g_pDiagCtx->GetScratchBuffer(&cbCurrent);
  39. // Read the current value into the diagnostic context's scratch
  40. // buffer.
  41. //
  42. hr = HrRegQueryTypeSzBuffer (hkey, pszValueName, REG_MULTI_SZ,
  43. pmszCurrent, &cbCurrent);
  44. // Grow the scratch buffer and retry if the value is bigger than
  45. // than will fit.
  46. //
  47. if ((HRESULT_FROM_WIN32(ERROR_MORE_DATA) == hr) ||
  48. ((NULL == pmszCurrent) && (S_OK == hr)))
  49. {
  50. pmszCurrent = (PWSTR)g_pDiagCtx->GrowScratchBuffer(&cbCurrent);
  51. if (pmszCurrent)
  52. {
  53. hr = HrRegQueryTypeSzBuffer (hkey, pszValueName, REG_MULTI_SZ,
  54. pmszCurrent, &cbCurrent);
  55. }
  56. else
  57. {
  58. hr = E_OUTOFMEMORY;
  59. }
  60. }
  61. if (S_OK == hr)
  62. {
  63. DWORD cbValue = CbOfMultiSzAndTermSafe(pmszValue);
  64. // Compare the values and log if they are different.
  65. //
  66. if ((cbValue != cbCurrent) ||
  67. (memcmp(pmszValue, pmszCurrent, cbCurrent)))
  68. {
  69. FILE *LogFile = g_pDiagCtx->LogFile();
  70. fprintf(LogFile,
  71. "reset Linkage\\%S for %S. bad value was:\n",
  72. pszValueName, pComponent->PszGetPnpIdOrInfId());
  73. fprintf(LogFile, " REG_MULTI_SZ =\n");
  74. if (*pmszCurrent)
  75. {
  76. while (*pmszCurrent)
  77. {
  78. fprintf(LogFile, " %S\n", pmszCurrent);
  79. pmszCurrent += wcslen(pmszCurrent) + 1;
  80. }
  81. }
  82. else
  83. {
  84. fprintf(LogFile, " <empty>\n");
  85. }
  86. fprintf(LogFile, "\n");
  87. }
  88. else
  89. {
  90. // The value is correct. No need to write it.
  91. //
  92. return S_OK;
  93. }
  94. }
  95. else if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr)
  96. {
  97. fprintf(g_pDiagCtx->LogFile(),
  98. "added Linkage\\%S for %S\n",
  99. pszValueName, pComponent->PszGetPnpIdOrInfId());
  100. }
  101. }
  102. // N.B. success or failure of the diagnostic portion of this routine
  103. // (above) should NOT affect the return value of this routine.
  104. //
  105. return HrRegSetMultiSz (hkey, pszValueName, pmszValue);
  106. }
  107. HRESULT
  108. HrCreateLinkageKey (
  109. IN const CComponent* pComponent,
  110. IN CFilterDevice* pDevice,
  111. IN HDEVINFO hdi,
  112. OUT HKEY* phKey)
  113. {
  114. HRESULT hr = E_UNEXPECTED;
  115. HKEY hkeyParent = NULL;
  116. CONST REGSAM samDesired = KEY_READ | KEY_WRITE;
  117. Assert (pComponent || pDevice);
  118. Assert (!(pComponent && pDevice));
  119. Assert (FIff(pDevice, hdi));
  120. Assert (phKey);
  121. if (pComponent)
  122. {
  123. // Open the parent of the linkage key. This is the instance key if
  124. // the component is enumerated or does not have a service.
  125. //
  126. if (FIsEnumerated (pComponent->Class()) || !pComponent->FHasService())
  127. {
  128. hr = pComponent->HrOpenInstanceKey (samDesired,
  129. &hkeyParent,
  130. NULL, NULL);
  131. if ((S_OK == hr) && FIsEnumerated (pComponent->Class()))
  132. {
  133. // Write out the netcfg instance id. Connections will use
  134. // this to determine if the device is known by net config
  135. // and will create the <instance guid> key under network
  136. // to store its connection info. We only need to do this
  137. // for enumerated components.
  138. //
  139. hr = HrRegSetGuidAsSz (hkeyParent, L"NetCfgInstanceId",
  140. pComponent->m_InstanceGuid);
  141. }
  142. }
  143. else
  144. {
  145. hr = pComponent->HrOpenServiceKey (samDesired, &hkeyParent);
  146. }
  147. }
  148. else
  149. {
  150. Assert (pDevice);
  151. Assert (hdi);
  152. hr = HrSetupDiOpenDevRegKey (
  153. hdi,
  154. &pDevice->m_deid,
  155. DICS_FLAG_GLOBAL,
  156. 0,
  157. DIREG_DRV,
  158. samDesired,
  159. &hkeyParent);
  160. }
  161. if (S_OK == hr)
  162. {
  163. Assert (hkeyParent);
  164. hr = HrRegCreateKeyEx (
  165. hkeyParent,
  166. L"Linkage",
  167. REG_OPTION_NON_VOLATILE,
  168. samDesired,
  169. NULL,
  170. phKey,
  171. NULL);
  172. RegCloseKey (hkeyParent);
  173. }
  174. TraceHr (ttidError, FAL, hr,
  175. (SPAPI_E_NO_SUCH_DEVINST == hr),
  176. "HrCreateLinkageKey");
  177. return hr;
  178. }
  179. HRESULT
  180. HrWriteLinkageValues (
  181. IN const CComponent* pComponent,
  182. IN PCWSTR pmszBind,
  183. IN PCWSTR pmszExport,
  184. IN PCWSTR pmszRoute)
  185. {
  186. HRESULT hr;
  187. HKEY hkeyLinkage;
  188. PCWSTR pmsz;
  189. Assert (pmszBind);
  190. Assert (pmszExport);
  191. Assert (pmszRoute);
  192. g_pDiagCtx->Printf (ttidBeDiag, " %S (%S)\n",
  193. pComponent->Ext.PszBindName(),
  194. pComponent->PszGetPnpIdOrInfId());
  195. if (FIsEnumerated (pComponent->Class()))
  196. {
  197. g_pDiagCtx->Printf (ttidBeDiag, " UpperBind:\n");
  198. }
  199. else
  200. {
  201. g_pDiagCtx->Printf (ttidBeDiag, " Bind:\n");
  202. }
  203. pmsz = pmszBind;
  204. while (*pmsz)
  205. {
  206. g_pDiagCtx->Printf (ttidBeDiag, " %S\n", pmsz);
  207. pmsz += wcslen (pmsz) + 1;
  208. }
  209. g_pDiagCtx->Printf (ttidBeDiag, " Export:\n");
  210. pmsz = pmszExport;
  211. while (*pmsz)
  212. {
  213. g_pDiagCtx->Printf (ttidBeDiag, " %S\n", pmsz);
  214. pmsz += wcslen (pmsz) + 1;
  215. }
  216. g_pDiagCtx->Printf (ttidBeDiag, "\n");
  217. hr = HrCreateLinkageKey (pComponent, NULL, NULL, &hkeyLinkage);
  218. if (S_OK == hr)
  219. {
  220. // For enumerated components, write RootDevice, UpperBind, and Export.
  221. // For non-enumerated components, write Bind and Export.
  222. //
  223. if (FIsEnumerated (pComponent->Class()))
  224. {
  225. // Create the root device multi-sz from the bindname.
  226. //
  227. WCHAR mszRootDevice [_MAX_PATH];
  228. wcscpy (mszRootDevice, pComponent->Ext.PszBindName());
  229. mszRootDevice [wcslen(mszRootDevice) + 1] = 0;
  230. hr = HrRegSetMultiSzAndLogDifference (
  231. hkeyLinkage, L"RootDevice", mszRootDevice, pComponent);
  232. if (S_OK == hr)
  233. {
  234. hr = HrRegSetMultiSzAndLogDifference (
  235. hkeyLinkage, L"UpperBind", pmszBind, pComponent);
  236. }
  237. }
  238. else
  239. {
  240. hr = HrRegSetMultiSzAndLogDifference (
  241. hkeyLinkage, L"Bind", pmszBind, pComponent);
  242. if (S_OK == hr)
  243. {
  244. hr = HrRegSetMultiSzAndLogDifference (
  245. hkeyLinkage, L"Route", pmszRoute, pComponent);
  246. }
  247. }
  248. if ((S_OK == hr) && *pmszExport)
  249. {
  250. hr = HrRegSetMultiSzAndLogDifference (
  251. hkeyLinkage, L"Export", pmszExport, pComponent);
  252. }
  253. RegCloseKey (hkeyLinkage);
  254. }
  255. TraceHr (ttidError, FAL, hr,
  256. (SPAPI_E_NO_SUCH_DEVINST == hr),
  257. "HrWriteLinkageValues");
  258. return hr;
  259. }
  260. HRESULT
  261. HrWriteFilterDeviceLinkage (
  262. IN CFilterDevice* pDevice,
  263. IN HDEVINFO hdi,
  264. IN PCWSTR pmszExport,
  265. IN PCWSTR pmszRootDevice,
  266. IN PCWSTR pmszUpperBind)
  267. {
  268. HRESULT hr;
  269. HKEY hkeyLinkage;
  270. PCWSTR pmsz;
  271. g_pDiagCtx->Printf (ttidBeDiag, " %S filter over %S adapter\n",
  272. pDevice->m_pFilter->m_pszInfId,
  273. pDevice->m_pAdapter->m_pszPnpId);
  274. g_pDiagCtx->Printf (ttidBeDiag, " Export:\n");
  275. pmsz = pmszExport;
  276. while (*pmsz)
  277. {
  278. g_pDiagCtx->Printf (ttidBeDiag, " %S\n", pmsz);
  279. pmsz += wcslen (pmsz) + 1;
  280. }
  281. g_pDiagCtx->Printf (ttidBeDiag, " RootDevice:\n");
  282. pmsz = pmszRootDevice;
  283. while (*pmsz)
  284. {
  285. g_pDiagCtx->Printf (ttidBeDiag, " %S\n", pmsz);
  286. pmsz += wcslen (pmsz) + 1;
  287. }
  288. g_pDiagCtx->Printf (ttidBeDiag, " UpperBind:\n");
  289. pmsz = pmszUpperBind;
  290. while (*pmsz)
  291. {
  292. g_pDiagCtx->Printf (ttidBeDiag, " %S\n", pmsz);
  293. pmsz += wcslen (pmsz) + 1;
  294. }
  295. g_pDiagCtx->Printf (ttidBeDiag, "\n");
  296. hr = HrCreateLinkageKey (NULL, pDevice, hdi, &hkeyLinkage);
  297. if (S_OK == hr)
  298. {
  299. hr = HrRegSetMultiSz (hkeyLinkage, L"Export", pmszExport);
  300. if (S_OK == hr)
  301. {
  302. hr = HrRegSetMultiSz (hkeyLinkage, L"RootDevice", pmszRootDevice);
  303. }
  304. if (S_OK == hr)
  305. {
  306. hr = HrRegSetMultiSz (hkeyLinkage, L"UpperBind", pmszUpperBind);
  307. }
  308. // Delete values used by the previous binding engine that are
  309. // not needed any longer.
  310. //
  311. RegDeleteValue (hkeyLinkage, L"BindPath");
  312. RegDeleteValue (hkeyLinkage, L"Bind");
  313. RegDeleteValue (hkeyLinkage, L"Route");
  314. RegDeleteKey (hkeyLinkage, L"Disabled");
  315. RegCloseKey (hkeyLinkage);
  316. }
  317. // Now write to the standard filter parameter registry layout under
  318. // the filter's service key.
  319. //
  320. if (pDevice->m_pFilter->Ext.PszService())
  321. {
  322. HKEY hkeyAdapterParams;
  323. WCHAR szRegPath [_MAX_PATH];
  324. Assert (pDevice->m_pFilter->Ext.PszService());
  325. Assert (pDevice->m_pAdapter->Ext.PszBindName());
  326. wsprintfW (
  327. szRegPath,
  328. L"System\\CurrentControlSet\\Services\\%s\\Parameters\\Adapters\\%s",
  329. pDevice->m_pFilter->Ext.PszService(),
  330. pDevice->m_pAdapter->Ext.PszBindName());
  331. hr = HrRegCreateKeyEx (
  332. HKEY_LOCAL_MACHINE,
  333. szRegPath,
  334. REG_OPTION_NON_VOLATILE,
  335. KEY_WRITE,
  336. NULL,
  337. &hkeyAdapterParams,
  338. NULL);
  339. if (S_OK == hr)
  340. {
  341. // UpperBindings is a REG_SZ, not a REG_MULTI_SZ.
  342. //
  343. hr = HrRegSetSz (hkeyAdapterParams, L"UpperBindings", pmszExport);
  344. RegCloseKey (hkeyAdapterParams);
  345. }
  346. }
  347. TraceHr (ttidError, FAL, hr, FALSE, "HrWriteFilterDeviceLinkage");
  348. return hr;
  349. }
  350. HRESULT
  351. HrWriteFilteredAdapterUpperBind (
  352. IN const CComponent* pAdapter,
  353. IN PCWSTR pmszUpperBind)
  354. {
  355. HRESULT hr;
  356. HKEY hkeyLinkage;
  357. hr = HrCreateLinkageKey (pAdapter, NULL, NULL, &hkeyLinkage);
  358. if (S_OK == hr)
  359. {
  360. hr = HrRegSetMultiSz (hkeyLinkage, L"UpperBind", pmszUpperBind);
  361. RegCloseKey (hkeyLinkage);
  362. }
  363. TraceHr (ttidError, FAL, hr, FALSE, "HrWriteFilteredAdapterUpperBind");
  364. return hr;
  365. }
  366. HRESULT
  367. CRegistryBindingsContext::HrPrepare (
  368. IN CNetConfig* pNetConfig)
  369. {
  370. HRESULT hr;
  371. Assert (pNetConfig);
  372. m_pNetConfig = pNetConfig;
  373. hr = m_BindValue.HrReserveBytes (4096);
  374. if (S_OK != hr)
  375. {
  376. return hr;
  377. }
  378. hr = m_ExportValue.HrReserveBytes (4096);
  379. if (S_OK != hr)
  380. {
  381. return hr;
  382. }
  383. hr = m_RouteValue.HrReserveBytes (4096);
  384. if (S_OK != hr)
  385. {
  386. return hr;
  387. }
  388. // Ensure all of the external data for all components is loaded.
  389. //
  390. hr = m_pNetConfig->HrEnsureExternalDataLoadedForAllComponents ();
  391. if (S_OK != hr)
  392. {
  393. return hr;
  394. }
  395. // Ensure all of the notify objects have been initialized.
  396. //
  397. hr = m_pNetConfig->Notify.HrEnsureNotifyObjectsInitialized ();
  398. if (S_OK != hr)
  399. {
  400. return hr;
  401. }
  402. return S_OK;
  403. }
  404. HRESULT
  405. CRegistryBindingsContext::HrDeleteBindingsForComponent (
  406. IN const CComponent* pComponent)
  407. {
  408. return HrWriteLinkageValues (pComponent, L"", L"", L"");
  409. }
  410. HRESULT
  411. CRegistryBindingsContext::HrGetAdapterUpperBindValue (
  412. IN const CComponent* pAdapter)
  413. {
  414. HRESULT hr;
  415. const CBindPath* pBindPath;
  416. m_BindValue.Clear();
  417. // Get the upper bindings of the component. This returns a bindset
  418. // with binpaths only 2 levels deep. That is, the bindpaths begin
  419. // with the components one level above pComponent.
  420. //
  421. hr = m_pNetConfig->Core.HrGetComponentUpperBindings (
  422. pAdapter,
  423. GBF_PRUNE_DISABLED_BINDINGS,
  424. &m_BindSet);
  425. if (S_OK == hr)
  426. {
  427. for (pBindPath = m_BindSet.begin();
  428. pBindPath != m_BindSet.end();
  429. pBindPath++)
  430. {
  431. // Don't put filters in the UpperBind of an adapter.
  432. //
  433. if (pBindPath->POwner()->FIsFilter())
  434. {
  435. continue;
  436. }
  437. hr = m_BindValue.HrCopyString (
  438. pBindPath->POwner()->Ext.PszBindName());
  439. if (S_OK != hr)
  440. {
  441. break;
  442. }
  443. }
  444. hr = m_BindValue.HrCopyString (L"");
  445. }
  446. TraceHr (ttidError, FAL, hr, FALSE,
  447. "CRegistryBindingsContext::HrGetAdapterUpperBindValue");
  448. return hr;
  449. }
  450. HRESULT
  451. CRegistryBindingsContext::HrWriteBindingsForComponent (
  452. IN const CComponent* pComponent)
  453. {
  454. HRESULT hr;
  455. const CBindPath* pBindPath;
  456. CBindPath::const_iterator iter;
  457. const CComponent* pUpper;
  458. const CComponent* pLower;
  459. WCHAR szBind [_MAX_BIND_LENGTH];
  460. WCHAR szExport [_MAX_BIND_LENGTH];
  461. WCHAR szRoute [_MAX_BIND_LENGTH];
  462. PWCHAR pchBind;
  463. PWCHAR pchExport;
  464. Assert (pComponent);
  465. pComponent->Ext.DbgVerifyExternalDataLoaded ();
  466. // If the component is not bindable, we have nothing to do.
  467. //
  468. if (!pComponent->FIsBindable())
  469. {
  470. return S_OK;
  471. }
  472. m_BindValue.Clear ();
  473. m_ExportValue.Clear ();
  474. m_RouteValue.Clear ();
  475. wcscpy (szExport, L"\\Device\\");
  476. wcscat (szExport, pComponent->Ext.PszBindName());
  477. hr = m_ExportValue.HrCopyString (szExport);
  478. Assert (S_OK == hr);
  479. hr = m_ExportValue.HrCopyString (L"");
  480. Assert (S_OK == hr);
  481. if (FIsEnumerated (pComponent->Class()))
  482. {
  483. // UpperBind
  484. //
  485. hr = HrGetAdapterUpperBindValue (pComponent);
  486. }
  487. else
  488. {
  489. // Bind, Export
  490. //
  491. hr = m_pNetConfig->Core.HrGetComponentBindings (
  492. pComponent,
  493. GBF_PRUNE_DISABLED_BINDINGS,
  494. &m_BindSet);
  495. if ((S_OK == hr) && (m_BindSet.CountBindPaths() > 0))
  496. {
  497. // Since the component has bindings, it's export value will be
  498. // different from the default one we initialized with above.
  499. //
  500. m_ExportValue.Clear ();
  501. for (pBindPath = m_BindSet.begin();
  502. pBindPath != m_BindSet.end();
  503. pBindPath++)
  504. {
  505. Assert (pBindPath->CountComponents() > 1);
  506. wcscpy (szBind, L"\\Device\\");
  507. wcscpy (szExport, L"\\Device\\");
  508. *szRoute = 0;
  509. for (iter = pBindPath->begin();
  510. iter != pBindPath->end();
  511. iter++)
  512. {
  513. pUpper = *iter;
  514. Assert (pUpper);
  515. // For the bind value, skip the first component in each
  516. // path because it is the component we are writing the
  517. // bindings for.
  518. //
  519. if (iter != pBindPath->begin())
  520. {
  521. Assert (wcslen(szBind) + 1 +
  522. wcslen(pUpper->Ext.PszBindName())
  523. < celems(szBind));
  524. // If this isn't the first component to come after
  525. // \Device\, add underscores to seperate the
  526. // components.
  527. //
  528. if (iter != (pBindPath->begin() + 1))
  529. {
  530. wcscat (szBind, L"_");
  531. wcscat (szRoute, L" ");
  532. }
  533. wcscat (szBind, pUpper->Ext.PszBindName());
  534. wcscat (szRoute, L"\"");
  535. wcscat (szRoute, pUpper->Ext.PszBindName());
  536. wcscat (szRoute, L"\"");
  537. }
  538. Assert (wcslen(szExport) + 1 +
  539. wcslen(pUpper->Ext.PszBindName())
  540. < celems(szExport));
  541. // If this isn't the first component to come after
  542. // \Device\, add underscores to seperate the
  543. // components.
  544. //
  545. if (iter != pBindPath->begin())
  546. {
  547. wcscat (szExport, L"_");
  548. }
  549. wcscat (szExport, pUpper->Ext.PszBindName());
  550. // If the next component in the bindpath is the last
  551. // component, it is an adapter (by convention). Check
  552. // to see if there are multiple interfaces to be expanded
  553. // for the current component over this adapter.
  554. //
  555. if ((iter + 1) == (pBindPath->end() - 1))
  556. {
  557. DWORD cInterfaces;
  558. GUID* pguidInterfaceIds;
  559. pLower = *(iter + 1);
  560. hr = pUpper->Notify.HrGetInterfaceIdsForAdapter (
  561. m_pNetConfig->Notify.PINetCfg(),
  562. pLower,
  563. &cInterfaces,
  564. &pguidInterfaceIds);
  565. if (FAILED(hr))
  566. {
  567. break;
  568. }
  569. if (cInterfaces)
  570. {
  571. Assert (pguidInterfaceIds);
  572. if (iter != pBindPath->begin())
  573. {
  574. wcscat (szBind, L"_");
  575. pchBind = szBind + wcslen(szBind);
  576. Assert (wcslen(szBind) +
  577. c_cchGuidWithTerm < celems(szBind));
  578. }
  579. else
  580. {
  581. // The first component in the bindpath is
  582. // one that has multiple interfaces over the
  583. // adapter. The bind value should be as
  584. // normal, the export value will have the
  585. // expand interfaces.
  586. //
  587. Assert (wcslen(szBind) +
  588. wcslen(pLower->Ext.PszBindName())
  589. < celems(szBind));
  590. wcscat (szBind, pLower->Ext.PszBindName());
  591. hr = m_BindValue.HrCopyString (szBind);
  592. if (S_OK != hr)
  593. {
  594. break;
  595. }
  596. }
  597. wcscat (szExport, L"_");
  598. pchExport = szExport + wcslen(szExport);
  599. Assert (wcslen(szExport) +
  600. c_cchGuidWithTerm < celems(szExport));
  601. for (UINT i = 0; i < cInterfaces; i++)
  602. {
  603. if (iter != pBindPath->begin())
  604. {
  605. StringFromGUID2 (
  606. pguidInterfaceIds[i],
  607. pchBind, c_cchGuidWithTerm);
  608. hr = m_BindValue.HrCopyString (szBind);
  609. if (S_OK != hr)
  610. {
  611. break;
  612. }
  613. }
  614. StringFromGUID2 (
  615. pguidInterfaceIds[i],
  616. pchExport, c_cchGuidWithTerm);
  617. hr = m_ExportValue.HrCopyString (szExport);
  618. if (S_OK != hr)
  619. {
  620. break;
  621. }
  622. }
  623. CoTaskMemFree (pguidInterfaceIds);
  624. if (iter != pBindPath->begin())
  625. {
  626. wcscat (szRoute, L" ");
  627. }
  628. wcscat (szRoute, L"\"");
  629. wcscat (szRoute, pLower->Ext.PszBindName());
  630. wcscat (szRoute, L"\"");
  631. hr = m_RouteValue.HrCopyString (szRoute);
  632. if (S_OK != hr)
  633. {
  634. break;
  635. }
  636. // We only allow one component in a bindpath
  637. // to support mutliple interfaces and it always
  638. // comes at the end of the bindpath. Therefore,
  639. // after expanding them, we are done with the
  640. // bindpath and proceed to the next. (Hence, the
  641. // 'break').
  642. //
  643. break;
  644. }
  645. }
  646. }
  647. // If we exited the loop because we traversed the entire
  648. // bindpath (as opposed to expanding multiple interfaces,
  649. // where we would have stopped short), then add the bind
  650. // and export strings for this bindpath to the buffer and
  651. // proceed to the next bindpath.
  652. //
  653. if (iter == pBindPath->end())
  654. {
  655. hr = m_BindValue.HrCopyString (szBind);
  656. if (S_OK != hr)
  657. {
  658. break;
  659. }
  660. hr = m_ExportValue.HrCopyString (szExport);
  661. if (S_OK != hr)
  662. {
  663. break;
  664. }
  665. hr = m_RouteValue.HrCopyString (szRoute);
  666. if (S_OK != hr)
  667. {
  668. break;
  669. }
  670. }
  671. }
  672. // The bind and export values are multi-sz, so make sure they
  673. // are double null-terminiated.
  674. //
  675. hr = m_BindValue.HrCopyString (L"");
  676. if (S_OK == hr)
  677. {
  678. hr = m_ExportValue.HrCopyString (L"");
  679. }
  680. if (S_OK == hr)
  681. {
  682. hr = m_RouteValue.HrCopyString (L"");
  683. }
  684. }
  685. // Special case: NCF_DONTEXPOSELOWER
  686. //
  687. if ((S_OK == hr) &&
  688. ((pComponent->m_dwCharacter & NCF_DONTEXPOSELOWER) ||
  689. (0 == wcscmp(L"ms_nwspx", pComponent->m_pszInfId))))
  690. {
  691. wcscpy (szExport, L"\\Device\\");
  692. wcscat (szExport, pComponent->Ext.PszBindName());
  693. m_ExportValue.Clear ();
  694. hr = m_ExportValue.HrCopyString (szExport);
  695. Assert (S_OK == hr);
  696. hr = m_ExportValue.HrCopyString (L"");
  697. Assert (S_OK == hr);
  698. }
  699. // End Special case
  700. }
  701. if (S_OK == hr)
  702. {
  703. // Need to write out lanamap before writing new bindings since
  704. // we need the old binding information to persist lana numbers.
  705. //
  706. if (0 == wcscmp (pComponent->m_pszInfId, L"ms_netbios"))
  707. {
  708. (VOID) HrUpdateLanaConfig (
  709. m_pNetConfig->Core.Components,
  710. (PCWSTR)m_BindValue.PbBuffer(),
  711. m_BindSet.CountBindPaths());
  712. }
  713. hr = HrWriteLinkageValues (
  714. pComponent,
  715. (PCWSTR)m_BindValue.PbBuffer(),
  716. (PCWSTR)m_ExportValue.PbBuffer(),
  717. (PCWSTR)m_RouteValue.PbBuffer());
  718. if(S_OK == hr)
  719. {
  720. // mbend June 20, 2000
  721. // RAID 23275: Default gateway isn't respecting the adapter order specified under connections->advanced->properties
  722. // Notify NDIS when the binding list for a component changes.
  723. //
  724. UNICODE_STRING LowerComponent;
  725. UNICODE_STRING UpperComponent;
  726. UNICODE_STRING BindList;
  727. BOOL bOk = TRUE;
  728. if (FIsEnumerated(pComponent->Class()))
  729. {
  730. RtlInitUnicodeString(&BindList, NULL);
  731. RtlInitUnicodeString(&LowerComponent, NULL);
  732. RtlInitUnicodeString(&UpperComponent, pComponent->Ext.PszBindName());
  733. bOk = NdisHandlePnPEvent(
  734. NDIS,
  735. BIND_LIST,
  736. &LowerComponent,
  737. &UpperComponent,
  738. &BindList,
  739. const_cast<PBYTE>(m_BindValue.PbBuffer()),
  740. m_BindValue.CountOfBytesUsed());
  741. }
  742. else
  743. {
  744. RtlInitUnicodeString(&BindList, NULL);
  745. RtlInitUnicodeString(&LowerComponent, NULL);
  746. RtlInitUnicodeString(&UpperComponent, pComponent->Ext.PszBindName());
  747. TraceTag(ttidBeDiag, "BindName (TDI Client): %S", pComponent->Ext.PszBindName());
  748. bOk = NdisHandlePnPEvent(
  749. TDI,
  750. RECONFIGURE,
  751. &LowerComponent,
  752. &UpperComponent,
  753. &BindList,
  754. const_cast<PBYTE>(m_BindValue.PbBuffer()),
  755. m_BindValue.CountOfBytesUsed());
  756. }
  757. if(!bOk)
  758. {
  759. // hr = HrFromLastWin32Error();
  760. }
  761. }
  762. }
  763. TraceHr (ttidError, FAL, hr, FALSE,
  764. "CRegistryBindingsContext::HrWriteBindingsForComponent");
  765. return hr;
  766. }
  767. HRESULT
  768. CRegistryBindingsContext::HrWriteBindingsForFilterDevices (
  769. IN CFilterDevices* pFilterDevices)
  770. {
  771. HRESULT hr;
  772. CFilterDevices::iterator iter;
  773. CFilterDevices::iterator next;
  774. CFilterDevice* pDevice;
  775. CFilterDevice* pNextDevice;
  776. CFilterDevice* pPrevDevice;
  777. PCWSTR pmszRootDevice;
  778. PCWSTR pmszUpperBind;
  779. #define SZ_DEVICE_LEN 8 // characters in L"\\Device\\"
  780. WCHAR mszExport [SZ_DEVICE_LEN + c_cchGuidWithTerm + 1];
  781. WCHAR* const pchExportGuid = mszExport + SZ_DEVICE_LEN;
  782. // Pre-fill the beginning of the Export string.
  783. // Set the terminating NULL for the mutli-sz too.
  784. //
  785. wcscpy (mszExport, L"\\Device\\");
  786. Assert (SZ_DEVICE_LEN == wcslen(mszExport));
  787. mszExport[celems(mszExport) - 1] = 0;
  788. hr = S_OK;
  789. // Sort the filter devices by pAdapter and then by
  790. // pFilter->m_dwFilterClassOrdinal. We will then iterate all filter
  791. // devices to write the bindings. Because of the sort, we'll iterate
  792. // all filter devices for a given adapter in class order from smallest
  793. // to largest. (Smaller class ordinals have affinity for the protocol.)
  794. //
  795. pFilterDevices->SortForWritingBindings ();
  796. pPrevDevice = NULL;
  797. for (iter = pFilterDevices->begin();
  798. iter != pFilterDevices->end();
  799. iter++)
  800. {
  801. pDevice = *iter;
  802. Assert (pDevice);
  803. // Generate the rest of the Export string.
  804. // \Device\{GUID}
  805. //
  806. Assert ((c_cchGuidWithTerm - 1) == wcslen(pDevice->m_szInstanceGuid));
  807. wcscpy (pchExportGuid, pDevice->m_szInstanceGuid);
  808. // If this device's adapter is different than the previous device's
  809. // adapter, we are dealing with the top of a new chain. We need
  810. // to initialize RootDevice which will be the multi-sz of all
  811. // bindnames in the chain including the adapter.
  812. //
  813. if (!pPrevDevice ||
  814. (pDevice->m_pAdapter != pPrevDevice->m_pAdapter))
  815. {
  816. // Compute RootDevice.
  817. // We'll use m_ExportValue as the buffer.
  818. //
  819. m_ExportValue.Clear();
  820. m_ExportValue.HrCopyString (pDevice->m_szInstanceGuid);
  821. for (next = iter + 1;
  822. next != pFilterDevices->end();
  823. next++)
  824. {
  825. pNextDevice = *next;
  826. Assert (pNextDevice);
  827. // We're done when we reach the next filter chain.
  828. //
  829. if (pNextDevice->m_pAdapter != pDevice->m_pAdapter)
  830. {
  831. break;
  832. }
  833. m_ExportValue.HrCopyString (pNextDevice->m_szInstanceGuid);
  834. }
  835. m_ExportValue.HrCopyString (pDevice->m_pAdapter->Ext.PszBindName());
  836. m_ExportValue.HrCopyString (L"");
  837. pmszRootDevice = (PCWSTR)m_ExportValue.PbBuffer();
  838. Assert (*pmszRootDevice);
  839. // Compute UpperBind.
  840. // We'll use m_BindValue as the buffer.
  841. //
  842. hr = HrGetAdapterUpperBindValue (pDevice->m_pAdapter);
  843. }
  844. // We're continuing in the filter chain and this device is not
  845. // the topmost. (not closest to the protocol).
  846. //
  847. else
  848. {
  849. // Since RootDevice was built up for the top device in the chain,
  850. // each successive device just needs to skip past the next
  851. // string in the mutli-sz.
  852. //
  853. Assert (*pmszRootDevice);
  854. pmszRootDevice += wcslen(pmszRootDevice) + 1;
  855. // UpperBind is the previous device's filter's bind name.
  856. //
  857. m_BindValue.Clear();
  858. m_BindValue.HrCopyString (pPrevDevice->m_pFilter->Ext.PszBindName());
  859. m_BindValue.HrCopyString (L"");
  860. }
  861. pmszUpperBind = (PCWSTR)m_BindValue.PbBuffer();
  862. // We now have:
  863. // Export in mszExport
  864. // RootDevice at pmszRootDevice (in m_ExportValue)
  865. // UpperBind at pmszUpperBind (in m_BindValue)
  866. //
  867. hr = HrWriteFilterDeviceLinkage (
  868. pDevice, pFilterDevices->m_hdi,
  869. mszExport, pmszRootDevice, pmszUpperBind);
  870. // If this is the last device in the chain, we need to write
  871. // the UpperBind of the adapter to be this filter device.
  872. //
  873. next = iter + 1;
  874. if ((next == pFilterDevices->end()) ||
  875. (*next)->m_pAdapter != pDevice->m_pAdapter)
  876. {
  877. // UpperBind is this last device's filter's bind name.
  878. //
  879. m_BindValue.Clear();
  880. m_BindValue.HrCopyString (pDevice->m_pFilter->Ext.PszBindName());
  881. m_BindValue.HrCopyString (L"");
  882. pmszUpperBind = (PCWSTR)m_BindValue.PbBuffer();
  883. hr = HrWriteFilteredAdapterUpperBind (
  884. pDevice->m_pAdapter,
  885. pmszUpperBind);
  886. }
  887. // Remember the previous device so that when we go to the next
  888. // device, we'll know we're dealing with a different chain if
  889. // the next device's adapter is different than this one.
  890. //
  891. pPrevDevice = pDevice;
  892. }
  893. TraceHr (ttidError, FAL, hr, FALSE,
  894. "CRegistryBindingsContext::HrWriteBindingsForFilterDevices");
  895. return hr;
  896. }