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.

1202 lines
32 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1999.
  5. //
  6. // File: L A N A M A P . C P P
  7. //
  8. // Contents: NetBios Lana map routines.
  9. //
  10. // Notes:
  11. //
  12. // Author: billbe 17 Feb 1999
  13. //
  14. //----------------------------------------------------------------------------
  15. #include <pch.h>
  16. #pragma hdrstop
  17. #include "lanamap.h"
  18. #include "nceh.h"
  19. #include "ncerror.h"
  20. #include "ncreg.h"
  21. #include "ncsetup.h"
  22. #include "netsetup.h"
  23. #include "persist.h"
  24. const WCHAR c_szRegKeyNetBiosLinkage[] =
  25. L"System\\CurrentControlSet\\Services\\NetBios\\Linkage";
  26. const WCHAR c_szRegKeyNetBiosParameters[] =
  27. L"System\\CurrentControlSet\\Services\\NetBIOS\\Parameters";
  28. const WCHAR c_szRegValueLanaMap[] = L"LanaMap";
  29. const WCHAR c_szRegValueMaxLana[] = L"MaxLana";
  30. #if DBG
  31. VOID DbgVerifyBindPathString (PCWSTR pszBindPath);
  32. #else
  33. VOID DbgVerifyBindPathString (PCWSTR /*pszBindPath*/) {}
  34. #endif
  35. typedef vector<const GUID*> VECTOR_OF_GUIDS;
  36. struct LANA_BIND_PATH
  37. {
  38. VECTOR_OF_GUIDS GuidsOfComponentsOnPath;
  39. BYTE LanaNumber;
  40. };
  41. VOID
  42. GetFirstComponentFromBindPath (
  43. IN PCWSTR pszBindPath,
  44. OUT PCWSTR* ppszComponentStart,
  45. OUT DWORD* pcchComponent)
  46. {
  47. PCWSTR pszComponentEnd;
  48. PCWSTR pszComponentStart;
  49. Assert (pszBindPath);
  50. Assert (ppszComponentStart);
  51. Assert (pcchComponent);
  52. *pcchComponent = 0;
  53. // The Bind path is of the form \Device\<component>_<component>_<etc.>
  54. //
  55. pszComponentEnd = wcschr (pszBindPath, L'_');
  56. if (!pszComponentEnd)
  57. {
  58. // There is no underscore so set the end pointer
  59. // to the end of the string.
  60. pszComponentEnd = pszBindPath + wcslen (pszBindPath);
  61. }
  62. for (pszComponentStart = pszComponentEnd;
  63. pszComponentStart != pszBindPath; pszComponentStart--)
  64. {
  65. // Backup from the end until we get to the slash.
  66. // If we don't find a slash, the loop will stop when
  67. // we hit the beginning.
  68. //
  69. if (L'\\' == *pszComponentStart)
  70. {
  71. // We hit the slash. The Component start is one character
  72. // past that.
  73. pszComponentStart++;
  74. break;
  75. }
  76. }
  77. *ppszComponentStart = pszComponentStart;
  78. *pcchComponent = pszComponentEnd - pszComponentStart;
  79. }
  80. VOID
  81. CLanaMap::Dump (
  82. OUT CWideString* pstr) const
  83. {
  84. Assert (this);
  85. Assert (pstr);
  86. WCHAR pszBuf[1024];
  87. pstr->erase();
  88. const CLanaEntry* pEntry;
  89. for (pEntry = begin(); pEntry != end(); pEntry++)
  90. {
  91. swprintf (pszBuf, L"Lana: %3d Export: %d Path: %s\n",
  92. pEntry->RegLanaEntry.LanaNumber,
  93. pEntry->RegLanaEntry.Exported, pEntry->pszBindPath);
  94. pstr->append (pszBuf);
  95. }
  96. }
  97. HRESULT
  98. CLanaMap::HrLoadLanaMap()
  99. {
  100. HRESULT hr;
  101. HKEY hkey;
  102. // The lana map is stored in Netbios's linkage key.
  103. //
  104. hr = HrRegOpenKeyEx (HKEY_LOCAL_MACHINE, c_szRegKeyNetBiosLinkage,
  105. KEY_READ, &hkey);
  106. if (S_OK == hr)
  107. {
  108. REG_LANA_ENTRY* pRegEntries;
  109. DWORD cbLanaEntries;
  110. // Read in the lana map binary blob.
  111. hr = HrRegQueryBinaryWithAlloc (hkey, c_szRegValueLanaMap,
  112. (BYTE**)&pRegEntries, &cbLanaEntries);
  113. if (S_OK == hr)
  114. {
  115. DWORD cEntries = cbLanaEntries / sizeof (REG_LANA_ENTRY);
  116. PWSTR pmszBindPaths;
  117. // Grab the bind paths for NetBios so we can match them
  118. // up with the lana map.
  119. hr = HrRegQueryMultiSzWithAlloc (hkey, L"Bind", &pmszBindPaths);
  120. if (S_OK == hr)
  121. {
  122. PCWSTR pszScan;
  123. DWORD cPaths;
  124. for (pszScan = pmszBindPaths, cPaths = 0;
  125. *pszScan;
  126. pszScan += wcslen(pszScan) + 1)
  127. {
  128. ++cPaths;
  129. }
  130. m_pszBindPathsBuffer = pmszBindPaths;
  131. hr = HrReserveRoomForEntries (cPaths);
  132. if (S_OK == hr)
  133. {
  134. DWORD dw = 0;
  135. CLanaEntry Entry;
  136. for (pszScan = pmszBindPaths;
  137. *pszScan;
  138. pszScan += wcslen(pszScan) + 1)
  139. {
  140. Entry.pszBindPath = pszScan;
  141. if (dw < cEntries)
  142. {
  143. Entry.RegLanaEntry.LanaNumber =
  144. pRegEntries[dw].LanaNumber;
  145. Entry.RegLanaEntry.Exported =
  146. pRegEntries[dw].Exported;
  147. }
  148. else
  149. {
  150. // We have more bind paths but no more
  151. // lana map entries to correlate.
  152. // Now we assign available lanas.
  153. //
  154. BYTE* location = find (m_LanasInUse,
  155. m_LanasInUse + MAX_LANA, 0);
  156. if (location != m_LanasInUse + MAX_LANA)
  157. {
  158. Entry.RegLanaEntry.LanaNumber =
  159. location - m_LanasInUse;
  160. Entry.RegLanaEntry.Exported = 1;
  161. }
  162. }
  163. // Mark this Lana as taken.
  164. m_LanasInUse[Entry.RegLanaEntry.LanaNumber] = 1;
  165. hr = HrAppendEntry (&Entry);
  166. if (S_OK != hr)
  167. {
  168. break;
  169. }
  170. dw++;
  171. }
  172. }
  173. }
  174. MemFree (pRegEntries);
  175. }
  176. // If lana map or bind is not there, it is okay since we will be
  177. // recreating the info.
  178. //
  179. if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr)
  180. {
  181. hr = S_OK;
  182. }
  183. RegCloseKey (hkey);
  184. }
  185. else
  186. {
  187. // If the linkage has not been created yet, it is okay since it will
  188. // be creating after the lanamap is written out. This occurs when
  189. // NetBios is first installed.
  190. //
  191. if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr)
  192. {
  193. hr = S_OK;
  194. }
  195. }
  196. TraceHr (ttidError, FAL, hr, FALSE, "CLanaMap::HrLoadLanaMap");
  197. return hr;
  198. }
  199. #if DBG
  200. VOID
  201. DbgVerifyBindPathString (
  202. PCWSTR pszBindPath)
  203. {
  204. const WCHAR c_szDevice[] = L"\\Device\\";
  205. Assert (pszBindPath);
  206. Assert (0 == _wcsnicmp (pszBindPath, c_szDevice, celems(c_szDevice)-1));
  207. }
  208. #endif // DBG
  209. BOOL
  210. FBindPathContainsMultipleInterface (
  211. IN const CComponentList& Components,
  212. IN PCWSTR pszBindPath)
  213. {
  214. BOOL fContainsMultipleInterface = FALSE;
  215. PCWSTR pszLastDevice = wcsrchr (pszBindPath, L'{');
  216. if (pszLastDevice)
  217. {
  218. GUID Guid;
  219. if (S_OK == IIDFromString ((PWSTR)pszLastDevice, &Guid))
  220. {
  221. // If this is a multiple interface, it will not exist
  222. // as a component.
  223. //
  224. CComponent* pComponent;
  225. pComponent = Components.
  226. PFindComponentByInstanceGuid (&Guid);
  227. if (!pComponent)
  228. {
  229. // This means the path contains a multiple interface.
  230. fContainsMultipleInterface = TRUE;
  231. }
  232. }
  233. }
  234. return fContainsMultipleInterface;
  235. }
  236. HRESULT
  237. CLanaMap::HrAppendEntry (
  238. IN CLanaEntry* pEntry)
  239. {
  240. HRESULT hr;
  241. Assert (pEntry);
  242. Assert (pEntry->pszBindPath && *(pEntry->pszBindPath));
  243. DbgVerifyBindPathString (pEntry->pszBindPath);
  244. NC_TRY
  245. {
  246. push_back (*pEntry);
  247. hr = S_OK;
  248. }
  249. NC_CATCH_ALL
  250. {
  251. hr = E_OUTOFMEMORY;
  252. }
  253. if (S_OK == hr)
  254. {
  255. // Update out lanas in use map.
  256. m_LanasInUse[pEntry->RegLanaEntry.LanaNumber] = 1;
  257. }
  258. TraceHr (ttidError, FAL, hr, FALSE, "CLanaMap::HrAppendLanaEntry");
  259. return hr;
  260. }
  261. HRESULT
  262. CLanaMap::HrCreateRegistryMap()
  263. {
  264. HRESULT hr;
  265. CLanaEntry* pEntry;
  266. if (m_RegistryLanaMap.CountOfBytesUsed())
  267. {
  268. m_RegistryLanaMap.Clear();
  269. }
  270. hr = m_RegistryLanaMap.HrReserveBytes (
  271. CountEntries() * sizeof (REG_LANA_ENTRY));
  272. if (S_OK == hr)
  273. {
  274. for (pEntry = begin(); pEntry != end(); pEntry++)
  275. {
  276. hr = m_RegistryLanaMap.HrCopyBytes ((BYTE*)&pEntry->RegLanaEntry,
  277. sizeof (REG_LANA_ENTRY));
  278. }
  279. }
  280. TraceHr (ttidError, FAL, hr, FALSE, "CLanaEntry::HrCreateRegistryMap");
  281. return hr;
  282. }
  283. HRESULT
  284. CLanaMap::HrReserveRoomForEntries (
  285. IN UINT cEntries)
  286. {
  287. HRESULT hr;
  288. NC_TRY
  289. {
  290. reserve (cEntries);
  291. hr = S_OK;
  292. }
  293. NC_CATCH_ALL
  294. {
  295. hr = E_OUTOFMEMORY;
  296. }
  297. TraceHr (ttidError, FAL, hr, FALSE, "CLanaMap::HrReserveRoomForEntries");
  298. return hr;
  299. }
  300. BYTE
  301. CLanaMap::GetExportValue (
  302. IN const CComponentList& Components,
  303. IN PCWSTR pszBindPath)
  304. {
  305. const WCHAR c_szNdisWanNbfIn[] = L"NdisWanNbfIn{";
  306. BYTE Exported = 1;
  307. PCWSTR pszLastDevice;
  308. Assert (pszBindPath && *pszBindPath);
  309. // Get the last "device" on the bind path.
  310. // If it matches NbfIn, we don't export.
  311. //
  312. pszLastDevice = wcsrchr (pszBindPath, L'_');
  313. if (!pszLastDevice)
  314. {
  315. pszLastDevice = wcsrchr (pszBindPath, L'\\');
  316. if (!pszLastDevice)
  317. {
  318. pszLastDevice = pszBindPath;
  319. }
  320. }
  321. if (pszLastDevice != pszBindPath)
  322. {
  323. pszLastDevice++;
  324. }
  325. if (0 == _wcsnicmp (pszLastDevice, c_szNdisWanNbfIn,
  326. wcslen (c_szNdisWanNbfIn)))
  327. {
  328. Exported = 0;
  329. }
  330. // If we haven't turned off export, check to see if this bind path
  331. // contains a multiple interface.
  332. //
  333. if (0 != Exported && FBindPathContainsMultipleInterface (Components,
  334. pszBindPath))
  335. {
  336. Exported = 0;
  337. }
  338. return Exported;
  339. }
  340. VOID
  341. CLanaMap::GetLanaEntry (
  342. IN const CComponentList& Components,
  343. IN CLanaEntry* pEntry)
  344. {
  345. CLanaEntry* pCurrentEntry;
  346. BOOL fFound = FALSE;
  347. Assert (pEntry->pszBindPath);
  348. // Check the map for the entry
  349. //
  350. for (pCurrentEntry = begin(); pCurrentEntry != end(); pCurrentEntry++)
  351. {
  352. if (0 == _wcsicmp (pEntry->pszBindPath, pCurrentEntry->pszBindPath))
  353. {
  354. // Found the entry, set the lana number and figure out
  355. // if this entry should be exported.
  356. //
  357. pEntry->RegLanaEntry.Exported =
  358. GetExportValue (Components, pEntry->pszBindPath);
  359. pEntry->RegLanaEntry.LanaNumber =
  360. pCurrentEntry->RegLanaEntry.LanaNumber;
  361. fFound = TRUE;
  362. break;
  363. }
  364. }
  365. if (!fFound)
  366. {
  367. // no match, get next available lana number
  368. BYTE* location = find (m_LanasInUse, m_LanasInUse + MAX_LANA, 0);
  369. if (location != m_LanasInUse + MAX_LANA)
  370. {
  371. pEntry->RegLanaEntry.Exported =
  372. GetExportValue (Components, pEntry->pszBindPath);
  373. pEntry->RegLanaEntry.LanaNumber = location - m_LanasInUse;
  374. m_LanasInUse[location - m_LanasInUse] = 1;
  375. }
  376. else
  377. {
  378. // They tell me this is impossible.
  379. AssertSz (FALSE, "No more available Lanas.");
  380. pEntry->RegLanaEntry.Exported = 0;
  381. pEntry->RegLanaEntry.LanaNumber = MAX_LANA + 1;
  382. }
  383. }
  384. }
  385. HRESULT
  386. CLanaMap::HrWriteLanaMapConfig()
  387. {
  388. HKEY hkeyLinkage;
  389. HRESULT hr;
  390. hr = HrRegCreateKeyEx (HKEY_LOCAL_MACHINE, c_szRegKeyNetBiosLinkage,
  391. REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hkeyLinkage, NULL);
  392. if (S_OK == hr)
  393. {
  394. const BYTE* pbBuffer;
  395. DWORD cbBuffer = m_RegistryLanaMap.CountOfBytesUsed();
  396. if (cbBuffer > 0)
  397. {
  398. pbBuffer = m_RegistryLanaMap.PbBuffer();
  399. }
  400. else
  401. {
  402. pbBuffer = NULL;
  403. }
  404. hr = HrRegSetBinary (hkeyLinkage, c_szRegValueLanaMap,
  405. pbBuffer, cbBuffer);
  406. RegCloseKey (hkeyLinkage);
  407. }
  408. if (S_OK == hr)
  409. {
  410. HKEY hkeyParams;
  411. hr = HrRegCreateKeyEx (HKEY_LOCAL_MACHINE,
  412. c_szRegKeyNetBiosParameters, REG_OPTION_NON_VOLATILE,
  413. KEY_WRITE, NULL, &hkeyParams, NULL);
  414. if (S_OK == hr)
  415. {
  416. hr = HrRegSetDword (hkeyParams, c_szRegValueMaxLana,
  417. GetMaxLana());
  418. RegCloseKey (hkeyParams);
  419. }
  420. }
  421. TraceHr (ttidError, FAL, hr, FALSE, "CLanaMap::HrWriteLanaMapConfig");
  422. return hr;
  423. }
  424. HRESULT
  425. HrGetNetBiosProviderName (
  426. IN CComponent* pComponent,
  427. OUT PWSTR pszName)
  428. {
  429. HRESULT hr;
  430. Assert (pComponent);
  431. Assert (pszName);
  432. // The netbios provider name for a component is stored in its
  433. // <service>\Parameters key.
  434. //
  435. HKEY hkeyService;
  436. hr = pComponent->HrOpenServiceKey (KEY_READ, &hkeyService);
  437. if (S_OK == hr)
  438. {
  439. HKEY hkeyParams;
  440. hr = HrRegOpenKeyEx (hkeyService, L"Parameters", KEY_READ,
  441. &hkeyParams);
  442. if (S_OK == hr)
  443. {
  444. DWORD cbBuffer = _MAX_PATH;
  445. hr = HrRegQuerySzBuffer (hkeyParams, L"NbProvider", pszName,
  446. &cbBuffer);
  447. RegCloseKey (hkeyParams);
  448. }
  449. RegCloseKey (hkeyService);
  450. }
  451. TraceHr (ttidError, FAL, hr,
  452. HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr,
  453. "HrGetNetBiosProviderName");
  454. return hr;
  455. }
  456. HRESULT
  457. CLanaMap::HrSetLanaNumber (
  458. IN BYTE OldLanaNumber,
  459. IN BYTE NewLanaNumber)
  460. {
  461. HRESULT hr = S_OK;
  462. if (0 == m_LanasInUse[NewLanaNumber])
  463. {
  464. CLanaEntry* pEntry;
  465. for (pEntry = begin(); pEntry != end(); pEntry++)
  466. {
  467. if (OldLanaNumber == pEntry->RegLanaEntry.LanaNumber)
  468. {
  469. // free up the lana number this entry had.
  470. m_LanasInUse[pEntry->RegLanaEntry.LanaNumber] = 0;
  471. // Give the entry the new lana number.
  472. pEntry->RegLanaEntry.LanaNumber = NewLanaNumber;
  473. m_LanasInUse[NewLanaNumber] = 1;
  474. break;
  475. }
  476. }
  477. if (pEntry == end())
  478. {
  479. hr = HRESULT_FROM_WIN32 (ERROR_OBJECT_NOT_FOUND);
  480. }
  481. }
  482. else
  483. {
  484. // The lana is not free. We will swap the lanas used by the
  485. // two paths.
  486. //
  487. CLanaEntry* pEntry;
  488. CLanaEntry* pEntryToSet = NULL;
  489. CLanaEntry* pEntryUsingLana = NULL;
  490. for (pEntry = begin(); pEntry != end(); pEntry++)
  491. {
  492. if (!pEntryToSet &&
  493. (OldLanaNumber == pEntry->RegLanaEntry.LanaNumber))
  494. {
  495. pEntryToSet = pEntry;
  496. }
  497. else if (!pEntryUsingLana &&
  498. (NewLanaNumber == pEntry->RegLanaEntry.LanaNumber))
  499. {
  500. pEntryUsingLana = pEntry;
  501. }
  502. if (pEntryToSet && pEntryUsingLana)
  503. {
  504. // Give the entry the new lana number.
  505. pEntryToSet->RegLanaEntry.LanaNumber = NewLanaNumber;
  506. // Give the old lana number to the entry that was using the
  507. // new lana number.
  508. pEntryUsingLana->RegLanaEntry.LanaNumber = OldLanaNumber;
  509. break;
  510. }
  511. }
  512. if (!pEntryToSet || !pEntryUsingLana)
  513. {
  514. hr = HRESULT_FROM_WIN32 (ERROR_OBJECT_NOT_FOUND);
  515. }
  516. }
  517. TraceHr (ttidError, FAL, hr, FALSE, "CLanaMap::HrSetLanaNumber");
  518. return hr;
  519. }
  520. BYTE
  521. CLanaMap::GetMaxLana()
  522. {
  523. for (BYTE b = MAX_LANA; b; b--)
  524. {
  525. if (m_LanasInUse[b]) return b;
  526. }
  527. return 0;
  528. }
  529. HRESULT
  530. CLanaMap::HrWriteLanaConfiguration (
  531. IN const CComponentList& Components)
  532. {
  533. HRESULT hr;
  534. // Create the registry map that will be stored.
  535. hr = HrCreateRegistryMap();
  536. if (S_OK == hr)
  537. {
  538. // Write out the map and other lana info.
  539. hr = HrWriteLanaMapConfig();
  540. }
  541. TraceHr (ttidError, FAL, hr, FALSE, "HrWriteLanaConfiguration");
  542. return hr;
  543. }
  544. VOID
  545. DumpLanaBindPaths (
  546. IN LANA_BIND_PATH* pBindSet,
  547. IN DWORD cPaths)
  548. {
  549. LANA_BIND_PATH* pPath = pBindSet;
  550. DWORD dw = 0;
  551. VECTOR_OF_GUIDS::iterator iter;
  552. for (dw = 0; dw < cPaths; dw++)
  553. {
  554. TraceTag (ttidNetcfgBase, "Path %d", dw);
  555. for (iter = pPath->GuidsOfComponentsOnPath.begin();
  556. iter != pPath->GuidsOfComponentsOnPath.end();
  557. iter++)
  558. {
  559. const GUID* guid = *iter;
  560. TraceTag (ttidNetcfgBase, " %lX", guid->Data1);
  561. }
  562. pPath++;
  563. }
  564. }
  565. VOID
  566. UpdateLanaConfigWithAnswerFileInfo (
  567. IN CLanaMap* pLanaMap,
  568. IN DWORD cAfPaths,
  569. IN LANA_BIND_PATH* pOriginalBindSet,
  570. IN LANA_BIND_PATH* pAnswerFileBindSet)
  571. {
  572. DWORD dwAnswerFile;
  573. DWORD dwPaths;
  574. DWORD dwComponents;
  575. DWORD dwNumberOfComponents;
  576. BOOL fEqual;
  577. LANA_BIND_PATH* pAfEntry;
  578. LANA_BIND_PATH* pOEntry;
  579. Assert (pLanaMap);
  580. Assert (pOriginalBindSet);
  581. Assert (pAnswerFileBindSet);
  582. TraceTag (ttidNetcfgBase, "Dumping original bind set");
  583. DumpLanaBindPaths (pOriginalBindSet, pLanaMap->CountEntries());
  584. TraceTag (ttidNetcfgBase, "Dumping af bind set");
  585. DumpLanaBindPaths (pAnswerFileBindSet, cAfPaths);
  586. pAfEntry = pAnswerFileBindSet;
  587. for (dwAnswerFile = 0; dwAnswerFile < cAfPaths; dwAnswerFile++)
  588. {
  589. // Do we have a valid path?
  590. if (!pAfEntry->GuidsOfComponentsOnPath.empty())
  591. {
  592. pOEntry = pOriginalBindSet;
  593. for (dwPaths = 0; dwPaths < pLanaMap->CountEntries(); dwPaths++)
  594. {
  595. if (pAfEntry->GuidsOfComponentsOnPath.size() ==
  596. pOEntry->GuidsOfComponentsOnPath.size())
  597. {
  598. dwNumberOfComponents =
  599. pAfEntry->GuidsOfComponentsOnPath.size();
  600. fEqual = TRUE;
  601. for (dwComponents = 0;
  602. dwComponents < dwNumberOfComponents;
  603. dwComponents++)
  604. {
  605. if (pAfEntry->GuidsOfComponentsOnPath[dwComponents] !=
  606. pOEntry->GuidsOfComponentsOnPath[dwComponents])
  607. {
  608. fEqual = FALSE;
  609. }
  610. }
  611. if (fEqual)
  612. {
  613. HRESULT hr;
  614. hr = pLanaMap->HrSetLanaNumber (
  615. pOEntry->LanaNumber,
  616. pAfEntry->LanaNumber);
  617. TraceTag (ttidNetcfgBase, "af path %d matches %d",
  618. dwAnswerFile, dwPaths);
  619. TraceTag (ttidNetcfgBase, "Changing lana number "
  620. "from %X to %X", pOEntry->LanaNumber,
  621. pAfEntry->LanaNumber);
  622. TraceHr (ttidError, FAL, hr, FALSE, "Setting lana");
  623. }
  624. }
  625. pOEntry++;
  626. }
  627. }
  628. pAfEntry++;
  629. }
  630. }
  631. VOID
  632. ConvertAnswerFileComponentsToGuids (
  633. IN const CComponentList& Components,
  634. IN PCWSTR mszComponents,
  635. OUT VECTOR_OF_GUIDS* pvector)
  636. {
  637. CComponent* pComponent;
  638. PCWSTR pszScan;
  639. const GUID* pguid;
  640. GUID guidTemp;
  641. Assert (mszComponents);
  642. Assert (pvector);
  643. for (pszScan = mszComponents; *pszScan; pszScan += wcslen (pszScan) + 1)
  644. {
  645. TraceTag (ttidNetcfgBase, " Looking for af component %S", pszScan);
  646. // Look for the component in our installed components list.
  647. //
  648. pComponent = Components.PFindComponentByInfId (pszScan, NULL);
  649. if (pComponent)
  650. {
  651. pguid = &pComponent->m_InstanceGuid;
  652. }
  653. else
  654. {
  655. TraceTag (ttidNetcfgBase, " Id did not match installed ids. "
  656. "Checking af map");
  657. // The component wasn't listed in our installed list. The inf
  658. // id might be something that the answerfile processor has mapped
  659. // to the component's instance guid. This happens for adapters.
  660. // e.g. Id is listed as Adapter01 so netsetup uses an alogrithm
  661. // to determine which adapter it is and then save off its
  662. // instance guid in a map.
  663. //
  664. if (FGetInstanceGuidOfComponentFromAnswerFileMap (
  665. pszScan, &guidTemp))
  666. {
  667. pComponent = Components.PFindComponentByInstanceGuid (
  668. &guidTemp);
  669. }
  670. else
  671. {
  672. TraceTag (ttidError, " Component %S not found in answerfile "
  673. "map", pszScan);
  674. }
  675. // If we found the component, store a reference to its
  676. // instance guid
  677. //
  678. if (pComponent)
  679. {
  680. TraceTag (ttidNetcfgBase, " Found component");
  681. pguid = &pComponent->m_InstanceGuid;
  682. }
  683. else
  684. {
  685. // We didn't find the component. Store GUID_NULL.
  686. pguid = &GUID_NULL;
  687. }
  688. }
  689. TraceTag (ttidNetcfgBase, " Using GUID %lX", pguid->Data1);
  690. pvector->push_back (pguid);
  691. }
  692. }
  693. HRESULT
  694. HrConvertAnswerFileParamsToLanaBindSet (
  695. IN INFCONTEXT& ctxLana,
  696. IN const CComponentList& Components,
  697. IN DWORD cPaths,
  698. OUT LANA_BIND_PATH* pBindSet)
  699. {
  700. DWORD cchField = _MAX_PATH;
  701. DWORD cchRequired;
  702. INT LanaCode;
  703. PWSTR mszComponents;
  704. HRESULT hr;
  705. DWORD dw;
  706. INFCONTEXT ctx = ctxLana;
  707. LANA_BIND_PATH* pPath;
  708. hr = S_OK;
  709. mszComponents = (PWSTR)MemAlloc (cchField * sizeof (WCHAR));
  710. pPath = pBindSet;
  711. for (dw = 0; dw < cPaths; dw++)
  712. {
  713. if (mszComponents && (S_OK == hr))
  714. {
  715. hr = HrSetupGetMultiSzField (ctx, 1, mszComponents, cchField,
  716. &cchRequired);
  717. if (S_OK == hr)
  718. {
  719. TraceTag (ttidNetcfgBase, "Path %ld", dw);
  720. ConvertAnswerFileComponentsToGuids (Components,
  721. mszComponents,
  722. &(pPath->GuidsOfComponentsOnPath));
  723. hr = HrSetupFindNextLine (ctx, &ctx);
  724. if (S_OK == hr)
  725. {
  726. hr = HrSetupGetIntField (ctx, 1, &LanaCode);
  727. if (S_OK == hr)
  728. {
  729. pPath->LanaNumber = LanaCode & 0xff;
  730. TraceTag (ttidNetcfgBase, " Using LanaNumber %X for "
  731. "path", pPath->LanaNumber);
  732. }
  733. else
  734. {
  735. TraceTag (ttidNetcfgBase, " Bad lana code");
  736. // Bad lana number, clear the guids so we won't match
  737. // this path and use this info.
  738. //
  739. pPath->GuidsOfComponentsOnPath.erase(
  740. pPath->GuidsOfComponentsOnPath.begin(),
  741. pPath->GuidsOfComponentsOnPath.end());
  742. }
  743. }
  744. hr = HrSetupFindNextMatchLine (ctx, L"LanaPath", &ctx);
  745. if (S_FALSE == hr)
  746. {
  747. break;
  748. }
  749. pPath++;
  750. }
  751. else if (HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER) == hr)
  752. {
  753. // Reallocate the buffer.
  754. //
  755. hr = S_OK;
  756. MemFree (mszComponents);
  757. mszComponents = (PWSTR)MemAlloc (cchRequired * sizeof(WCHAR));
  758. cchField = cchRequired;
  759. }
  760. }
  761. else
  762. {
  763. hr = E_OUTOFMEMORY;
  764. break;
  765. }
  766. }
  767. if (S_FALSE == hr)
  768. {
  769. // Check to see if we were really finished.
  770. if ((dw + 1) < cPaths)
  771. {
  772. TraceTag (ttidError, "Answerfile specified %d lana paths "
  773. "but only %d were found", cPaths, (dw + 1));
  774. }
  775. // This fcn only returns S_OK on success.
  776. hr = S_OK;
  777. }
  778. TraceHr (ttidError, FAL, hr, FALSE,
  779. "HrConvertAnswerFileParamsToLanaBindSet");
  780. return hr;
  781. }
  782. HRESULT
  783. HrProcessAnswerFile (
  784. IN PCWSTR pszAnswerFile,
  785. IN PCWSTR pszSection,
  786. IN const CComponentList& Components,
  787. OUT LANA_BIND_PATH** ppBindSet,
  788. OUT DWORD* pcPaths)
  789. {
  790. HINF hinf;
  791. PCWSTR pszBindPath;
  792. WCHAR szBindName[_MAX_PATH];
  793. HRESULT hr;
  794. Assert (pszAnswerFile);
  795. Assert (pszSection);
  796. Assert (ppBindSet);
  797. Assert (pcPaths);
  798. *pcPaths = 0;
  799. *ppBindSet = NULL;
  800. hr = HrSetupOpenInfFile (pszAnswerFile, NULL,
  801. INF_STYLE_OLDNT | INF_STYLE_WIN4, NULL, &hinf);
  802. if (S_OK == hr)
  803. {
  804. hr = HrSetupGetFirstDword (hinf, pszSection,
  805. L"NumberOfPaths", pcPaths);
  806. if (S_OK == hr)
  807. {
  808. TraceTag (ttidNetcfgBase, "\n\n");
  809. TraceTag (ttidNetcfgBase, "%d paths found in answerfile",
  810. *pcPaths);
  811. hr = E_OUTOFMEMORY;
  812. *ppBindSet = new LANA_BIND_PATH[*pcPaths];
  813. if (*ppBindSet)
  814. {
  815. hr = S_OK;
  816. }
  817. }
  818. if (S_OK == hr)
  819. {
  820. INFCONTEXT ctx;
  821. hr = HrSetupFindFirstLine (hinf, pszSection, L"LanaPath", &ctx);
  822. if (S_OK == hr)
  823. {
  824. hr = HrConvertAnswerFileParamsToLanaBindSet (ctx, Components,
  825. *pcPaths, *ppBindSet);
  826. }
  827. }
  828. }
  829. TraceHr (ttidError, FAL, hr, FALSE, "HrProcessAnswerFile");
  830. return hr;
  831. }
  832. HRESULT
  833. HrConvertBindingsToLanaBindSet (
  834. IN const CComponentList& Components,
  835. IN const CLanaMap& LanaMap,
  836. OUT LANA_BIND_PATH** ppBindSet)
  837. {
  838. PCWSTR pszBindPath;
  839. WCHAR szBindName[_MAX_PATH];
  840. HRESULT hr;
  841. DWORD cPaths;
  842. Assert (ppBindSet);
  843. cPaths = LanaMap.CountEntries();
  844. TraceTag (ttidNetcfgBase, "%d paths in system", cPaths);
  845. hr = E_OUTOFMEMORY;
  846. *ppBindSet = new LANA_BIND_PATH[cPaths];
  847. if (*ppBindSet)
  848. {
  849. LANA_BIND_PATH* pBindPath = *ppBindSet;
  850. CComponent* pComponent;
  851. PCWSTR pszCompStart;
  852. PCWSTR pszCompEnd;
  853. DWORD cchComp;
  854. hr = S_OK;
  855. const CLanaEntry* pEntry;
  856. for (pEntry = LanaMap.begin(); pEntry != LanaMap.end(); pEntry++)
  857. {
  858. pszBindPath = pEntry->pszBindPath;
  859. TraceTag (ttidNetcfgBase, "BindPath %S", pszBindPath);
  860. pBindPath->LanaNumber = pEntry->RegLanaEntry.LanaNumber;
  861. TraceTag (ttidNetcfgBase, "Lana %X", pBindPath->LanaNumber);
  862. GetFirstComponentFromBindPath (pszBindPath, &pszCompStart,
  863. &cchComp);
  864. while (*pszCompStart)
  865. {
  866. wcsncpy (szBindName, pszCompStart, cchComp);
  867. szBindName[cchComp] = L'\0';
  868. TraceTag (ttidNetcfgBase, " Searching for component with bind name %S",
  869. szBindName);
  870. pComponent = Components.PFindComponentByBindName (NC_INVALID,
  871. szBindName);
  872. if (pComponent)
  873. {
  874. TraceTag (ttidNetcfgBase, " Found component. Guid = %lX",
  875. pComponent->m_InstanceGuid.Data1);
  876. pBindPath->GuidsOfComponentsOnPath.push_back (&pComponent->m_InstanceGuid);
  877. }
  878. else
  879. {
  880. if (*pszCompEnd)
  881. {
  882. AssertSz (FALSE, " Bind Name not found in component list");
  883. pBindPath->GuidsOfComponentsOnPath.push_back (&GUID_NULL);
  884. }
  885. }
  886. pszCompStart = pszCompStart + cchComp;
  887. if (*pszCompStart)
  888. {
  889. pszCompStart++;
  890. pszCompEnd = wcschr (pszCompStart, L'_');
  891. if (!pszCompEnd)
  892. {
  893. // There is no underscore so set the end pointer
  894. // to the end of the string.
  895. pszCompEnd = pszBindPath + wcslen (pszBindPath);
  896. }
  897. }
  898. cchComp = pszCompEnd - pszCompStart;
  899. }
  900. pBindPath++;
  901. }
  902. }
  903. TraceHr (ttidError, FAL, hr, FALSE, "HrConvertBindingsToLanaBindSet");
  904. return hr;
  905. }
  906. HRESULT
  907. HrUpdateLanaConfig (
  908. IN const CComponentList& Components,
  909. IN PCWSTR pszBindPaths,
  910. IN UINT cPaths)
  911. {
  912. CLanaMap CurrentLanaMap;
  913. CLanaMap NewLanaMap;
  914. HRESULT hr;
  915. hr = CurrentLanaMap.HrLoadLanaMap();
  916. if (S_OK == hr)
  917. {
  918. hr = NewLanaMap.HrReserveRoomForEntries (cPaths);
  919. if (S_OK == hr)
  920. {
  921. PCWSTR pszScan;
  922. CLanaEntry LanaEntry;
  923. for (pszScan = pszBindPaths;
  924. *pszScan;
  925. pszScan += wcslen (pszScan) + 1)
  926. {
  927. LanaEntry.pszBindPath = pszScan;
  928. CurrentLanaMap.GetLanaEntry (Components, &LanaEntry);
  929. hr = NewLanaMap.HrAppendEntry (&LanaEntry);
  930. if (S_OK != hr)
  931. {
  932. break;
  933. }
  934. }
  935. if (S_OK == hr)
  936. {
  937. hr = NewLanaMap.HrWriteLanaConfiguration (Components);
  938. }
  939. }
  940. }
  941. TraceHr (ttidError, FAL, hr, FALSE, "HrUpdateLanaConfig");
  942. return hr;
  943. }
  944. EXTERN_C
  945. VOID
  946. WINAPI
  947. UpdateLanaConfigUsingAnswerfile (
  948. IN PCWSTR pszAnswerFile,
  949. IN PCWSTR pszSection)
  950. {
  951. HRESULT hr;
  952. CLanaMap LanaMap;
  953. // Load the current lanamap information.
  954. hr = LanaMap.HrLoadLanaMap();
  955. if (S_OK == hr)
  956. {
  957. TraceTag (ttidNetcfgBase, "Answerfile params %S:%S",
  958. pszAnswerFile, pszSection);
  959. // Load up the current network configuration.
  960. //
  961. CNetConfig NetConfig;
  962. hr = HrLoadNetworkConfigurationFromRegistry (KEY_READ, &NetConfig);
  963. if (S_OK == hr)
  964. {
  965. hr = NetConfig.HrEnsureExternalDataLoadedForAllComponents();
  966. if (S_OK == hr)
  967. {
  968. // Convert our current lana bind paths to a lana bind set.
  969. //
  970. LANA_BIND_PATH* pBindSet;
  971. hr = HrConvertBindingsToLanaBindSet (
  972. NetConfig.Core.Components, LanaMap, &pBindSet);
  973. if (S_OK == hr)
  974. {
  975. // Convert the answerfile lana bind paths
  976. // to a lana bind set.
  977. //
  978. LANA_BIND_PATH* pAnswerFileBindSet;
  979. DWORD cAnswerFilePaths;
  980. hr = HrProcessAnswerFile (
  981. pszAnswerFile, pszSection,
  982. NetConfig.Core.Components, &pAnswerFileBindSet,
  983. &cAnswerFilePaths);
  984. if (S_OK == hr)
  985. {
  986. // Now update the config using the answerfile info.
  987. //
  988. UpdateLanaConfigWithAnswerFileInfo (
  989. &LanaMap, cAnswerFilePaths,
  990. pBindSet, pAnswerFileBindSet);
  991. // Write out the information.
  992. hr = LanaMap.HrWriteLanaConfiguration (
  993. NetConfig.Core.Components);
  994. delete [] pAnswerFileBindSet;
  995. }
  996. delete [] pBindSet;
  997. }
  998. }
  999. }
  1000. }
  1001. TraceHr (ttidError, FAL, hr, FALSE, "UpdateLanaConfigUsingAnswerfile");
  1002. }