Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1450 lines
28 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. rmALG.cpp
  5. Abstract:
  6. This module contains routines for the ALG Manager module's
  7. interface to the IP router-manager. (See ROUTPROT.H for details).
  8. Author:
  9. JPDup 10-Nov-2000
  10. Revision History:
  11. --*/
  12. #include "precomp.h"
  13. #pragma hdrstop
  14. #include <ipnatapi.h>
  15. #include <initguid.h>
  16. #include <atlbase.h>
  17. extern CComModule _Module;
  18. #include <atlcom.h>
  19. #include "Alg_private.h"
  20. #include "NatPrivateAPI_Imp.h"
  21. #include <MyTrace.h>
  22. MYTRACE_ENABLE
  23. //
  24. // Globals
  25. //
  26. COMPONENT_REFERENCE AlgComponentReference;
  27. PIP_ALG_GLOBAL_INFO AlgGlobalInfo = NULL;
  28. CRITICAL_SECTION AlgGlobalInfoLock;
  29. HANDLE AlgNotificationEvent;
  30. HANDLE AlgTimerQueueHandle = NULL;
  31. HANDLE AlgPortReservationHandle = NULL;
  32. HANDLE AlgTranslatorHandle = NULL;
  33. ULONG AlgProtocolStopped = 0;
  34. IP_ALG_STATISTICS AlgStatistics;
  35. SUPPORT_FUNCTIONS AlgSupportFunctions;
  36. //
  37. // GIT cookie for the IHNetCfgMgr instance
  38. //
  39. DWORD AlgGITcookie = 0;
  40. IGlobalInterfaceTable* AlgGITp = NULL;
  41. const MPR_ROUTING_CHARACTERISTICS AlgRoutingCharacteristics =
  42. {
  43. MS_ROUTER_VERSION,
  44. MS_IP_ALG,
  45. RF_ROUTING|RF_ADD_ALL_INTERFACES,
  46. AlgRmStartProtocol,
  47. AlgRmStartComplete,
  48. AlgRmStopProtocol,
  49. AlgRmGetGlobalInfo,
  50. AlgRmSetGlobalInfo,
  51. NULL,
  52. NULL,
  53. AlgRmAddInterface,
  54. AlgRmDeleteInterface,
  55. AlgRmInterfaceStatus,
  56. NULL,
  57. NULL,
  58. NULL,
  59. NULL,
  60. NULL,
  61. NULL,
  62. NULL,
  63. NULL,
  64. NULL,
  65. NULL,
  66. NULL, //AlgRmMibGet,
  67. NULL, //AlgRmMibSet,
  68. NULL, //AlgRmMibGetFirst,
  69. NULL, //AlgRmMibGetNext,
  70. NULL,
  71. NULL
  72. };
  73. #define COMINIT_BEGIN \
  74. bool bComInitialized = true; \
  75. hr = CoInitializeEx(NULL, COINIT_MULTITHREADED | COINIT_DISABLE_OLE1DDE ); \
  76. if ( FAILED(hr) ) \
  77. { \
  78. bComInitialized = FALSE; \
  79. if (RPC_E_CHANGED_MODE == hr) \
  80. hr = S_OK; \
  81. } \
  82. #define COMINIT_END if (TRUE == bComInitialized) { CoUninitialize(); }
  83. #define IID_PPV_ARG(Type, Expr) \
  84. __uuidof(Type), reinterpret_cast<void**>(static_cast<Type **>((Expr)))
  85. //
  86. //
  87. //
  88. HRESULT
  89. GetAlgControllerInterface(
  90. IAlgController** ppAlgController
  91. )
  92. /*++
  93. Routine Description:
  94. This routine obtains a pointer to the home networking configuration
  95. manager.
  96. Arguments:
  97. ppAlgController - receives the IAlgController pointer. The caller must release this pointer.
  98. Return Value:
  99. standard HRESULT
  100. Environment:
  101. COM must be initialized on the calling thread
  102. --*/
  103. {
  104. HRESULT hr = S_OK;
  105. if ( NULL == AlgGITp )
  106. {
  107. IAlgController* pIAlgController;
  108. //
  109. // Create the global interface table
  110. //
  111. hr = CoCreateInstance(
  112. CLSID_StdGlobalInterfaceTable,
  113. NULL,
  114. CLSCTX_INPROC_SERVER,
  115. IID_PPV_ARG(IGlobalInterfaceTable, &AlgGITp)
  116. );
  117. if ( SUCCEEDED(hr) )
  118. {
  119. //
  120. // Create the ALG Interface (ALG.exe will start as a service by COM)
  121. //
  122. hr = CoCreateInstance(
  123. CLSID_AlgController,
  124. NULL,
  125. CLSCTX_LOCAL_SERVER,
  126. IID_PPV_ARG(IAlgController, &pIAlgController)
  127. );
  128. if ( FAILED(hr) )
  129. {
  130. NhTrace(
  131. TRACE_FLAG_INIT,
  132. "GetAlgControllerInterface: Unable to create pIAlgController (0x%08x)",
  133. hr
  134. );
  135. }
  136. }
  137. else
  138. {
  139. NhTrace(
  140. TRACE_FLAG_INIT,
  141. "GetAlgControllerInterface: Unable to create GIT (0x%08x)",
  142. hr
  143. );
  144. }
  145. if (SUCCEEDED(hr))
  146. {
  147. //
  148. // Store the CfgMgr pointer in the GIT
  149. //
  150. hr = AlgGITp->RegisterInterfaceInGlobal(
  151. pIAlgController,
  152. IID_IAlgController,
  153. &AlgGITcookie
  154. );
  155. pIAlgController->Release();
  156. if ( FAILED(hr) )
  157. {
  158. NhTrace(
  159. TRACE_FLAG_INIT,
  160. "GetAlgControllerInterface: Unable to register pIAlgController (0x%08x)",
  161. hr
  162. );
  163. }
  164. }
  165. }
  166. if ( SUCCEEDED(hr) )
  167. {
  168. hr = AlgGITp->GetInterfaceFromGlobal(
  169. AlgGITcookie,
  170. IID_PPV_ARG(IAlgController, ppAlgController)
  171. );
  172. }
  173. return hr;
  174. } // GetAlgControllerInterface
  175. //
  176. //
  177. //
  178. void
  179. FreeAlgControllerInterface()
  180. {
  181. //
  182. // Free up HNetCfgMgr pointers
  183. //
  184. if ( !AlgGITp )
  185. return; // nothing to free
  186. //
  187. // Make sure COM is initialized
  188. //
  189. HRESULT hr;
  190. COMINIT_BEGIN;
  191. if ( SUCCEEDED(hr) )
  192. {
  193. //
  194. // Release the ALG.exe private interface from the GIT
  195. //
  196. AlgGITp->RevokeInterfaceFromGlobal(AlgGITcookie);
  197. AlgGITcookie = 0;
  198. //
  199. // Release the GIT
  200. //
  201. AlgGITp->Release();
  202. AlgGITp = NULL;
  203. }
  204. COMINIT_END;
  205. }
  206. VOID
  207. AlgCleanupModule(
  208. VOID
  209. )
  210. /*++
  211. Routine Description:
  212. This routine is invoked to cleanup the ALG transparent proxy module.
  213. Arguments:
  214. none.
  215. Return Value:
  216. none.
  217. Environment:
  218. Invoked from within a 'DllMain' routine on 'DLL_PROCESS_DETACH'.
  219. --*/
  220. {
  221. DeleteCriticalSection(&AlgGlobalInfoLock);
  222. DeleteComponentReference(&AlgComponentReference);
  223. } // AlgCleanupModule
  224. VOID
  225. AlgCleanupProtocol(
  226. VOID
  227. )
  228. /*++
  229. Routine Description:
  230. This routine is invoked to cleanup the ALG transparent proxy
  231. protocol-component after a 'StopProtocol'. It runs when the last reference
  232. to the component is released. (See 'COMPREF.H').
  233. Arguments:
  234. none.
  235. Return Value:
  236. none.
  237. Environment:
  238. Invoked from within an arbitrary context with no locks held.
  239. --*/
  240. {
  241. PROFILE("AlgCleanupProtocol");
  242. if (AlgGlobalInfo) { NH_FREE(AlgGlobalInfo); AlgGlobalInfo = NULL; }
  243. if (AlgTimerQueueHandle) {
  244. DeleteTimerQueueEx(AlgTimerQueueHandle, INVALID_HANDLE_VALUE);
  245. AlgTimerQueueHandle = NULL;
  246. }
  247. if (AlgPortReservationHandle) {
  248. NatShutdownPortReservation(AlgPortReservationHandle);
  249. AlgPortReservationHandle = NULL;
  250. }
  251. if (AlgTranslatorHandle) {
  252. NatShutdownTranslator(AlgTranslatorHandle); AlgTranslatorHandle = NULL;
  253. }
  254. InterlockedExchange(reinterpret_cast<LPLONG>(&AlgProtocolStopped), 1);
  255. SetEvent(AlgNotificationEvent);
  256. ResetComponentReference(&AlgComponentReference);
  257. //
  258. // Free the GIT and AlgController interface
  259. //
  260. FreeAlgControllerInterface();
  261. } // AlgCleanupProtocol
  262. BOOLEAN
  263. AlgInitializeModule(
  264. VOID
  265. )
  266. /*++
  267. Routine Description:
  268. This routine is invoked to initialize the FnP module.
  269. Arguments:
  270. none.
  271. Return Value:
  272. BOOLEAN - TRUE if initialization succeeded, FALSE otherwise
  273. Environment:
  274. Invoked in the context of a 'DllMain' routine on 'DLL_PROCESS_ATTACH'.
  275. --*/
  276. {
  277. if (InitializeComponentReference(
  278. &AlgComponentReference, AlgCleanupProtocol
  279. ))
  280. {
  281. return FALSE;
  282. }
  283. __try
  284. {
  285. InitializeCriticalSection(&AlgGlobalInfoLock);
  286. }
  287. __except(EXCEPTION_EXECUTE_HANDLER)
  288. {
  289. DeleteComponentReference(&AlgComponentReference);
  290. return FALSE;
  291. }
  292. return TRUE;
  293. } // AlgInitializeModule
  294. //
  295. // Get ALG COM Interface to Start the ALG and give call back Interface
  296. //
  297. HRESULT
  298. Initialise_ALG()
  299. {
  300. HRESULT hr;
  301. COMINIT_BEGIN;
  302. if ( FAILED(hr) )
  303. return hr;
  304. //
  305. // Get COM to load the ALG.exe
  306. // The ALG will be launch using a LOCAL_SERVICE priviledge
  307. // See the RunAs entry under the AppID of the ALG.exe
  308. //
  309. IAlgController* pIAlgController=NULL;
  310. hr = GetAlgControllerInterface(&pIAlgController);
  311. if ( SUCCEEDED(hr) )
  312. {
  313. //
  314. // We create our Private COM interface to the NAT api
  315. //
  316. CComObject<CNat>* pComponentNat;
  317. hr = CComObject<CNat>::CreateInstance(&pComponentNat);
  318. if ( SUCCEEDED(hr) )
  319. {
  320. pComponentNat->AddRef();
  321. //
  322. // Make sure we pass a INat interface
  323. //
  324. INat* pINat=NULL;
  325. hr = pComponentNat->QueryInterface(IID_INat, (void**)&pINat);
  326. if ( SUCCEEDED(hr) )
  327. {
  328. //
  329. // Let the ALG manager start the loading of all the ALG modules
  330. //
  331. hr = pIAlgController->Start(pINat);
  332. if ( FAILED(hr) )
  333. {
  334. NhTrace(
  335. TRACE_FLAG_INIT,
  336. "Initialise_ALG: Error (0x%08x) on pIAlgController->Start(pINat)",
  337. hr
  338. );
  339. }
  340. //
  341. // ALG manager will have AddRef this INat so we can release
  342. //
  343. pINat->Release();
  344. }
  345. pComponentNat->Release();
  346. }
  347. }
  348. else
  349. {
  350. NhTrace(
  351. TRACE_FLAG_INIT,
  352. "Initialise_ALG: Error (0x%08x) Getting the IAlgController interface",
  353. hr
  354. );
  355. return hr;
  356. }
  357. if ( pIAlgController )
  358. pIAlgController->Release();
  359. COMINIT_END;
  360. return S_OK;
  361. }
  362. ULONG
  363. APIENTRY
  364. AlgRmStartProtocol(
  365. HANDLE NotificationEvent,
  366. PSUPPORT_FUNCTIONS SupportFunctions,
  367. PVOID GlobalInfo,
  368. ULONG StructureVersion,
  369. ULONG StructureSize,
  370. ULONG StructureCount
  371. )
  372. /*++
  373. Routine Description:
  374. This routine is invoked to indicate the component's operation should begin.
  375. Arguments:
  376. NotificationEvent - event on which we notify the router-manager
  377. about asynchronous occurrences
  378. SupportFunctions - functions for initiating router-related operations
  379. GlobalInfo - configuration for the component
  380. Return Value:
  381. ULONG - Win32 status code.
  382. Environment:
  383. The routine runs in the context of an IP router-manager thread.
  384. --*/
  385. {
  386. MYTRACE_START(L"rmALG");
  387. MYTRACE_ENTER("AlgRmStartProtocol");
  388. PROFILE("AlgRmStartProtocol");
  389. ULONG Error = NO_ERROR;
  390. ULONG Size;
  391. REFERENCE_ALG_OR_RETURN(ERROR_CAN_NOT_COMPLETE);
  392. if (!GlobalInfo) { DEREFERENCE_ALG_AND_RETURN(ERROR_INVALID_PARAMETER); }
  393. do {
  394. //
  395. // Copy the global configuration
  396. //
  397. EnterCriticalSection(&AlgGlobalInfoLock);
  398. Size = sizeof(*AlgGlobalInfo);
  399. AlgGlobalInfo =
  400. reinterpret_cast<PIP_ALG_GLOBAL_INFO>(NH_ALLOCATE(Size));
  401. if (!AlgGlobalInfo) {
  402. LeaveCriticalSection(&AlgGlobalInfoLock);
  403. NhTrace(
  404. TRACE_FLAG_INIT,
  405. "AlgRmStartProtocol: cannot allocate global info"
  406. );
  407. NhErrorLog(
  408. IP_ALG_LOG_ALLOCATION_FAILED,
  409. 0,
  410. "%d",
  411. Size
  412. );
  413. Error = ERROR_NOT_ENOUGH_MEMORY;
  414. break;
  415. }
  416. CopyMemory(AlgGlobalInfo, GlobalInfo, Size);
  417. //
  418. // Save the notification event
  419. //
  420. AlgNotificationEvent = NotificationEvent;
  421. //
  422. // Save the support functions
  423. //
  424. if (!SupportFunctions) {
  425. ZeroMemory(&AlgSupportFunctions, sizeof(AlgSupportFunctions));
  426. } else {
  427. CopyMemory(
  428. &AlgSupportFunctions,
  429. SupportFunctions,
  430. sizeof(*SupportFunctions)
  431. );
  432. }
  433. //
  434. // Obtain a handle to the kernel-mode translation module.
  435. //
  436. Error = NatInitializeTranslator(&AlgTranslatorHandle);
  437. if (Error) {
  438. NhTrace(
  439. TRACE_FLAG_INIT,
  440. "AlgRmStartProtocol: error %d initializing translator",
  441. Error
  442. );
  443. break;
  444. }
  445. //
  446. // Obtain a port-reservation handle
  447. //
  448. Error = NatInitializePortReservation(
  449. ALG_PORT_RESERVATION_BLOCK_SIZE,
  450. &AlgPortReservationHandle
  451. );
  452. if (Error)
  453. {
  454. NhTrace(
  455. TRACE_FLAG_INIT,
  456. "AlgRmStartProtocol: error %d initializing port-reservation",
  457. Error
  458. );
  459. break;
  460. }
  461. AlgTimerQueueHandle = CreateTimerQueue();
  462. if (AlgTimerQueueHandle == NULL) {
  463. Error = GetLastError();
  464. NhTrace(
  465. TRACE_FLAG_INIT,
  466. "AlgRmStartProtocol: error %d initializing timer queue",
  467. Error
  468. );
  469. break;
  470. }
  471. //
  472. // Start the ALG.exe
  473. //
  474. Initialise_ALG();
  475. LeaveCriticalSection(&AlgGlobalInfoLock);
  476. InterlockedExchange(reinterpret_cast<LPLONG>(&AlgProtocolStopped), 0);
  477. } while (FALSE);
  478. DEREFERENCE_ALG_AND_RETURN(Error);
  479. } // AlgRmStartProtocol
  480. ULONG
  481. APIENTRY
  482. AlgRmStartComplete(
  483. VOID
  484. )
  485. /*++
  486. Routine Description:
  487. This routine is invoked when the router has finished adding the initial
  488. configuration.
  489. Arguments:
  490. none.
  491. Return Value:
  492. ULONG - Win32 status code
  493. Environment:
  494. The routine runs in the context of an IP router-manager thread.
  495. --*/
  496. {
  497. return NO_ERROR;
  498. } // AlgRmStartComplete
  499. ULONG
  500. APIENTRY
  501. AlgRmStopProtocol(
  502. VOID
  503. )
  504. /*++
  505. Routine Description:
  506. This routine is invoked to stop the protocol.
  507. Arguments:
  508. none.
  509. Return Value:
  510. ULONG - Win32 status code
  511. Environment:
  512. The routine runs in the context of an IP router-manager thread.
  513. --*/
  514. {
  515. MYTRACE_ENTER("AlgRmStopProtocol");
  516. PROFILE("AlgRmStopProtocol");
  517. //
  518. // Reference the module to make sure it's running
  519. //
  520. REFERENCE_ALG_OR_RETURN(ERROR_CAN_NOT_COMPLETE);
  521. //
  522. // Stop all ALG
  523. //
  524. HRESULT hr;
  525. COMINIT_BEGIN;
  526. if ( SUCCEEDED(hr) )
  527. {
  528. IAlgController* pIAlgController=NULL;
  529. hr = GetAlgControllerInterface(&pIAlgController);
  530. if ( SUCCEEDED(hr) )
  531. {
  532. hr = pIAlgController->Stop();
  533. if ( FAILED(hr) )
  534. {
  535. NhTrace(
  536. TRACE_FLAG_INIT,
  537. "AlgRmStopProtocol: Error (0x%08x) returned from pIalgController->Stop()",
  538. hr
  539. );
  540. }
  541. ULONG nRef = pIAlgController->Release();
  542. //
  543. // We are done with the ALG
  544. // Free the GIT and AlgController interface
  545. //
  546. FreeAlgControllerInterface();
  547. }
  548. }
  549. COMINIT_END;
  550. //
  551. // Drop the initial reference to cause a cleanup
  552. //
  553. ReleaseInitialComponentReference(&AlgComponentReference);
  554. MYTRACE_STOP;
  555. return DEREFERENCE_ALG() ? NO_ERROR : ERROR_PROTOCOL_STOP_PENDING;
  556. } // AlgRmStopProtocol
  557. ULONG
  558. APIENTRY
  559. AlgRmAddInterface(
  560. PWCHAR Name,
  561. ULONG Index,
  562. NET_INTERFACE_TYPE Type,
  563. ULONG MediaType,
  564. USHORT AccessType,
  565. USHORT ConnectionType,
  566. PVOID InterfaceInfo,
  567. ULONG StructureVersion,
  568. ULONG StructureSize,
  569. ULONG StructureCount
  570. )
  571. /*++
  572. Routine Description:
  573. This routine is invoked to add an interface to the component.
  574. Arguments:
  575. Name - the name of the interface (unused)
  576. Index - the index of the interface
  577. Type - the type of the interface
  578. InterfaceInfo - the configuration information for the interface
  579. Return Value:
  580. ULONG - Win32 status code.
  581. Environment:
  582. The routine runs in the context of an IP router-manager thread.
  583. --*/
  584. {
  585. PROFILE("AlgRmAddInterface");
  586. REFERENCE_ALG_OR_RETURN(ERROR_CAN_NOT_COMPLETE);
  587. ULONG Error = NO_ERROR;
  588. //
  589. // Also notify the ALG.exe manager
  590. //
  591. HRESULT hr;
  592. COMINIT_BEGIN;
  593. if ( SUCCEEDED(hr) )
  594. {
  595. IAlgController* pIAlgController=NULL;
  596. HRESULT hr = GetAlgControllerInterface(&pIAlgController);
  597. if ( SUCCEEDED(hr) )
  598. {
  599. ULONG nInterfaceCharacteristics = NatGetInterfaceCharacteristics(Index);
  600. short nTypeOfAdapter = 0;
  601. if ( NAT_IFC_BOUNDARY(nInterfaceCharacteristics) )
  602. nTypeOfAdapter |= eALG_BOUNDARY;
  603. if ( NAT_IFC_FW(nInterfaceCharacteristics) )
  604. nTypeOfAdapter |= eALG_FIREWALLED;
  605. if ( NAT_IFC_PRIVATE(nInterfaceCharacteristics) )
  606. nTypeOfAdapter |= eALG_PRIVATE;
  607. hr = pIAlgController->Adapter_Add(
  608. Index,
  609. (short)nTypeOfAdapter
  610. );
  611. if ( FAILED(hr) )
  612. {
  613. NhTrace(
  614. TRACE_FLAG_INIT,
  615. "AlgRmAddInterface: Error (0x%08x) returned from pIalgController->Adapter_Add()",
  616. hr
  617. );
  618. }
  619. pIAlgController->Release();
  620. }
  621. }
  622. COMINIT_END;
  623. DEREFERENCE_ALG_AND_RETURN(Error);
  624. } // AlgRmAddInterface
  625. ULONG
  626. APIENTRY
  627. AlgRmDeleteInterface(
  628. ULONG Index
  629. )
  630. /*++
  631. Routine Description:
  632. This routine is invoked to delete an interface from the component.
  633. Arguments:
  634. Index - the index of the interface
  635. Return Value:
  636. ULONG - Win32 status code
  637. Environment:
  638. The routine runs in the context of an IP router-manager thread.
  639. --*/
  640. {
  641. ULONG Error = S_OK;
  642. PROFILE("AlgRmDeleteInterface");
  643. REFERENCE_ALG_OR_RETURN(ERROR_CAN_NOT_COMPLETE);
  644. //
  645. // Also notify the ALG.exe manager
  646. //
  647. HRESULT hr;
  648. COMINIT_BEGIN;
  649. if ( SUCCEEDED(hr) )
  650. {
  651. IAlgController* pIAlgController=NULL;
  652. HRESULT hr = GetAlgControllerInterface(&pIAlgController);
  653. if ( SUCCEEDED(hr) )
  654. {
  655. hr = pIAlgController->Adapter_Remove(Index);
  656. if ( FAILED(hr) )
  657. {
  658. NhTrace(
  659. TRACE_FLAG_INIT,
  660. "AlgRmAddInterface: Error (0x%08x) returned from pIalgController->Adapter_Remove()",
  661. hr
  662. );
  663. }
  664. pIAlgController->Release();
  665. }
  666. }
  667. COMINIT_END;
  668. DEREFERENCE_ALG_AND_RETURN(Error);
  669. } // AlgRmDeleteInterface
  670. ULONG
  671. APIENTRY
  672. AlgRmInterfaceStatus(
  673. ULONG Index,
  674. BOOL InterfaceActive,
  675. ULONG StatusType,
  676. PVOID StatusInfo
  677. )
  678. /*++
  679. Routine Description:
  680. This routine is invoked to bind/unbind, enable/disable an interface
  681. Arguments:
  682. Index - the interface to be bound
  683. InterfaceActive - whether the interface is active
  684. StatusType - type of status being changed (bind or enabled)
  685. StatusInfo - Info pertaining to the state being changed
  686. Return Value:
  687. ULONG - Win32 Status code
  688. Environment:
  689. The routine runs in the context of an IP router-manager thread.
  690. --*/
  691. {
  692. ULONG Error = NO_ERROR;
  693. switch(StatusType) {
  694. case RIS_INTERFACE_ADDRESS_CHANGE: {
  695. PIP_ADAPTER_BINDING_INFO BindInfo =
  696. (PIP_ADAPTER_BINDING_INFO)StatusInfo;
  697. if (BindInfo->AddressCount) {
  698. Error = AlgRmBindInterface(Index, StatusInfo);
  699. } else {
  700. Error = AlgRmUnbindInterface(Index);
  701. }
  702. break;
  703. }
  704. case RIS_INTERFACE_ENABLED: {
  705. Error = AlgRmEnableInterface(Index);
  706. break;
  707. }
  708. case RIS_INTERFACE_DISABLED: {
  709. Error = AlgRmDisableInterface(Index);
  710. break;
  711. }
  712. }
  713. return Error;
  714. } // AlgRmInterfaceStatus
  715. ULONG
  716. AlgRmBindInterface(
  717. ULONG Index,
  718. PVOID BindingInfo
  719. )
  720. /*++
  721. Routine Description:
  722. This routine is invoked to bind an interface to its IP address(es).
  723. Arguments:
  724. Index - the interface to be bound
  725. BindingInfo - the addressing information
  726. Return Value:
  727. ULONG - Win32 status code.
  728. Environment:
  729. The routine runs in the context of an IP router-manager thread.
  730. --*/
  731. {
  732. ULONG Error = NO_ERROR;
  733. PROFILE("AlgRmBindInterface");
  734. REFERENCE_ALG_OR_RETURN(ERROR_CAN_NOT_COMPLETE);
  735. HRESULT hr;
  736. //
  737. // Also notify the ALG.exe manager
  738. //
  739. ULONG nAddressCount = ((PIP_ADAPTER_BINDING_INFO)BindingInfo)->AddressCount;
  740. //
  741. // Build a simple array of address(DWORD) to send over RPC
  742. //
  743. DWORD* apdwAddress = new DWORD[((PIP_ADAPTER_BINDING_INFO)BindingInfo)->AddressCount];
  744. if(NULL != apdwAddress)
  745. {
  746. for ( ULONG nAddress=0; nAddress < nAddressCount; nAddress++ )
  747. {
  748. apdwAddress[nAddress] = ((PIP_ADAPTER_BINDING_INFO)BindingInfo)->Address[nAddress].Address;
  749. }
  750. COMINIT_BEGIN;
  751. if ( SUCCEEDED(hr) )
  752. {
  753. IAlgController* pIAlgController=NULL;
  754. HRESULT hr = GetAlgControllerInterface(&pIAlgController);
  755. if ( SUCCEEDED(hr) )
  756. {
  757. ULONG nRealAdapterIndex = NhMapAddressToAdapter(apdwAddress[0]);
  758. hr = pIAlgController->Adapter_Bind(
  759. Index,
  760. nRealAdapterIndex,
  761. nAddressCount,
  762. apdwAddress
  763. );
  764. if ( FAILED(hr) )
  765. {
  766. NhTrace(
  767. TRACE_FLAG_INIT,
  768. "AlgRmBinInterface: Error (0x%08x) returned from pIalgController->Adapter_Bind()",
  769. hr
  770. );
  771. }
  772. pIAlgController->Release();
  773. }
  774. }
  775. COMINIT_END;
  776. delete [] apdwAddress;
  777. }
  778. DEREFERENCE_ALG_AND_RETURN(Error);
  779. } // AlgRmBindInterface
  780. ULONG
  781. AlgRmUnbindInterface(
  782. ULONG Index
  783. )
  784. /*++
  785. Routine Description:
  786. This routine is invoked to unbind an interface from its IP address(es).
  787. Arguments:
  788. Index - the interface to be unbound
  789. Return Value:
  790. ULONG - Win32 status code.
  791. Environment:
  792. The routine runs in the context of an IP router-manager thread.
  793. --*/
  794. {
  795. ULONG Error = NO_ERROR;
  796. PROFILE("AlgRmUnbindInterface");
  797. REFERENCE_ALG_OR_RETURN(ERROR_CAN_NOT_COMPLETE);
  798. /*
  799. Error =
  800. AlgUnbindInterface(
  801. Index
  802. );
  803. */
  804. DEREFERENCE_ALG_AND_RETURN(Error);
  805. } // AlgRmUnbindInterface
  806. ULONG
  807. AlgRmEnableInterface(
  808. ULONG Index
  809. )
  810. /*++
  811. Routine Description:
  812. This routine is invoked to enable operation on an interface.
  813. Arguments:
  814. Index - the interface to be enabled.
  815. Return Value:
  816. ULONG - Win32 status code.
  817. Environment:
  818. The routine runs in the context of an IP router-manager thread.
  819. --*/
  820. {
  821. ULONG Error = NO_ERROR;
  822. PROFILE("AlgRmEnableInterface");
  823. REFERENCE_ALG_OR_RETURN(ERROR_CAN_NOT_COMPLETE);
  824. /*
  825. Error =
  826. AlgEnableInterface(
  827. Index
  828. );
  829. */
  830. DEREFERENCE_ALG_AND_RETURN(Error);
  831. } // AlgRmEnableInterface
  832. ULONG
  833. AlgRmDisableInterface(
  834. ULONG Index
  835. )
  836. /*++
  837. Routine Description:
  838. This routine is invoked to disable operation on an interface.
  839. Arguments:
  840. Index - the interface to be disabled.
  841. Return Value:
  842. ULONG - Win32 status code.
  843. Environment:
  844. The routine runs in the context of an IP router-manager thread.
  845. --*/
  846. {
  847. ULONG Error = NO_ERROR;
  848. PROFILE("AlgRmDisableInterface");
  849. REFERENCE_ALG_OR_RETURN(ERROR_CAN_NOT_COMPLETE);
  850. DEREFERENCE_ALG_AND_RETURN(Error);
  851. } // AlgRmDisableInterface
  852. ULONG
  853. APIENTRY
  854. AlgRmGetGlobalInfo(
  855. PVOID GlobalInfo,
  856. IN OUT PULONG GlobalInfoSize,
  857. IN OUT PULONG StructureVersion,
  858. IN OUT PULONG StructureSize,
  859. IN OUT PULONG StructureCount
  860. )
  861. /*++
  862. Routine Description:
  863. This routine is invoked to retrieve the configuration for the component.
  864. Arguments:
  865. GlobalInfo - receives the configuration
  866. GlobalInfoSize - receives the size of the configuration
  867. Return Value:
  868. ULONG - Win32 status code
  869. Environment:
  870. The routine runs in the context of an IP router-manager thread.
  871. --*/
  872. {
  873. ULONG Size;
  874. PROFILE("AlgRmGetGlobalInfo");
  875. REFERENCE_ALG_OR_RETURN(ERROR_CAN_NOT_COMPLETE);
  876. if (!GlobalInfoSize || (*GlobalInfoSize && !GlobalInfo)) {
  877. DEREFERENCE_ALG_AND_RETURN(ERROR_INVALID_PARAMETER);
  878. }
  879. EnterCriticalSection(&AlgGlobalInfoLock);
  880. Size = sizeof(*AlgGlobalInfo);
  881. if (*GlobalInfoSize < Size) {
  882. LeaveCriticalSection(&AlgGlobalInfoLock);
  883. *StructureSize = *GlobalInfoSize = Size;
  884. if (StructureCount) {*StructureCount = 1;}
  885. DEREFERENCE_ALG_AND_RETURN(ERROR_INSUFFICIENT_BUFFER);
  886. }
  887. CopyMemory(GlobalInfo, AlgGlobalInfo, Size);
  888. LeaveCriticalSection(&AlgGlobalInfoLock);
  889. *StructureSize = *GlobalInfoSize = Size;
  890. if (StructureCount) {*StructureCount = 1;}
  891. DEREFERENCE_ALG_AND_RETURN(NO_ERROR);
  892. } // AlgRmGetGlobalInfo
  893. ULONG
  894. APIENTRY
  895. AlgRmSetGlobalInfo(
  896. PVOID GlobalInfo,
  897. ULONG StructureVersion,
  898. ULONG StructureSize,
  899. ULONG StructureCount
  900. )
  901. /*++
  902. Routine Description:
  903. This routine is invoked to change the configuration for the component.
  904. Arguments:
  905. GlobalInfo - the new configuration
  906. Return Value:
  907. ULONG - Win32 status code
  908. Environment:
  909. The routine runs in the context of an IP router-manager thread.
  910. --*/
  911. {
  912. ULONG OldFlags;
  913. ULONG NewFlags;
  914. PIP_ALG_GLOBAL_INFO NewInfo;
  915. ULONG Size;
  916. PROFILE("AlgRmSetGlobalInfo");
  917. REFERENCE_ALG_OR_RETURN(ERROR_CAN_NOT_COMPLETE);
  918. if (!GlobalInfo) { DEREFERENCE_ALG_AND_RETURN(ERROR_INVALID_PARAMETER); }
  919. Size = sizeof(*AlgGlobalInfo);
  920. NewInfo = reinterpret_cast<PIP_ALG_GLOBAL_INFO>(NH_ALLOCATE(Size));
  921. if (!NewInfo) {
  922. NhTrace(
  923. TRACE_FLAG_INIT,
  924. "AlgRmSetGlobalInfo: error reallocating global info"
  925. );
  926. NhErrorLog(
  927. IP_ALG_LOG_ALLOCATION_FAILED,
  928. 0,
  929. "%d",
  930. Size
  931. );
  932. DEREFERENCE_ALG_AND_RETURN(ERROR_NOT_ENOUGH_MEMORY);
  933. }
  934. CopyMemory(NewInfo, GlobalInfo, Size);
  935. EnterCriticalSection(&AlgGlobalInfoLock);
  936. OldFlags = AlgGlobalInfo->Flags;
  937. NH_FREE(AlgGlobalInfo);
  938. AlgGlobalInfo = NewInfo;
  939. NewFlags = AlgGlobalInfo->Flags;
  940. LeaveCriticalSection(&AlgGlobalInfoLock);
  941. DEREFERENCE_ALG_AND_RETURN(NO_ERROR);
  942. } // AlgRmSetGlobalInfo
  943. ULONG
  944. AlgRmPortMappingChanged(
  945. ULONG Index,
  946. UCHAR Protocol,
  947. USHORT Port
  948. )
  949. /*++
  950. Routine Description:
  951. This routine is invoked when a port mapping has changed for
  952. an interface.
  953. Arguments:
  954. Index - the index of the interface on which the port mapping
  955. changed.
  956. Protcol - the IP protocol for the port mapping
  957. Port - the port for the port mapping
  958. Return Value:
  959. ULONG - Win32 status code
  960. Environment:
  961. This method must be called by a COM-initialized thread.
  962. --*/
  963. {
  964. ULONG Error = NO_ERROR;
  965. HRESULT hr;
  966. IAlgController* pIAlgController;
  967. PROFILE("AlgRmPortMappingChanged");
  968. REFERENCE_ALG_OR_RETURN(ERROR_CAN_NOT_COMPLETE);
  969. hr = GetAlgControllerInterface(&pIAlgController);
  970. if (SUCCEEDED(hr))
  971. {
  972. hr = pIAlgController->Adapter_PortMappingChanged(
  973. Index,
  974. Protocol,
  975. Port
  976. );
  977. pIAlgController->Release();
  978. }
  979. if (FAILED(hr))
  980. {
  981. Error = ERROR_CAN_NOT_COMPLETE;
  982. }
  983. DEREFERENCE_ALG_AND_RETURN(Error);
  984. } // AlgRmPortMappingChanged