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.

1992 lines
59 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1997.
  5. //
  6. // File: S T E E L H E A D . C P P
  7. //
  8. // Contents: Implementation of Steelhead configuration object.
  9. //
  10. // Notes:
  11. //
  12. // Author: shaunco 15 Jun 1997
  13. //
  14. //----------------------------------------------------------------------------
  15. #include "pch.h"
  16. #pragma hdrstop
  17. #include <mprerror.h>
  18. #include <tdi.h> // must include for isnkrnl.h
  19. #include <isnkrnl.h>
  20. #include <rtinfo.h>
  21. #include <rasman.h>
  22. #include "ncreg.h"
  23. #include "rasobj.h"
  24. #include "ncsvc.h"
  25. #include "netcfgp.h"
  26. #include "router.h"
  27. extern const WCHAR c_szBiNdis5[];
  28. extern const WCHAR c_szInfId_MS_NdisWan[];
  29. //+---------------------------------------------------------------------------
  30. // Static data for adding router managers.
  31. //
  32. static const WCHAR c_szRtrMgrIp [] = L"Ip";
  33. static const WCHAR c_szRtrMgrDllIp [] = L"%SystemRoot%\\System32\\iprtrmgr.dll";
  34. static const WCHAR c_szRtrMgrIpx [] = L"Ipx";
  35. static const WCHAR c_szRtrMgrDllIpx[] = L"%SystemRoot%\\System32\\ipxrtmgr.dll";
  36. static const ROUTER_MANAGER_INFO c_rmiIp =
  37. {
  38. PID_IP,
  39. 0,
  40. c_szRtrMgrIp,
  41. c_szRtrMgrDllIp,
  42. MakeIpInterfaceInfo,
  43. MakeIpTransportInfo,
  44. };
  45. static const ROUTER_MANAGER_INFO c_rmiIpx =
  46. {
  47. PID_IPX,
  48. ISN_FRAME_TYPE_AUTO,
  49. c_szRtrMgrIpx,
  50. c_szRtrMgrDllIpx ,
  51. MakeIpxInterfaceInfo,
  52. MakeIpxTransportInfo,
  53. };
  54. // These guids are defined in sdk\inc\ifguid.h
  55. // We need the string versions.
  56. //
  57. // DEFINE_GUID(GUID_IpLoopbackInterface, 0xca6c0780, 0x7526, 0x11d2, 0xba, 0xf4, 0x00, 0x60, 0x08, 0x15, 0xa4, 0xbd);
  58. // DEFINE_GUID(GUID_IpRasServerInterface, 0x6e06f030, 0x7526, 0x11d2, 0xba, 0xf4, 0x00, 0x60, 0x08, 0x15, 0xa4, 0xbd);
  59. // DEFINE_GUID(GUID_IpxInternalInterface, 0xa571ba70, 0x7527, 0x11d2, 0xba, 0xf4, 0x00, 0x60, 0x08, 0x15, 0xa4, 0xbd);
  60. //static const WCHAR c_szIpLoopbackInterface [] = L"ca6c0780-7526-11d2-00600815a4bd";
  61. //static const WCHAR c_szIpRasServerInterface [] = L"6e06f030-7526-11d2-00600815a4bd";
  62. //static const WCHAR c_szIpxInternalInterface [] = L"a571ba70-7527-11d2-00600815a4bd";
  63. // For Ipx, the adapter name is the bind name.
  64. // We need to create an interface per frame type.
  65. // The interface name is the adapter name followed
  66. // by these strings.
  67. //
  68. #pragma BEGIN_CONST_SECTION
  69. static const MAP_SZ_DWORD c_mapFrameType [] =
  70. {
  71. L"/EthII", MISN_FRAME_TYPE_ETHERNET_II,
  72. L"/802.3", MISN_FRAME_TYPE_802_3,
  73. L"/802.2", MISN_FRAME_TYPE_802_2,
  74. L"/SNAP", MISN_FRAME_TYPE_SNAP,
  75. };
  76. #pragma END_CONST_SECTION
  77. NOTHROW
  78. BOOL
  79. FMapFrameTypeToString (
  80. DWORD dwFrameType,
  81. PCWSTR* ppszFrameType)
  82. {
  83. Assert (ppszFrameType);
  84. for (int i = 0; i < celems (c_mapFrameType); i++)
  85. {
  86. if (dwFrameType == c_mapFrameType[i].dwValue)
  87. {
  88. *ppszFrameType = c_mapFrameType[i].pszValue;
  89. return TRUE;
  90. }
  91. }
  92. TraceTag (ttidRasCfg, "FMapFrameTypeToString: Unknown frame type %d!",
  93. dwFrameType);
  94. *ppszFrameType = NULL;
  95. return FALSE;
  96. }
  97. NOTHROW
  98. BOOL
  99. FMapStringToFrameType (
  100. PCWSTR pszFrameType,
  101. DWORD* pdwFrameType)
  102. {
  103. Assert (pszFrameType);
  104. Assert (pdwFrameType);
  105. for (int i = 0; i < celems (c_mapFrameType); i++)
  106. {
  107. if (0 == lstrcmpW (pszFrameType, c_mapFrameType[i].pszValue))
  108. {
  109. *pdwFrameType = c_mapFrameType[i].dwValue;
  110. return TRUE;
  111. }
  112. }
  113. TraceTag (ttidRasCfg, "FMapStringToFrameType: Unknown frame type %S!",
  114. pszFrameType);
  115. *pdwFrameType = NULL;
  116. return FALSE;
  117. }
  118. //+---------------------------------------------------------------------------
  119. //
  120. // Function: HrShouldRouteOverAdapter
  121. //
  122. // Purpose: Indicate if we should router over the adapter or not.
  123. //
  124. // Arguments:
  125. // pnccAdapter [in] Adapter to test.
  126. // ppszBindName [out] Returned bindname if S_OK is returned.
  127. //
  128. // Returns: S_OK if we should router over the adapter, S_FALSE if not.
  129. //
  130. // Author: shaunco 27 Aug 1997
  131. //
  132. // Notes:
  133. //
  134. HRESULT
  135. HrShouldRouteOverAdapter (
  136. INetCfgComponent* pnccAdapter,
  137. PWSTR* ppszBindName)
  138. {
  139. Assert (pnccAdapter);
  140. // Initialize the output parameter.
  141. //
  142. if (ppszBindName)
  143. {
  144. *ppszBindName = NULL;
  145. }
  146. // We should return S_OK if the adapter is physical or it supports
  147. // a binding interface of ndis5. S_FALSE otherwise.
  148. //
  149. DWORD dwCharacter;
  150. HRESULT hr = pnccAdapter->GetCharacteristics (&dwCharacter);
  151. if (SUCCEEDED(hr) && !(dwCharacter & NCF_PHYSICAL))
  152. {
  153. INetCfgComponentBindings* pnccBindings;
  154. hr = pnccAdapter->QueryInterface (
  155. IID_INetCfgComponentBindings,
  156. reinterpret_cast<VOID**>(&pnccBindings));
  157. if (SUCCEEDED(hr))
  158. {
  159. hr = pnccBindings->SupportsBindingInterface (
  160. NCF_UPPER, c_szBiNdis5);
  161. ReleaseObj (pnccBindings);
  162. }
  163. if (S_OK == hr)
  164. {
  165. // Only consider devices which are present.
  166. //
  167. // This check is made *after* the check for binding interface
  168. // match above for two reasons. 1) It's much more expensive
  169. // 2) for ndiswan devices which do not come online when they
  170. // are installed (e.g. ndiswannbfout), GetDeviceStatus will
  171. // fail. For this case we don't want to route over ndiswannbf
  172. // anyhow so we should just return S_FALSE and not a failure.
  173. //
  174. DWORD dwStatus;
  175. hr = pnccAdapter->GetDeviceStatus(&dwStatus);
  176. if (SUCCEEDED(hr) && (CM_PROB_DEVICE_NOT_THERE == dwStatus))
  177. {
  178. hr = S_FALSE;
  179. }
  180. }
  181. }
  182. // SupportsBindingInterface may return S_OK or S_FALSE.
  183. // We only want the bind name if we're going to return S_OK.
  184. //
  185. if ((S_OK == hr) && ppszBindName)
  186. {
  187. hr = pnccAdapter->GetBindName (ppszBindName);
  188. }
  189. TraceError ("HrShouldRouteOverAdapter", (S_FALSE == hr) ? S_OK : hr);
  190. return hr;
  191. }
  192. #if (WINVER >= 0x0501)
  193. BOOL
  194. InitializeDialInRestriction();
  195. #endif
  196. //+---------------------------------------------------------------------------
  197. //
  198. // Member: CSteelhead::CSteelhead
  199. //
  200. // Purpose: Constructor
  201. //
  202. // Arguments:
  203. // (none)
  204. //
  205. // Returns: Nothing.
  206. //
  207. // Author: shaunco 28 Jul 1997
  208. //
  209. // Notes:
  210. //
  211. CSteelhead::CSteelhead () : CRasBindObject ()
  212. {
  213. m_hMprConfig = NULL;
  214. m_hMprAdmin = NULL;
  215. m_fRemoving = FALSE;
  216. m_fUpdateRouterConfiguration = FALSE;
  217. m_pnccMe = NULL;
  218. }
  219. //+---------------------------------------------------------------------------
  220. //
  221. // Member: CSteelhead::~CSteelhead
  222. //
  223. // Purpose: Destructor
  224. //
  225. // Arguments:
  226. // (none)
  227. //
  228. // Returns: Nothing.
  229. //
  230. // Author: shaunco 28 Jul 1997
  231. //
  232. // Notes:
  233. //
  234. CSteelhead::~CSteelhead ()
  235. {
  236. Assert (!m_hMprConfig);
  237. Assert (!m_hMprAdmin);
  238. ReleaseObj (m_pnccMe);
  239. }
  240. //+---------------------------------------------------------------------------
  241. //
  242. // Member: CSteelhead::FAdapterExistsWithMatchingBindName
  243. //
  244. // Purpose:
  245. //
  246. // Arguments:
  247. // pszAdapterName [in]
  248. // ppnccAdapter [out]
  249. //
  250. // Returns:
  251. //
  252. // Author: shaunco 27 Aug 1997
  253. //
  254. // Notes:
  255. //
  256. BOOL
  257. CSteelhead::FAdapterExistsWithMatchingBindName (
  258. PCWSTR pszAdapterName,
  259. INetCfgComponent** ppnccAdapter)
  260. {
  261. Assert (pszAdapterName);
  262. Assert (ppnccAdapter);
  263. *ppnccAdapter = NULL;
  264. BOOL fFound = FALSE;
  265. // Enumerate physical adapters in the system.
  266. //
  267. HRESULT hr = S_OK;
  268. CIterNetCfgComponent nccIter (m_pnc, &GUID_DEVCLASS_NET);
  269. INetCfgComponent* pnccAdapter;
  270. while (!fFound && S_OK == (hr = nccIter.HrNext (&pnccAdapter)))
  271. {
  272. // Only consider this adapter if we should router over it.
  273. //
  274. PWSTR pszBindName;
  275. hr = HrShouldRouteOverAdapter (pnccAdapter, &pszBindName);
  276. if (S_OK == hr)
  277. {
  278. if (0 == lstrcmpW (pszAdapterName, pszBindName))
  279. {
  280. fFound = TRUE;
  281. *ppnccAdapter = pnccAdapter;
  282. AddRefObj (pnccAdapter);
  283. }
  284. CoTaskMemFree (pszBindName);
  285. }
  286. ReleaseObj (pnccAdapter);
  287. }
  288. return fFound;
  289. }
  290. //+---------------------------------------------------------------------------
  291. //
  292. // Member: CSteelhead::FIpxFrameTypeInUseOnAdapter
  293. //
  294. // Purpose:
  295. //
  296. // Arguments:
  297. // dwFrameType []
  298. // pszAdapterName []
  299. //
  300. // Returns:
  301. //
  302. // Author: shaunco 27 Aug 1997
  303. //
  304. // Notes:
  305. //
  306. BOOL
  307. CSteelhead::FIpxFrameTypeInUseOnAdapter (
  308. DWORD dwFrameType,
  309. PCWSTR pszAdapterName)
  310. {
  311. // Assume its not in use. If PnccIpx() is NULL, it means IPX is not
  312. // installed and the frame type is definately not in use on the adapter.
  313. //
  314. BOOL fRet = FALSE;
  315. if (PnccIpx())
  316. {
  317. // Get the private interface off of the INetCfgComponent for IPX
  318. // then we can query for a notify object interface
  319. //
  320. INetCfgComponentPrivate* pinccp;
  321. HRESULT hr = PnccIpx()->QueryInterface(
  322. IID_INetCfgComponentPrivate,
  323. reinterpret_cast<VOID**>(&pinccp));
  324. if (SUCCEEDED(hr))
  325. {
  326. IIpxAdapterInfo* pIpxAdapterInfo;
  327. hr = pinccp->QueryNotifyObject(
  328. IID_IIpxAdapterInfo,
  329. reinterpret_cast<VOID**>(&pIpxAdapterInfo));
  330. if (SUCCEEDED(hr))
  331. {
  332. // Get the frametypes in use for this adapter.
  333. //
  334. DWORD adwFrameType [MISN_FRAME_TYPE_MAX + 1];
  335. DWORD cdwFrameType;
  336. hr = pIpxAdapterInfo->GetFrameTypesForAdapter (
  337. pszAdapterName,
  338. celems (adwFrameType),
  339. adwFrameType,
  340. &cdwFrameType);
  341. if (SUCCEEDED(hr))
  342. {
  343. for (DWORD i = 0; i < cdwFrameType; i++)
  344. {
  345. if (dwFrameType == adwFrameType[i])
  346. {
  347. fRet = TRUE;
  348. break;
  349. }
  350. }
  351. }
  352. ReleaseObj (pIpxAdapterInfo);
  353. }
  354. ReleaseObj (pinccp);
  355. }
  356. }
  357. return fRet;
  358. }
  359. //+---------------------------------------------------------------------------
  360. //
  361. // Member: CSteelhead::FIpxFrameTypeInUseOnAdapter
  362. //
  363. // Purpose:
  364. //
  365. // Arguments:
  366. // pszFrameType []
  367. // pszAdapterName []
  368. //
  369. // Returns:
  370. //
  371. // Author: shaunco 27 Aug 1997
  372. //
  373. // Notes:
  374. //
  375. BOOL
  376. CSteelhead::FIpxFrameTypeInUseOnAdapter (
  377. PCWSTR pszFrameType,
  378. PCWSTR pszAdapterName)
  379. {
  380. // Assume its not in use. If PnccIpx() is NULL, it means IPX is not
  381. // installed and the frame type is definately not in use on the adapter.
  382. //
  383. BOOL fRet = FALSE;
  384. DWORD dwFrameType;
  385. if (PnccIpx() && FMapStringToFrameType (pszFrameType, &dwFrameType))
  386. {
  387. fRet = FIpxFrameTypeInUseOnAdapter (dwFrameType, pszAdapterName);
  388. }
  389. return fRet;
  390. }
  391. //+---------------------------------------------------------------------------
  392. //
  393. // Member: CSteelhead::HrEnsureRouterInterfaceForAdapter
  394. //
  395. // Purpose: Ensures the router interface block for the specified
  396. // interface (adapter) is present and that the specified router
  397. // manger is configured for that interface.
  398. //
  399. // Arguments:
  400. // dwIfType [in] Interface type
  401. // dwPacketType [in] The packet type (IPX only, ignored othewise)
  402. // pszAdapterName [in] The adapter name
  403. // pszInterfaceName [in] The interface name
  404. // rmi [in] The router manager
  405. //
  406. // Returns: S_OK or an error code.
  407. //
  408. // Author: shaunco 28 Jul 1997
  409. //
  410. // Notes:
  411. //
  412. HRESULT
  413. CSteelhead::HrEnsureRouterInterfaceForAdapter (
  414. ROUTER_INTERFACE_TYPE dwIfType,
  415. DWORD dwPacketType,
  416. PCWSTR pszAdapterName,
  417. PCWSTR pszInterfaceName,
  418. const ROUTER_MANAGER_INFO& rmi)
  419. {
  420. // Make sure the interface is created.
  421. //
  422. HANDLE hConfigInterface;
  423. HANDLE hAdminInterface;
  424. HRESULT hr = HrEnsureRouterInterface (
  425. dwIfType,
  426. pszInterfaceName,
  427. &hConfigInterface,
  428. &hAdminInterface);
  429. if (SUCCEEDED(hr))
  430. {
  431. // Ensure the router manager is added to the interface.
  432. //
  433. hr = HrEnsureRouterInterfaceTransport (
  434. pszAdapterName,
  435. dwPacketType,
  436. hConfigInterface,
  437. hAdminInterface,
  438. rmi);
  439. }
  440. TraceError ("CSteelhead::HrEnsureRouterInterfaceForAdapter", hr);
  441. return hr;
  442. }
  443. //+---------------------------------------------------------------------------
  444. //
  445. // Member: CSteelhead::HrEnsureIpxRouterInterfacesForAdapter
  446. //
  447. // Purpose:
  448. //
  449. // Arguments:
  450. // pszAdapterName []
  451. //
  452. // Returns:
  453. //
  454. // Author: shaunco 27 Aug 1997
  455. //
  456. // Notes:
  457. //
  458. HRESULT
  459. CSteelhead::HrEnsureIpxRouterInterfacesForAdapter (
  460. PCWSTR pszAdapterName)
  461. {
  462. AssertSz (PnccIpx(), "Why is this being called if IPX isn't installed?");
  463. // Get the IIpxAdapterInfo interface from the IPX notify object.
  464. // We'll use it to find out how adapters are configured under IPX.
  465. //
  466. IIpxAdapterInfo* pIpxAdapterInfo;
  467. HRESULT hr = HrQueryNotifyObject (
  468. PnccIpx(),
  469. IID_IIpxAdapterInfo,
  470. reinterpret_cast<VOID**>(&pIpxAdapterInfo));
  471. if (SUCCEEDED(hr))
  472. {
  473. // Get the frametypes in use for this adapter.
  474. //
  475. DWORD adwFrameType [MISN_FRAME_TYPE_MAX + 1];
  476. DWORD cdwFrameType;
  477. hr = pIpxAdapterInfo->GetFrameTypesForAdapter (
  478. pszAdapterName,
  479. celems (adwFrameType),
  480. adwFrameType,
  481. &cdwFrameType);
  482. if (SUCCEEDED(hr) && cdwFrameType)
  483. {
  484. // If more than one frame type is in use, or if there is only
  485. // one and it isn't auto, then we'll be creating interfaces
  486. // for those frame types explicitly.
  487. //
  488. if ((cdwFrameType > 1) ||
  489. ((1 == cdwFrameType) &&
  490. (ISN_FRAME_TYPE_AUTO != adwFrameType[0])))
  491. {
  492. for (DWORD i = 0; SUCCEEDED(hr) && (i < cdwFrameType); i++)
  493. {
  494. PCWSTR pszFrameType;
  495. if (FMapFrameTypeToString (adwFrameType[i], &pszFrameType))
  496. {
  497. // Make the interface name by catenating the
  498. // adapter (bind) name with the frame type.
  499. //
  500. WCHAR szInterfaceName [512];
  501. lstrcpyW (szInterfaceName, pszAdapterName);
  502. lstrcatW (szInterfaceName, pszFrameType);
  503. hr = HrEnsureRouterInterfaceForAdapter (
  504. ROUTER_IF_TYPE_DEDICATED,
  505. adwFrameType[i],
  506. pszAdapterName,
  507. szInterfaceName,
  508. c_rmiIpx);
  509. }
  510. }
  511. }
  512. // Otherwise, we'll create the interface for the auto frame
  513. // type case.
  514. //
  515. else
  516. {
  517. #ifdef DBG
  518. AssertSz (1 == cdwFrameType,
  519. "IPX should report at least one frame type. "
  520. "You may continue without a problem.");
  521. if (1 == cdwFrameType)
  522. {
  523. AssertSz (ISN_FRAME_TYPE_AUTO == adwFrameType[0],
  524. "Frame type should be auto here. "
  525. "You may continue without a problem.");
  526. }
  527. #endif
  528. hr = HrEnsureRouterInterfaceForAdapter (
  529. ROUTER_IF_TYPE_DEDICATED,
  530. ISN_FRAME_TYPE_AUTO,
  531. pszAdapterName,
  532. pszAdapterName,
  533. c_rmiIpx);
  534. }
  535. }
  536. ReleaseObj (pIpxAdapterInfo);
  537. }
  538. TraceError ("CSteelhead::HrEnsureIpxRouterInterfacesForAdapter", hr);
  539. return hr;
  540. }
  541. //+---------------------------------------------------------------------------
  542. //
  543. // Member: CSteelhead::HrEnsureRouterInterface
  544. //
  545. // Purpose: Ensures the specified router interface is present and
  546. // returns a handle to it.
  547. //
  548. // Arguments:
  549. // pszInterfaceName [in] The interface (adapter) name
  550. // phConfigInterface [out] Returned handle to the interface
  551. //
  552. // Returns: S_OK or an error code.
  553. //
  554. // Author: shaunco 28 Jul 1997
  555. //
  556. // Notes:
  557. //
  558. HRESULT
  559. CSteelhead::HrEnsureRouterInterface (
  560. ROUTER_INTERFACE_TYPE dwIfType,
  561. PCWSTR pszInterfaceName,
  562. HANDLE* phConfigInterface,
  563. HANDLE* phAdminInterface)
  564. {
  565. Assert (pszInterfaceName);
  566. Assert (phConfigInterface);
  567. Assert (phAdminInterface);
  568. // Initialize the output parameters.
  569. //
  570. *phConfigInterface = NULL;
  571. *phAdminInterface = NULL;
  572. HRESULT hrConfig;
  573. HRESULT hrAdmin;
  574. hrConfig = HrMprConfigInterfaceGetHandle (m_hMprConfig,
  575. const_cast<PWSTR>(pszInterfaceName),
  576. phConfigInterface);
  577. hrAdmin = HrMprAdminInterfaceGetHandle (m_hMprAdmin,
  578. const_cast<PWSTR>(pszInterfaceName),
  579. phAdminInterface, FALSE);
  580. if ((HRESULT_FROM_WIN32 (ERROR_NO_SUCH_INTERFACE ) == hrConfig) ||
  581. (HRESULT_FROM_WIN32 (ERROR_NO_SUCH_INTERFACE ) == hrAdmin))
  582. {
  583. // It's not installed, so we'll create it.
  584. //
  585. MPR_INTERFACE_0 ri0;
  586. ZeroMemory (&ri0, sizeof(ri0));
  587. ri0.hInterface = INVALID_HANDLE_VALUE;
  588. ri0.fEnabled = TRUE; // thanks gibbs
  589. ri0.dwIfType = dwIfType;
  590. // Copy the interface name into the buffer.
  591. //
  592. AssertSz (lstrlenW (pszInterfaceName) < celems (ri0.wszInterfaceName),
  593. "Bindname too big for MPR_INTERFACE_0 buffer.");
  594. lstrcpyW (ri0.wszInterfaceName, pszInterfaceName);
  595. // Create the interface.
  596. //
  597. if (HRESULT_FROM_WIN32 (ERROR_NO_SUCH_INTERFACE) == hrConfig)
  598. {
  599. hrConfig = HrMprConfigInterfaceCreate (
  600. m_hMprConfig, 0, (LPBYTE)&ri0, phConfigInterface);
  601. TraceTag (ttidRasCfg, "MprConfigInterfaceCreate for %S",
  602. pszInterfaceName);
  603. }
  604. if (HRESULT_FROM_WIN32 (ERROR_NO_SUCH_INTERFACE) == hrAdmin)
  605. {
  606. hrAdmin = HrMprAdminInterfaceCreate (
  607. m_hMprAdmin, 0, (LPBYTE)&ri0, phAdminInterface);
  608. TraceTag (ttidRasCfg, "MprAdminInterfaceCreate for %S",
  609. pszInterfaceName);
  610. }
  611. }
  612. TraceError ("CSteelhead::HrEnsureRouterInterface", hrConfig);
  613. return hrConfig;
  614. }
  615. //+---------------------------------------------------------------------------
  616. //
  617. // Member: CSteelhead::HrEnsureRouterInterfaceTransport
  618. //
  619. // Purpose: Ensures the specified router manager is configured over
  620. // the specified interface.
  621. //
  622. // Arguments:
  623. // pszAdapterName [in] The adapter name
  624. // dwPacketType [in] The packet type (IPX only, ignored otherwise)
  625. // hInterface [in] Handle to the interface
  626. // rmi [in] The router manager
  627. //
  628. // Returns: S_OK or an error code.
  629. //
  630. // Author: shaunco 28 Jul 1997
  631. //
  632. // Notes:
  633. //
  634. HRESULT
  635. CSteelhead::HrEnsureRouterInterfaceTransport (
  636. PCWSTR pszAdapterName,
  637. DWORD dwPacketType,
  638. HANDLE hConfigInterface,
  639. HANDLE hAdminInterface,
  640. const ROUTER_MANAGER_INFO& rmi)
  641. {
  642. Assert (hConfigInterface);
  643. // hAdminInterface may be NULL if the router is not running.
  644. HRESULT hrConfig;
  645. // See if the router manager is present on the interface.
  646. //
  647. HANDLE hIfTransport;
  648. hrConfig = HrMprConfigInterfaceTransportGetHandle (
  649. m_hMprConfig, hConfigInterface,
  650. rmi.dwTransportId, &hIfTransport);
  651. if (FAILED(hrConfig))
  652. {
  653. // Ensure the router manager is present.
  654. //
  655. hrConfig = HrEnsureRouterManager (rmi);
  656. if (SUCCEEDED(hrConfig))
  657. {
  658. // Create the interface info and add the router manager to
  659. // the interface.
  660. //
  661. PRTR_INFO_BLOCK_HEADER pibh;
  662. Assert (rmi.pfnMakeInterfaceInfo);
  663. rmi.pfnMakeInterfaceInfo (pszAdapterName,
  664. dwPacketType,
  665. (LPBYTE*)&pibh);
  666. hrConfig = HrMprConfigInterfaceTransportAdd (
  667. m_hMprConfig,
  668. hConfigInterface,
  669. rmi.dwTransportId,
  670. const_cast<PWSTR>(rmi.pszwTransportName),
  671. (LPBYTE)pibh,
  672. pibh->Size,
  673. &hIfTransport);
  674. TraceTag (ttidRasCfg, "MprConfigInterfaceTransportAdd for "
  675. "%S on %S",
  676. rmi.pszwTransportName,
  677. pszAdapterName);
  678. if (SUCCEEDED(hrConfig) && hAdminInterface)
  679. {
  680. Assert (m_hMprAdmin);
  681. (VOID) HrMprAdminInterfaceTransportAdd (
  682. m_hMprAdmin,
  683. hAdminInterface,
  684. rmi.dwTransportId,
  685. (LPBYTE)pibh,
  686. pibh->Size);
  687. TraceTag (ttidRasCfg, "MprAdminInterfaceTransportAdd for "
  688. "%S on %S",
  689. rmi.pszwTransportName,
  690. pszAdapterName);
  691. }
  692. MemFree (pibh);
  693. }
  694. }
  695. TraceError ("CSteelhead::HrEnsureRouterInterfaceTransport", hrConfig);
  696. return hrConfig;
  697. }
  698. //+---------------------------------------------------------------------------
  699. //
  700. // Member: CSteelhead::HrEnsureRouterManager
  701. //
  702. // Purpose: Ensures that the specified router manager is installed.
  703. //
  704. // Arguments:
  705. // rmi [in] The router manager.
  706. //
  707. // Returns: S_OK or an error code.
  708. //
  709. // Author: shaunco 28 Jul 1997
  710. //
  711. // Notes:
  712. //
  713. HRESULT
  714. CSteelhead::HrEnsureRouterManager (
  715. const ROUTER_MANAGER_INFO& rmi)
  716. {
  717. PRTR_INFO_BLOCK_HEADER pibhGlobal;
  718. BOOL fCreate = FALSE;
  719. // See if the router manager is installed.
  720. //
  721. HANDLE hTransport;
  722. HRESULT hr = HrMprConfigTransportGetHandle (m_hMprConfig,
  723. rmi.dwTransportId,
  724. &hTransport);
  725. if (HRESULT_FROM_WIN32 (ERROR_UNKNOWN_PROTOCOL_ID) == hr)
  726. {
  727. // It's not installed, we'll create it.
  728. //
  729. fCreate = TRUE;
  730. }
  731. else if (SUCCEEDED(hr))
  732. {
  733. // Its installed, see if its transport info is available.
  734. //
  735. DWORD dwSize;
  736. hr = HrMprConfigTransportGetInfo (m_hMprConfig, hTransport,
  737. (LPBYTE*)&pibhGlobal, &dwSize,
  738. NULL, NULL, NULL);
  739. if (SUCCEEDED(hr))
  740. {
  741. if (!pibhGlobal)
  742. {
  743. // Global info is missing, we'll create it.
  744. //
  745. fCreate = TRUE;
  746. }
  747. else
  748. {
  749. MprConfigBufferFree (pibhGlobal);
  750. }
  751. }
  752. }
  753. if (fCreate)
  754. {
  755. // Install the router manager.
  756. //
  757. Assert (rmi.pfnMakeTransportInfo);
  758. PRTR_INFO_BLOCK_HEADER pibhClient;
  759. rmi.pfnMakeTransportInfo ((LPBYTE*)&pibhGlobal,
  760. (LPBYTE*)&pibhClient);
  761. hr = HrMprConfigTransportCreate (
  762. m_hMprConfig,
  763. rmi.dwTransportId,
  764. const_cast<PWSTR>(rmi.pszwTransportName),
  765. (LPBYTE)pibhGlobal, (pibhGlobal) ? pibhGlobal->Size : 0,
  766. (LPBYTE)pibhClient, (pibhClient) ? pibhClient->Size : 0,
  767. const_cast<PWSTR>(rmi.pszwDllPath),
  768. &hTransport);
  769. (VOID) HrMprAdminTransportCreate (
  770. m_hMprAdmin,
  771. rmi.dwTransportId,
  772. const_cast<PWSTR>(rmi.pszwTransportName),
  773. (LPBYTE)pibhGlobal, (pibhGlobal) ? pibhGlobal->Size : 0,
  774. (LPBYTE)pibhClient, (pibhClient) ? pibhClient->Size : 0,
  775. const_cast<PWSTR>(rmi.pszwDllPath));
  776. MemFree (pibhGlobal);
  777. MemFree (pibhClient);
  778. }
  779. TraceError ("CSteelhead::HrEnsureRouterManager", hr);
  780. return hr;
  781. }
  782. //+---------------------------------------------------------------------------
  783. //
  784. // Member: CSteelhead::HrEnsureRouterManagerDeleted
  785. //
  786. // Purpose: Ensures that the specified router manager is not installed.
  787. //
  788. // Arguments:
  789. // rmi [in] The router manager.
  790. //
  791. // Returns: S_OK or an error code.
  792. //
  793. // Author: shaunco 6 Sep 1997
  794. //
  795. // Notes:
  796. //
  797. HRESULT CSteelhead::HrEnsureRouterManagerDeleted (
  798. const ROUTER_MANAGER_INFO& rmi)
  799. {
  800. // See if the router manager is installed.
  801. //
  802. HANDLE hTransport;
  803. HRESULT hr = HrMprConfigTransportGetHandle (m_hMprConfig,
  804. rmi.dwTransportId,
  805. &hTransport);
  806. if (SUCCEEDED(hr))
  807. {
  808. // It is installed, so we need to delete it.
  809. //
  810. (VOID) HrMprConfigTransportDelete (m_hMprConfig, hTransport);
  811. }
  812. TraceError ("CSteelhead::HrEnsureRouterManagerDeleted",
  813. (HRESULT_FROM_WIN32 (ERROR_UNKNOWN_PROTOCOL_ID) == hr)
  814. ? S_OK : hr);
  815. return hr;
  816. }
  817. //+---------------------------------------------------------------------------
  818. //
  819. // Member: CSteelhead::HrPassToAddInterfaces
  820. //
  821. // Purpose:
  822. //
  823. // Arguments:
  824. // (none)
  825. //
  826. // Returns:
  827. //
  828. // Author: shaunco 27 Aug 1997
  829. //
  830. // Notes:
  831. //
  832. HRESULT
  833. CSteelhead::HrPassToAddInterfaces ()
  834. {
  835. HRESULT hr = S_OK;
  836. // Enumerate physical adapters in the system.
  837. //
  838. CIterNetCfgComponent nccIter(m_pnc, &GUID_DEVCLASS_NET);
  839. INetCfgComponent* pnccAdapter;
  840. while (S_OK == (hr = nccIter.HrNext(&pnccAdapter)))
  841. {
  842. // Only consider this adapter if we should router over it.
  843. //
  844. PWSTR pszBindName;
  845. hr = HrShouldRouteOverAdapter (pnccAdapter, &pszBindName);
  846. if (S_OK == hr)
  847. {
  848. INetCfgComponentBindings* pnccBindingsIp = NULL;
  849. INetCfgComponentBindings* pnccBindingsIpx = NULL;
  850. // If Ip is bound to the adapter, create and interface
  851. // for it.
  852. //
  853. if (PnccIp())
  854. {
  855. hr = PnccIp()->QueryInterface (IID_INetCfgComponentBindings,
  856. reinterpret_cast<VOID**>(&pnccBindingsIp) );
  857. }
  858. if (PnccIp() && SUCCEEDED(hr) &&
  859. (S_OK == (hr = pnccBindingsIp->IsBoundTo (pnccAdapter))))
  860. {
  861. // Interface name is the same as the adapter name
  862. // is the same as the bind name.
  863. //
  864. hr = HrEnsureRouterInterfaceForAdapter (
  865. ROUTER_IF_TYPE_DEDICATED,
  866. 0,
  867. pszBindName,
  868. pszBindName,
  869. c_rmiIp);
  870. }
  871. ReleaseObj (pnccBindingsIp);
  872. // If Ipx is bound to the adapter, create the interface(s)
  873. // for it.
  874. if (PnccIpx())
  875. {
  876. hr = PnccIpx()->QueryInterface (IID_INetCfgComponentBindings,
  877. reinterpret_cast<VOID**>(&pnccBindingsIpx));
  878. }
  879. if (PnccIpx() &&
  880. (S_OK == (hr = pnccBindingsIpx->IsBoundTo( pnccAdapter )) ))
  881. {
  882. #if (WINVER < 0x0501)
  883. hr = HrEnsureIpxRouterInterfacesForAdapter (pszBindName);
  884. #endif
  885. }
  886. ReleaseObj (pnccBindingsIpx);
  887. CoTaskMemFree (pszBindName);
  888. }
  889. ReleaseObj (pnccAdapter);
  890. }
  891. // Normalize the HRESULT. (i.e. don't return S_FALSE)
  892. if (S_FALSE == hr)
  893. {
  894. hr = S_OK;
  895. }
  896. TraceError ("CSteelhead::HrPassToAddInterfaces", hr);
  897. return hr;
  898. }
  899. //+---------------------------------------------------------------------------
  900. //
  901. // Member: CSteelhead::HrPassToRemoveInterfaces
  902. //
  903. // Purpose:
  904. //
  905. // Arguments:
  906. // (none)
  907. //
  908. // Returns:
  909. //
  910. // Author: shaunco 27 Aug 1997
  911. //
  912. // Notes:
  913. //
  914. HRESULT
  915. CSteelhead::HrPassToRemoveInterfaces (
  916. BOOL fFromRunningRouter)
  917. {
  918. // Enumerate all of the installed router interfaces.
  919. //
  920. MPR_INTERFACE_0* ari0;
  921. DWORD dwEntriesRead;
  922. DWORD dwTotalEntries;
  923. HRESULT hr;
  924. if (fFromRunningRouter)
  925. {
  926. Assert (m_hMprAdmin);
  927. hr = HrMprAdminInterfaceEnum (m_hMprAdmin, 0,
  928. reinterpret_cast<LPBYTE*>(&ari0),
  929. -1, &dwEntriesRead, &dwTotalEntries, NULL);
  930. }
  931. else
  932. {
  933. hr = HrMprConfigInterfaceEnum (m_hMprConfig, 0,
  934. reinterpret_cast<LPBYTE*>(&ari0),
  935. -1, &dwEntriesRead, &dwTotalEntries, NULL);
  936. }
  937. if (SUCCEEDED(hr))
  938. {
  939. // By passing -1, we want everything, so we should get everything.
  940. Assert (dwEntriesRead == dwTotalEntries);
  941. // Iterate all of the interfaces.
  942. //
  943. for (MPR_INTERFACE_0* pri0 = ari0; dwEntriesRead--; pri0++)
  944. {
  945. BOOL fDeleteInterface = FALSE;
  946. PCWSTR pszInternalAdapter = SzLoadIds (IDS_RAS_INTERNAL_ADAPTER);
  947. // If its the internal interface and IP and IPX are no longer
  948. // installed delete the interface.
  949. //
  950. if ((ROUTER_IF_TYPE_INTERNAL == pri0->dwIfType) &&
  951. !PnccIpx() && !PnccIp() &&
  952. (0 == lstrcmpW (pri0->wszInterfaceName, pszInternalAdapter)))
  953. {
  954. fDeleteInterface = TRUE;
  955. }
  956. else if (ROUTER_IF_TYPE_DEDICATED != pri0->dwIfType)
  957. {
  958. // Skip non-dedicated interfaces.
  959. //
  960. continue;
  961. }
  962. BOOL fSpecialIpxInterface = FALSE;
  963. INetCfgComponent* pnccAdapter = NULL;
  964. // Get the name of the interface and look for a '/' separator.
  965. // If present, it means this is a special IPX interface where
  966. // the first substring is the adapter name, and the second
  967. // substring is the frame type.
  968. //
  969. WCHAR* pchwSep = wcschr (pri0->wszInterfaceName, L'/');
  970. if (!fDeleteInterface && pchwSep)
  971. {
  972. fSpecialIpxInterface = TRUE;
  973. // Point to the frame type string.
  974. //
  975. PCWSTR pszFrameType = pchwSep;
  976. // Copy the adapter name into its own buffer.
  977. //
  978. WCHAR szAdapterName [MAX_INTERFACE_NAME_LEN+1];
  979. lstrcpynW (szAdapterName, pri0->wszInterfaceName,
  980. (int)(pchwSep - pri0->wszInterfaceName + 1));
  981. // If the frame type is not in use for the adapter, we need
  982. // to delete this interface. This condition happens when
  983. // IPX configuration is changed and the frame type is removed
  984. // from the adapter.
  985. //
  986. if (!FIpxFrameTypeInUseOnAdapter (pszFrameType,
  987. szAdapterName))
  988. {
  989. fDeleteInterface = TRUE;
  990. TraceTag (ttidRasCfg, "%S no longer in use on %S. "
  991. "Deleting the router interface.",
  992. pszFrameType, szAdapterName);
  993. }
  994. }
  995. // It's not a special interface, so just make sure an adapter
  996. // exists with a matching bind name. If not, we will delete
  997. // the interface.
  998. //
  999. else if (!fDeleteInterface)
  1000. {
  1001. if (!FAdapterExistsWithMatchingBindName (
  1002. pri0->wszInterfaceName,
  1003. &pnccAdapter))
  1004. {
  1005. fDeleteInterface = TRUE;
  1006. TraceTag (ttidRasCfg, "%S no longer present. "
  1007. "Deleting the router interface.",
  1008. pri0->wszInterfaceName);
  1009. }
  1010. }
  1011. // Delete the interface if we need to.
  1012. //
  1013. if (fDeleteInterface)
  1014. {
  1015. if (fFromRunningRouter)
  1016. {
  1017. MprAdminInterfaceDelete (m_hMprAdmin, pri0->hInterface);
  1018. }
  1019. else
  1020. {
  1021. MprConfigInterfaceDelete (m_hMprConfig, pri0->hInterface);
  1022. }
  1023. }
  1024. // If we don't need to delete the entire interface, check
  1025. // for transports on the interface that we may need to delete.
  1026. // Don't do this for the running router because there is
  1027. // no MprAdminInterfaceTransportEnum API.
  1028. //
  1029. else if (!fFromRunningRouter)
  1030. {
  1031. // If its not an IPX special interface, the adapter
  1032. // is the interface name. If it is an IPX special
  1033. // interface, then we would have already remove the entire
  1034. // interface above if it were invalid.
  1035. //
  1036. (VOID) HrPassToRemoveInterfaceTransports (
  1037. pri0,
  1038. (!fSpecialIpxInterface) ? pri0->wszInterfaceName
  1039. : NULL,
  1040. pnccAdapter);
  1041. }
  1042. ReleaseObj (pnccAdapter);
  1043. }
  1044. MprConfigBufferFree (ari0);
  1045. }
  1046. else if ((HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS) == hr) ||
  1047. (HRESULT_FROM_WIN32(RPC_S_SERVER_UNAVAILABLE) == hr) ||
  1048. (HRESULT_FROM_WIN32(RPC_S_UNKNOWN_IF) == hr))
  1049. {
  1050. hr = S_OK;
  1051. }
  1052. TraceError ("CSteelhead::HrPassToRemoveInterfaces", hr);
  1053. return hr;
  1054. }
  1055. //+---------------------------------------------------------------------------
  1056. //
  1057. // Member: CSteelhead::HrPassToRemoveInterfaceTransports
  1058. //
  1059. // Purpose:
  1060. //
  1061. // Arguments:
  1062. // hInterface []
  1063. // pszAdapterName []
  1064. //
  1065. // Returns:
  1066. //
  1067. // Author: shaunco 27 Aug 1997
  1068. //
  1069. // Notes:
  1070. //
  1071. HRESULT
  1072. CSteelhead::HrPassToRemoveInterfaceTransports (
  1073. MPR_INTERFACE_0* pri0,
  1074. PCWSTR pszAdapterName,
  1075. INetCfgComponent* pnccAdapter)
  1076. {
  1077. Assert (FImplies(pnccAdapter, pszAdapterName));
  1078. // Enumerate all of the transports active on the router interface.
  1079. //
  1080. MPR_IFTRANSPORT_0* arit0;
  1081. DWORD dwEntriesRead;
  1082. DWORD dwTotalEntries;
  1083. HRESULT hr = HrMprConfigInterfaceTransportEnum (m_hMprConfig,
  1084. pri0->hInterface, 0,
  1085. reinterpret_cast<LPBYTE*>(&arit0),
  1086. -1, &dwEntriesRead, &dwTotalEntries, NULL);
  1087. if (SUCCEEDED(hr))
  1088. {
  1089. // By passing -1, we want everything, so we should get everything.
  1090. Assert (dwEntriesRead == dwTotalEntries);
  1091. INetCfgComponentBindings* pnccBindingsIpx = NULL;
  1092. INetCfgComponentBindings* pnccBindingsIp = NULL;
  1093. if (PnccIp())
  1094. {
  1095. hr = PnccIp()->QueryInterface (IID_INetCfgComponentBindings,
  1096. reinterpret_cast<VOID**>(&pnccBindingsIp));
  1097. }
  1098. if (SUCCEEDED(hr))
  1099. {
  1100. if (PnccIpx())
  1101. {
  1102. hr = PnccIpx()->QueryInterface (IID_INetCfgComponentBindings,
  1103. reinterpret_cast<VOID**>(&pnccBindingsIpx));
  1104. }
  1105. if (SUCCEEDED(hr))
  1106. {
  1107. // Iterate all of the transports.
  1108. //
  1109. for (MPR_IFTRANSPORT_0* prit0 = arit0; dwEntriesRead--; prit0++)
  1110. {
  1111. BOOL fDeleteInterfaceTransport = FALSE;
  1112. if (prit0->dwTransportId == c_rmiIp.dwTransportId)
  1113. {
  1114. if (!PnccIp())
  1115. {
  1116. fDeleteInterfaceTransport = TRUE;
  1117. TraceTag (ttidRasCfg, "TCP/IP no longer present. "
  1118. "Deleting this transport from interface %S.",
  1119. pri0->wszInterfaceName);
  1120. }
  1121. else if (pnccAdapter &&
  1122. (S_OK != (hr = pnccBindingsIp->IsBoundTo (pnccAdapter))))
  1123. {
  1124. fDeleteInterfaceTransport = TRUE;
  1125. TraceTag (ttidRasCfg, "TCP/IP no longer bound. "
  1126. "Deleting this transport from interface %S.",
  1127. pri0->wszInterfaceName);
  1128. }
  1129. }
  1130. else if (prit0->dwTransportId == c_rmiIpx.dwTransportId)
  1131. {
  1132. if (!PnccIpx())
  1133. {
  1134. fDeleteInterfaceTransport = TRUE;
  1135. TraceTag (ttidRasCfg, "IPX no longer present. "
  1136. "Deleting this transport from interface %S.",
  1137. pri0->wszInterfaceName);
  1138. }
  1139. else if (pnccAdapter &&
  1140. (S_OK != (hr = pnccBindingsIpx->IsBoundTo (pnccAdapter))))
  1141. {
  1142. fDeleteInterfaceTransport = TRUE;
  1143. TraceTag (ttidRasCfg, "IPX no longer bound. "
  1144. "Deleting this transport from interface %S.",
  1145. pri0->wszInterfaceName);
  1146. }
  1147. else if (pszAdapterName)
  1148. {
  1149. Assert (PnccIpx());
  1150. // if frame type is not auto on this adapter, delete
  1151. // the transport
  1152. if (!FIpxFrameTypeInUseOnAdapter (ISN_FRAME_TYPE_AUTO,
  1153. pszAdapterName))
  1154. {
  1155. fDeleteInterfaceTransport = TRUE;
  1156. TraceTag (ttidRasCfg, "IPX Auto frame type no longer "
  1157. "in use on %S. "
  1158. "Deleting this transport from interface %S.",
  1159. pszAdapterName, pri0->wszInterfaceName);
  1160. }
  1161. }
  1162. }
  1163. if (fDeleteInterfaceTransport)
  1164. {
  1165. MprConfigInterfaceTransportRemove (
  1166. m_hMprConfig,
  1167. pri0->hInterface,
  1168. prit0->hIfTransport);
  1169. }
  1170. }
  1171. MprConfigBufferFree (arit0);
  1172. ReleaseObj (pnccBindingsIpx);
  1173. }
  1174. ReleaseObj (pnccBindingsIp);
  1175. }
  1176. }
  1177. else if (HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS) == hr)
  1178. {
  1179. // If there are no transports for this interface, that's okay.
  1180. //
  1181. hr = S_OK;
  1182. }
  1183. TraceError ("CSteelhead::HrPassToRemoveInterfaceTransports", hr);
  1184. return hr;
  1185. }
  1186. //+---------------------------------------------------------------------------
  1187. //
  1188. // Member: CSteelhead::HrUpdateRouterConfiguration
  1189. //
  1190. // Purpose: Updates the router configuration by ensuring router managers
  1191. // are installed for the protocols present on the system (IP and
  1192. // IPX). Further, router interfaces are created for each
  1193. // physical netcard present on the system.
  1194. //
  1195. // Arguments:
  1196. // (none)
  1197. //
  1198. // Returns: S_OK or an error code.
  1199. //
  1200. // Author: shaunco 28 Jul 1997
  1201. //
  1202. // Notes:
  1203. //
  1204. HRESULT
  1205. CSteelhead::HrUpdateRouterConfiguration ()
  1206. {
  1207. HKEY hKey;
  1208. Assert (!m_hMprConfig);
  1209. HRESULT hr = HrMprConfigServerConnect (NULL, &m_hMprConfig);
  1210. if (SUCCEEDED(hr))
  1211. {
  1212. PCWSTR pszInternalAdapter = SzLoadIds (IDS_RAS_INTERNAL_ADAPTER);
  1213. PCWSTR pszLoopbackAdapter = SzLoadIds (IDS_RAS_LOOPBACK_ADAPTER);
  1214. // Connect to the running router if able.
  1215. // (m_hMprAdmin will be non-NULL if we do.)
  1216. //
  1217. Assert (!m_hMprAdmin);
  1218. (VOID) HrMprAdminServerConnect (NULL, &m_hMprAdmin);
  1219. // Ensure router managers are installed for the protocols
  1220. // we know about. Good to do this in case no physical adapters.
  1221. // are found below. We actually do this by ensuring the internal
  1222. // interface exists. This will implicitly ensure the router
  1223. // manger is created.
  1224. //
  1225. if (PnccIp())
  1226. {
  1227. (VOID) HrEnsureRouterInterfaceForAdapter (
  1228. ROUTER_IF_TYPE_LOOPBACK,
  1229. c_rmiIp.dwPacketType,
  1230. pszLoopbackAdapter,
  1231. pszLoopbackAdapter,
  1232. c_rmiIp);
  1233. (VOID) HrEnsureRouterInterfaceForAdapter (
  1234. ROUTER_IF_TYPE_INTERNAL,
  1235. c_rmiIp.dwPacketType,
  1236. pszInternalAdapter,
  1237. pszInternalAdapter,
  1238. c_rmiIp);
  1239. }
  1240. else
  1241. {
  1242. (VOID) HrEnsureRouterManagerDeleted (c_rmiIp);
  1243. }
  1244. if (PnccIpx())
  1245. {
  1246. (VOID) HrEnsureRouterInterfaceForAdapter (
  1247. ROUTER_IF_TYPE_INTERNAL,
  1248. c_rmiIpx.dwPacketType,
  1249. pszInternalAdapter,
  1250. pszInternalAdapter,
  1251. c_rmiIpx);
  1252. }
  1253. else
  1254. {
  1255. (VOID) HrEnsureRouterManagerDeleted (c_rmiIpx);
  1256. }
  1257. (VOID) HrPassToAddInterfaces ();
  1258. (VOID) HrPassToRemoveInterfaces (FALSE);
  1259. // If we have a connection to the running router, make a pass
  1260. // to remove interfaces from it.
  1261. //
  1262. if (m_hMprAdmin)
  1263. {
  1264. (VOID) HrPassToRemoveInterfaces (TRUE);
  1265. #if (WINVER >= 0x0501)
  1266. (VOID) HrRemoveIPXRouterConfiguration(TRUE);
  1267. #endif
  1268. MprAdminServerDisconnect (m_hMprAdmin);
  1269. m_hMprAdmin = NULL;
  1270. }
  1271. #if (WINVER >= 0x0501)
  1272. (VOID) HrRemoveIPXRouterConfiguration(FALSE);
  1273. //
  1274. // Remove IPX router Manager configuration
  1275. //
  1276. (VOID) HrEnsureRouterManagerDeleted(c_rmiIpx);
  1277. //
  1278. // Remove IPX keys under HKLM\Software\Microsoft\Router\CurrentVersion
  1279. //
  1280. hr = HrRegOpenKeyEx(
  1281. HKEY_LOCAL_MACHINE,
  1282. L"Software\\Microsoft\\Router\\CurrentVersion\\RouterManagers",
  1283. KEY_ALL_ACCESS,
  1284. &hKey
  1285. );
  1286. if (SUCCEEDED(hr))
  1287. {
  1288. (VOID) SHDeleteKey(hKey, L"Ipx");
  1289. RegCloseKey(hKey);
  1290. hKey = NULL;
  1291. }
  1292. //
  1293. // Remove IPX keys under HKLM\Software\Microsoft\IPXMibAgent
  1294. //
  1295. hr = HrRegOpenKeyEx(
  1296. HKEY_LOCAL_MACHINE,
  1297. L"Software\\Microsoft",
  1298. KEY_ALL_ACCESS,
  1299. &hKey
  1300. );
  1301. if (SUCCEEDED(hr))
  1302. {
  1303. (VOID) SHDeleteKey(hKey, L"IPXMibAgent");
  1304. RegCloseKey(hKey);
  1305. hKey = NULL;
  1306. }
  1307. //
  1308. // Remove keys for NWLNKFWD and NWLNKFLT
  1309. //
  1310. hr = HrRegOpenKeyEx(
  1311. HKEY_LOCAL_MACHINE,
  1312. L"System\\CurrentControlSet\\Services",
  1313. KEY_ALL_ACCESS,
  1314. &hKey
  1315. );
  1316. if (SUCCEEDED(hr))
  1317. {
  1318. (VOID) SHDeleteKey(hKey, L"NwlnkFwd");
  1319. (VOID) SHDeleteKey(hKey, L"NwlnkFlt");
  1320. RegCloseKey(hKey);
  1321. hKey = NULL;
  1322. }
  1323. //
  1324. // Restrict ports on non-Enterprise/non-datacenter SKU to
  1325. // 100 per media type
  1326. //
  1327. //
  1328. // Check server version.
  1329. //
  1330. hr = S_OK;
  1331. if (InitializeDialInRestriction())
  1332. {
  1333. //
  1334. // For standard version, limit ports for all media types to a 100
  1335. //
  1336. //
  1337. // Open key "System\\CurrentControlSet\\Control
  1338. // \\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}"
  1339. //
  1340. hr = HrRegOpenKeyEx(
  1341. HKEY_LOCAL_MACHINE,
  1342. L"System\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}",
  1343. KEY_ALL_ACCESS,
  1344. &hKey
  1345. );
  1346. if (SUCCEEDED(hr))
  1347. {
  1348. // Enumerate subkeys
  1349. // - for each key check value of WanEndpoints
  1350. // - if value greater than MAX_DIALIN restrict it to that.
  1351. //
  1352. //
  1353. DWORD dwIndex = 0;
  1354. WCHAR wcKeyName[MAX_PATH + 1];
  1355. DWORD dwSize = MAX_PATH + 1, dwValue;
  1356. HKEY hEnumKey = NULL;
  1357. FILETIME ft;
  1358. do
  1359. {
  1360. dwSize = MAX_PATH + 1;
  1361. hr = HrRegEnumKeyEx(
  1362. hKey,
  1363. dwIndex,
  1364. wcKeyName,
  1365. &dwSize,
  1366. NULL,
  1367. NULL,
  1368. &ft
  1369. );
  1370. if (HRESULT_CODE(hr) == ERROR_NO_MORE_ITEMS)
  1371. {
  1372. hr = HRESULT_FROM_WIN32(ERROR_SUCCESS);
  1373. break;
  1374. }
  1375. if ((HRESULT_CODE(hr) != ERROR_MORE_DATA) &&
  1376. (HRESULT_CODE(hr) != ERROR_SUCCESS))
  1377. {
  1378. dwIndex++;
  1379. continue;
  1380. }
  1381. hr = HrRegOpenKeyEx(
  1382. hKey,
  1383. wcKeyName,
  1384. KEY_ALL_ACCESS,
  1385. &hEnumKey
  1386. );
  1387. if (FAILED(hr))
  1388. {
  1389. //
  1390. // Move to next key
  1391. //
  1392. dwIndex++;
  1393. continue;
  1394. }
  1395. dwValue = 0;
  1396. hr = HrRegQueryDword(
  1397. hEnumKey,
  1398. L"WanEndPoints",
  1399. &dwValue
  1400. );
  1401. if (SUCCEEDED(hr) && (dwValue > MAX_ALLOWED_DIALIN))
  1402. {
  1403. HrRegSetDword(
  1404. hEnumKey,
  1405. L"WanEndPoints",
  1406. MAX_ALLOWED_DIALIN
  1407. );
  1408. }
  1409. RegCloseKey(hEnumKey);
  1410. hEnumKey = NULL;
  1411. dwIndex++;
  1412. } while( TRUE );
  1413. RegCloseKey(hKey);
  1414. hKey = NULL;
  1415. }
  1416. if (FAILED(hr))
  1417. {
  1418. //
  1419. // Since this code may be invoked by non-admin, e.g NetCfgop,
  1420. // when IP addresses etc. are changed, access denied can be
  1421. // ignored in those cases
  1422. //
  1423. if (HRESULT_CODE(hr) == ERROR_ACCESS_DENIED)
  1424. {
  1425. TraceError ("CSteelhead::HrUpdateRouterConfiguration, "
  1426. "ignoring ", hr);
  1427. hr = HRESULT_FROM_WIN32(ERROR_SUCCESS);
  1428. }
  1429. }
  1430. }
  1431. #endif
  1432. MprConfigServerDisconnect (m_hMprConfig);
  1433. m_hMprConfig = NULL;
  1434. }
  1435. TraceError ("CSteelhead::HrUpdateRouterConfiguration", hr);
  1436. return hr;
  1437. }
  1438. #if (WINVER >= 0x0501)
  1439. //+---------------------------------------------------------------------------
  1440. //
  1441. // Member : CSteelhead::HrRemoveIPXRouterConfiguration
  1442. //
  1443. // Purpose: Updates the router configuration to remove all the IPX related
  1444. // configuration
  1445. //
  1446. // Arguments:
  1447. // fRouter - Remove from running instance of router
  1448. //
  1449. // Returns: S_OK or an error code.
  1450. //
  1451. // Author: vraman 17 April 2002
  1452. //
  1453. // Notes:
  1454. //
  1455. HRESULT
  1456. CSteelhead::HrRemoveIPXRouterConfiguration(
  1457. BOOL fRouter)
  1458. {
  1459. HRESULT hr = S_OK;
  1460. MPR_INTERFACE_0 *ari0;
  1461. DWORD dwIfRead, dwIfTotal, dwIfTransRead, dwIfTransTotal;
  1462. HANDLE hIfTransport;
  1463. //
  1464. // Enumerate interfaces
  1465. //
  1466. if (fRouter)
  1467. {
  1468. Assert (m_hMprAdmin);
  1469. hr = HrMprAdminInterfaceEnum(
  1470. m_hMprAdmin,
  1471. 0,
  1472. reinterpret_cast<LPBYTE*>(&ari0),
  1473. -1,
  1474. &dwIfRead,
  1475. &dwIfTotal,
  1476. NULL
  1477. );
  1478. }
  1479. else
  1480. {
  1481. hr = HrMprConfigInterfaceEnum(
  1482. m_hMprConfig,
  1483. 0,
  1484. reinterpret_cast<LPBYTE*>(&ari0),
  1485. -1,
  1486. &dwIfRead,
  1487. &dwIfTotal,
  1488. NULL
  1489. );
  1490. }
  1491. if (SUCCEEDED(hr))
  1492. {
  1493. for (MPR_INTERFACE_0 *pri0 = ari0; dwIfRead--; pri0++)
  1494. {
  1495. //
  1496. // For each interface, remove RRAS IPX config
  1497. //
  1498. if (fRouter)
  1499. {
  1500. hr = HrMprAdminInterfaceTransportRemove(
  1501. m_hMprAdmin,
  1502. pri0->hInterface,
  1503. PID_IPX
  1504. );
  1505. }
  1506. else
  1507. {
  1508. hr = HrMprConfigInterfaceTransportGetHandle(
  1509. m_hMprConfig,
  1510. pri0->hInterface,
  1511. PID_IPX,
  1512. &hIfTransport
  1513. );
  1514. if (SUCCEEDED(hr))
  1515. {
  1516. hr = HrMprConfigInterfaceTransportRemove(
  1517. m_hMprConfig,
  1518. pri0->hInterface,
  1519. hIfTransport
  1520. );
  1521. }
  1522. }
  1523. }
  1524. }
  1525. TraceError ("CSteelhead::HrRemoveIPXRouterConfiguration", hr);
  1526. return hr;
  1527. }
  1528. #endif
  1529. //+---------------------------------------------------------------------------
  1530. // INetCfgComponentControl
  1531. //
  1532. STDMETHODIMP
  1533. CSteelhead::Initialize (
  1534. INetCfgComponent* pncc,
  1535. INetCfg* pnc,
  1536. BOOL fInstalling)
  1537. {
  1538. Validate_INetCfgNotify_Initialize (pncc, pnc, fInstalling);
  1539. // Hold on to our the component representing us and our host
  1540. // INetCfg object.
  1541. AddRefObj (m_pnccMe = pncc);
  1542. AddRefObj (m_pnc = pnc);
  1543. m_fUpdateRouterConfiguration = fInstalling;
  1544. return S_OK;
  1545. }
  1546. STDMETHODIMP
  1547. CSteelhead::Validate ()
  1548. {
  1549. return S_OK;
  1550. }
  1551. STDMETHODIMP
  1552. CSteelhead::CancelChanges ()
  1553. {
  1554. return S_OK;
  1555. }
  1556. STDMETHODIMP
  1557. CSteelhead::ApplyRegistryChanges ()
  1558. {
  1559. HRESULT hr = S_OK;
  1560. if (!m_fRemoving && m_fUpdateRouterConfiguration)
  1561. {
  1562. m_fUpdateRouterConfiguration = FALSE;
  1563. TraceTag (ttidRasCfg, "Updating Steelhead configuration.");
  1564. hr = HrFindOtherComponents ();
  1565. if (SUCCEEDED(hr))
  1566. {
  1567. hr = HrUpdateRouterConfiguration ();
  1568. ReleaseOtherComponents ();
  1569. }
  1570. if (FAILED(hr))
  1571. {
  1572. hr = NETCFG_S_REBOOT;
  1573. }
  1574. }
  1575. Validate_INetCfgNotify_Apply_Return (hr);
  1576. TraceError ("CSteelhead::ApplyRegistryChanges",
  1577. (NETCFG_S_REBOOT == hr) ? S_OK : hr);
  1578. return hr;
  1579. }
  1580. //+---------------------------------------------------------------------------
  1581. // INetCfgComponentSetup
  1582. //
  1583. STDMETHODIMP
  1584. CSteelhead::ReadAnswerFile (
  1585. PCWSTR pszAnswerFile,
  1586. PCWSTR pszAnswerSection)
  1587. {
  1588. return S_OK;
  1589. }
  1590. STDMETHODIMP
  1591. CSteelhead::Install (DWORD dwSetupFlags)
  1592. {
  1593. HRESULT hr;
  1594. Validate_INetCfgNotify_Install (dwSetupFlags);
  1595. // Install NdisWan.
  1596. hr = HrInstallComponentOboComponent (m_pnc, NULL,
  1597. GUID_DEVCLASS_NETTRANS,
  1598. c_szInfId_MS_NdisWan,
  1599. m_pnccMe,
  1600. NULL);
  1601. TraceError ("CSteelhead::Install", hr);
  1602. return hr;
  1603. }
  1604. STDMETHODIMP
  1605. CSteelhead::Removing ()
  1606. {
  1607. HRESULT hr;
  1608. m_fRemoving = TRUE;
  1609. // Remove NdisWan.
  1610. hr = HrRemoveComponentOboComponent (m_pnc,
  1611. GUID_DEVCLASS_NETTRANS,
  1612. c_szInfId_MS_NdisWan,
  1613. m_pnccMe);
  1614. TraceError ("CSteelhead::Removing", hr);
  1615. return hr;
  1616. }
  1617. STDMETHODIMP
  1618. CSteelhead::Upgrade (
  1619. DWORD dwSetupFlags,
  1620. DWORD dwUpgradeFromBuildNo)
  1621. {
  1622. return S_FALSE;
  1623. }
  1624. //+---------------------------------------------------------------------------
  1625. // INetCfgSystemNotify
  1626. //
  1627. STDMETHODIMP
  1628. CSteelhead::GetSupportedNotifications (
  1629. DWORD* pdwNotificationFlag)
  1630. {
  1631. Validate_INetCfgSystemNotify_GetSupportedNotifications (pdwNotificationFlag);
  1632. *pdwNotificationFlag = NCN_NET | NCN_NETTRANS |
  1633. NCN_ADD | NCN_REMOVE |
  1634. NCN_PROPERTYCHANGE;
  1635. return S_OK;
  1636. }
  1637. STDMETHODIMP
  1638. CSteelhead::SysQueryBindingPath (
  1639. DWORD dwChangeFlag,
  1640. INetCfgBindingPath* pncbp)
  1641. {
  1642. return S_OK;
  1643. }
  1644. STDMETHODIMP
  1645. CSteelhead::SysQueryComponent (
  1646. DWORD dwChangeFlag,
  1647. INetCfgComponent* pncc)
  1648. {
  1649. return S_OK;
  1650. }
  1651. STDMETHODIMP
  1652. CSteelhead::SysNotifyBindingPath (
  1653. DWORD dwChangeFlag,
  1654. INetCfgBindingPath* pncbp)
  1655. {
  1656. return S_FALSE;
  1657. }
  1658. STDMETHODIMP
  1659. CSteelhead::SysNotifyComponent (
  1660. DWORD dwChangeFlag,
  1661. INetCfgComponent* pncc)
  1662. {
  1663. HRESULT hr;
  1664. Validate_INetCfgSystemNotify_SysNotifyComponent (dwChangeFlag, pncc);
  1665. // Assume we won't be dirty as a result of this notification.
  1666. //
  1667. hr = S_FALSE;
  1668. if (!m_fUpdateRouterConfiguration)
  1669. {
  1670. // If we're being called for a change to a net device, make sure
  1671. // its physical before deciding we need to update our configuration.
  1672. //
  1673. GUID guidClass;
  1674. hr = pncc->GetClassGuid (&guidClass);
  1675. if (S_OK == hr)
  1676. {
  1677. if (GUID_DEVCLASS_NET == guidClass)
  1678. {
  1679. hr = HrShouldRouteOverAdapter (pncc, NULL);
  1680. if (S_OK == hr)
  1681. {
  1682. TraceTag (ttidRasCfg, "CSteelhead::SysNotifyComponent: "
  1683. "called for adapter install/remove.");
  1684. m_fUpdateRouterConfiguration = TRUE;
  1685. Assert (S_OK == hr);
  1686. }
  1687. }
  1688. else
  1689. {
  1690. TraceTag (ttidRasCfg, "CSteelhead::SysNotifyComponent: "
  1691. "called for protocol add/remove/change.");
  1692. // If we're called for non-net devices, we want to
  1693. // update our configuration. (GetSupportedNotifications
  1694. // controls how often we fall into this.)
  1695. //
  1696. m_fUpdateRouterConfiguration = TRUE;
  1697. Assert (S_OK == hr);
  1698. }
  1699. }
  1700. }
  1701. TraceHr (ttidError, FAL, hr, (S_FALSE == hr),
  1702. "CSteelhead::SysNotifyComponent", hr);
  1703. return hr;
  1704. }
  1705. #if (WINVER >= 0x0501)
  1706. //+---------------------------------------------------------------------------
  1707. //
  1708. // Member : InitializeDialInRestriction
  1709. //
  1710. // Purpose: Checks if the upgrade is to the enterprise or datacenter
  1711. // edition of server. If so there is no restriction on the
  1712. // number of dialin ports. Otherwise the max number should
  1713. // be restricted to a 100.
  1714. //
  1715. // Arguments:
  1716. //
  1717. // Returns: TRUE if dailin restriction is required, false otherwise
  1718. //
  1719. // Author: vraman, 30 August 2002
  1720. //
  1721. // Notes:
  1722. //
  1723. BOOL
  1724. InitializeDialInRestriction()
  1725. {
  1726. OSVERSIONINFOEX osvi;
  1727. ULONGLONG ConditionMask;
  1728. BOOL bRestrictDialIn = TRUE;
  1729. //
  1730. // if its a server and the flavour is not Enterprise (ads) or DataCenter
  1731. // apply the restriction. Note his doesn't take care of various other
  1732. // combinations like embedded/blade, etc.
  1733. //
  1734. ConditionMask = 0;
  1735. ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
  1736. osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
  1737. osvi.wProductType = (USHORT)VER_NT_SERVER;
  1738. VER_SET_CONDITION(ConditionMask, VER_PRODUCT_TYPE, VER_EQUAL);
  1739. if(VerifyVersionInfo(&osvi, VER_PRODUCT_TYPE, ConditionMask))
  1740. {
  1741. //
  1742. // Upgrade is to a server version
  1743. //
  1744. ConditionMask = 0;
  1745. ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
  1746. osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
  1747. osvi.wSuiteMask = VER_SUITE_ENTERPRISE
  1748. | VER_SUITE_DATACENTER
  1749. | VER_SUITE_SECURITY_APPLIANCE;
  1750. VER_SET_CONDITION(ConditionMask, VER_SUITENAME, VER_OR);
  1751. if(VerifyVersionInfo(&osvi, VER_SUITENAME, ConditionMask))
  1752. {
  1753. //
  1754. // Upgrade is to a enterprise or datacenter edition
  1755. // Do not restrict server edition
  1756. //
  1757. bRestrictDialIn = FALSE;
  1758. }
  1759. }
  1760. return bRestrictDialIn;
  1761. }
  1762. #endif