Leaked source code of windows server 2003
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.

1667 lines
49 KiB

  1. // nwlnkipx.cpp : Implementation of CNwlnkIPX
  2. #include "pch.h"
  3. #pragma hdrstop
  4. #include <ncxbase.h>
  5. #include <netconp.h>
  6. #include "ncmisc.h"
  7. #include "ncnetcfg.h"
  8. #include "ncpnp.h"
  9. #include "ncreg.h"
  10. #include "nwlnkipx.h"
  11. extern const WCHAR c_szAdapterSections[];
  12. extern const WCHAR c_szAdapters[];
  13. extern const WCHAR c_szSpecificTo[];
  14. extern const WCHAR c_szSvcNwlnkIpx[];
  15. extern const WCHAR c_szInfId_MS_NWNB[];
  16. extern const WCHAR c_szInfId_MS_NWSPX[];
  17. static const WCHAR c_szProviderOrderVal[] = L"ProviderOrder";
  18. static const WCHAR c_szSrvProvOrderKey[] = L"System\\CurrentControlSet\\Control\\ServiceProvider\\Order";
  19. const WCHAR c_sz0xPrefix[] = L"0x";
  20. const WCHAR c_sz8Zeros[] = L"00000000";
  21. const DWORD c_dwPktTypeDefault = AUTO;
  22. const WCHAR c_szMediaType[] = L"MediaType";
  23. static const WCHAR c_szIpxParameters[] = L"System\\CurrentControlSet\\Services\\NwlnkIpx\\Parameters";
  24. static const WCHAR c_szPktType[] = L"PktType";
  25. static const WCHAR c_szNetworkNumber[] = L"NetworkNumber";
  26. static const WCHAR c_szDedicatedRouter[] = L"DedicatedRouter";
  27. static const WCHAR c_szEnableWANRouter[] = L"EnableWANRouter";
  28. static const WCHAR c_szInitDatagrams[] = L"InitDatagrams";
  29. static const WCHAR c_szMaxDatagrams[] = L"MaxDatagrams";
  30. static const WCHAR c_szReplaceConfigDialog[] = L"ReplaceConfigDialog";
  31. static const WCHAR c_szRipCount[] = L"RipCount";
  32. static const WCHAR c_szRipTimeout[] = L"RipTimeout";
  33. static const WCHAR c_szRipUsageTime[] = L"RipUsageTime";
  34. static const WCHAR c_szSocketEnd[] = L"SocketEnd";
  35. static const WCHAR c_szSocketStart[] = L"SocketStart";
  36. static const WCHAR c_szSocketUniqueness[] = L"SocketUniqueness";
  37. static const WCHAR c_szSourceRouteUsageTime[]= L"SourceRouteUsageTime";
  38. static const WCHAR c_szVirtualNetworkNumber[]= L"VirtualNetworkNumber";
  39. static const DWORD c_dwBindSap = 0x8137;
  40. static const DWORD c_dwEnableFuncaddr = 1;
  41. static const DWORD c_dwMaxPktSize = 0;
  42. static const DWORD c_dwSourceRouteBCast = 0;
  43. static const DWORD c_dwSourceRouteMCast = 0;
  44. static const DWORD c_dwSourceRouteDef = 0;
  45. static const DWORD c_dwSourceRouting = 1;
  46. static const WCHAR c_szBindSap[] = L"BindSap";
  47. static const WCHAR c_szEnableFuncaddr[] = L"EnableFuncaddr";
  48. static const WCHAR c_szMaxPktSize[] = L"MaxPktSize";
  49. static const WCHAR c_szSourceRouteBCast[] = L"SourceRouteBCast";
  50. static const WCHAR c_szSourceRouteMCast[] = L"SourceRouteMCast";
  51. static const WCHAR c_szSourceRouteDef[] = L"SourceRouteDef";
  52. static const WCHAR c_szSourceRouting[] = L"SourceRouting";
  53. static const DWORD c_dwDedicatedRouter = 0;
  54. static const DWORD c_dwEnableWANRouter = 0;
  55. static const DWORD c_dwInitDatagrams = 0xa;
  56. static const DWORD c_dwMaxDatagrams = 0x32;
  57. static const DWORD c_dwReplaceConfigDialog = 0;
  58. static const DWORD c_dwRipCount = 0x5;
  59. static const DWORD c_dwRipTimeout = 0x1;
  60. static const DWORD c_dwRipUsageTime = 0xf;
  61. static const DWORD c_dwSocketEnd = 0x5fff;
  62. static const DWORD c_dwSocketStart = 0x4000;
  63. static const DWORD c_dwSocketUniqueness = 0x8;
  64. static const DWORD c_dwSourceRouteUsageTime = 0xf;
  65. static const DWORD c_dwVirtualNetworkNumber = 0;
  66. static const REGBATCH regbatchIpx[] = {
  67. {HKEY_LOCAL_MACHINE, c_szIpxParameters, c_szDedicatedRouter, REG_DWORD,
  68. offsetof(IpxParams,dwDedicatedRouter), (BYTE *)&c_dwDedicatedRouter},
  69. {HKEY_LOCAL_MACHINE, c_szIpxParameters, c_szEnableWANRouter, REG_DWORD,
  70. offsetof(IpxParams,dwEnableWANRouter), (BYTE *)&c_dwEnableWANRouter},
  71. {HKEY_LOCAL_MACHINE, c_szIpxParameters, c_szInitDatagrams, REG_DWORD,
  72. offsetof(IpxParams,dwInitDatagrams), (BYTE *)&c_dwInitDatagrams},
  73. {HKEY_LOCAL_MACHINE, c_szIpxParameters, c_szMaxDatagrams, REG_DWORD,
  74. offsetof(IpxParams,dwMaxDatagrams), (BYTE *)&c_dwMaxDatagrams},
  75. {HKEY_LOCAL_MACHINE, c_szIpxParameters, c_szReplaceConfigDialog, REG_DWORD,
  76. offsetof(IpxParams,dwReplaceConfigDialog), (BYTE *)&c_dwReplaceConfigDialog},
  77. {HKEY_LOCAL_MACHINE, c_szIpxParameters, c_szRipCount, REG_DWORD,
  78. offsetof(IpxParams,dwRipCount), (BYTE *)&c_dwRipCount},
  79. {HKEY_LOCAL_MACHINE, c_szIpxParameters, c_szRipTimeout, REG_DWORD,
  80. offsetof(IpxParams,dwRipTimeout), (BYTE *)&c_dwRipTimeout},
  81. {HKEY_LOCAL_MACHINE, c_szIpxParameters, c_szRipUsageTime, REG_DWORD,
  82. offsetof(IpxParams,dwRipUsageTime), (BYTE *)&c_dwRipUsageTime},
  83. {HKEY_LOCAL_MACHINE, c_szIpxParameters, c_szSocketEnd, REG_DWORD,
  84. offsetof(IpxParams,dwSocketEnd), (BYTE *)&c_dwSocketEnd},
  85. {HKEY_LOCAL_MACHINE, c_szIpxParameters, c_szSocketStart, REG_DWORD,
  86. offsetof(IpxParams,dwSocketStart), (BYTE *)&c_dwSocketStart},
  87. {HKEY_LOCAL_MACHINE, c_szIpxParameters, c_szSocketUniqueness, REG_DWORD,
  88. offsetof(IpxParams,dwSocketUniqueness), (BYTE *)&c_dwSocketUniqueness},
  89. {HKEY_LOCAL_MACHINE, c_szIpxParameters, c_szSourceRouteUsageTime, REG_DWORD,
  90. offsetof(IpxParams,dwSourceRouteUsageTime), (BYTE *)&c_dwSourceRouteUsageTime},
  91. {HKEY_LOCAL_MACHINE, c_szIpxParameters, c_szVirtualNetworkNumber, REG_DWORD,
  92. offsetof(IpxParams,dwVirtualNetworkNumber), (BYTE *)&c_dwVirtualNetworkNumber}};
  93. CNwlnkIPX::CNwlnkIPX() :
  94. m_pnccMe(NULL),
  95. m_pNetCfg(NULL),
  96. m_fNetworkInstall(FALSE),
  97. m_fAdapterListChanged(FALSE),
  98. m_fPropertyChanged(FALSE),
  99. m_eInstallAction(eActUnknown),
  100. m_pspObj1(NULL),
  101. m_pspObj2(NULL),
  102. m_pIpxEnviroment(NULL),
  103. m_pUnkPropContext(NULL)
  104. {
  105. }
  106. CNwlnkIPX::~CNwlnkIPX()
  107. {
  108. ReleaseObj(m_pUnkPropContext);
  109. ReleaseObj(m_pNetCfg);
  110. ReleaseObj(m_pnccMe);
  111. delete m_pIpxEnviroment;
  112. CleanupPropPages();
  113. }
  114. // INetCfgNotify
  115. STDMETHODIMP CNwlnkIPX::Initialize (
  116. INetCfgComponent* pncc,
  117. INetCfg* pNetCfg,
  118. BOOL fInstalling)
  119. {
  120. HRESULT hr;
  121. Validate_INetCfgNotify_Initialize(pncc, pNetCfg, fInstalling);
  122. // Hold on to our the component representing us and our host
  123. // INetCfg object.
  124. AddRefObj (m_pnccMe = pncc);
  125. AddRefObj (m_pNetCfg = pNetCfg);
  126. //
  127. // Determine if the Netware stack is installed, if so DO NOT
  128. // install over it.
  129. //
  130. if (FIsNetwareIpxInstalled())
  131. {
  132. //TODO: EventLog(Novell Netware already installed);
  133. //$REVIEW: Do we just want to silently proceed an do nothing?
  134. }
  135. // Query current settings
  136. hr = CIpxEnviroment::HrCreate(this, &m_pIpxEnviroment);
  137. TraceError("CNwlnkIPX::Initialize",hr);
  138. return hr;
  139. }
  140. STDMETHODIMP CNwlnkIPX::Upgrade(DWORD, DWORD)
  141. {
  142. return S_FALSE;
  143. }
  144. STDMETHODIMP CNwlnkIPX::ReadAnswerFile (
  145. PCWSTR pszAnswerFile,
  146. PCWSTR pszAnswerSection)
  147. {
  148. HRESULT hr = S_OK;
  149. Validate_INetCfgNotify_ReadAnswerFile(pszAnswerFile, pszAnswerSection );
  150. // Record the fact that this is a network installation
  151. m_fNetworkInstall = TRUE;
  152. m_eInstallAction = eActInstall;
  153. // Only process answer file and install sub-components if the answer file
  154. // is present. If the answer file is not present we should already be installed.
  155. if (NULL == pszAnswerFile)
  156. {
  157. goto Error; // Success case
  158. }
  159. // Read the Answer file contents
  160. hr = HrProcessAnswerFile(pszAnswerFile,
  161. pszAnswerSection);
  162. if (FAILED(hr))
  163. {
  164. goto Error;
  165. }
  166. Error:
  167. TraceError("CNwlnkIPX::ReadAnswerFile",hr);
  168. return hr;
  169. }
  170. //
  171. // Function: CNwlnkIPX::HrProcessAnswerFile
  172. //
  173. // Purpose: Process the answer file information, merging
  174. // its contents into the internal information
  175. //
  176. // Parameters:
  177. //
  178. // Returns: HRESULT, S_OK on success
  179. //
  180. HRESULT CNwlnkIPX::HrProcessAnswerFile(PCWSTR pszAnswerFile,
  181. PCWSTR pszAnswerSection)
  182. {
  183. CSetupInfFile csif;
  184. DWORD dwData;
  185. BOOL fValue;
  186. HRESULT hr = S_OK;
  187. INFCONTEXT infctx;
  188. AssertSz(pszAnswerFile, "Answer file string is NULL!");
  189. AssertSz(pszAnswerSection, "Answer file sections string is NULL!");
  190. // Open the answer file.
  191. hr = csif.HrOpen(pszAnswerFile, NULL, INF_STYLE_OLDNT | INF_STYLE_WIN4, NULL);
  192. if (FAILED(hr))
  193. {
  194. goto Error;
  195. }
  196. // Release all of the adapter specific info
  197. Assert(NULL != m_pIpxEnviroment);
  198. m_pIpxEnviroment->ReleaseAdapterInfo();
  199. // Read the DedicatedRouter parameter
  200. hr = csif.HrGetStringAsBool(pszAnswerSection, c_szDedicatedRouter,
  201. &fValue);
  202. if (SUCCEEDED(hr))
  203. {
  204. m_pIpxEnviroment->SetDedicatedRouter(fValue);
  205. }
  206. // Read the EnableWANRouter parameter
  207. hr = csif.HrGetStringAsBool(pszAnswerSection, c_szEnableWANRouter,
  208. &fValue);
  209. if (SUCCEEDED(hr))
  210. {
  211. m_pIpxEnviroment->SetEnableWANRouter(fValue);
  212. }
  213. // Read the virtual network number
  214. hr = csif.HrGetDword(pszAnswerSection, c_szVirtualNetworkNumber, &dwData);
  215. if (SUCCEEDED(hr))
  216. {
  217. m_pIpxEnviroment->SetVirtualNetworkNumber(dwData);
  218. }
  219. // Read the property containing the list of adapter sections
  220. hr = ::HrSetupFindFirstLine(csif.Hinf(), pszAnswerSection,
  221. c_szAdapterSections, &infctx);
  222. if (SUCCEEDED(hr))
  223. {
  224. DWORD dwIdx;
  225. DWORD dwCnt = SetupGetFieldCount(&infctx);
  226. tstring str;
  227. // For each adapter in the list read the adapter information
  228. for (dwIdx=1; dwIdx <= dwCnt; dwIdx++)
  229. {
  230. hr = ::HrSetupGetStringField(infctx, dwIdx, &str);
  231. if (FAILED(hr))
  232. {
  233. TraceError("CNwlnkIPX::HrProcessAnswerFile - Failed to read adapter section name",hr);
  234. break;
  235. }
  236. hr = HrReadAdapterAnswerFileSection(&csif, str.c_str());
  237. if (FAILED(hr))
  238. {
  239. goto Error;
  240. }
  241. }
  242. }
  243. hr = S_OK;
  244. Error:
  245. TraceError("CNwlnkIpx::HrProcessAnswerFile", hr);
  246. return hr;
  247. }
  248. //
  249. // Function: CNwlnkIPX::HrReadAdapterAnswerFileSection
  250. //
  251. // Purpose: Read the adapter answer file section and create
  252. // the adapter info section if successful
  253. //
  254. // Parameters:
  255. //
  256. // Returns:
  257. //
  258. HRESULT
  259. CNwlnkIPX::HrReadAdapterAnswerFileSection(CSetupInfFile * pcsif,
  260. PCWSTR pszSection)
  261. {
  262. HRESULT hr = S_OK;
  263. CIpxAdapterInfo * pAI = NULL;
  264. INetCfgComponent* pncc = NULL;
  265. tstring str;
  266. // Read the SpecificTo adapter name
  267. hr = pcsif->HrGetString(pszSection, c_szSpecificTo, &str);
  268. if (FAILED(hr))
  269. {
  270. goto Error;
  271. }
  272. // Search for the specified adapter in the set of existing adapters
  273. hr = ::HrAnswerFileAdapterToPNCC(m_pNetCfg, str.c_str(), &pncc);
  274. if (FAILED(hr))
  275. {
  276. goto Error;
  277. }
  278. // if we found the adapter component object (pncc != NULL) process
  279. // the adapter section
  280. if (pncc)
  281. {
  282. DWORD dwIdx;
  283. DWORD dwCnt;
  284. INFCONTEXT infctx;
  285. pAI = new CIpxAdapterInfo;
  286. Assert(NULL != pAI);
  287. // Query the adapter component info
  288. hr = ::HrQueryAdapterComponentInfo(pncc, pAI);
  289. if (FAILED(hr))
  290. {
  291. goto Error;
  292. }
  293. // Read the PktType (Failure is usually just "not found")
  294. hr = ::HrSetupFindFirstLine(pcsif->Hinf(), pszSection, c_szPktType,
  295. &infctx);
  296. if (SUCCEEDED(hr))
  297. {
  298. dwCnt = ::SetupGetFieldCount(&infctx);
  299. // For each adapter in the list read the adapter information
  300. for (dwIdx=1; dwIdx <= dwCnt; dwIdx++)
  301. {
  302. hr = ::HrSetupGetStringField(infctx, dwIdx, &str);
  303. if (FAILED(hr))
  304. {
  305. TraceError("CNwlnkIPX::HrProcessAnswerFile - Failed to read adapter section name",hr);
  306. goto Error;
  307. }
  308. Assert(!str.empty());
  309. // Raid # 205831 - Trim any leading "0x"
  310. //
  311. if (0 == _wcsnicmp(str.c_str(), c_sz0xPrefix, wcslen(c_sz0xPrefix)))
  312. {
  313. str.erase(0, wcslen(c_sz0xPrefix));
  314. }
  315. pAI->PFrmTypeList()->push_back(new tstring(str));
  316. }
  317. }
  318. // Default PktType?
  319. if (0 == pAI->PFrmTypeList()->size())
  320. {
  321. WCHAR szBuf[10];
  322. // If the info was not found or contained no elements, add the
  323. // default value.
  324. wsprintfW(szBuf,L"%X",c_dwPktTypeDefault);
  325. pAI->PFrmTypeList()->push_back(new tstring(szBuf));
  326. }
  327. // Read the NetworkNumber
  328. hr = ::HrSetupFindFirstLine(pcsif->Hinf(), pszSection, c_szNetworkNumber,
  329. &infctx);
  330. if (SUCCEEDED(hr))
  331. {
  332. dwCnt = SetupGetFieldCount(&infctx);
  333. // For each adapter in the list read the adapter information
  334. for (dwIdx=1; dwIdx <= dwCnt; dwIdx++)
  335. {
  336. hr = ::HrSetupGetStringField(infctx, dwIdx, &str);
  337. if (FAILED(hr))
  338. {
  339. TraceError("CNwlnkIPX::HrProcessAnswerFile - Failed to read adapter section name",hr);
  340. goto Error;
  341. }
  342. Assert(!str.empty());
  343. pAI->PNetworkNumList()->push_back(new tstring(str));
  344. }
  345. }
  346. // Default Network Number?
  347. if (0 == pAI->PNetworkNumList()->size())
  348. {
  349. // If the info was not found or contained no elements, add the
  350. // default value.
  351. pAI->PNetworkNumList()->push_back(new tstring(c_sz8Zeros));
  352. }
  353. // Ensure that the network number list has the same number of
  354. // elements as the frame type list. This can happen when the user
  355. // configures multiple frame types on 3.51 but only one network
  356. // number is used. We'll extend the last network number used
  357. // and pad it to make the network number list the same size.
  358. //
  359. Assert (pAI->PNetworkNumList()->size());
  360. while (pAI->PNetworkNumList()->size() < pAI->PFrmTypeList()->size())
  361. {
  362. pAI->PNetworkNumList()->push_back(
  363. new tstring(*pAI->PNetworkNumList()->back()));
  364. }
  365. pAI->SetDirty(TRUE);
  366. m_pIpxEnviroment->AdapterInfoList().push_back(pAI);
  367. MarkAdapterListChanged();
  368. }
  369. #ifdef ENABLETRACE
  370. else
  371. {
  372. TraceTag(ttidDefault, "CNwlnkIPX::HrReadAdapterAnswerFileSection - "
  373. "Adapter \"%S\" not yet installed.",str.c_str());
  374. }
  375. #endif
  376. // Normalize return
  377. hr = S_OK;
  378. Done:
  379. ReleaseObj(pncc);
  380. return hr;
  381. Error:
  382. delete pAI;
  383. TraceError("CNwlnkIpx::HrReadAdapterAnswerFileSection",hr);
  384. goto Done;
  385. }
  386. STDMETHODIMP CNwlnkIPX::Install (DWORD)
  387. {
  388. HRESULT hr;
  389. CIpxAdapterInfo * pAI;
  390. ADAPTER_INFO_LIST::iterator iter;
  391. m_eInstallAction = eActInstall;
  392. // Mark all the initially detected adapters as dirty
  393. for (iter = m_pIpxEnviroment->AdapterInfoList().begin();
  394. iter != m_pIpxEnviroment->AdapterInfoList().end();
  395. iter++)
  396. {
  397. pAI = *iter;
  398. pAI->SetDirty(TRUE);
  399. }
  400. // Install NwlnkNb.
  401. hr = ::HrInstallComponentOboComponent (m_pNetCfg, NULL,
  402. GUID_DEVCLASS_NETTRANS,
  403. c_szInfId_MS_NWNB,
  404. m_pnccMe,
  405. NULL);
  406. if (FAILED(hr))
  407. {
  408. goto Error;
  409. }
  410. // Install NwlnkSpx.
  411. hr = ::HrInstallComponentOboComponent (m_pNetCfg, NULL,
  412. GUID_DEVCLASS_NETTRANS,
  413. c_szInfId_MS_NWSPX,
  414. m_pnccMe,
  415. NULL);
  416. Error:
  417. TraceError("CNwlnkIPX::Install",hr);
  418. return hr;
  419. }
  420. STDMETHODIMP CNwlnkIPX::Removing ()
  421. {
  422. HRESULT hr;
  423. m_eInstallAction = eActRemove;
  424. // Remove NwlnkNb.
  425. hr = ::HrRemoveComponentOboComponent(m_pNetCfg, GUID_DEVCLASS_NETTRANS,
  426. c_szInfId_MS_NWNB, m_pnccMe);
  427. if (FAILED(hr))
  428. goto Error;
  429. // Remove NwlnkSpx.
  430. hr = ::HrRemoveComponentOboComponent(m_pNetCfg, GUID_DEVCLASS_NETTRANS,
  431. c_szInfId_MS_NWSPX, m_pnccMe);
  432. Error:
  433. TraceError("CNwlnkIPX::Removing",hr);
  434. return hr;
  435. }
  436. STDMETHODIMP CNwlnkIPX::Validate ( )
  437. {
  438. return S_OK;
  439. }
  440. STDMETHODIMP CNwlnkIPX::CancelChanges ()
  441. {
  442. return S_OK;
  443. }
  444. STDMETHODIMP CNwlnkIPX::ApplyRegistryChanges ()
  445. {
  446. HRESULT hr = E_INVALIDARG;
  447. switch(m_eInstallAction)
  448. {
  449. case eActInstall:
  450. hr = HrCommitInstall();
  451. break;
  452. case eActRemove:
  453. hr = HrCommitRemove();
  454. break;
  455. default: // eActUnknown (Configuration)
  456. if (m_fAdapterListChanged || m_fPropertyChanged)
  457. {
  458. // Update the registry if the adapter list changed
  459. Assert(m_pIpxEnviroment);
  460. hr = m_pIpxEnviroment->HrUpdateRegistry();
  461. if (SUCCEEDED(hr))
  462. {
  463. // Send change notification
  464. hr = HrReconfigIpx();
  465. }
  466. }
  467. break;
  468. }
  469. TraceError("CNwlnkIPX::ApplyRegistryChanges",hr);
  470. return hr;
  471. }
  472. // INetCfgComponentPropertyUi
  473. STDMETHODIMP CNwlnkIPX::SetContext(IUnknown * pUnk)
  474. {
  475. ReleaseObj(m_pUnkPropContext);
  476. m_pUnkPropContext = pUnk;
  477. if (m_pUnkPropContext)
  478. {
  479. AddRefObj(m_pUnkPropContext);
  480. }
  481. return S_OK;
  482. }
  483. STDMETHODIMP CNwlnkIPX::MergePropPages (
  484. IN OUT DWORD* pdwDefPages,
  485. OUT LPBYTE* pahpspPrivate,
  486. OUT UINT* pcPages,
  487. IN HWND hwndParent,
  488. OUT PCWSTR* pszStartPage)
  489. {
  490. Validate_INetCfgProperties_MergePropPages (
  491. pdwDefPages, pahpspPrivate, pcPages, hwndParent, pszStartPage);
  492. HRESULT hr = S_OK;
  493. HPROPSHEETPAGE * ahpsp = NULL;
  494. PRODUCT_FLAVOR pf;
  495. int nPages = 0;
  496. CIpxAdapterInfo * pAI = NULL;
  497. Assert(pahpspPrivate);
  498. Assert(*pahpspPrivate == NULL); // Out param init done via Validate above
  499. *pcPages = 0;
  500. // Start with new property pages each time.
  501. CleanupPropPages();
  502. // Get the current Adapter
  503. if (NULL != m_pUnkPropContext)
  504. {
  505. CIpxAdapterInfo * pAITmp;
  506. INetLanConnectionUiInfo * pLanConn = NULL;
  507. ADAPTER_INFO_LIST::iterator iter;
  508. hr = m_pUnkPropContext->QueryInterface(IID_INetLanConnectionUiInfo,
  509. reinterpret_cast<LPVOID *>(&pLanConn));
  510. if (SUCCEEDED(hr))
  511. {
  512. GUID guid;
  513. hr = pLanConn->GetDeviceGuid(&guid);
  514. ReleaseObj(pLanConn);
  515. if (FAILED(hr))
  516. {
  517. goto Error;
  518. }
  519. // Find the adapter in our adapter list
  520. for (iter = m_pIpxEnviroment->AdapterInfoList().begin();
  521. iter != m_pIpxEnviroment->AdapterInfoList().end();
  522. iter++)
  523. {
  524. pAITmp = *iter;
  525. if (guid == *pAITmp->PInstanceGuid())
  526. {
  527. pAI = pAITmp;
  528. break;
  529. }
  530. }
  531. Assert(SUCCEEDED(hr));
  532. // If we have an adapter but it's
  533. // disabled/hidden/deleted we show no pages
  534. if ((NULL != pAI) && (pAI->FDeletePending() ||
  535. pAI->FDisabled() || pAI->FHidden()))
  536. {
  537. Assert(0 == *pcPages);
  538. hr = S_FALSE;
  539. goto cleanup;
  540. }
  541. }
  542. else if (E_NOINTERFACE == hr)
  543. {
  544. // RAS doesn't have the notion of a current adapter
  545. hr = S_OK;
  546. }
  547. }
  548. else
  549. {
  550. // m_pUnkPropContext should have been set first
  551. hr = E_UNEXPECTED;
  552. }
  553. if (FAILED(hr))
  554. {
  555. goto Error;
  556. }
  557. // If the product is not workstation (therefore NTAS)
  558. GetProductFlavor(NULL, &pf);
  559. if ((PF_WORKSTATION != pf) && (NULL != pAI))
  560. {
  561. // Server
  562. #ifdef INCLUDE_RIP_ROUTING
  563. nPages = 2;
  564. #else
  565. nPages = 1;
  566. #endif
  567. // Allocate a buffer large enough to hold the handle to the IPX config.
  568. // property page.
  569. ahpsp = (HPROPSHEETPAGE *)CoTaskMemAlloc(sizeof(HPROPSHEETPAGE) * nPages);
  570. if (!ahpsp)
  571. {
  572. hr = E_OUTOFMEMORY;
  573. goto cleanup; // Alloc failed to no need to free ahpsp
  574. }
  575. // Allocate the CPropSheetPage objects
  576. m_pspObj1 = new CIpxASConfigDlg(this, m_pIpxEnviroment, pAI);
  577. #ifdef INCLUDE_RIP_ROUTING
  578. m_pspObj2 = new CIpxASInternalDlg(this, m_pIpxEnviroment, pAI);
  579. #endif
  580. // Create the actual PROPSHEETPAGE for each object.
  581. // This needs to be done regardless of whether the classes existed before.
  582. ahpsp[0] = m_pspObj1->CreatePage(DLG_IPXAS_CONFIG, 0);
  583. #ifdef INCLUDE_RIP_ROUTING
  584. ahpsp[1] = m_pspObj2->CreatePage(DLG_IPXAS_INTERNAL, 0);
  585. #endif
  586. }
  587. else
  588. {
  589. // Workstation
  590. nPages = 1;
  591. // Allocate a buffer large enough to hold the handle to the IPX config.
  592. // property page.
  593. ahpsp = (HPROPSHEETPAGE *)CoTaskMemAlloc(sizeof(HPROPSHEETPAGE) * nPages);
  594. if (!ahpsp)
  595. {
  596. hr = E_OUTOFMEMORY;
  597. goto cleanup; // Alloc failed to no need to free ahpsp
  598. }
  599. // Allocate the CPropSheetPage object
  600. m_pspObj1 = new CIpxConfigDlg(this, m_pIpxEnviroment, pAI);
  601. // Create the actual PROPSHEETPAGE for each object.
  602. // This needs to be done regardless of whether the classes existed before.
  603. ahpsp[0] = m_pspObj1->CreatePage(DLG_IPX_CONFIG, 0);
  604. }
  605. if (NULL != ahpsp[0])
  606. {
  607. *pahpspPrivate = (LPBYTE)ahpsp;
  608. *pcPages = nPages;
  609. }
  610. else
  611. {
  612. hr = E_OUTOFMEMORY;
  613. goto Error;
  614. }
  615. cleanup:
  616. TraceError("CNwlnkIPX::MergePropPages", hr);
  617. return hr;
  618. Error:
  619. CoTaskMemFree(ahpsp);
  620. goto cleanup;
  621. }
  622. VOID CNwlnkIPX::CleanupPropPages()
  623. {
  624. delete m_pspObj1;
  625. m_pspObj1 = NULL;
  626. #ifdef INCLUDE_RIP_ROUTING
  627. delete m_pspObj2;
  628. m_pspObj2 = NULL;
  629. #endif
  630. }
  631. STDMETHODIMP CNwlnkIPX::ValidateProperties (HWND)
  632. {
  633. m_fPropertyChanged = TRUE;
  634. return S_OK;
  635. }
  636. STDMETHODIMP CNwlnkIPX::CancelProperties ()
  637. {
  638. return S_OK;
  639. }
  640. STDMETHODIMP CNwlnkIPX::ApplyProperties ()
  641. {
  642. return S_OK;
  643. }
  644. // INetCfgComponentNotifyBinding
  645. STDMETHODIMP CNwlnkIPX::QueryBindingPath ( DWORD dwChangeFlag,
  646. INetCfgBindingPath* pncbpItem )
  647. {
  648. return S_OK;
  649. }
  650. STDMETHODIMP CNwlnkIPX::NotifyBindingPath ( DWORD dwChangeFlag,
  651. INetCfgBindingPath* pncbpItem )
  652. {
  653. HRESULT hr = S_OK;
  654. INetCfgComponent *pnccFound = NULL;
  655. Validate_INetCfgBindNotify_NotifyBindingPath( dwChangeFlag, pncbpItem );
  656. Assert(NULL != m_pIpxEnviroment);
  657. // Only Interested in lower binding Add's and Remove's
  658. if (dwChangeFlag & (NCN_ADD | NCN_REMOVE | NCN_ENABLE | NCN_DISABLE))
  659. {
  660. CIterNetCfgBindingInterface ncbiIter(pncbpItem);
  661. INetCfgBindingInterface *pncbi;
  662. // Enumerate the binding interfaces looking for an Adapter
  663. while (SUCCEEDED(hr) &&
  664. (S_OK == (hr = ncbiIter.HrNext (&pncbi))))
  665. {
  666. INetCfgComponent *pncc;
  667. hr = pncbi->GetLowerComponent(&pncc);
  668. if (S_OK == hr)
  669. {
  670. GUID guidClass;
  671. hr = pncc->GetClassGuid(&guidClass);
  672. if ((S_OK == hr) && (GUID_DEVCLASS_NET == guidClass))
  673. {
  674. ReleaseObj(pnccFound);
  675. pnccFound = pncc; // Transfer Ownership
  676. pncc = NULL;
  677. }
  678. else
  679. {
  680. ReleaseObj(pncc);
  681. }
  682. }
  683. ReleaseObj(pncbi);
  684. }
  685. if (FAILED(hr))
  686. goto Error;
  687. // Did we find the Adapter?
  688. if (pnccFound)
  689. {
  690. BOOL fFound = FALSE;
  691. PWSTR pszBindName = NULL;
  692. CIpxAdapterInfo * pAI;
  693. ADAPTER_INFO_LIST::iterator iterAdapterInfo;
  694. Assert(m_pIpxEnviroment);
  695. hr = pnccFound->GetBindName(&pszBindName);
  696. if (S_OK != hr)
  697. {
  698. goto Error;
  699. }
  700. // Search the adapter list
  701. for (iterAdapterInfo = m_pIpxEnviroment->AdapterInfoList().begin();
  702. iterAdapterInfo != m_pIpxEnviroment->AdapterInfoList().end();
  703. iterAdapterInfo++)
  704. {
  705. pAI = *iterAdapterInfo;
  706. Assert (pAI);
  707. if (0 == lstrcmpiW(pszBindName, pAI->SzBindName()))
  708. {
  709. fFound = TRUE;
  710. break;
  711. }
  712. }
  713. Assert(pszBindName);
  714. CoTaskMemFree(pszBindName);
  715. // Apply the appropriate delta to the adapter list
  716. if (fFound && (dwChangeFlag & NCN_REMOVE))
  717. {
  718. // Mark the adapter as Delete Pending
  719. pAI->SetDeletePending(TRUE);
  720. m_fAdapterListChanged = TRUE;
  721. }
  722. else if (!fFound && (dwChangeFlag & NCN_ADD))
  723. {
  724. // Add the adapter to the list
  725. hr = m_pIpxEnviroment->HrAddAdapter(pnccFound);
  726. m_fAdapterListChanged = TRUE;
  727. }
  728. else if (fFound && (dwChangeFlag & NCN_ADD))
  729. {
  730. // Re-enable the adapters existance
  731. pAI->SetDeletePending(FALSE);
  732. }
  733. if (fFound)
  734. {
  735. if (dwChangeFlag & NCN_ENABLE)
  736. {
  737. pAI->SetDisabled(FALSE);
  738. m_fAdapterListChanged = TRUE;
  739. }
  740. else if (dwChangeFlag & NCN_DISABLE)
  741. {
  742. pAI->SetDisabled(TRUE);
  743. m_fAdapterListChanged = TRUE;
  744. }
  745. }
  746. }
  747. if (SUCCEEDED(hr))
  748. hr = S_OK; // Normailze return value
  749. }
  750. Error:
  751. ReleaseObj(pnccFound);
  752. TraceError("CNwlnkIPX::NotifyBindingPath",hr);
  753. return hr;
  754. }
  755. STDMETHODIMP CNwlnkIPX::GetFrameTypesForAdapter(PCWSTR pszAdapterBindName,
  756. DWORD cFrameTypesMax,
  757. DWORD* anFrameTypes,
  758. DWORD* pcFrameTypes)
  759. {
  760. Assert(pszAdapterBindName);
  761. Assert(cFrameTypesMax);
  762. Assert(anFrameTypes);
  763. Assert(pcFrameTypes);
  764. *pcFrameTypes = 0;
  765. ADAPTER_INFO_LIST::iterator iterAI;
  766. for (iterAI = m_pIpxEnviroment->AdapterInfoList().begin();
  767. iterAI != m_pIpxEnviroment->AdapterInfoList().end();
  768. iterAI++)
  769. {
  770. CIpxAdapterInfo *pAI = *iterAI;
  771. if (0 == lstrcmpW(pszAdapterBindName, pAI->SzBindName()))
  772. {
  773. list<tstring *>::iterator iterFrmType;
  774. for (iterFrmType = pAI->PFrmTypeList()->begin();
  775. (iterFrmType != pAI->PFrmTypeList()->end()) &&
  776. (*pcFrameTypes < cFrameTypesMax);
  777. iterFrmType++)
  778. {
  779. // Copy the Frame Type
  780. tstring *pstr1 = *iterFrmType;
  781. anFrameTypes[(*pcFrameTypes)++] = DwFromSz(pstr1->c_str(), 16);
  782. }
  783. break;
  784. }
  785. }
  786. return S_OK;
  787. }
  788. STDMETHODIMP CNwlnkIPX::GetVirtualNetworkNumber(DWORD* pdwVNetworkNumber)
  789. {
  790. HRESULT hr = S_OK;
  791. if (NULL == pdwVNetworkNumber)
  792. {
  793. hr = E_INVALIDARG;
  794. goto Error;
  795. }
  796. Assert(NULL != m_pIpxEnviroment);
  797. *pdwVNetworkNumber = m_pIpxEnviroment->DwVirtualNetworkNumber();
  798. Error:
  799. TraceError("CNwlnkIPX::GetVirtualNetworkNumber",hr);
  800. return hr;
  801. }
  802. STDMETHODIMP CNwlnkIPX::SetVirtualNetworkNumber(DWORD dwVNetworkNumber)
  803. {
  804. HRESULT hr;
  805. Assert(NULL != m_pIpxEnviroment);
  806. m_pIpxEnviroment->SetVirtualNetworkNumber(dwVNetworkNumber);
  807. m_fPropertyChanged = TRUE;
  808. // Tell INetCfg that our component is dirty
  809. INetCfgComponentPrivate* pinccp = NULL;
  810. Assert(NULL != m_pnccMe);
  811. hr = m_pnccMe->QueryInterface(IID_INetCfgComponentPrivate,
  812. reinterpret_cast<void**>(&pinccp));
  813. if (SUCCEEDED(hr))
  814. {
  815. hr = pinccp->SetDirty();
  816. pinccp->Release();
  817. }
  818. return hr;
  819. }
  820. //
  821. // Function: CNwlnkIPX::HrCommitInstall
  822. //
  823. // Purpose: Commit Installation registry changes to the registry
  824. //
  825. // Parameters: None
  826. //
  827. // Returns: HRESULT, S_OK on success
  828. //
  829. //
  830. STDMETHODIMP CNwlnkIPX::HrCommitInstall()
  831. {
  832. HRESULT hr;
  833. Assert(m_pIpxEnviroment);
  834. hr = m_pIpxEnviroment->HrUpdateRegistry();
  835. TraceError("CNwlnkIPX::HrCommitInstall",hr);
  836. return hr;
  837. }
  838. //
  839. // Function: CNwlnkIPX::HrCommitRemove
  840. //
  841. // Purpose: Remove from the registry settings which were created by this
  842. // component's installation.
  843. //
  844. // Parameters: None
  845. //
  846. // Returns: HRESULT, S_OK on success
  847. //
  848. //
  849. STDMETHODIMP CNwlnkIPX::HrCommitRemove()
  850. {
  851. // Remove "NwlnkIpx" from the:
  852. // System\CurrentControlSet\Control\ServiceProvider\Order\ProviderOrder value
  853. (void) HrRegRemoveStringFromMultiSz(c_szSvcNwlnkIpx, HKEY_LOCAL_MACHINE,
  854. c_szSrvProvOrderKey,
  855. c_szProviderOrderVal,
  856. STRING_FLAG_REMOVE_ALL);
  857. return S_OK;
  858. }
  859. CIpxAdapterInfo::CIpxAdapterInfo() : m_dwMediaType(ETHERNET_MEDIA),
  860. m_fDeletePending(FALSE),
  861. m_fDisabled(FALSE),
  862. m_fDirty(FALSE),
  863. m_dwCharacteristics(0L)
  864. {
  865. ZeroMemory(&m_guidInstance, sizeof(m_guidInstance));
  866. }
  867. CIpxAdapterInfo::~CIpxAdapterInfo()
  868. {
  869. DeleteColString(&m_lstpstrFrmType);
  870. DeleteColString(&m_lstpstrNetworkNum);
  871. }
  872. CIpxEnviroment::CIpxEnviroment(CNwlnkIPX *pno)
  873. {
  874. Assert(NULL != pno);
  875. m_pno = pno; // Retain the Notification object
  876. m_fRipInstalled = FALSE;
  877. m_fEnableRip = FALSE;
  878. m_dwRipValue = 0;
  879. ZeroMemory(&m_IpxParams, sizeof(m_IpxParams));
  880. }
  881. CIpxEnviroment::~CIpxEnviroment()
  882. {
  883. ReleaseAdapterInfo();
  884. // Note: Do nothing with the m_pno notification object, we just borrowed it
  885. }
  886. //
  887. // Member: CIpxEnviroment::ReleaseAdapterInfo
  888. //
  889. // Purpose: Release the adapter info
  890. //
  891. // Arguments: none
  892. //
  893. // Returns: nothing
  894. //
  895. void CIpxEnviroment::ReleaseAdapterInfo()
  896. {
  897. CIpxAdapterInfo *pAI;
  898. while (!m_lstpAdapterInfo.empty())
  899. {
  900. pAI = m_lstpAdapterInfo.front();
  901. m_lstpAdapterInfo.pop_front();
  902. delete pAI;
  903. }
  904. }
  905. //
  906. // Member: CIpxEnviroment::DwCountValidAdapters
  907. //
  908. // Purpose: Return the count of adapters not marked as delete pending,
  909. // disabled, or hidden.
  910. //
  911. // Arguments: none
  912. //
  913. // Returns: nothing
  914. //
  915. DWORD CIpxEnviroment::DwCountValidAdapters()
  916. {
  917. DWORD dwCount = 0;
  918. ADAPTER_INFO_LIST::iterator iterAI;
  919. for (iterAI = AdapterInfoList().begin();
  920. iterAI != AdapterInfoList().end();
  921. iterAI++)
  922. {
  923. CIpxAdapterInfo *pAI = *iterAI;
  924. if (pAI->FDeletePending() || pAI->FDisabled() || pAI->FHidden())
  925. continue;
  926. dwCount++;
  927. }
  928. return dwCount;
  929. }
  930. HRESULT CIpxEnviroment::HrOpenIpxAdapterSubkey(HKEY *phkey, BOOL fCreateIfMissing)
  931. {
  932. DWORD dwDisposition;
  933. HRESULT hr;
  934. tstring str;
  935. // Open the NetCard key
  936. str = c_szIpxParameters;
  937. str += L"\\";
  938. str += c_szAdapters;
  939. if (fCreateIfMissing)
  940. {
  941. hr = ::HrRegCreateKeyEx(HKEY_LOCAL_MACHINE, str.c_str(),
  942. REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL,
  943. phkey, &dwDisposition);
  944. }
  945. else
  946. {
  947. hr = ::HrRegOpenKeyEx(HKEY_LOCAL_MACHINE, str.c_str(), KEY_READ, phkey );
  948. }
  949. if (S_OK != hr)
  950. goto Error;
  951. Error:
  952. TraceError("CIpxEnviroment::HrOpenIpxAdapterSubkey",
  953. HRESULT_FROM_WIN32 (ERROR_FILE_NOT_FOUND) == hr ? S_OK : hr);
  954. return hr;
  955. }
  956. HRESULT CIpxEnviroment::HrOpenIpxAdapterSubkeyEx(PCWSTR pszKeyName,
  957. DWORD dwAccess,
  958. BOOL fCreateIfMissing,
  959. HKEY *phkey)
  960. {
  961. HRESULT hr;
  962. HKEY hkeyRoot = NULL;
  963. Assert(pszKeyName);
  964. Assert(0 < lstrlenW(pszKeyName));
  965. // Open the NetCard key
  966. hr = HrOpenIpxAdapterSubkey(&hkeyRoot, fCreateIfMissing);
  967. if (S_OK != hr)
  968. {
  969. goto Error;
  970. }
  971. // Open the adapter specific subkey (creating if requested and required)
  972. if (fCreateIfMissing)
  973. {
  974. DWORD dwDisposition;
  975. hr = HrRegCreateKeyEx(HKEY_LOCAL_MACHINE, pszKeyName,
  976. REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL,
  977. phkey, &dwDisposition);
  978. }
  979. else
  980. {
  981. // Try exact match first, it's faster
  982. hr = HrRegOpenKeyEx( hkeyRoot, pszKeyName, dwAccess, phkey );
  983. }
  984. Error:
  985. RegSafeCloseKey(hkeyRoot);
  986. TraceError("CIpxEnviroment::HrOpenIpxAdapterSubkeyEx",
  987. HRESULT_FROM_WIN32 (ERROR_FILE_NOT_FOUND) == hr ? S_OK : hr);
  988. return hr;
  989. }
  990. HRESULT CIpxEnviroment::HrGetIpxParams()
  991. {
  992. RegReadValues(celems(regbatchIpx), regbatchIpx, (BYTE *)&m_IpxParams,
  993. KEY_READ);
  994. return S_OK;
  995. }
  996. HRESULT CIpxEnviroment::HrGetOneAdapterInfo(INetCfgComponent *pNCC,
  997. CIpxAdapterInfo **ppAI)
  998. {
  999. HKEY hkeyCard = NULL;
  1000. HRESULT hr = S_OK;
  1001. CIpxAdapterInfo * pAI = NULL;
  1002. Assert(NULL != pNCC);
  1003. // Init the return value
  1004. *ppAI = NULL;
  1005. pAI = (CIpxAdapterInfo *)new CIpxAdapterInfo;
  1006. Assert(NULL != pAI);
  1007. if (pAI == NULL)
  1008. {
  1009. return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
  1010. }
  1011. // Query the adapter component info
  1012. hr = ::HrQueryAdapterComponentInfo(pNCC, pAI);
  1013. if (FAILED(hr))
  1014. goto Error;
  1015. // Open the IPX subkey specific to this adapter
  1016. hr = HrOpenIpxAdapterSubkeyEx(pAI->SzBindName(), KEY_READ, FALSE,
  1017. &hkeyCard);
  1018. if (S_OK == hr)
  1019. {
  1020. // Get the packet types
  1021. //
  1022. hr = HrRegQueryColString(hkeyCard, c_szPktType,
  1023. &pAI->m_lstpstrFrmType);
  1024. if (S_OK != hr)
  1025. {
  1026. goto Error;
  1027. }
  1028. // Get the network numbers
  1029. //
  1030. hr = HrRegQueryColString(hkeyCard, c_szNetworkNumber,
  1031. &pAI->m_lstpstrNetworkNum);
  1032. if (S_OK != hr)
  1033. {
  1034. goto Error;
  1035. }
  1036. }
  1037. else if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr)
  1038. {
  1039. // Normalize any ERROR_FILE_NOT_FOUND errors
  1040. hr = S_OK;
  1041. }
  1042. else if (FAILED(hr))
  1043. {
  1044. goto Error;
  1045. }
  1046. // Default PktType?
  1047. if (0 == pAI->PFrmTypeList()->size())
  1048. {
  1049. WCHAR szBuf[10];
  1050. // If the info was not found or contained no elements, add the
  1051. // default value.
  1052. wsprintfW(szBuf,L"%X",c_dwPktTypeDefault);
  1053. pAI->PFrmTypeList()->push_back(new tstring(szBuf));
  1054. }
  1055. // Default Network Number?
  1056. if (0 == pAI->PNetworkNumList()->size())
  1057. {
  1058. // If the info was not found or contained no elements, add the
  1059. // default value.
  1060. pAI->PNetworkNumList()->push_back(new tstring(c_sz8Zeros));
  1061. }
  1062. // Update the return value with the new object
  1063. *ppAI = pAI;
  1064. Done:
  1065. ::RegSafeCloseKey(hkeyCard);
  1066. TraceError("CIpxEnviroment::HrGetOneAdapterInfo",hr);
  1067. return hr;
  1068. Error:
  1069. delete pAI;
  1070. goto Done;
  1071. }
  1072. HRESULT CIpxEnviroment::HrGetAdapterInfo()
  1073. {
  1074. HRESULT hr = S_OK;
  1075. CIpxAdapterInfo * pAI = NULL;
  1076. INetCfgComponent* pncc = NULL;
  1077. INetCfgComponent* pnccUse = NULL;
  1078. // Find each netcard, to do so, trace the bindings to their end
  1079. // If the endpoint is a netcard then add it to the list
  1080. CIterNetCfgBindingPath ncbpIter(m_pno->m_pnccMe);
  1081. INetCfgBindingPath* pncbp;
  1082. while (SUCCEEDED(hr) && (S_OK == (hr = ncbpIter.HrNext (&pncbp))))
  1083. {
  1084. // Iterate the binding interfaces of this path.
  1085. CIterNetCfgBindingInterface ncbiIter(pncbp);
  1086. INetCfgBindingInterface* pncbi;
  1087. while (SUCCEEDED(hr) && (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. ReleaseObj(pnccUse);
  1099. pnccUse = pncc;
  1100. pncc = NULL;
  1101. }
  1102. else
  1103. {
  1104. // Release the lower component
  1105. ReleaseObj(pncc);
  1106. }
  1107. }
  1108. // Release the binding interface
  1109. ReleaseObj (pncbi);
  1110. }
  1111. if (NULL != pnccUse)
  1112. {
  1113. // Query the Adapter information
  1114. hr = HrGetOneAdapterInfo(pnccUse, &pAI);
  1115. if (SUCCEEDED(hr))
  1116. {
  1117. if (S_FALSE == pncbp->IsEnabled())
  1118. pAI->SetDisabled(TRUE);
  1119. // Add this Adapter to the list
  1120. m_lstpAdapterInfo.push_back(pAI);
  1121. }
  1122. ReleaseObj(pnccUse);
  1123. pnccUse = NULL;
  1124. }
  1125. // Release the binding path
  1126. ReleaseObj (pncbp);
  1127. }
  1128. // Normalize the HRESULT. (i.e. don't return S_FALSE)
  1129. if (SUCCEEDED(hr))
  1130. {
  1131. hr = S_OK;
  1132. }
  1133. TraceError("CIpxEnviroment::HrGetNetCardInfo",hr);
  1134. return hr;
  1135. }
  1136. HRESULT CIpxEnviroment::HrWriteOneAdapterInfo(HKEY hkeyAdapters,
  1137. CIpxAdapterInfo* pAI)
  1138. {
  1139. DWORD dwDisposition;
  1140. HRESULT hr;
  1141. HKEY hkeyCard = NULL;
  1142. PWSTR psz = NULL;
  1143. // Open the IPX subkey for this specific adapter
  1144. hr = ::HrRegCreateKeyEx(hkeyAdapters, pAI->SzBindName(), REG_OPTION_NON_VOLATILE,
  1145. KEY_ALL_ACCESS, NULL, &hkeyCard, &dwDisposition);
  1146. if (S_OK != hr)
  1147. goto Error;
  1148. // Write the packet info
  1149. // Generate the data to write
  1150. AssertSz(pAI->m_lstpstrFrmType.size(),"Did not expect an empty list, default value missing");
  1151. ColStringToMultiSz(pAI->m_lstpstrFrmType, &psz);
  1152. if (psz)
  1153. {
  1154. hr = ::HrRegSetMultiSz(hkeyCard, c_szPktType, psz);
  1155. if (S_OK != hr)
  1156. goto Error;
  1157. delete [] psz;
  1158. psz = NULL;
  1159. }
  1160. #ifdef DBG
  1161. else
  1162. {
  1163. AssertSz(0,"PacketType value is NULL?");
  1164. }
  1165. #endif
  1166. // Write the network number
  1167. AssertSz(pAI->m_lstpstrNetworkNum.size(),"Did not expect an empty list, default value missing");
  1168. ColStringToMultiSz(pAI->m_lstpstrNetworkNum, &psz);
  1169. if (psz)
  1170. {
  1171. hr = ::HrRegSetMultiSz(hkeyCard, c_szNetworkNumber, psz);
  1172. if (S_OK != hr)
  1173. goto Error;
  1174. delete [] psz;
  1175. psz = NULL;
  1176. }
  1177. #ifdef DBG
  1178. else
  1179. {
  1180. AssertSz(0,"NetworkNumber value is NULL?");
  1181. }
  1182. #endif
  1183. // If the key for this adapter didn't exist previously
  1184. // write the base set of values
  1185. if (REG_CREATED_NEW_KEY == dwDisposition)
  1186. {
  1187. struct
  1188. {
  1189. PCWSTR pszProp;
  1190. DWORD dwValue;
  1191. } rgAdapterSettings[] = {{c_szBindSap,c_dwBindSap},
  1192. {c_szEnableFuncaddr,c_dwEnableFuncaddr},
  1193. {c_szMaxPktSize,c_dwMaxPktSize},
  1194. {c_szSourceRouteBCast,c_dwSourceRouteBCast},
  1195. {c_szSourceRouteMCast,c_dwSourceRouteMCast},
  1196. {c_szSourceRouteDef,c_dwSourceRouteDef},
  1197. {c_szSourceRouting,c_dwSourceRouting}};
  1198. for (int nIdx=0; nIdx<celems(rgAdapterSettings); nIdx++)
  1199. {
  1200. hr = ::HrRegSetDword(hkeyCard, rgAdapterSettings[nIdx].pszProp,
  1201. rgAdapterSettings[nIdx].dwValue);
  1202. if (FAILED(hr))
  1203. {
  1204. goto Error;
  1205. }
  1206. }
  1207. }
  1208. Error:
  1209. delete [] psz;
  1210. ::RegSafeCloseKey(hkeyCard);
  1211. TraceError("CIpxEnviroment::HrWriteOneAdapterInfo",hr);
  1212. return hr;
  1213. }
  1214. HRESULT CIpxEnviroment::HrWriteAdapterInfo()
  1215. {
  1216. HRESULT hr = S_OK;
  1217. HKEY hkeyAdapters = NULL;
  1218. ADAPTER_INFO_LIST::iterator iterAdapterInfo;
  1219. CIpxAdapterInfo * pAI;
  1220. // Create the IPX Adapter Subkey
  1221. hr = HrOpenIpxAdapterSubkey(&hkeyAdapters, TRUE);
  1222. if (S_OK != hr)
  1223. goto Error;
  1224. // Now commit the contents of the adapter list to the registry
  1225. for (iterAdapterInfo = m_lstpAdapterInfo.begin();
  1226. iterAdapterInfo != m_lstpAdapterInfo.end();
  1227. iterAdapterInfo++)
  1228. {
  1229. pAI = *iterAdapterInfo;
  1230. // Write out all adapter's not marked with delete pending
  1231. if (pAI->FDeletePending())
  1232. {
  1233. // Remove the NwlnkIpx\Adapter\{bindname} tree
  1234. (VOID)::HrRegDeleteKeyTree(hkeyAdapters, pAI->SzBindName());
  1235. }
  1236. else if (pAI->IsDirty())
  1237. {
  1238. hr = HrWriteOneAdapterInfo(hkeyAdapters, pAI);
  1239. if (S_OK != hr)
  1240. goto Error;
  1241. }
  1242. }
  1243. Error:
  1244. ::RegSafeCloseKey(hkeyAdapters);
  1245. TraceError("CIpxEnviroment::HrWriteAdapterInfo",hr);
  1246. return hr;
  1247. }
  1248. HRESULT CIpxEnviroment::HrCreate(CNwlnkIPX *pno, CIpxEnviroment ** ppIpxEnviroment)
  1249. {
  1250. HRESULT hr;
  1251. CIpxEnviroment * pIpxEnviroment = (CIpxEnviroment *)new CIpxEnviroment(pno);
  1252. if (pIpxEnviroment == NULL)
  1253. {
  1254. return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
  1255. }
  1256. *ppIpxEnviroment = NULL;
  1257. // Get the Ipx Parameter Key info
  1258. hr = pIpxEnviroment->HrGetIpxParams();
  1259. if (FAILED(hr))
  1260. goto Error;
  1261. // Collect the Adapter Info for all cards installed
  1262. hr = pIpxEnviroment->HrGetAdapterInfo();
  1263. if (FAILED(hr))
  1264. goto Error;
  1265. *ppIpxEnviroment = pIpxEnviroment;
  1266. Complete:
  1267. TraceError("CIpxEnviroment::HrCreate",hr);
  1268. return hr;
  1269. Error:
  1270. delete pIpxEnviroment;
  1271. goto Complete;
  1272. }
  1273. HRESULT CIpxEnviroment::HrUpdateRegistry()
  1274. {
  1275. HRESULT hr;
  1276. // Commit the registry changes
  1277. hr = ::HrRegWriteValues(celems(regbatchIpx), regbatchIpx,
  1278. (BYTE *)&m_IpxParams, REG_OPTION_NON_VOLATILE,
  1279. KEY_ALL_ACCESS);
  1280. if (S_OK != hr)
  1281. goto Error;
  1282. // Write adapter info to registry
  1283. hr = HrWriteAdapterInfo();
  1284. Error:
  1285. TraceError("CIpxEnviroment::HrUpdateRegistry",hr);
  1286. return hr;
  1287. }
  1288. VOID CIpxEnviroment::RemoveAdapter(CIpxAdapterInfo * pAI)
  1289. {
  1290. Assert(NULL != pAI);
  1291. m_lstpAdapterInfo.remove(pAI);
  1292. delete pAI;
  1293. }
  1294. HRESULT CIpxEnviroment::HrAddAdapter(INetCfgComponent * pncc)
  1295. {
  1296. HRESULT hr = S_OK;
  1297. CIpxAdapterInfo * pAI = NULL;
  1298. hr = HrGetOneAdapterInfo(pncc, &pAI);
  1299. if (FAILED(hr))
  1300. goto Error;
  1301. if (SUCCEEDED(hr))
  1302. hr = S_OK; // Normalize return
  1303. // Add the Adapter to the list
  1304. pAI->SetDirty(TRUE);
  1305. m_lstpAdapterInfo.push_back(pAI);
  1306. Error:
  1307. TraceError("CIpxEnviroment::HrAddAdapter",hr);
  1308. return hr;
  1309. }
  1310. //$ REVIEW - Start - This is moving to windows\inc\ipxpnp.h
  1311. #define IPX_RECONFIG_VERSION 0x1
  1312. #define RECONFIG_AUTO_DETECT 1
  1313. #define RECONFIG_MANUAL 2
  1314. #define RECONFIG_PREFERENCE_1 3
  1315. #define RECONFIG_NETWORK_NUMBER_1 4
  1316. #define RECONFIG_PREFERENCE_2 5
  1317. #define RECONFIG_NETWORK_NUMBER_2 6
  1318. #define RECONFIG_PREFERENCE_3 7
  1319. #define RECONFIG_NETWORK_NUMBER_3 8
  1320. #define RECONFIG_PREFERENCE_4 9
  1321. #define RECONFIG_NETWORK_NUMBER_4 10
  1322. #define RECONFIG_PARAMETERS 10
  1323. //
  1324. // Main configuration structure.
  1325. //
  1326. struct RECONFIG
  1327. {
  1328. ULONG ulVersion;
  1329. BOOLEAN InternalNetworkNumber;
  1330. BOOLEAN AdapterParameters[RECONFIG_PARAMETERS];
  1331. };
  1332. //$ REVIEW - End - This is moving to windows\inc\ipxpnp.h
  1333. //+---------------------------------------------------------------------------
  1334. //
  1335. // Member: CNwlnkIPX::HrReconfigIpx
  1336. //
  1337. // Purpose: Notify Ipx of configuration changes
  1338. //
  1339. // Arguments: none
  1340. //
  1341. // Returns: HRESULT, S_OK on success, NETCFG_S_REBOOT on failure
  1342. //
  1343. HRESULT CNwlnkIPX::HrReconfigIpx()
  1344. {
  1345. HRESULT hrRet;
  1346. HRESULT hr = S_OK;
  1347. INT nIdx;
  1348. RECONFIG Config;
  1349. CIpxAdapterInfo * pAI;
  1350. PRODUCT_FLAVOR pf;
  1351. ADAPTER_INFO_LIST::iterator iter;
  1352. ULONG ulConfigSize;
  1353. if (0 == m_pIpxEnviroment->DwCountValidAdapters())
  1354. {
  1355. return S_OK; // Nothing to configure
  1356. }
  1357. ZeroMemory(&Config, sizeof(Config));
  1358. Config.ulVersion = IPX_RECONFIG_VERSION;
  1359. // Workstation or server?
  1360. GetProductFlavor(NULL, &pf);
  1361. if (PF_WORKSTATION != pf)
  1362. {
  1363. Config.InternalNetworkNumber = TRUE;
  1364. // Now submit the global reconfig notification
  1365. hrRet = HrSendNdisPnpReconfig(NDIS, c_szSvcNwlnkIpx, c_szEmpty,
  1366. &Config, sizeof(RECONFIG));
  1367. if (FAILED(hrRet) &&
  1368. (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) != hrRet))
  1369. {
  1370. hr = NETCFG_S_REBOOT;
  1371. }
  1372. }
  1373. Config.InternalNetworkNumber = FALSE;
  1374. // For each adapter...
  1375. for (nIdx=0, iter = m_pIpxEnviroment->AdapterInfoList().begin();
  1376. iter != m_pIpxEnviroment->AdapterInfoList().end();
  1377. nIdx++, iter++)
  1378. {
  1379. pAI = *iter;
  1380. if (pAI->FDeletePending() || pAI->FDisabled() || !pAI->IsDirty())
  1381. continue;
  1382. ZeroMemory(&Config.AdapterParameters, sizeof(Config.AdapterParameters));
  1383. if (AUTO == pAI->DwFrameType())
  1384. Config.AdapterParameters[RECONFIG_AUTO_DETECT] = TRUE;
  1385. else
  1386. Config.AdapterParameters[RECONFIG_MANUAL] = TRUE;
  1387. // We are performing a shortcut here by setting a range to TRUE
  1388. // based on the number of frames in use. For example if there is
  1389. // only one frame in use we need to set both:
  1390. // RECONFIG_PREFERENCE_1 and RECONFIG_NETWORK_NUMBER_1 to TRUE
  1391. Assert(RECONFIG_PREFERENCE_1 + 1 == RECONFIG_NETWORK_NUMBER_1);
  1392. Assert(RECONFIG_NETWORK_NUMBER_1 + 1 == RECONFIG_PREFERENCE_2);
  1393. Assert(RECONFIG_PREFERENCE_2 + 1 == RECONFIG_NETWORK_NUMBER_2);
  1394. Assert(RECONFIG_NETWORK_NUMBER_2 + 1 == RECONFIG_PREFERENCE_3);
  1395. Assert(RECONFIG_PREFERENCE_3 + 1 == RECONFIG_NETWORK_NUMBER_3);
  1396. Assert(RECONFIG_NETWORK_NUMBER_3 + 1 == RECONFIG_PREFERENCE_4);
  1397. Assert(RECONFIG_PREFERENCE_4 + 1 == RECONFIG_NETWORK_NUMBER_4);
  1398. INT nCntFrms = pAI->PFrmTypeList()->size();
  1399. if ((0 < nCntFrms) && (4 >= nCntFrms))
  1400. {
  1401. memset(&Config.AdapterParameters[RECONFIG_PREFERENCE_1],
  1402. TRUE, sizeof(BOOLEAN) * nCntFrms * 2);
  1403. }
  1404. Assert(lstrlenW(pAI->SzBindName()));
  1405. // Now submit the reconfig notification
  1406. hrRet = HrSendNdisPnpReconfig(NDIS, c_szSvcNwlnkIpx, pAI->SzBindName(),
  1407. &Config, sizeof(RECONFIG));
  1408. if (FAILED(hrRet) &&
  1409. (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) != hrRet))
  1410. {
  1411. hr = NETCFG_S_REBOOT;
  1412. }
  1413. }
  1414. TraceError("CNwlnkIPX::HrReconfigIpx",hr);
  1415. return hr;
  1416. }