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.

2430 lines
64 KiB

  1. // ATlkObj.cpp : Implementation of CATlkObj
  2. #include "pch.h"
  3. #pragma hdrstop
  4. #include <atalkwsh.h>
  5. #include "atlkobj.h"
  6. #include "ncatlui.h"
  7. #include "ncmisc.h"
  8. #include "ncreg.h"
  9. #include "ncpnp.h"
  10. #include "ncsvc.h"
  11. #include <netconp.h>
  12. extern const WCHAR c_szAdapterSections[];
  13. //extern const WCHAR c_szAdapters[];
  14. extern const WCHAR c_szBackslash[];
  15. extern const WCHAR c_szDevice[];
  16. extern const WCHAR c_szSpecificTo[];
  17. extern const WCHAR c_szInfId_MS_NdisWanAtalk[];
  18. extern const WCHAR c_szEmpty[];
  19. // Registry Paths
  20. static const WCHAR c_szAtlk[] = L"AppleTalk";
  21. static const WCHAR c_szATLKParameters[] = L"System\\CurrentControlSet\\Services\\AppleTalk\\Parameters";
  22. static const WCHAR c_szATLKAdapters[] = L"System\\CurrentControlSet\\Services\\AppleTalk\\Parameters\\Adapters";
  23. // Values under the Adapter component's "Parameters" key
  24. static const WCHAR c_szMediaType[] = L"MediaType"; //$ REVIEW duplicate string
  25. // Values under AppleTalk\Parameters
  26. static const WCHAR c_szDefaultPort[] = L"DefaultPort"; // REG_SZ
  27. static const WCHAR c_szDesiredZone[] = L"DesiredZone"; // REG_SZ
  28. static const WCHAR c_szEnableRouter[] = L"EnableRouter"; // REG_DWORD
  29. // Values under AppleTalk\Parameters\Adapters\<AdapterId>
  30. static const WCHAR c_szAarpRetries[] = L"AarpRetries"; // REG_DWORD
  31. static const WCHAR c_szDdpCheckSums[] = L"DdpCheckSums"; // REG_DWORD
  32. static const WCHAR c_szDefaultZone[] = L"DefaultZone"; // REG_SZ
  33. static const WCHAR c_szNetworkRangeLowerEnd[] = L"NetworkRangeLowerEnd";// REG_DWORD
  34. static const WCHAR c_szNetworkRangeUpperEnd[] = L"NetworkRangeUpperEnd";// REG_DWORD
  35. static const WCHAR c_szPortName[] = L"PortName"; // REG_SZ
  36. static const WCHAR c_szRouterPramNode[] = L"RouterPramNode"; // REG_DWORD
  37. static const WCHAR c_szSeedingNetwork[] = L"SeedingNetwork"; // REG_DWORD
  38. static const WCHAR c_szUserPramNode1[] = L"UserPramNode1"; // REG_DWORD
  39. static const WCHAR c_szUserPramNode2[] = L"UserPramNode2"; // REG_DWORD
  40. static const WCHAR c_szZoneList[] = L"ZoneList"; // REG_MULTI_SZ
  41. // Useful default constant
  42. const WCHAR c_chAt = L'@';
  43. static const WCHAR c_dwZero = 0L;
  44. static const WCHAR c_dwTen = 10L;
  45. //static const WCHAR c_szMacPrint[] = L"MacPrint";
  46. // Declare structure for reading/writing AppleTalk\Parameters values
  47. static const REGBATCH regbatchATLKParams[] = {
  48. {HKEY_LOCAL_MACHINE, c_szATLKParameters, c_szDefaultPort, REG_SZ,
  49. offsetof(ATLK_PARAMS,szDefaultPort), (BYTE *)&c_szEmpty},
  50. {HKEY_LOCAL_MACHINE, c_szATLKParameters, c_szDesiredZone, REG_SZ,
  51. offsetof(ATLK_PARAMS,szDesiredZone), (BYTE *)&c_szEmpty},
  52. {HKEY_LOCAL_MACHINE, c_szATLKParameters, c_szEnableRouter, REG_DWORD,
  53. offsetof(ATLK_PARAMS,dwEnableRouter), (BYTE *)&c_szEmpty}};
  54. static const REGBATCH regbatchATLKAdapters[] = {
  55. {HKEY_LOCAL_MACHINE, c_szEmpty, c_szAarpRetries, REG_DWORD,
  56. offsetof(ATLK_ADAPTER,m_dwAarpRetries), (BYTE *)&c_dwTen},
  57. {HKEY_LOCAL_MACHINE, c_szEmpty, c_szDdpCheckSums, REG_DWORD,
  58. offsetof(ATLK_ADAPTER,m_dwDdpCheckSums), (BYTE *)&c_dwZero},
  59. {HKEY_LOCAL_MACHINE, c_szEmpty, c_szNetworkRangeLowerEnd, REG_DWORD,
  60. offsetof(ATLK_ADAPTER,m_dwNetworkRangeLowerEnd), (BYTE *)&c_dwZero},
  61. {HKEY_LOCAL_MACHINE, c_szEmpty, c_szNetworkRangeUpperEnd, REG_DWORD,
  62. offsetof(ATLK_ADAPTER,m_dwNetworkRangeUpperEnd), (BYTE *)&c_dwZero},
  63. {HKEY_LOCAL_MACHINE, c_szEmpty, c_szRouterPramNode, REG_DWORD,
  64. offsetof(ATLK_ADAPTER,m_dwRouterPramNode), (BYTE *)&c_dwZero},
  65. {HKEY_LOCAL_MACHINE, c_szEmpty, c_szSeedingNetwork, REG_DWORD,
  66. offsetof(ATLK_ADAPTER,m_dwSeedingNetwork), (BYTE *)&c_dwZero},
  67. {HKEY_LOCAL_MACHINE, c_szEmpty, c_szUserPramNode1, REG_DWORD,
  68. offsetof(ATLK_ADAPTER,m_dwUserPramNode1), (BYTE *)&c_dwZero},
  69. {HKEY_LOCAL_MACHINE, c_szEmpty, c_szUserPramNode2, REG_DWORD,
  70. offsetof(ATLK_ADAPTER,m_dwUserPramNode2), (BYTE *)&c_dwZero},
  71. {HKEY_LOCAL_MACHINE, c_szEmpty, c_szMediaType, REG_DWORD,
  72. offsetof(ATLK_ADAPTER,m_dwMediaType), (BYTE *)&c_dwZero},
  73. {HKEY_LOCAL_MACHINE, c_szEmpty, c_szDefaultZone, REG_SZ,
  74. offsetof(ATLK_ADAPTER,m_szDefaultZone), (BYTE *)&c_szEmpty},
  75. {HKEY_LOCAL_MACHINE, c_szEmpty, c_szPortName, REG_SZ,
  76. offsetof(ATLK_ADAPTER,m_szPortName), (BYTE *)&c_szEmpty}};
  77. // Local utility functions
  78. HRESULT HrQueryAdapterComponentInfo(INetCfgComponent *pncc,
  79. CAdapterInfo * pAI);
  80. HRESULT HrPortNameFromAdapter(INetCfgComponent *pncc, tstring * pstr);
  81. // Prototype from nwlnkcfg\nwlnkutl.h
  82. HRESULT HrAnswerFileAdapterToPNCC(INetCfg *pnc, PCWSTR pszAdapterId,
  83. INetCfgComponent** ppncc);
  84. //
  85. // Function: CATlkObj::CATlkObj
  86. //
  87. // Purpose: ctor for the CATlkObj class
  88. //
  89. // Parameters: none
  90. //
  91. // Returns: none
  92. //
  93. CATlkObj::CATlkObj() : m_pNetCfg(NULL),
  94. m_pNCC(NULL),
  95. m_eInstallAction(eActUnknown),
  96. m_pspObj(NULL),
  97. m_pATLKEnv(NULL),
  98. m_pATLKEnv_PP(NULL),
  99. m_pUnkPropContext(NULL),
  100. m_nIdxAdapterSelected(CB_ERR),
  101. m_fAdapterListChanged(FALSE),
  102. m_fPropertyChange(FALSE),
  103. m_fFirstTimeInstall(FALSE)
  104. {
  105. }
  106. //
  107. // Function: CATlkObj::CATlkObj
  108. //
  109. // Purpose: dtor for the CATlkObj class
  110. //
  111. // Parameters: none
  112. //
  113. // Returns: none
  114. //
  115. CATlkObj::~CATlkObj()
  116. {
  117. // Should always be cleaned up in advance of reach this dtor
  118. Assert(NULL == m_pATLKEnv_PP);
  119. ReleaseObj(m_pUnkPropContext);
  120. ReleaseObj(m_pNetCfg);
  121. ReleaseObj(m_pNCC);
  122. CleanupPropPages();
  123. delete m_pATLKEnv;
  124. }
  125. // INetCfgNotify
  126. STDMETHODIMP CATlkObj::Initialize ( INetCfgComponent* pnccItem,
  127. INetCfg* pNetCfg, BOOL fInstalling )
  128. {
  129. Validate_INetCfgNotify_Initialize(pnccItem, pNetCfg, fInstalling);
  130. ReleaseObj(m_pNCC);
  131. m_pNCC = pnccItem;
  132. AddRefObj(m_pNCC);
  133. ReleaseObj(m_pNetCfg);
  134. m_pNetCfg = pNetCfg;
  135. AddRefObj(m_pNetCfg);
  136. m_fFirstTimeInstall = fInstalling;
  137. // Read the current configuration
  138. HRESULT hr = CATLKEnv::HrCreate(&m_pATLKEnv, this);
  139. TraceError("CATlkObj::Initialize",hr);
  140. return hr;
  141. }
  142. STDMETHODIMP CATlkObj::ReadAnswerFile(PCWSTR pszAnswerFile,
  143. PCWSTR pszAnswerSection )
  144. {
  145. Validate_INetCfgNotify_ReadAnswerFile(pszAnswerFile, pszAnswerSection );
  146. HRESULT hr = S_OK;
  147. m_eInstallAction = eActInstall;
  148. // Only process answer file and install sub-components if the answer file
  149. // is present. If the answer file is not present we should already be installed.
  150. if (NULL != pszAnswerFile)
  151. {
  152. hr = HrProcessAnswerFile(pszAnswerFile, pszAnswerSection);
  153. }
  154. TraceError("CATlkObj::ReadAnswerFile",hr);
  155. return hr;
  156. }
  157. //
  158. // Function: CATlkObj::HrProcessAnswerFile
  159. //
  160. // Purpose: Process the answer file information, merging
  161. // its contents into the internal information
  162. //
  163. // Parameters:
  164. //
  165. // Returns: HRESULT, S_OK on success
  166. //
  167. HRESULT CATlkObj::HrProcessAnswerFile(PCWSTR pszAnswerFile,
  168. PCWSTR pszAnswerSection)
  169. {
  170. TraceFileFunc(ttidDefault);
  171. CSetupInfFile csif;
  172. BOOL fValue;
  173. HRESULT hr = S_OK;
  174. INFCONTEXT infctx;
  175. tstring str;
  176. AssertSz(pszAnswerFile, "Answer file string is NULL!");
  177. AssertSz(pszAnswerSection, "Answer file sections string is NULL!");
  178. // Open the answer file.
  179. hr = csif.HrOpen(pszAnswerFile, NULL, INF_STYLE_OLDNT | INF_STYLE_WIN4, NULL);
  180. if (FAILED(hr))
  181. {
  182. goto Error;
  183. }
  184. // Read the property containing the list of adapter sections
  185. hr = ::HrSetupFindFirstLine(csif.Hinf(), pszAnswerSection,
  186. c_szAdapterSections, &infctx);
  187. if (S_OK == hr)
  188. {
  189. DWORD dwIdx;
  190. DWORD dwCnt = SetupGetFieldCount(&infctx);
  191. // For each adapter in the list read the adapter information
  192. for (dwIdx=1; dwIdx <= dwCnt; dwIdx++)
  193. {
  194. hr = ::HrSetupGetStringField(infctx, dwIdx, &str);
  195. if (FAILED(hr))
  196. {
  197. TraceError("CATlkObj::HrProcessAnswerFile - Failed to read adapter section name",hr);
  198. break;
  199. }
  200. hr = HrReadAdapterAnswerFileSection(&csif, str.c_str());
  201. if (FAILED(hr))
  202. {
  203. goto Error;
  204. }
  205. }
  206. }
  207. TraceTag(ttidDefault, "***Appletalk processing default port***");
  208. // Read the default port property (REG_SZ)
  209. hr = csif.HrGetString(pszAnswerSection, c_szDefaultPort, &str);
  210. if (SUCCEEDED(hr))
  211. {
  212. tstring strNew = str;
  213. // If the \device\ prefix is present, strip it off
  214. //
  215. if (0 == _wcsnicmp(str.c_str(), c_szDevice, wcslen(c_szDevice)))
  216. {
  217. strNew = ((PWSTR)str.c_str()) + wcslen(c_szDevice);
  218. TraceTag(ttidDefault, "Removing the device prefix. Device=%S",strNew.c_str());
  219. }
  220. // Convert the Adapter0x to \Device\{bind-name}
  221. INetCfgComponent* pncc = NULL;
  222. hr = ::HrAnswerFileAdapterToPNCC(PNetCfg(), strNew.c_str(), &pncc);
  223. if (S_OK == hr)
  224. {
  225. PWSTR pszBindName;
  226. hr = pncc->GetBindName(&pszBindName);
  227. ReleaseObj(pncc);
  228. if (FAILED(hr))
  229. {
  230. goto Error;
  231. }
  232. str = c_szDevice;
  233. str += pszBindName;
  234. CoTaskMemFree(pszBindName);
  235. TraceTag(ttidDefault, "Port located and configured");
  236. m_pATLKEnv->SetDefaultPort(str.c_str());
  237. }
  238. }
  239. TraceTag(ttidDefault, "***Appletalk finished processing default port***");
  240. // Read the default zone property (REG_SZ)
  241. hr = csif.HrGetString(pszAnswerSection, c_szDesiredZone, &str);
  242. if (SUCCEEDED(hr))
  243. {
  244. m_pATLKEnv->SetDesiredZone(str.c_str());
  245. }
  246. // Read the EnableRouter property (DWORD used as a boolean)
  247. hr = csif.HrGetStringAsBool(pszAnswerSection, c_szEnableRouter, &fValue);
  248. if (SUCCEEDED(hr))
  249. {
  250. m_pATLKEnv->EnableRouting(fValue);
  251. }
  252. // Determine the best default port overriding the recorded default only
  253. // if the default port cannot be found
  254. m_pATLKEnv->InitDefaultPort();
  255. hr = S_OK;
  256. m_fPropertyChange = TRUE;
  257. Error:
  258. TraceError("CATlkObj::HrProcessAnswerFile", hr);
  259. return hr;
  260. }
  261. //
  262. // Function: CATlkObj::HrReadAdapterAnswerFileSection
  263. //
  264. // Purpose: Read the adapter answer file section and create
  265. // the adapter info section if successful
  266. //
  267. // Parameters:
  268. //
  269. // Returns:
  270. //
  271. HRESULT
  272. CATlkObj::HrReadAdapterAnswerFileSection(CSetupInfFile * pcsif,
  273. PCWSTR pszSection)
  274. {
  275. HRESULT hr = S_OK;
  276. CAdapterInfo * pAI = NULL;
  277. tstring str;
  278. INetCfgComponent* pncc = NULL;
  279. // Read the SpecificTo adapter name
  280. hr = pcsif->HrGetString(pszSection, c_szSpecificTo, &str);
  281. if (FAILED(hr))
  282. {
  283. goto Error;
  284. }
  285. // Search for the specified adapter in the set of existing adapters
  286. hr = ::HrAnswerFileAdapterToPNCC(PNetCfg(), str.c_str(), &pncc);
  287. if (FAILED(hr))
  288. {
  289. goto Error;
  290. }
  291. // if we found the adapter component object (pncc != NULL) process
  292. // the adapter section
  293. if (pncc)
  294. {
  295. DWORD dwData;
  296. DWORD dwDataUpper;
  297. INFCONTEXT infctx;
  298. pAI = new CAdapterInfo();
  299. Assert(NULL != pAI);
  300. pAI->SetDirty(TRUE);
  301. // Get the adapter component info (media type, description, ...)
  302. hr = ::HrQueryAdapterComponentInfo(pncc, pAI);
  303. if (FAILED(hr))
  304. {
  305. goto Error;
  306. }
  307. // Read the NetworkRangeUpperEnd
  308. hr = pcsif->HrGetDword(pszSection, c_szNetworkRangeUpperEnd, &dwDataUpper);
  309. if (FAILED(hr))
  310. {
  311. dwDataUpper = pAI->DwQueryNetRangeUpper();
  312. TraceTag(ttidDefault, "CATlkObj::HrReadAdapterAnswerFileSection - Defaulting property %S",c_szNetworkRangeUpperEnd);
  313. }
  314. // Read the NetworkRangeLowerEnd
  315. hr = pcsif->HrGetDword(pszSection, c_szNetworkRangeLowerEnd, &dwData);
  316. if (FAILED(hr))
  317. {
  318. dwData = pAI->DwQueryNetRangeLower();
  319. TraceTag(ttidDefault, "CATlkObj::HrReadAdapterAnswerFileSection - Defaulting property %S",c_szNetworkRangeLowerEnd);
  320. }
  321. pAI->SetAdapterNetRange(dwData, dwDataUpper);
  322. // Read the DefaultZone
  323. hr = pcsif->HrGetString(pszSection, c_szDefaultZone, &str);
  324. if (SUCCEEDED(hr))
  325. {
  326. pAI->SetDefaultZone(str.c_str());
  327. }
  328. // Read the SeedingNetwork
  329. hr = pcsif->HrGetDword(pszSection, c_szNetworkRangeLowerEnd, &dwData);
  330. if (SUCCEEDED(hr))
  331. {
  332. pAI->SetSeedingNetwork(!!dwData);
  333. }
  334. // Generate the PortName
  335. hr = ::HrPortNameFromAdapter(pncc, &str);
  336. if (FAILED(hr))
  337. {
  338. goto Error;
  339. }
  340. pAI->SetPortName(str.c_str());
  341. // Read the ZoneList
  342. hr = HrSetupFindFirstLine(pcsif->Hinf(), pszSection, c_szZoneList,
  343. &infctx);
  344. if (S_OK == hr)
  345. {
  346. DWORD dwIdx;
  347. DWORD dwCnt = SetupGetFieldCount(&infctx);
  348. // For each adapter in the list read the adapter information
  349. for (dwIdx=1; dwIdx <= dwCnt; dwIdx++)
  350. {
  351. hr = ::HrSetupGetStringField(infctx, dwIdx, &str);
  352. if (FAILED(hr))
  353. {
  354. TraceError("CATlkObj::HrProcessAnswerFile - Failed to read adapter section name",hr);
  355. goto Error;
  356. }
  357. if (!str.empty())
  358. {
  359. pAI->LstpstrZoneList().push_back(new tstring(str));
  360. }
  361. }
  362. }
  363. pAI->SetDirty(TRUE);
  364. m_pATLKEnv->AdapterInfoList().push_back(pAI);
  365. MarkAdapterListChanged();
  366. }
  367. // Normalize any errors
  368. hr = S_OK;
  369. Done:
  370. ReleaseObj(pncc);
  371. return hr;
  372. Error:
  373. delete pAI;
  374. TraceError("CATlkObj::HrReadAdapterAnswerFileSection",hr);
  375. goto Done;
  376. }
  377. STDMETHODIMP CATlkObj::Install (DWORD)
  378. {
  379. CAdapterInfo * pAI;
  380. ATLK_ADAPTER_INFO_LIST::iterator iter;
  381. m_eInstallAction = eActInstall;
  382. // Mark all the initially detected adapters as dirty
  383. for (iter = m_pATLKEnv->AdapterInfoList().begin();
  384. iter != m_pATLKEnv->AdapterInfoList().end();
  385. iter++)
  386. {
  387. pAI = *iter;
  388. pAI->SetDirty(TRUE);
  389. }
  390. return S_OK;
  391. }
  392. STDMETHODIMP CATlkObj::Removing ()
  393. {
  394. m_eInstallAction = eActRemove;
  395. return S_OK;
  396. }
  397. STDMETHODIMP CATlkObj::Validate ()
  398. {
  399. return S_OK;
  400. }
  401. STDMETHODIMP CATlkObj::CancelChanges ()
  402. {
  403. return S_OK;
  404. }
  405. STDMETHODIMP CATlkObj::ApplyRegistryChanges ()
  406. {
  407. HRESULT hr = S_OK;
  408. // Have any changes been validated?
  409. switch(m_eInstallAction)
  410. {
  411. case eActInstall:
  412. hr = HrCommitInstall();
  413. if (SUCCEEDED(hr))
  414. {
  415. m_fFirstTimeInstall = FALSE;
  416. hr = HrAtlkReconfig();
  417. }
  418. break;
  419. case eActRemove:
  420. hr = HrCommitRemove();
  421. break;
  422. default: // eActUnknown
  423. if (m_fAdapterListChanged || m_fPropertyChange)
  424. {
  425. // Update the registry if the adapter list changed
  426. Assert(NULL != m_pATLKEnv);
  427. hr = m_pATLKEnv->HrUpdateRegistry();
  428. if (SUCCEEDED(hr))
  429. {
  430. hr = HrAtlkReconfig();
  431. }
  432. }
  433. break;
  434. }
  435. TraceError("CATlkObj::ApplyRegistryChanges",hr);
  436. return hr;
  437. }
  438. // INetCfgProperties
  439. STDMETHODIMP CATlkObj::SetContext(IUnknown * pUnk)
  440. {
  441. ReleaseObj(m_pUnkPropContext);
  442. m_pUnkPropContext = pUnk;
  443. if (m_pUnkPropContext)
  444. {
  445. AddRefObj(m_pUnkPropContext);
  446. }
  447. return S_OK;
  448. }
  449. STDMETHODIMP CATlkObj::MergePropPages (
  450. IN OUT DWORD* pdwDefPages,
  451. OUT LPBYTE* pahpspPrivate,
  452. OUT UINT* pcPages,
  453. IN HWND hwndParent,
  454. OUT PCWSTR* pszStartPage)
  455. {
  456. Validate_INetCfgProperties_MergePropPages (
  457. pdwDefPages, pahpspPrivate, pcPages, hwndParent, pszStartPage);
  458. HRESULT hr = S_OK;
  459. HPROPSHEETPAGE *ahpsp = NULL;
  460. CAdapterInfo * pAI = NULL;
  461. Assert(pahpspPrivate);
  462. Assert(NULL == *pahpspPrivate); // Out param init done via Validate above
  463. *pcPages = 0;
  464. Assert(NULL != m_pATLKEnv);
  465. if (NULL != m_pATLKEnv_PP)
  466. {
  467. TraceError("CATlkObj::MergePropPages - multiple property page instances requested.", hr);
  468. return E_UNEXPECTED;
  469. }
  470. // AppleTalk requires "complete" installation before property changes are
  471. // allowed. If we've just installed but Apply has not yet been pressed,
  472. // disallow property page display
  473. if (m_fFirstTimeInstall)
  474. {
  475. NcMsgBox(::GetFocus(), IDS_ATLK_CAPTION, IDS_ATLK_INSTALL_PENDING,
  476. MB_OK | MB_ICONEXCLAMATION);
  477. return S_FALSE;
  478. }
  479. // Start with new property pages each time.
  480. CleanupPropPages();
  481. // Locate the adapter referenced in the connection we stashed away
  482. if (NULL != m_pUnkPropContext)
  483. {
  484. INetLanConnectionUiInfo * pLanConn = NULL;
  485. ATLK_ADAPTER_INFO_LIST::iterator iter;
  486. hr = m_pUnkPropContext->QueryInterface(IID_INetLanConnectionUiInfo,
  487. reinterpret_cast<LPVOID *>(&pLanConn));
  488. if (S_OK == hr)
  489. {
  490. GUID guid;
  491. hr = pLanConn->GetDeviceGuid(&guid);
  492. ReleaseObj(pLanConn);
  493. if (SUCCEEDED(hr))
  494. {
  495. // Find the adapter in our adapter list
  496. for (iter = m_pATLKEnv->AdapterInfoList().begin();
  497. iter != m_pATLKEnv->AdapterInfoList().end();
  498. iter++)
  499. {
  500. CAdapterInfo * pAITmp = *iter;
  501. if (guid == *pAITmp->PInstanceGuid())
  502. {
  503. // Copy the adapter data
  504. hr = pAITmp->HrCopy(&pAI);
  505. break;
  506. }
  507. }
  508. }
  509. }
  510. if (SUCCEEDED(hr))
  511. {
  512. // If no adapter in this connection or it's
  513. // disabled/hidden/deleted we show no pages
  514. if ((NULL == pAI) || pAI->FDeletePending() ||
  515. pAI->FDisabled() || pAI->FHidden())
  516. {
  517. Assert(0 == *pcPages);
  518. hr = S_FALSE;
  519. goto cleanup;
  520. }
  521. }
  522. }
  523. else
  524. {
  525. // m_pUnkPropContext should have been set first
  526. hr = E_UNEXPECTED;
  527. }
  528. if (FAILED(hr))
  529. {
  530. goto Error;
  531. }
  532. // Create a copy of the enviroment for property page usage
  533. hr = m_pATLKEnv->HrCopy(&m_pATLKEnv_PP);
  534. if (FAILED(hr))
  535. {
  536. goto Error;
  537. }
  538. Assert(NULL != m_pATLKEnv_PP);
  539. Assert(NULL != pAI);
  540. // Query the zonelist every time, only for non-Seeding adapters.
  541. if (!pAI->FSeedingNetwork() || !m_pATLKEnv_PP->FRoutingEnabled())
  542. {
  543. (void) m_pATLKEnv->HrGetAppleTalkInfoFromNetwork(pAI);
  544. }
  545. // Add the adapter to the property sheet's list
  546. m_pATLKEnv_PP->AdapterInfoList().push_back(pAI);
  547. // Allocate the CPropSheetPage object for the "General" page
  548. m_pspObj = new CATLKGeneralDlg(this, m_pATLKEnv_PP);
  549. // Allocate a buffer large enough to hold the handle to the Appletalk config.
  550. // property page.
  551. ahpsp = (HPROPSHEETPAGE *)CoTaskMemAlloc(sizeof(HPROPSHEETPAGE));
  552. if (!ahpsp)
  553. {
  554. hr = E_OUTOFMEMORY;
  555. goto cleanup; // Alloc failed to no need to free ahpsp
  556. }
  557. // Create the actual PROPSHEETPAGE for each object.
  558. ahpsp[0] = m_pspObj->CreatePage(DLG_ATLK_GENERAL, 0);
  559. // Validate what we've created
  560. if (NULL == ahpsp[0])
  561. {
  562. hr = E_OUTOFMEMORY;
  563. goto Error;
  564. }
  565. else
  566. {
  567. *pahpspPrivate = (LPBYTE)ahpsp;
  568. *pcPages = 1;
  569. }
  570. cleanup:
  571. TraceError("CATlkObj::MergePropPages", hr);
  572. return hr;
  573. Error:
  574. CoTaskMemFree(ahpsp);
  575. delete m_pATLKEnv_PP;
  576. m_pATLKEnv_PP = NULL;
  577. goto cleanup;
  578. }
  579. //
  580. // Function: CATlkObj::CleanupPropPages
  581. //
  582. // Purpose:
  583. //
  584. // Parameters:
  585. //
  586. // Returns: nothing
  587. //
  588. VOID CATlkObj::CleanupPropPages()
  589. {
  590. delete m_pspObj;
  591. m_pspObj = NULL;
  592. }
  593. //
  594. // Function: CATlkObj::ValidateProperties
  595. //
  596. // Purpose:
  597. //
  598. // Parameters:
  599. //
  600. // Returns: HRESULT, S_OK on success
  601. //
  602. STDMETHODIMP CATlkObj::ValidateProperties (HWND)
  603. {
  604. return S_OK;
  605. }
  606. //
  607. // Function: CATlkObj::CancelProperties
  608. //
  609. // Purpose:
  610. //
  611. // Parameters:
  612. //
  613. // Returns: HRESULT, S_OK on success
  614. //
  615. STDMETHODIMP CATlkObj::CancelProperties ()
  616. {
  617. // Discard any changes made via the property pages
  618. delete m_pATLKEnv_PP;
  619. m_pATLKEnv_PP = NULL;
  620. return S_OK;
  621. }
  622. //
  623. // Function: CATlkObj::ApplyProperties
  624. //
  625. // Purpose:
  626. //
  627. // Parameters:
  628. //
  629. // Returns: HRESULT, S_OK on success
  630. //
  631. STDMETHODIMP CATlkObj::ApplyProperties ()
  632. {
  633. // Extract the adapter info from the property sheet's
  634. // enviroment block
  635. Assert(!m_pATLKEnv_PP->AdapterInfoList().empty());
  636. CAdapterInfo * pAICurrent = m_pATLKEnv_PP->AdapterInfoList().front();
  637. m_pATLKEnv_PP->AdapterInfoList().pop_front();
  638. Assert(NULL != pAICurrent);
  639. // Remove the current adapter from the original enviroment
  640. CAdapterInfo * pAI;
  641. ATLK_ADAPTER_INFO_LIST::iterator iter;
  642. for (iter = m_pATLKEnv->AdapterInfoList().begin();
  643. iter != m_pATLKEnv->AdapterInfoList().end();
  644. iter++)
  645. {
  646. pAI = *iter;
  647. if (0 == _wcsicmp(pAI->SzBindName(), pAICurrent->SzBindName()))
  648. {
  649. m_pATLKEnv->AdapterInfoList().erase(iter, iter);
  650. break;
  651. }
  652. }
  653. // Add pAICurrent to the base enviroment block
  654. m_pATLKEnv->AdapterInfoList().push_back(pAICurrent);
  655. // Update the base enviroment from the property sheet's enviroment
  656. m_pATLKEnv->SetDefaultMediaType(m_pATLKEnv_PP->DwDefaultAdaptersMediaType());
  657. m_pATLKEnv->EnableRouting(m_pATLKEnv_PP->FRoutingEnabled());
  658. m_pATLKEnv->SetDefaultPort(m_pATLKEnv_PP->SzDefaultPort());
  659. m_pATLKEnv->SetDesiredZone(m_pATLKEnv_PP->SzDesiredZone());
  660. m_pATLKEnv->SetRouterChanged(m_pATLKEnv_PP->FRouterChanged());
  661. m_pATLKEnv->SetDefAdapterChanged(m_pATLKEnv_PP->FDefAdapterChanged());
  662. // Delete the property pages enviroment block
  663. delete m_pATLKEnv_PP;
  664. m_pATLKEnv_PP = NULL;
  665. // Properties changed
  666. m_fPropertyChange = TRUE;
  667. return S_OK;
  668. }
  669. // INetCfgBindNotify
  670. STDMETHODIMP
  671. CATlkObj::QueryBindingPath (
  672. DWORD dwChangeFlag,
  673. INetCfgBindingPath* pncbpItem )
  674. {
  675. Validate_INetCfgBindNotify_QueryBindingPath( dwChangeFlag, pncbpItem );
  676. return S_OK;
  677. }
  678. STDMETHODIMP
  679. CATlkObj::NotifyBindingPath (
  680. DWORD dwChangeFlag,
  681. INetCfgBindingPath* pncbpItem )
  682. {
  683. HRESULT hr = S_OK;
  684. INetCfgComponent *pnccFound = NULL;
  685. Validate_INetCfgBindNotify_NotifyBindingPath( dwChangeFlag, pncbpItem );
  686. Assert(NULL != m_pATLKEnv);
  687. // Only Interested in lower binding Add's and Remove's
  688. if (dwChangeFlag & (NCN_ADD | NCN_REMOVE | NCN_ENABLE | NCN_DISABLE))
  689. {
  690. CIterNetCfgBindingInterface ncbiIter(pncbpItem);
  691. INetCfgBindingInterface *pncbi;
  692. // Enumerate the binding interfaces looking for the last Adapter
  693. while (SUCCEEDED(hr) &&
  694. (S_OK == (hr = ncbiIter.HrNext (&pncbi))))
  695. {
  696. INetCfgComponent *pncc;
  697. hr = pncbi->GetLowerComponent(&pncc);
  698. if (S_OK == hr)
  699. {
  700. GUID guidClass;
  701. hr = pncc->GetClassGuid(&guidClass);
  702. if ((S_OK == hr) && (GUID_DEVCLASS_NET == guidClass))
  703. {
  704. ULONG ulStatus = 0;
  705. hr = pncc->GetDeviceStatus(&ulStatus);
  706. if(S_OK == hr)
  707. {
  708. ReleaseObj(pnccFound);
  709. pnccFound = pncc; // Transfer Ownership
  710. pncc = NULL;
  711. }
  712. else
  713. {
  714. ReleaseObj(pncc);
  715. }
  716. }
  717. else
  718. {
  719. ReleaseObj(pncc);
  720. }
  721. }
  722. ReleaseObj(pncbi);
  723. }
  724. if (FAILED(hr))
  725. {
  726. goto Error;
  727. }
  728. // Did we find the Adapter?
  729. if (pnccFound)
  730. {
  731. BOOL fFound = FALSE;
  732. PWSTR pszBindName = NULL;
  733. CAdapterInfo * pAI;
  734. ATLK_ADAPTER_INFO_LIST::iterator iterAdapterInfo;
  735. Assert(NULL != m_pATLKEnv);
  736. ATLK_ADAPTER_INFO_LIST pAI_List = m_pATLKEnv->AdapterInfoList();
  737. hr = pnccFound->GetBindName(&pszBindName);
  738. if (S_OK != hr)
  739. {
  740. goto Error;
  741. }
  742. // Search the adapter list
  743. for (iterAdapterInfo = pAI_List.begin();
  744. iterAdapterInfo != pAI_List.end();
  745. iterAdapterInfo++)
  746. {
  747. pAI = *iterAdapterInfo;
  748. if (0 == lstrcmpiW(pszBindName, pAI->SzBindName()))
  749. {
  750. fFound = TRUE;
  751. break;
  752. }
  753. }
  754. Assert(NULL != pszBindName);
  755. CoTaskMemFree(pszBindName);
  756. // Apply the appropriate delta to the adapter list
  757. if (fFound && (dwChangeFlag & NCN_REMOVE))
  758. {
  759. // Delete the adapter from the list
  760. pAI->SetDeletePending(TRUE);
  761. m_fAdapterListChanged = TRUE;
  762. }
  763. else if (!fFound && (dwChangeFlag & NCN_ADD))
  764. {
  765. // Add the adapter to the list
  766. hr = m_pATLKEnv->HrAddAdapter(pnccFound);
  767. m_fAdapterListChanged = TRUE;
  768. }
  769. else if (fFound && (dwChangeFlag & NCN_ADD))
  770. {
  771. // Re-enable the adapters existance
  772. pAI->SetDeletePending(FALSE);
  773. }
  774. if (fFound)
  775. {
  776. if (dwChangeFlag & NCN_ENABLE)
  777. {
  778. pAI->SetDisabled(FALSE);
  779. m_fAdapterListChanged = TRUE;
  780. }
  781. else if (dwChangeFlag & NCN_DISABLE)
  782. {
  783. pAI->SetDisabled(TRUE);
  784. m_fAdapterListChanged = TRUE;
  785. }
  786. }
  787. }
  788. if (SUCCEEDED(hr))
  789. {
  790. hr = S_OK; // Normalize return value
  791. }
  792. }
  793. Error:
  794. ::ReleaseObj(pnccFound);
  795. TraceError("CATlkObj::NotifyBindingPath",hr);
  796. return hr;
  797. }
  798. //
  799. // Function: CATlkObj::HrCommitInstall
  800. //
  801. // Purpose: Commit Installation registry changes to the registry
  802. //
  803. // Parameters: None
  804. //
  805. // Returns: HRESULT, S_OK on success
  806. //
  807. //
  808. HRESULT CATlkObj::HrCommitInstall()
  809. {
  810. HRESULT hr;
  811. Assert(NULL != m_pATLKEnv);
  812. hr = m_pATLKEnv->HrUpdateRegistry();
  813. TraceError("CATlkObj::HrCommitInstall",hr);
  814. return hr;
  815. }
  816. //
  817. // Function: CATlkObj::HrCommitRemove
  818. //
  819. // Purpose: Remove from the registry settings which were created by this
  820. // component's installation.
  821. //
  822. // Parameters: None
  823. //
  824. // Returns: HRESULT, S_OK on success
  825. //
  826. //
  827. HRESULT CATlkObj::HrCommitRemove()
  828. {
  829. // Everything is removed via the inf file presently
  830. return S_OK;
  831. }
  832. //
  833. // Function: CATLKEnv::HrCreate
  834. //
  835. // Purpose: Construct the AppleTalk Enviroment tracking object
  836. //
  837. // Paramaters: ppATLKEnv [out] - AppleTalk Enviroment Object created
  838. // pmsc [in] - AppleTalk notification object
  839. //
  840. // Returns: HRESULT, S_OK on success
  841. //
  842. HRESULT CATLKEnv::HrCreate(CATLKEnv **ppATLKEnv, CATlkObj *pmsc)
  843. {
  844. HRESULT hr = S_OK;
  845. CATLKEnv *pATLKEnv = NULL;
  846. *ppATLKEnv = NULL;
  847. // Construct the new enviroment object
  848. pATLKEnv = new CATLKEnv(pmsc);
  849. if (pATLKEnv == NULL)
  850. {
  851. return(ERROR_NOT_ENOUGH_MEMORY);
  852. }
  853. // Read AppleTalk Info
  854. hr = pATLKEnv->HrReadAppleTalkInfo();
  855. if (FAILED(hr))
  856. {
  857. goto Error;
  858. }
  859. *ppATLKEnv = pATLKEnv;
  860. Done:
  861. return hr;
  862. Error:
  863. TraceError("CATLKEnv::HrCreate",hr);
  864. delete pATLKEnv;
  865. goto Done;
  866. }
  867. //
  868. // Function: CATLKEnv::CATLKEnv
  869. //
  870. // Purpose: ctor for the CATLKEnv class
  871. //
  872. // Parameters: none
  873. //
  874. // Returns: none
  875. //
  876. CATLKEnv::CATLKEnv(CATlkObj *pmsc) :
  877. m_pmsc(pmsc),
  878. m_fATrunning(FALSE),
  879. m_dwDefaultAdaptersMediaType(MEDIATYPE_ETHERNET),
  880. m_fRouterChanged(FALSE),
  881. m_fDefAdapterChanged(FALSE)
  882. {
  883. ZeroMemory(&m_Params, sizeof(m_Params));
  884. }
  885. //
  886. // Function: CATLKEnv::~CATLKEnv
  887. //
  888. // Purpose: dtor for the CATLKEnv class
  889. //
  890. // Parameters: none
  891. //
  892. // Returns: none
  893. //
  894. CATLKEnv::~CATLKEnv()
  895. {
  896. // Cleanup the AppleTalk\Parameters internal data structure
  897. delete [] m_Params.szDefaultPort;
  898. delete [] m_Params.szDesiredZone;
  899. // Cleanup the contents of the Adapter Info List
  900. while (!m_lstpAdapters.empty())
  901. {
  902. delete m_lstpAdapters.front();
  903. m_lstpAdapters.pop_front();
  904. }
  905. }
  906. //
  907. // Function: CATLKEnv::HrCopy
  908. //
  909. // Purpose: Creates a copy of the current Enviroment
  910. //
  911. // Parameters: ppEnv [out] - If the function succeeds, ppEnv will contain a
  912. // copy of the enviroment.
  913. //
  914. // Returns: HRESULT, S_OK on success
  915. //
  916. HRESULT CATLKEnv::HrCopy(CATLKEnv **ppEnv)
  917. {
  918. HRESULT hr = S_OK;
  919. CATLKEnv * pEnv;
  920. // Allocate a new enviroment object
  921. *ppEnv = NULL;
  922. pEnv = new CATLKEnv(m_pmsc);
  923. if (NULL != pEnv)
  924. {
  925. // Copy the members
  926. pEnv->m_fATrunning = m_fATrunning;
  927. pEnv->SetDefaultMediaType(DwDefaultAdaptersMediaType());
  928. pEnv->EnableRouting(FRoutingEnabled());
  929. pEnv->SetDefaultPort(SzDefaultPort());
  930. pEnv->SetDesiredZone(SzDesiredZone());
  931. pEnv->SetRouterChanged(FRouterChanged());
  932. pEnv->SetDefAdapterChanged(FDefAdapterChanged());
  933. *ppEnv = pEnv;
  934. }
  935. else
  936. {
  937. hr = E_OUTOFMEMORY;
  938. }
  939. TraceError("CATLKEnv::HrCopy",hr);
  940. return S_OK;
  941. }
  942. //
  943. // Function: CATLKEnv::HrReadAppleTalkInfo
  944. //
  945. // Purpose: Retrieve the AppleTalk registry Settings
  946. //
  947. // Parameters: none
  948. //
  949. // Returns: HRESULT, S_OK on success
  950. //
  951. HRESULT CATLKEnv::HrReadAppleTalkInfo()
  952. {
  953. HRESULT hr;
  954. // Read the AppleTalk\Parameters values
  955. RegReadValues(celems(regbatchATLKParams), regbatchATLKParams,
  956. (BYTE *)&m_Params, KEY_READ);
  957. // Read info for each adapter listed under AppleTalk\Parameters\Adapters
  958. hr = HrGetAdapterInfo();
  959. TraceError("CATLKEnv::HrReadAppleTalkInfo",hr);
  960. return hr;
  961. }
  962. //
  963. // Function: CATLKEnv::HrGetOneAdaptersInfo
  964. //
  965. // Purpose: Retrieve the AppleTalk Adapter information for one adapter
  966. //
  967. // Parameters:
  968. //
  969. // Returns: HRESULT, S_OK on success
  970. //
  971. HRESULT CATLKEnv::HrGetOneAdaptersInfo(INetCfgComponent* pncc,
  972. CAdapterInfo **ppAI)
  973. {
  974. HKEY hkeyAdapterRoot = NULL;
  975. HKEY hkeyAdapter = NULL;
  976. HRESULT hr;
  977. INT idx;
  978. CAdapterInfo * pAI = NULL;
  979. REGBATCH regbatch;
  980. tstring strKey;
  981. tstring strKeyPath = c_szATLKAdapters;
  982. *ppAI = NULL;
  983. // Construct the adapter info object
  984. pAI = new CAdapterInfo;
  985. if (pAI == NULL)
  986. {
  987. return(ERROR_NOT_ENOUGH_MEMORY);
  988. }
  989. // Get the adapter component info (media type, description, ...)
  990. hr = ::HrQueryAdapterComponentInfo(pncc, pAI);
  991. if (FAILED(hr))
  992. {
  993. goto Error;
  994. }
  995. hr = ::HrRegOpenKeyEx(HKEY_LOCAL_MACHINE, strKeyPath.c_str(),
  996. KEY_READ, &hkeyAdapterRoot);
  997. if (S_OK == hr)
  998. {
  999. strKey = pAI->SzBindName();
  1000. // Try to open the key for this specific adapter
  1001. hr = ::HrRegOpenKeyEx(hkeyAdapterRoot, pAI->SzBindName(),
  1002. KEY_READ, &hkeyAdapter);
  1003. if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr)
  1004. {
  1005. // We weren't able to find this in the registry, write it out
  1006. // when we can (self repair)
  1007. pAI->SetDirty(TRUE);
  1008. }
  1009. strKeyPath += c_szBackslash;
  1010. strKeyPath += strKey.c_str();
  1011. // If we located the key query the data
  1012. if (S_OK == hr)
  1013. {
  1014. hr = HrRegQueryColString(hkeyAdapter, c_szZoneList,
  1015. &pAI->LstpstrZoneList());
  1016. // Since CAdapterInfo defaults allocations, need to free
  1017. // them before RegReadValues writes over them and causes a leak.
  1018. //
  1019. delete [] pAI->m_AdapterInfo.m_szDefaultZone;
  1020. delete [] pAI->m_AdapterInfo.m_szPortName;
  1021. pAI->m_AdapterInfo.m_szDefaultZone = NULL;
  1022. pAI->m_AdapterInfo.m_szPortName = NULL;
  1023. // Read the adapter information
  1024. for (idx=0; idx<celems(regbatchATLKAdapters); idx++)
  1025. {
  1026. regbatch = regbatchATLKAdapters[idx];
  1027. regbatch.pszSubkey = strKeyPath.c_str();
  1028. RegReadValues(1, &regbatch, (BYTE *)pAI->PAdapterInfo(), KEY_READ);
  1029. }
  1030. }
  1031. }
  1032. if (FAILED(hr) && (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) != hr))
  1033. {
  1034. // Something other than a "not found" error
  1035. goto Error;
  1036. }
  1037. // Normalize return value
  1038. hr = S_OK;
  1039. // If the port name was not found then generate one
  1040. if (0 == wcslen(pAI->SzPortName()))
  1041. {
  1042. tstring str;
  1043. hr = ::HrPortNameFromAdapter(pncc, &str);
  1044. if (FAILED(hr))
  1045. {
  1046. goto Error;
  1047. }
  1048. pAI->SetPortName(str.c_str());
  1049. }
  1050. // Set the return value
  1051. *ppAI = pAI;
  1052. Done:
  1053. ::RegSafeCloseKey(hkeyAdapter);
  1054. ::RegSafeCloseKey(hkeyAdapterRoot);
  1055. return hr;
  1056. Error:
  1057. TraceError("CATLKEnv::HrGetOneAdaptersInfo",hr);
  1058. delete pAI;
  1059. goto Done;
  1060. }
  1061. //
  1062. // Function: CATLKEnv::HrGetAdapterInfo
  1063. //
  1064. // Purpose: Retrieve the AppleTalk Adapter information
  1065. //
  1066. // Parameters: none
  1067. //
  1068. // Returns: HRESULT, S_OK on success
  1069. //
  1070. HRESULT CATLKEnv::HrGetAdapterInfo()
  1071. {
  1072. HRESULT hr = S_OK;
  1073. CAdapterInfo * pAI = NULL;
  1074. INetCfgComponent* pncc = NULL;
  1075. INetCfgComponent* pnccUse = NULL;
  1076. // Find each netcard, to do so, trace the bindings to their end
  1077. // If the endpoint is a netcard then add it to the list
  1078. CIterNetCfgBindingPath ncbpIter(m_pmsc->PNCComponent());
  1079. INetCfgBindingPath* pncbp;
  1080. while (SUCCEEDED(hr) &&
  1081. (S_OK == (hr = ncbpIter.HrNext (&pncbp))))
  1082. {
  1083. // Iterate the binding interfaces of this path.
  1084. CIterNetCfgBindingInterface ncbiIter(pncbp);
  1085. INetCfgBindingInterface* pncbi;
  1086. while (SUCCEEDED(hr) &&
  1087. (S_OK == (hr = ncbiIter.HrNext (&pncbi))))
  1088. {
  1089. // Retrieve the lower component
  1090. hr = pncbi->GetLowerComponent(&pncc);
  1091. if (S_OK == hr)
  1092. {
  1093. GUID guidClass;
  1094. // Is it an Adapter?
  1095. hr = pncc->GetClassGuid(&guidClass);
  1096. if ((S_OK == hr) && (guidClass == GUID_DEVCLASS_NET))
  1097. {
  1098. ULONG ulStatus = 0;
  1099. hr = pncc->GetDeviceStatus(&ulStatus);
  1100. if(SUCCEEDED(hr))
  1101. {
  1102. ReleaseObj(pnccUse);
  1103. pnccUse = pncc;
  1104. pncc = NULL;
  1105. }
  1106. else
  1107. {
  1108. // Release the lower component
  1109. ReleaseObj(pncc);
  1110. hr = S_OK;
  1111. break;
  1112. }
  1113. }
  1114. else
  1115. {
  1116. // Release the lower component
  1117. ReleaseObj(pncc);
  1118. }
  1119. }
  1120. // Release the binding interface
  1121. ReleaseObj (pncbi);
  1122. }
  1123. if (NULL != pnccUse)
  1124. {
  1125. // Query the Adapter information
  1126. hr = HrGetOneAdaptersInfo(pnccUse, &pAI);
  1127. if (SUCCEEDED(hr))
  1128. {
  1129. if (S_FALSE == pncbp->IsEnabled())
  1130. {
  1131. pAI->SetDisabled(TRUE);
  1132. }
  1133. // Add this Adapter to the list
  1134. m_lstpAdapters.push_back(pAI);
  1135. }
  1136. ReleaseObj(pnccUse);
  1137. pnccUse = NULL;
  1138. }
  1139. // Release the binding path
  1140. ReleaseObj (pncbp);
  1141. }
  1142. if (FAILED(hr))
  1143. {
  1144. goto Error;
  1145. }
  1146. // Initialize the default port, etc
  1147. InitDefaultPort();
  1148. // Normalize the HRESULT. (i.e. don't return S_FALSE)
  1149. hr = S_OK;
  1150. Error:
  1151. TraceError("CATLKEnv::HrGetAdapterInfo",hr);
  1152. return hr;
  1153. }
  1154. //
  1155. // Function: CATLKEnv::HrGetAppleTalkInfoFromNetwork
  1156. //
  1157. // Purpose: ???
  1158. //
  1159. // Parameters: none
  1160. //
  1161. // Returns: HRESULT, S_OK on success
  1162. //
  1163. HRESULT CATLKEnv::HrGetAppleTalkInfoFromNetwork(CAdapterInfo * pAI)
  1164. {
  1165. SOCKADDR_AT address;
  1166. HRESULT hr = S_FALSE;
  1167. BOOL fWSInitialized = FALSE;
  1168. SOCKET mysocket = INVALID_SOCKET;
  1169. WSADATA wsadata;
  1170. DWORD wsaerr = 0;
  1171. tstring strPortName;
  1172. // Create the socket/bind
  1173. wsaerr = WSAStartup(0x0101, &wsadata);
  1174. if (0 != wsaerr)
  1175. {
  1176. goto Error;
  1177. }
  1178. // Winsock successfully initialized
  1179. fWSInitialized = TRUE;
  1180. mysocket = socket(AF_APPLETALK, SOCK_DGRAM, DDPPROTO_ZIP);
  1181. if (INVALID_SOCKET == mysocket)
  1182. {
  1183. goto Error;
  1184. }
  1185. address.sat_family = AF_APPLETALK;
  1186. address.sat_net = 0;
  1187. address.sat_node = 0;
  1188. address.sat_socket = 0;
  1189. wsaerr = bind(mysocket, (struct sockaddr *)&address, sizeof(address));
  1190. if (wsaerr != 0)
  1191. {
  1192. goto Error;
  1193. }
  1194. // Mark AppleTalk as running
  1195. SetATLKRunning(TRUE);
  1196. // For each known adapter, create a device name by merging the "\\device\\"
  1197. // prefix and the adapter's bind name.
  1198. strPortName = c_szDevice;
  1199. strPortName += pAI->SzBindName();
  1200. // Failures from query the zone list for a given adapter can be from
  1201. // the adapter not connected to the network, zone seeder not running, etc.
  1202. // Because we want to process all the adapters, we ignore these errors.
  1203. (void)pAI->HrGetAndSetNetworkInformation(mysocket,strPortName.c_str());
  1204. // Success, or at least not a critical failure
  1205. hr = S_OK;
  1206. Done:
  1207. if (INVALID_SOCKET != mysocket)
  1208. {
  1209. closesocket(mysocket);
  1210. }
  1211. if (fWSInitialized)
  1212. {
  1213. WSACleanup();
  1214. }
  1215. TraceError("CATLKEnv::HrGetAppleTalkInfoFromNetwork",(S_FALSE == hr ? S_OK : hr));
  1216. return hr;
  1217. Error:
  1218. wsaerr = ::WSAGetLastError();
  1219. goto Done;
  1220. }
  1221. //
  1222. // Function: CATLKEnv::HrAddAdapter
  1223. //
  1224. // Purpose: Add and adapter to the list of currently bound adapters
  1225. //
  1226. // Parameters: pnccFound - Notification object for the bound adapter to add
  1227. //
  1228. // Returns: HRESULT, S_OK on success
  1229. //
  1230. HRESULT CATLKEnv::HrAddAdapter(INetCfgComponent * pnccFound)
  1231. {
  1232. HRESULT hr;
  1233. CAdapterInfo * pAI = NULL;
  1234. Assert(NULL != pnccFound);
  1235. // Create an AdapterInfo instance for the adapter
  1236. hr = HrGetOneAdaptersInfo(pnccFound, &pAI);
  1237. if (FAILED(hr))
  1238. {
  1239. goto Error;
  1240. }
  1241. // Add this Adapter to the list
  1242. m_lstpAdapters.push_back(pAI);
  1243. pAI->SetDirty(TRUE);
  1244. // If there is now only one adapter in the list, update the defaults
  1245. if (1 == m_lstpAdapters.size())
  1246. {
  1247. tstring str;
  1248. str = c_szDevice;
  1249. str += m_lstpAdapters.front()->SzBindName();
  1250. SetDefaultPort(str.c_str());
  1251. SetDefaultMediaType(m_lstpAdapters.front()->DwMediaType());
  1252. }
  1253. Error:
  1254. TraceError("CATLKEnv::HrAddAdapter",hr);
  1255. return hr;
  1256. }
  1257. //
  1258. // Function: CATLKEnv::SetDefaultPort
  1259. //
  1260. // Purpose: Change the default port name
  1261. //
  1262. // Parameters: psz [in] - The new default port name
  1263. //
  1264. // Returns: HRESULT, S_OK on success
  1265. //
  1266. void CATLKEnv::SetDefaultPort(PCWSTR psz)
  1267. {
  1268. Assert(psz);
  1269. delete [] m_Params.szDefaultPort;
  1270. m_Params.szDefaultPort = new WCHAR[wcslen(psz)+1];
  1271. wcscpy(m_Params.szDefaultPort, psz);
  1272. }
  1273. //
  1274. // Function: CATLKEnv::SetDesiredZone
  1275. //
  1276. // Purpose: Change the desired zone
  1277. //
  1278. // Parameters: sz [in] - The new desired zone
  1279. //
  1280. // Returns: HRESULT, S_OK on success
  1281. //
  1282. void CATLKEnv::SetDesiredZone(PCWSTR psz)
  1283. {
  1284. Assert(psz);
  1285. delete [] m_Params.szDesiredZone;
  1286. m_Params.szDesiredZone = new WCHAR[wcslen(psz)+1];
  1287. wcscpy(m_Params.szDesiredZone, psz);
  1288. }
  1289. CAdapterInfo * CATLKEnv::PAIFindDefaultPort()
  1290. {
  1291. CAdapterInfo * pAI = NULL;
  1292. ATLK_ADAPTER_INFO_LIST::iterator iter;
  1293. // Find the default port
  1294. //
  1295. for (iter = m_lstpAdapters.begin();
  1296. iter != m_lstpAdapters.end();
  1297. iter++)
  1298. {
  1299. tstring strPortName;
  1300. pAI = *iter;
  1301. // Retain adapter selection as the default port
  1302. strPortName = c_szDevice;
  1303. strPortName += pAI->SzBindName();
  1304. if (pAI->FDeletePending() || pAI->FDisabled() || pAI->FHidden() ||
  1305. pAI->IsRasAdapter())
  1306. {
  1307. continue;
  1308. }
  1309. if (0 == _wcsicmp(SzDefaultPort(), strPortName.c_str()))
  1310. {
  1311. return pAI;
  1312. }
  1313. }
  1314. return NULL;
  1315. }
  1316. //
  1317. // Function: CATLKEnv::HrUpdateRegistry
  1318. //
  1319. // Purpose: Write the AppleTalk local (internal) data back to the registry
  1320. //
  1321. // Parameters: none
  1322. //
  1323. // Returns: HRESULT, S_OK on success
  1324. //
  1325. HRESULT CATLKEnv::HrUpdateRegistry()
  1326. {
  1327. HRESULT hr = S_OK;
  1328. CAdapterInfo * pAI = NULL;
  1329. HKEY hkeyAdapter;
  1330. DWORD dwDisposition;
  1331. ATLK_ADAPTER_INFO_LIST::iterator iter;
  1332. // If the current default port is unavailable, find an alternate
  1333. pAI = PAIFindDefaultPort();
  1334. if (NULL == pAI)
  1335. {
  1336. InitDefaultPort();
  1337. pAI = PAIFindDefaultPort();
  1338. }
  1339. // If the default adapter changed then three specific values for that
  1340. // adapter need to be reset to zero.
  1341. //
  1342. if (pAI && FDefAdapterChanged())
  1343. {
  1344. pAI->ZeroSpecialParams();
  1345. pAI->SetDirty(TRUE);
  1346. }
  1347. // Commit the registry changes
  1348. hr = ::HrRegWriteValues(celems(regbatchATLKParams), regbatchATLKParams,
  1349. (BYTE *)&m_Params, REG_OPTION_NON_VOLATILE,
  1350. KEY_ALL_ACCESS);
  1351. if (S_OK != hr)
  1352. {
  1353. goto Error;
  1354. }
  1355. // Create the Adapters key AppleTalk\Parameters\Adapters)
  1356. hr = HrRegCreateKeyEx(HKEY_LOCAL_MACHINE, c_szATLKAdapters,
  1357. REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL,
  1358. &hkeyAdapter, &dwDisposition);
  1359. if (S_OK == hr)
  1360. {
  1361. // Enumerate the bound adapters and write the internal adapter list
  1362. for (iter = m_lstpAdapters.begin();
  1363. (iter != m_lstpAdapters.end()) && (SUCCEEDED(hr));
  1364. iter++)
  1365. {
  1366. pAI = *iter;
  1367. if (pAI->FDeletePending())
  1368. {
  1369. // Remove the AppleTalk\Adapter\{bindname} tree
  1370. hr = ::HrRegDeleteKeyTree(hkeyAdapter, pAI->SzBindName());
  1371. if (FAILED(hr) && (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) != hr))
  1372. {
  1373. goto Error;
  1374. }
  1375. }
  1376. else if (pAI->IsDirty())
  1377. {
  1378. hr = HrWriteOneAdapter(pAI);
  1379. }
  1380. }
  1381. RegCloseKey (hkeyAdapter);
  1382. }
  1383. Error:
  1384. TraceError("CATLKEnv::HrUpdateRegistry",hr);
  1385. return hr;
  1386. }
  1387. //
  1388. // Function: CATLKEnv::HrWriteOneAdapter
  1389. //
  1390. // Purpose: Write one adapter instance to the registry
  1391. //
  1392. // Parameters: pAI [in] - The adapter to presist in the registry
  1393. //
  1394. // Returns: HRESULT, S_OK on success
  1395. //
  1396. HRESULT CATLKEnv::HrWriteOneAdapter(CAdapterInfo *pAI)
  1397. {
  1398. DWORD dwDisposition;
  1399. HKEY hkeyAdapter = NULL;
  1400. HRESULT hr;
  1401. INT idx;
  1402. REGBATCH regbatch;
  1403. tstring str;
  1404. str = c_szATLKAdapters;
  1405. str += c_szBackslash;
  1406. str += pAI->SzBindName();
  1407. // Create the key described in str (AppleTalk\Parameters\Adapters\<adapter>)
  1408. hr = ::HrRegCreateKeyEx(HKEY_LOCAL_MACHINE, str.c_str(),
  1409. REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL,
  1410. &hkeyAdapter, &dwDisposition);
  1411. if (FAILED(hr))
  1412. {
  1413. goto Error;
  1414. }
  1415. // Write out the adapter parameters
  1416. for (idx = 0; idx < celems(regbatchATLKAdapters); idx++)
  1417. {
  1418. regbatch = regbatchATLKAdapters[idx];
  1419. regbatch.pszSubkey = str.c_str();
  1420. hr = ::HrRegWriteValues(1, &regbatch, (BYTE *)pAI->PAdapterInfo(),
  1421. REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS);
  1422. if (FAILED(hr))
  1423. {
  1424. goto Error;
  1425. }
  1426. }
  1427. // Write out the zone list multi-sz (managed seperately)
  1428. hr = ::HrRegSetColString(hkeyAdapter, c_szZoneList, pAI->LstpstrZoneList());
  1429. Error:
  1430. ::RegSafeCloseKey(hkeyAdapter);
  1431. TraceError("CATLKEnv::HrWriteOneAdapter",hr);
  1432. return S_OK;
  1433. }
  1434. //
  1435. // Function: CATLKEnv::DwMediaPriority
  1436. //
  1437. // Purpose: When determining the appropriate adapter for use as the
  1438. // "DefaultPort" certain mediatype's are faster. So all
  1439. // other things being equal, selecting a faster mediatype
  1440. // benefits the user the most.
  1441. //
  1442. // Parameters: dwMediaType [in] - MediaType used to determine priority ranking
  1443. //
  1444. // Returns: DWORD, value (1-5) with the lowest value representing the
  1445. // highest priority.
  1446. //
  1447. DWORD CATLKEnv::DwMediaPriority(DWORD dwMediaType)
  1448. {
  1449. switch(dwMediaType)
  1450. {
  1451. case MEDIATYPE_ETHERNET:
  1452. return 2;
  1453. case MEDIATYPE_TOKENRING:
  1454. return 3;
  1455. case MEDIATYPE_FDDI:
  1456. return 1;
  1457. case MEDIATYPE_LOCALTALK:
  1458. return 4;
  1459. default:
  1460. return 5;
  1461. }
  1462. }
  1463. //
  1464. // Function: CATLKEnv::InitDefaultPort
  1465. //
  1466. // Purpose: Select a default port if none yet has been selected. Retain
  1467. // some select information for assisting in dialog display issues.
  1468. //
  1469. // Parameters: none
  1470. //
  1471. // Returns: nothing
  1472. //
  1473. void CATLKEnv::InitDefaultPort()
  1474. {
  1475. CAdapterInfo * pAI = NULL;
  1476. tstring str;
  1477. ATLK_ADAPTER_INFO_LIST::iterator iter;
  1478. // If DefaultPort is set, does the associated adapter exist?
  1479. if (wcslen(SzDefaultPort()))
  1480. {
  1481. // Search for the adapter in the list
  1482. for (iter = AdapterInfoList().begin();
  1483. iter != AdapterInfoList().end();
  1484. iter++)
  1485. {
  1486. pAI = *iter;
  1487. if (pAI->FDeletePending() || pAI->FDisabled() || pAI->FHidden() ||
  1488. pAI->IsRasAdapter())
  1489. {
  1490. pAI = NULL;
  1491. continue;
  1492. }
  1493. str = c_szDevice;
  1494. str += pAI->SzBindName();
  1495. if (0 == wcscmp(str.c_str(), SzDefaultPort()))
  1496. {
  1497. break;
  1498. }
  1499. pAI = NULL;
  1500. }
  1501. }
  1502. // If DefaultPort is not set locate the best candidate
  1503. if (NULL == pAI)
  1504. {
  1505. CAdapterInfo * pAIBest = NULL;
  1506. SetDefaultPort(c_szEmpty);
  1507. // Search through the adapter list for the adapter
  1508. // with the fastest media type.
  1509. for (iter = AdapterInfoList().begin();
  1510. iter != AdapterInfoList().end();
  1511. iter++)
  1512. {
  1513. pAI = *iter;
  1514. if (pAI->FDeletePending() || pAI->FDisabled() || pAI->FHidden() ||
  1515. pAI->IsRasAdapter())
  1516. {
  1517. continue;
  1518. }
  1519. if ((NULL == pAIBest) ||
  1520. (DwMediaPriority(pAIBest->DwMediaType()) >
  1521. DwMediaPriority(pAI->DwMediaType())))
  1522. {
  1523. SetDefAdapterChanged(TRUE);
  1524. pAIBest = pAI;
  1525. }
  1526. }
  1527. pAI = pAIBest;
  1528. }
  1529. if (NULL != pAI)
  1530. {
  1531. // retain the selected adapter as the default port
  1532. str = c_szDevice;
  1533. str += pAI->SzBindName();
  1534. SetDefaultPort(str.c_str());
  1535. // retain the default media type
  1536. SetDefaultMediaType(pAI->DwMediaType());
  1537. }
  1538. else
  1539. {
  1540. SetDefaultPort(c_szEmpty);
  1541. }
  1542. }
  1543. //
  1544. // Function: CAdapterInfo::CAdapterInfo
  1545. //
  1546. // Purpose: ctor for the CAdapters class
  1547. //
  1548. // Parameters: none
  1549. //
  1550. // Returns: nothing
  1551. //
  1552. CAdapterInfo::CAdapterInfo() :
  1553. m_fDeletePending(FALSE),
  1554. m_fDisabled(FALSE),
  1555. m_fDirty(FALSE),
  1556. m_fRasAdapter(FALSE),
  1557. m_fRouterOnNetwork(FALSE),
  1558. m_fZoneListValid(FALSE),
  1559. m_dwNetworkUpper(0),
  1560. m_dwNetworkLower(0),
  1561. m_dwCharacteristics(0)
  1562. {
  1563. ZeroMemory(&m_guidInstance, sizeof(m_guidInstance));
  1564. // Initialize the AdapterInfo default values
  1565. ZeroMemory(&m_AdapterInfo, sizeof(m_AdapterInfo));
  1566. m_AdapterInfo.m_dwAarpRetries = c_dwTen;
  1567. m_AdapterInfo.m_dwMediaType = MEDIATYPE_ETHERNET;
  1568. SetDefaultZone(c_szEmpty);
  1569. SetPortName(c_szEmpty);
  1570. }
  1571. //
  1572. // Function: CAdapterInfo::~CAdapterInfo
  1573. //
  1574. // Purpose: ctor for the CAdapters class
  1575. //
  1576. // Parameters: none
  1577. //
  1578. // Returns: nothing
  1579. //
  1580. CAdapterInfo::~CAdapterInfo()
  1581. {
  1582. // Cleanup the AppleTalk\Adapters\<adapter> internal data structure
  1583. delete [] m_AdapterInfo.m_szDefaultZone;
  1584. delete [] m_AdapterInfo.m_szPortName;
  1585. DeleteColString(&m_lstpstrDesiredZoneList);
  1586. DeleteColString(&m_lstpstrZoneList);
  1587. }
  1588. //
  1589. // Function: CAdapterInfo::SetDefaultZone
  1590. //
  1591. // Purpose: Set the default zone for this adapter
  1592. //
  1593. // Parameters: sz - The new default zone
  1594. //
  1595. // Returns: nothing
  1596. //
  1597. void CAdapterInfo::SetDefaultZone(PCWSTR psz)
  1598. {
  1599. Assert(psz);
  1600. delete [] m_AdapterInfo.m_szDefaultZone;
  1601. m_AdapterInfo.m_szDefaultZone = NULL;
  1602. m_AdapterInfo.m_szDefaultZone = new WCHAR[wcslen(psz)+1];
  1603. wcscpy(m_AdapterInfo.m_szDefaultZone, psz);
  1604. }
  1605. //
  1606. // Function: CAdapterInfo::SetPortName
  1607. //
  1608. // Purpose: Set the port name for this adapter
  1609. //
  1610. // Parameters: sz - The new port name
  1611. //
  1612. // Returns: nothing
  1613. //
  1614. void CAdapterInfo::SetPortName(PCWSTR psz)
  1615. {
  1616. Assert(psz);
  1617. delete [] m_AdapterInfo.m_szPortName;
  1618. m_AdapterInfo.m_szPortName = NULL;
  1619. m_AdapterInfo.m_szPortName = new WCHAR[wcslen(psz)+1];
  1620. wcscpy(m_AdapterInfo.m_szPortName, psz);
  1621. }
  1622. //
  1623. // Function: CAdapterInfo::HrGetAndSetNetworkInformation
  1624. //
  1625. // Purpose:
  1626. //
  1627. // Parameters:
  1628. //
  1629. // Returns: HRESULT, S_OK on success
  1630. //
  1631. #define PARM_BUF_LEN 512
  1632. #define ASTERISK_CHAR "*"
  1633. HRESULT
  1634. CAdapterInfo::HrGetAndSetNetworkInformation (
  1635. SOCKET socket,
  1636. PCWSTR pszDevName)
  1637. {
  1638. HRESULT hr = FALSE;
  1639. CHAR *pZoneBuffer = NULL;
  1640. CHAR *pDefParmsBuffer = NULL;
  1641. CHAR *pZoneListStart;
  1642. INT BytesNeeded ;
  1643. WCHAR *pwDefZone = NULL;
  1644. tstring strTmpZone;
  1645. INT ZoneLen = 0;
  1646. DWORD wsaerr = 0;
  1647. CHAR *pDefZone = NULL;
  1648. PWSH_LOOKUP_ZONES pGetNetZones;
  1649. PWSH_LOOKUP_NETDEF_ON_ADAPTER pGetNetDefaults;
  1650. Assert(pszDevName);
  1651. pZoneBuffer = new CHAR [ZONEBUFFER_LEN + sizeof(WSH_LOOKUP_ZONES)];
  1652. Assert(pZoneBuffer);
  1653. if (pZoneBuffer == NULL)
  1654. {
  1655. return(ERROR_NOT_ENOUGH_MEMORY);
  1656. }
  1657. pGetNetZones = (PWSH_LOOKUP_ZONES)pZoneBuffer;
  1658. wcscpy((WCHAR *)(pGetNetZones+1), pszDevName);
  1659. BytesNeeded = ZONEBUFFER_LEN;
  1660. wsaerr = getsockopt(socket, SOL_APPLETALK, SO_LOOKUP_ZONES_ON_ADAPTER,
  1661. (char *)pZoneBuffer, &BytesNeeded);
  1662. if (0 != wsaerr)
  1663. {
  1664. //$ REVIEW - error mapping
  1665. #ifdef DBG
  1666. DWORD dwErr = WSAGetLastError();
  1667. TraceTag(ttidError, "CAdapterInfo::HrGetAndSetNetworkInformation getsocketopt returned: %08X",dwErr);
  1668. #endif
  1669. hr = E_UNEXPECTED;
  1670. goto Error;
  1671. }
  1672. pZoneListStart = pZoneBuffer + sizeof(WSH_LOOKUP_ZONES);
  1673. if (!lstrcmpA(pZoneListStart, ASTERISK_CHAR))
  1674. {
  1675. // Success, wildcard zone set.
  1676. goto Done;
  1677. }
  1678. hr = HrConvertZoneListAndAddToPortInfo(pZoneListStart,
  1679. ((PWSH_LOOKUP_ZONES)pZoneBuffer)->NoZones);
  1680. if (FAILED(hr))
  1681. {
  1682. goto Error;
  1683. }
  1684. SetRouterOnNetwork(TRUE);
  1685. //
  1686. // Get the DefaultZone/NetworkRange Information
  1687. pDefParmsBuffer = new CHAR[PARM_BUF_LEN+sizeof(WSH_LOOKUP_NETDEF_ON_ADAPTER)];
  1688. Assert(pDefParmsBuffer);
  1689. if (pDefParmsBuffer == NULL)
  1690. {
  1691. return(ERROR_NOT_ENOUGH_MEMORY);
  1692. }
  1693. pGetNetDefaults = (PWSH_LOOKUP_NETDEF_ON_ADAPTER)pDefParmsBuffer;
  1694. BytesNeeded = PARM_BUF_LEN + sizeof(WSH_LOOKUP_NETDEF_ON_ADAPTER);
  1695. wcscpy((WCHAR*)(pGetNetDefaults+1), pszDevName);
  1696. pGetNetDefaults->NetworkRangeLowerEnd = pGetNetDefaults->NetworkRangeUpperEnd = 0;
  1697. wsaerr = getsockopt(socket, SOL_APPLETALK, SO_LOOKUP_NETDEF_ON_ADAPTER,
  1698. (char*)pDefParmsBuffer, &BytesNeeded);
  1699. if (0 != wsaerr)
  1700. {
  1701. #ifdef DBG
  1702. DWORD dwErr = WSAGetLastError();
  1703. #endif
  1704. hr = E_UNEXPECTED;
  1705. goto Error;
  1706. }
  1707. // Save the default information to PORT_INFO
  1708. SetExistingNetRange(pGetNetDefaults->NetworkRangeLowerEnd,
  1709. pGetNetDefaults->NetworkRangeUpperEnd);
  1710. pDefZone = pDefParmsBuffer + sizeof(WSH_LOOKUP_NETDEF_ON_ADAPTER);
  1711. ZoneLen = lstrlenA(pDefZone) + 1;
  1712. pwDefZone = new WCHAR [sizeof(WCHAR) * ZoneLen];
  1713. Assert(NULL != pwDefZone);
  1714. if (pwDefZone == NULL)
  1715. {
  1716. return(ERROR_NOT_ENOUGH_MEMORY);
  1717. }
  1718. mbstowcs(pwDefZone, pDefZone, ZoneLen);
  1719. strTmpZone = pwDefZone;
  1720. SetNetDefaultZone(strTmpZone.c_str());
  1721. if (pZoneBuffer != NULL)
  1722. {
  1723. delete [] pZoneBuffer;
  1724. }
  1725. if (pwDefZone != NULL)
  1726. {
  1727. delete [] pwDefZone;
  1728. }
  1729. if (pDefParmsBuffer != NULL)
  1730. {
  1731. delete [] pDefParmsBuffer;
  1732. }
  1733. Done:
  1734. Error:
  1735. TraceError("CAdapterInfo::HrGetAndSetNetworkInformation",hr);
  1736. return hr;
  1737. }
  1738. //
  1739. // Function: CAdapterInfo::HrConvertZoneListAndAddToPortInfo
  1740. //
  1741. // Purpose:
  1742. //
  1743. // Parameters:
  1744. //
  1745. // Returns: HRESULT, S_OK on success
  1746. //
  1747. HRESULT CAdapterInfo::HrConvertZoneListAndAddToPortInfo(CHAR * szZoneList, ULONG NumZones)
  1748. {
  1749. INT cbAscii = 0;
  1750. WCHAR *pszZone = NULL;
  1751. tstring *pstr;
  1752. Assert(NULL != szZoneList);
  1753. DeleteColString(&m_lstpstrDesiredZoneList);
  1754. while(NumZones--)
  1755. {
  1756. cbAscii = lstrlenA(szZoneList) + 1;
  1757. pszZone = new WCHAR [sizeof(WCHAR) * cbAscii];
  1758. Assert(NULL != pszZone);
  1759. if (pszZone == NULL)
  1760. {
  1761. return(ERROR_NOT_ENOUGH_MEMORY);
  1762. }
  1763. mbstowcs(pszZone, szZoneList, cbAscii);
  1764. pstr = new tstring(pszZone);
  1765. Assert(NULL != pstr);
  1766. m_lstpstrDesiredZoneList.push_back(pstr);
  1767. szZoneList += cbAscii;
  1768. delete [] pszZone;
  1769. }
  1770. return S_OK;
  1771. }
  1772. //
  1773. // Function: CAdapterInfo::HrCopy
  1774. //
  1775. // Purpose: Create a duplicate copy of 'this'
  1776. //
  1777. // Parameters: ppAI [out] - if the function succeeds, ppAI will contain the
  1778. // copy of 'this'.
  1779. //
  1780. // Returns: HRESULT, S_OK on success
  1781. //
  1782. HRESULT CAdapterInfo::HrCopy(CAdapterInfo ** ppAI)
  1783. {
  1784. CAdapterInfo *pAI;
  1785. list<tstring*>::iterator iter;
  1786. tstring * pstr;
  1787. Assert(NULL != ppAI);
  1788. // Create an adapter info structure
  1789. pAI = new CAdapterInfo;
  1790. Assert(pAI);
  1791. if (pAI == NULL)
  1792. {
  1793. return(ERROR_NOT_ENOUGH_MEMORY);
  1794. }
  1795. // Make a copy of everything
  1796. pAI->SetDisabled(FDisabled());
  1797. pAI->SetDeletePending(FDeletePending());
  1798. pAI->SetCharacteristics(GetCharacteristics());
  1799. pAI->SetMediaType(DwMediaType());
  1800. pAI->SetBindName(SzBindName());
  1801. pAI->SetDisplayName(SzDisplayName());
  1802. pAI->SetNetDefaultZone(SzNetDefaultZone());
  1803. pAI->SetRouterOnNetwork(FRouterOnNetwork());
  1804. pAI->SetExistingNetRange(DwQueryNetworkLower(), DwQueryNetworkUpper());
  1805. pAI->SetDirty(IsDirty());
  1806. pAI->SetRasAdapter(IsRasAdapter());
  1807. // Free the default data set by the constructor before overwriting it.
  1808. // (this whole thing is not a very good approach.)
  1809. //
  1810. delete [] pAI->m_AdapterInfo.m_szDefaultZone;
  1811. delete [] pAI->m_AdapterInfo.m_szPortName;
  1812. pAI->m_AdapterInfo = m_AdapterInfo;
  1813. // Cleanup the 'allocated' data cause by the bit copy
  1814. // so that SetDefaultZone and SetPortName don't try to free bogus
  1815. // stuff. (more "programming by side-affect")
  1816. //
  1817. pAI->m_AdapterInfo.m_szDefaultZone = NULL;
  1818. pAI->m_AdapterInfo.m_szPortName = NULL;
  1819. // Now copy the 'allocated' data
  1820. pAI->SetDefaultZone(SzDefaultZone());
  1821. pAI->SetPortName(SzPortName());
  1822. for (iter = LstpstrZoneList().begin();
  1823. iter != LstpstrZoneList().end();
  1824. iter++)
  1825. {
  1826. pstr = *iter;
  1827. pAI->LstpstrZoneList().push_back(new tstring(pstr->c_str()));
  1828. }
  1829. for (iter = LstpstrDesiredZoneList().begin();
  1830. iter != LstpstrDesiredZoneList().end();
  1831. iter++)
  1832. {
  1833. pstr = *iter;
  1834. pAI->LstpstrDesiredZoneList().push_back(new tstring(pstr->c_str()));
  1835. }
  1836. *ppAI = pAI;
  1837. return S_OK;
  1838. }
  1839. //
  1840. // Function: HrQueryAdapterComponentInfo
  1841. //
  1842. // Purpose: Fill out an CAdapterInfo instance with the data retrieved
  1843. // specifically from the component itself.
  1844. //
  1845. // Parameters: pncc [in] - The component object (adapter) to query
  1846. // pAI [in/out] - Where to place the queried info
  1847. //
  1848. // Returns: HRESULT, S_OK on success
  1849. //
  1850. HRESULT HrQueryAdapterComponentInfo(INetCfgComponent *pncc,
  1851. CAdapterInfo * pAI)
  1852. {
  1853. PWSTR psz = NULL;
  1854. DWORD dwCharacteristics;
  1855. HRESULT hr;
  1856. Assert(NULL != pncc);
  1857. Assert(NULL != pAI);
  1858. // Retrieve the component's name
  1859. hr = pncc->GetBindName(&psz);
  1860. if (FAILED(hr))
  1861. {
  1862. goto Error;
  1863. }
  1864. Assert(psz && *psz);
  1865. pAI->SetBindName(psz);
  1866. CoTaskMemFree(psz);
  1867. psz = NULL;
  1868. hr = pncc->GetInstanceGuid(pAI->PInstanceGuid());
  1869. if (FAILED(hr))
  1870. {
  1871. goto Error;
  1872. }
  1873. // Get the Adapter's display name
  1874. hr = pncc->GetDisplayName(&psz);
  1875. if (FAILED(hr))
  1876. {
  1877. goto Error;
  1878. }
  1879. Assert(psz);
  1880. pAI->SetDisplayName(psz);
  1881. CoTaskMemFree(psz);
  1882. psz = NULL;
  1883. // Get the Component ID so we can check if this is a RAS adapter
  1884. //
  1885. hr = pncc->GetId(&psz);
  1886. if (FAILED(hr))
  1887. {
  1888. goto Error;
  1889. }
  1890. Assert(psz && *psz);
  1891. pAI->SetRasAdapter(0 == _wcsicmp(c_szInfId_MS_NdisWanAtalk, psz));
  1892. CoTaskMemFree(psz);
  1893. psz = NULL;
  1894. // Failure is non-fatal
  1895. hr = pncc->GetCharacteristics(&dwCharacteristics);
  1896. if (SUCCEEDED(hr))
  1897. {
  1898. pAI->SetCharacteristics(dwCharacteristics);
  1899. }
  1900. // Get the media type (Optional key)
  1901. {
  1902. DWORD dwMediaType = MEDIATYPE_ETHERNET ;
  1903. INetCfgComponentBindings* pnccBindings = NULL;
  1904. hr = pncc->QueryInterface(IID_INetCfgComponentBindings,
  1905. reinterpret_cast<void**>(&pnccBindings));
  1906. if (S_OK == hr)
  1907. {
  1908. static const struct
  1909. {
  1910. PCWSTR pszInterface;
  1911. DWORD dwInterface;
  1912. DWORD dwFlags;
  1913. } InterfaceMap[] = {{L"ethernet", MEDIATYPE_ETHERNET, NCF_LOWER},
  1914. {L"tokenring", MEDIATYPE_TOKENRING, NCF_LOWER},
  1915. {L"fddi", MEDIATYPE_FDDI, NCF_LOWER},
  1916. {L"localtalk", MEDIATYPE_LOCALTALK, NCF_LOWER},
  1917. {L"wan", MEDIATYPE_WAN, NCF_LOWER}};
  1918. for (UINT nIdx=0; nIdx < celems(InterfaceMap); nIdx++)
  1919. {
  1920. hr = pnccBindings->SupportsBindingInterface(InterfaceMap[nIdx].dwFlags,
  1921. InterfaceMap[nIdx].pszInterface);
  1922. if (S_OK == hr)
  1923. {
  1924. dwMediaType = InterfaceMap[nIdx].dwInterface;
  1925. break;
  1926. }
  1927. }
  1928. ::ReleaseObj(pnccBindings);
  1929. }
  1930. pAI->SetMediaType(dwMediaType);
  1931. hr = S_OK;
  1932. }
  1933. Error:
  1934. TraceError("HrQueryAdapterComponentInfo",hr);
  1935. return hr;
  1936. }
  1937. //
  1938. // Function: HrPortNameFromAdapter
  1939. //
  1940. // Purpose: Create a port name, for use as an adapters PortName
  1941. //
  1942. // Parameters: pncc [in] - The component object (adapter) to query
  1943. // pstr [in/out] - On success will contain the PortName
  1944. //
  1945. // Returns: HRESULT, S_OK on success
  1946. //
  1947. HRESULT HrPortNameFromAdapter(INetCfgComponent *pncc, tstring * pstr)
  1948. {
  1949. HRESULT hr;
  1950. PWSTR psz;
  1951. PWSTR pszBindName = NULL;
  1952. WCHAR szComputerName[MAX_COMPUTERNAME_LENGTH + 1];
  1953. DWORD dwSize = sizeof(szComputerName) / sizeof(WCHAR);
  1954. Assert(NULL != pstr);
  1955. Assert(NULL != pncc);
  1956. if (!GetComputerName(szComputerName, &dwSize))
  1957. {
  1958. hr = ::HrFromLastWin32Error();
  1959. goto Error;
  1960. }
  1961. hr = pncc->GetBindName(&pszBindName);
  1962. if (FAILED(hr))
  1963. {
  1964. goto Error;
  1965. }
  1966. // Replace the instances of '-' and '{' with '0' so the constructed
  1967. // portname is of the form [a-zA-Z0-9]*@<Computer Name> and is less
  1968. // than MAX_ZONE_NAME_LEN long.
  1969. psz = pszBindName;
  1970. while (*psz)
  1971. {
  1972. if ((*psz == L'-') || (*psz == L'{'))
  1973. {
  1974. *psz = L'0';
  1975. }
  1976. psz++;
  1977. }
  1978. *pstr = pszBindName;
  1979. if (pstr->size() + 1 + dwSize > MAX_ZONE_NAME_LEN)
  1980. {
  1981. pstr->resize(MAX_ZONE_NAME_LEN - (dwSize + 1));
  1982. }
  1983. *pstr += c_chAt;
  1984. *pstr += szComputerName;
  1985. Assert( MAX_ZONE_NAME_LEN >= pstr->size());
  1986. Error:
  1987. CoTaskMemFree(pszBindName);
  1988. TraceError("HrPortNameFromAdapter",hr);
  1989. return hr;
  1990. }
  1991. HRESULT CATlkObj::HrAtlkReconfig()
  1992. {
  1993. CServiceManager csm;
  1994. CService svr;
  1995. HRESULT hr = S_OK;
  1996. HRESULT hrRet;
  1997. BOOL fDirty = FALSE;
  1998. CAdapterInfo * pAI;
  1999. CAdapterInfo * pAIDefault = NULL;
  2000. ATLK_ADAPTER_INFO_LIST::iterator iter;
  2001. ATALK_PNP_EVENT Config;
  2002. if (m_pATLKEnv->AdapterInfoList().empty())
  2003. {
  2004. return hr;
  2005. }
  2006. ZeroMemory(&Config, sizeof(Config));
  2007. // If routing changed notify appletalk and return. No need to do the
  2008. // per adapter notifications.
  2009. if (m_pATLKEnv->FRouterChanged())
  2010. {
  2011. // notify atlk
  2012. Config.PnpMessage = AT_PNP_SWITCH_ROUTING;
  2013. hrRet = HrSendNdisPnpReconfig(NDIS, c_szAtlk, c_szEmpty,
  2014. &Config, sizeof(ATALK_PNP_EVENT));
  2015. if (FAILED(hrRet) &&
  2016. (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) != hrRet))
  2017. {
  2018. hr = NETCFG_S_REBOOT;
  2019. }
  2020. m_pATLKEnv->SetRouterChanged(FALSE);
  2021. return hr;
  2022. }
  2023. // Find the default adapter and also if any adapter's have changed
  2024. for (iter = m_pATLKEnv->AdapterInfoList().begin();
  2025. iter != m_pATLKEnv->AdapterInfoList().end();
  2026. iter++)
  2027. {
  2028. pAI = *iter;
  2029. tstring strPortName = c_szDevice;
  2030. strPortName += pAI->SzBindName();
  2031. if (pAI->FDeletePending() || pAI->FDisabled())
  2032. {
  2033. continue;
  2034. }
  2035. // Locate the default port
  2036. if (0 == _wcsicmp(strPortName.c_str(), m_pATLKEnv->SzDefaultPort()))
  2037. {
  2038. pAIDefault = pAI;
  2039. }
  2040. if (pAI->IsDirty())
  2041. {
  2042. fDirty = TRUE;
  2043. }
  2044. }
  2045. if ((NULL != pAIDefault) && m_pATLKEnv->FDefAdapterChanged())
  2046. {
  2047. // notify atlk
  2048. Config.PnpMessage = AT_PNP_SWITCH_DEFAULT_ADAPTER;
  2049. hrRet = HrSendNdisPnpReconfig(NDIS, c_szAtlk, NULL,
  2050. &Config, sizeof(ATALK_PNP_EVENT));
  2051. if (FAILED(hrRet) &&
  2052. (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) != hrRet))
  2053. {
  2054. hr = NETCFG_S_REBOOT;
  2055. }
  2056. // Clear the dirty state
  2057. m_pATLKEnv->SetDefAdapterChanged(FALSE);
  2058. pAIDefault->SetDirty(FALSE);
  2059. }
  2060. Config.PnpMessage = AT_PNP_RECONFIGURE_PARMS;
  2061. for (iter = m_pATLKEnv->AdapterInfoList().begin();
  2062. iter != m_pATLKEnv->AdapterInfoList().end();
  2063. iter++)
  2064. {
  2065. pAI = *iter;
  2066. if (pAI->FDeletePending() || pAI->FDisabled())
  2067. {
  2068. continue;
  2069. }
  2070. if (pAI->IsDirty())
  2071. {
  2072. // Now submit the reconfig notification
  2073. hrRet = HrSendNdisPnpReconfig(NDIS, c_szAtlk, pAI->SzBindName(),
  2074. &Config, sizeof(ATALK_PNP_EVENT));
  2075. if (FAILED(hrRet) &&
  2076. (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) != hrRet))
  2077. {
  2078. hr = NETCFG_S_REBOOT;
  2079. }
  2080. // Clear the dirty state
  2081. pAI->SetDirty(FALSE);
  2082. }
  2083. }
  2084. TraceError("CATLKObj::HrAtlkReconfig",hr);
  2085. return hr;
  2086. }