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.

1412 lines
31 KiB

  1. /*++
  2. Copyright (c) 1998, Microsoft Corporation
  3. Module Name:
  4. rmapi.c
  5. Abstract:
  6. This module contains code for the part of the router-manager interface
  7. which is common to all the protocols in this component.
  8. Author:
  9. Abolade Gbadegesin (aboladeg) 4-Mar-1998
  10. Revision History:
  11. --*/
  12. #include "precomp.h"
  13. #pragma hdrstop
  14. #include <ras.h>
  15. #include <rasuip.h>
  16. #include <raserror.h>
  17. #include <ipinfo.h>
  18. #include "beacon.h"
  19. #include <atlbase.h>
  20. CComModule _Module;
  21. #include <atlcom.h>
  22. #include "nathlp_i.c"
  23. BEGIN_OBJECT_MAP(ObjectMap)
  24. OBJECT_ENTRY(CLSID_SAUpdate, CSharedAccessUpdate)
  25. END_OBJECT_MAP()
  26. extern "C" {
  27. #include <iphlpstk.h>
  28. }
  29. HANDLE NhpComponentEvent = NULL;
  30. NH_COMPONENT_MODE NhComponentMode = NhUninitializedMode;
  31. const WCHAR NhpDhcpDomainString[] = L"DhcpDomain";
  32. const WCHAR NhpDomainString[] = L"Domain";
  33. const WCHAR NhpEnableProxy[] = L"EnableProxy";
  34. LONG NhpIsWinsProxyEnabled = -1;
  35. CRITICAL_SECTION NhLock;
  36. HMODULE NhpRtrmgrDll = NULL;
  37. LIST_ENTRY NhApplicationSettingsList;
  38. LIST_ENTRY NhDhcpReservationList;
  39. DWORD NhDhcpScopeAddress = 0;
  40. DWORD NhDhcpScopeMask = 0;
  41. const WCHAR NhTcpipParametersString[] =
  42. L"\\Registry\\Machine\\System\\CurrentControlSet\\Services"
  43. L"\\Tcpip\\Parameters";
  44. //
  45. // EXTERNAL DECLARATIONS
  46. //
  47. BOOL
  48. APIENTRY
  49. DllMain(
  50. HINSTANCE Instance,
  51. ULONG Reason,
  52. PVOID Unused
  53. )
  54. /*++
  55. Routine Description:
  56. Standard DLL entry/exit routine.
  57. Initializes/shuts-down the modules implemented in the DLL.
  58. The initialization performed is sufficient that all the modules'
  59. interface lists can be searched, whether or not the protocols are
  60. installed or operational.
  61. Arguments:
  62. Instance - the instance of this DLL in this process
  63. Reason - the reason for invocation
  64. Unused - unused.
  65. Return Value:
  66. BOOL - indicates success or failure.
  67. --*/
  68. {
  69. switch (Reason) {
  70. case DLL_PROCESS_ATTACH: {
  71. WSADATA wd;
  72. DisableThreadLibraryCalls(Instance);
  73. __try {
  74. InitializeCriticalSection(&NhLock);
  75. } __except(EXCEPTION_EXECUTE_HANDLER) {
  76. return FALSE;
  77. }
  78. WSAStartup(MAKEWORD(2,2), &wd);
  79. NhInitializeTraceManagement();
  80. NhInitializeEventLogManagement();
  81. InitializeListHead(&NhApplicationSettingsList);
  82. InitializeListHead(&NhDhcpReservationList);
  83. if (NhInitializeBufferManagement()) { return FALSE; }
  84. if (NhInitializeTimerManagement()) { return FALSE; }
  85. if (!NatInitializeModule()) { return FALSE; }
  86. if (!DhcpInitializeModule()) { return FALSE; }
  87. if (!DnsInitializeModule()) { return FALSE; }
  88. #ifndef NO_FTP_PROXY
  89. if (!FtpInitializeModule()) { return FALSE; }
  90. #endif
  91. if (!AlgInitializeModule()) { return FALSE; }
  92. if (!H323InitializeModule()) { return FALSE; }
  93. if(FAILED(InitializeBeaconSvr())) { return FALSE; }
  94. _Module.Init(ObjectMap, Instance, &LIBID_IPNATHelperLib);
  95. _Module.RegisterTypeLib();
  96. break;
  97. }
  98. case DLL_PROCESS_DETACH: {
  99. NhResetComponentMode();
  100. TerminateBeaconSvr();
  101. H323CleanupModule();
  102. #ifndef NO_FTP_PROXY
  103. FtpCleanupModule();
  104. #endif
  105. AlgCleanupModule();
  106. DnsCleanupModule();
  107. DhcpCleanupModule();
  108. NatCleanupModule();
  109. NhShutdownTimerManagement();
  110. NhShutdownBufferManagement();
  111. NhShutdownEventLogManagement();
  112. NhShutdownTraceManagement();
  113. WSACleanup();
  114. if (NhpRtrmgrDll) {
  115. FreeLibrary(NhpRtrmgrDll); NhpRtrmgrDll = NULL;
  116. }
  117. DeleteCriticalSection(&NhLock);
  118. _Module.Term();
  119. break;
  120. }
  121. }
  122. return TRUE;
  123. } // DllMain
  124. VOID
  125. NhBuildDhcpReservations(
  126. VOID
  127. )
  128. /*++
  129. Routine Description:
  130. Builds the list of DHCP reservations
  131. Arguments:
  132. none.
  133. Return Value:
  134. None.
  135. Environment:
  136. Invoked with NhLock held on a COM-initialized thread.
  137. --*/
  138. {
  139. HRESULT hr;
  140. IHNetCfgMgr *pCfgMgr = NULL;
  141. IEnumHNetPortMappingBindings *pEnumBindings;
  142. IHNetIcsSettings *pIcsSettings;
  143. PNAT_DHCP_RESERVATION pReservation;
  144. ULONG ulCount;
  145. hr = NhGetHNetCfgMgr(&pCfgMgr);
  146. if (SUCCEEDED(hr))
  147. {
  148. //
  149. // Get the ICS settings interface
  150. //
  151. hr = pCfgMgr->QueryInterface(
  152. IID_PPV_ARG(IHNetIcsSettings, &pIcsSettings)
  153. );
  154. }
  155. if (SUCCEEDED(hr))
  156. {
  157. //
  158. // Get DHCP scope information
  159. //
  160. hr = pIcsSettings->GetDhcpScopeSettings(
  161. &NhDhcpScopeAddress,
  162. &NhDhcpScopeMask
  163. );
  164. //
  165. // Get enumeration of DHCP reservered addresses
  166. //
  167. if (SUCCEEDED(hr))
  168. {
  169. hr = pIcsSettings->EnumDhcpReservedAddresses(&pEnumBindings);
  170. }
  171. pIcsSettings->Release();
  172. }
  173. if (SUCCEEDED(hr))
  174. {
  175. //
  176. // Process the items in the enum
  177. //
  178. do
  179. {
  180. IHNetPortMappingBinding *pBinding;
  181. hr = pEnumBindings->Next(1, &pBinding, &ulCount);
  182. if (SUCCEEDED(hr) && 1 == ulCount)
  183. {
  184. //
  185. // Allocate a new reservation entry
  186. //
  187. pReservation = reinterpret_cast<PNAT_DHCP_RESERVATION>(
  188. NH_ALLOCATE(sizeof(*pReservation))
  189. );
  190. if (NULL != pReservation)
  191. {
  192. ZeroMemory(pReservation, sizeof(*pReservation));
  193. //
  194. // Get computer name
  195. //
  196. hr = pBinding->GetTargetComputerName(
  197. &pReservation->Name
  198. );
  199. if (SUCCEEDED(hr))
  200. {
  201. //
  202. // Get reserved address
  203. //
  204. hr = pBinding->GetTargetComputerAddress(
  205. &pReservation->Address
  206. );
  207. }
  208. if (SUCCEEDED(hr))
  209. {
  210. //
  211. // Add entry to list
  212. //
  213. InsertTailList(
  214. &NhDhcpReservationList,
  215. &pReservation->Link)
  216. ;
  217. }
  218. else
  219. {
  220. //
  221. // Free entry
  222. //
  223. NH_FREE(pReservation);
  224. }
  225. }
  226. else
  227. {
  228. hr = E_OUTOFMEMORY;
  229. }
  230. pBinding->Release();
  231. }
  232. } while (SUCCEEDED(hr) && 1 == ulCount);
  233. pEnumBindings->Release();
  234. }
  235. if (NULL != pCfgMgr)
  236. {
  237. pCfgMgr->Release();
  238. }
  239. } // NhBuildDhcpReservations
  240. ULONG
  241. NhDialSharedConnection(
  242. VOID
  243. )
  244. /*++
  245. Routine Description:
  246. This routine is invoked to connect a home-router interface.
  247. The connection is established by invoking the RAS autodial process
  248. with the appropriate phonebook and entry-name in the security context
  249. of the logged-on user.
  250. Arguments:
  251. none.
  252. Return Value:
  253. ULONG - Win32 status code.
  254. --*/
  255. {
  256. return RasAutoDialSharedConnection();
  257. } // NhDialSharedConnection
  258. VOID
  259. NhFreeApplicationSettings(
  260. VOID
  261. )
  262. /*++
  263. Routine Description:
  264. Frees the list of application settings
  265. Arguments:
  266. none.
  267. Return Value:
  268. None.
  269. Environment:
  270. Invoked with NhLock held.
  271. --*/
  272. {
  273. PLIST_ENTRY Link;
  274. PNAT_APP_ENTRY pAppEntry;
  275. PROFILE("NhFreeApplicationSettings");
  276. while (!IsListEmpty(&NhApplicationSettingsList))
  277. {
  278. Link = RemoveHeadList(&NhApplicationSettingsList);
  279. pAppEntry = CONTAINING_RECORD(Link, NAT_APP_ENTRY, Link);
  280. CoTaskMemFree(pAppEntry->ResponseArray);
  281. NH_FREE(pAppEntry);
  282. }
  283. } // NhFreeApplicationSettings
  284. VOID
  285. NhFreeDhcpReservations(
  286. VOID
  287. )
  288. /*++
  289. Routine Description:
  290. Frees the list of DHCP reservations
  291. Arguments:
  292. none.
  293. Return Value:
  294. None.
  295. Environment:
  296. Invoked with NhLock held.
  297. --*/
  298. {
  299. PLIST_ENTRY Link;
  300. PNAT_DHCP_RESERVATION pReservation;
  301. PROFILE("NhFreeDhcpReservations");
  302. while (!IsListEmpty(&NhDhcpReservationList))
  303. {
  304. Link = RemoveHeadList(&NhDhcpReservationList);
  305. pReservation = CONTAINING_RECORD(Link, NAT_DHCP_RESERVATION, Link);
  306. CoTaskMemFree(pReservation->Name);
  307. NH_FREE(pReservation);
  308. }
  309. } // NhFreeDhcpReservations
  310. BOOLEAN
  311. NhIsDnsProxyEnabled(
  312. VOID
  313. )
  314. /*++
  315. Routine Description:
  316. This routine is invoked to discover whether the DNS proxy is enabled.
  317. Arguments:
  318. none.
  319. Return Value:
  320. BOOLEAN - TRUE if DNS proxy is enabled, FALSE otherwise
  321. Environment:
  322. Invoked from an arbitrary context.
  323. --*/
  324. {
  325. PROFILE("NhIsDnsProxyEnabled");
  326. return DnsIsDnsEnabled();
  327. } // NhIsDnsProxyEnabled
  328. BOOLEAN
  329. NhIsLocalAddress(
  330. ULONG Address
  331. )
  332. /*++
  333. Routine Description:
  334. This routine is invoked to determine whether the given IP address
  335. is for a local interface.
  336. Arguments:
  337. Address - the IP address to find
  338. Return Value:
  339. BOOLEAN - TRUE if the address is found, FALSE otherwise
  340. --*/
  341. {
  342. ULONG Error;
  343. ULONG i;
  344. PMIB_IPADDRTABLE Table;
  345. Error =
  346. AllocateAndGetIpAddrTableFromStack(
  347. &Table, FALSE, GetProcessHeap(), 0
  348. );
  349. if (Error) {
  350. NhTrace(
  351. TRACE_FLAG_IF,
  352. "NhIsLocalAddress: GetIpAddrTableFromStack=%d", Error
  353. );
  354. return FALSE;
  355. }
  356. for (i = 0; i < Table->dwNumEntries; i++) {
  357. if (Table->table[i].dwAddr == Address) {
  358. HeapFree(GetProcessHeap(), 0, Table);
  359. return TRUE;
  360. }
  361. }
  362. HeapFree(GetProcessHeap(), 0, Table);
  363. return FALSE;
  364. } // NhIsLocalAddress
  365. BOOLEAN
  366. NhIsWinsProxyEnabled(
  367. VOID
  368. )
  369. /*++
  370. Routine Description:
  371. This routine is invoked to discover whether the WINS proxy is enabled.
  372. Arguments:
  373. none.
  374. Return Value:
  375. BOOLEAN - TRUE if WINS proxy is enabled, FALSE otherwise
  376. Environment:
  377. Invoked from an arbitrary context.
  378. --*/
  379. {
  380. PROFILE("NhIsWinsProxyEnabled");
  381. return DnsIsWinsEnabled();
  382. } // NhIsWinsProxyEnabled
  383. PIP_ADAPTER_BINDING_INFO
  384. NhQueryBindingInformation(
  385. ULONG AdapterIndex
  386. )
  387. /*++
  388. Routine Description:
  389. This routine is called to obtain the binding information
  390. for the adapter with the given index.
  391. It does this by obtaining a table of IP addresses from the stack,
  392. and determining which addresses correspond to the given index.
  393. Arguments:
  394. AdapterIndex - the adapter for which binding information is required
  395. Return Value:
  396. PIP_ADAPTER_BINDING_INFO - the allocated binding information
  397. --*/
  398. {
  399. PIP_ADAPTER_BINDING_INFO BindingInfo = NULL;
  400. ULONG Count = 0;
  401. ULONG i;
  402. PMIB_IPADDRTABLE Table;
  403. if (AllocateAndGetIpAddrTableFromStack(
  404. &Table, FALSE, GetProcessHeap(), 0
  405. ) == NO_ERROR) {
  406. //
  407. // Count the adapter's addresses
  408. //
  409. for (i = 0; i < Table->dwNumEntries; i++) {
  410. if (Table->table[i].dwIndex == AdapterIndex) { ++Count; }
  411. }
  412. //
  413. // Allocate space for the binding info
  414. //
  415. BindingInfo = reinterpret_cast<PIP_ADAPTER_BINDING_INFO>(
  416. NH_ALLOCATE(SIZEOF_IP_BINDING(Count))
  417. );
  418. if (BindingInfo) {
  419. //
  420. // Fill in the binding info
  421. //
  422. BindingInfo->AddressCount = Count;
  423. BindingInfo->RemoteAddress = 0;
  424. Count = 0;
  425. for (i = 0; i < Table->dwNumEntries; i++) {
  426. if (Table->table[i].dwIndex != AdapterIndex) { continue; }
  427. BindingInfo->Address[Count].Address = Table->table[i].dwAddr;
  428. BindingInfo->Address[Count].Mask = Table->table[i].dwMask;
  429. ++Count;
  430. }
  431. }
  432. HeapFree(GetProcessHeap(), 0, Table);
  433. }
  434. return BindingInfo;
  435. } // NhQueryBindingInformation
  436. NTSTATUS
  437. NhQueryDomainName(
  438. PCHAR* DomainName
  439. )
  440. /*++
  441. Routine Description:
  442. This routine is invoked to obtain the local domain name.
  443. Arguments:
  444. DomainName - receives the allocated string containing the domain name
  445. Return Value:
  446. NTSTATUS - NT status code.
  447. Environment:
  448. Invoked from an arbitrary context.
  449. --*/
  450. {
  451. PKEY_VALUE_PARTIAL_INFORMATION Information;
  452. IO_STATUS_BLOCK IoStatus;
  453. HANDLE Key;
  454. ULONG Length;
  455. OBJECT_ATTRIBUTES ObjectAttributes;
  456. NTSTATUS status;
  457. UNICODE_STRING UnicodeString;
  458. PROFILE("NhQueryDomainName");
  459. *DomainName = NULL;
  460. RtlInitUnicodeString(&UnicodeString, NhTcpipParametersString);
  461. InitializeObjectAttributes(
  462. &ObjectAttributes,
  463. &UnicodeString,
  464. OBJ_CASE_INSENSITIVE,
  465. NULL,
  466. NULL
  467. );
  468. //
  469. // Open the 'Tcpip' registry key
  470. //
  471. status =
  472. NtOpenKey(
  473. &Key,
  474. KEY_ALL_ACCESS,
  475. &ObjectAttributes
  476. );
  477. if (!NT_SUCCESS(status)) {
  478. NhTrace(
  479. TRACE_FLAG_REG,
  480. "NhQueryDomainName: error %x opening registry key",
  481. status
  482. );
  483. return status;
  484. }
  485. //
  486. // Read the 'Domain' value
  487. //
  488. status =
  489. NhQueryValueKey(
  490. Key,
  491. NhpDomainString,
  492. &Information
  493. );
  494. if (!NT_SUCCESS(status)) {
  495. status =
  496. NhQueryValueKey(
  497. Key,
  498. NhpDhcpDomainString,
  499. &Information
  500. );
  501. }
  502. if (!NT_SUCCESS(status)) {
  503. NhTrace(
  504. TRACE_FLAG_REG,
  505. "NhQueryDomainName: error %x querying domain name",
  506. status
  507. );
  508. NtClose(Key);
  509. return status;
  510. }
  511. //
  512. // Copy the domain name
  513. //
  514. Length = lstrlenW((PWCHAR)Information->Data) + 1;
  515. *DomainName = reinterpret_cast<PCHAR>(NH_ALLOCATE(Length));
  516. if (!*DomainName) {
  517. NH_FREE(Information);
  518. NhTrace(
  519. TRACE_FLAG_REG,
  520. "NhQueryDomainName: error allocating domain name"
  521. );
  522. return STATUS_NO_MEMORY;
  523. }
  524. RtlUnicodeToMultiByteN(
  525. *DomainName,
  526. Length,
  527. NULL,
  528. (PWCHAR)Information->Data,
  529. Length * sizeof(WCHAR)
  530. );
  531. NH_FREE(Information);
  532. return STATUS_SUCCESS;
  533. } // NhQueryDomainName
  534. NTSTATUS
  535. NhQueryValueKey(
  536. HANDLE Key,
  537. const WCHAR ValueName[],
  538. PKEY_VALUE_PARTIAL_INFORMATION* Information
  539. )
  540. /*++
  541. Routine Description:
  542. This routine is called to obtain the value of a registry key.
  543. Arguments:
  544. Key - the key to be queried
  545. ValueName - the value to be queried
  546. Information - receives a pointer to the information read
  547. Return Value:
  548. NTSTATUS - NT status code.
  549. --*/
  550. {
  551. UCHAR Buffer[sizeof(KEY_VALUE_PARTIAL_INFORMATION)];
  552. ULONG InformationLength;
  553. NTSTATUS status;
  554. UNICODE_STRING UnicodeString;
  555. PROFILE("NhQueryValueKey");
  556. RtlInitUnicodeString(&UnicodeString, ValueName);
  557. *Information = (PKEY_VALUE_PARTIAL_INFORMATION)Buffer;
  558. InformationLength = sizeof(KEY_VALUE_PARTIAL_INFORMATION);
  559. //
  560. // Read the value's size
  561. //
  562. status =
  563. NtQueryValueKey(
  564. Key,
  565. &UnicodeString,
  566. KeyValuePartialInformation,
  567. *Information,
  568. InformationLength,
  569. &InformationLength
  570. );
  571. if (!NT_SUCCESS(status) &&
  572. status != STATUS_BUFFER_OVERFLOW &&
  573. status != STATUS_BUFFER_TOO_SMALL
  574. ) {
  575. NhTrace(
  576. TRACE_FLAG_REG,
  577. "NhQueryValueKey: status %08x obtaining value size",
  578. status
  579. );
  580. *Information = NULL;
  581. return status;
  582. }
  583. //
  584. // Allocate space for the value's size
  585. //
  586. *Information =
  587. (PKEY_VALUE_PARTIAL_INFORMATION)NH_ALLOCATE(InformationLength + 2);
  588. if (!*Information) {
  589. NhTrace(
  590. TRACE_FLAG_REG,
  591. "NhQueryValueKey: error allocating %d bytes",
  592. InformationLength + 2
  593. );
  594. return STATUS_NO_MEMORY;
  595. }
  596. //
  597. // Read the value's data
  598. //
  599. status =
  600. NtQueryValueKey(
  601. Key,
  602. &UnicodeString,
  603. KeyValuePartialInformation,
  604. *Information,
  605. InformationLength,
  606. &InformationLength
  607. );
  608. if (!NT_SUCCESS(status)) {
  609. NhTrace(
  610. TRACE_FLAG_REG,
  611. "NhQueryValueKey: status %08x obtaining value data",
  612. status
  613. );
  614. NH_FREE(*Information);
  615. *Information = NULL;
  616. }
  617. return status;
  618. } // NhQueryValueKey
  619. ULONG
  620. NhMapAddressToAdapter(
  621. ULONG Address
  622. )
  623. /*++
  624. Routine Description:
  625. This routine is invoked to map an IP address to an adapter index.
  626. It does so by obtaining the stack's address-table, which contains
  627. valid adapter-indices rather than IP router-manager indices.
  628. This table is then used to obtain the IP address's adapter-index.
  629. Arguments:
  630. Address - the local address for which an adapter-index is required
  631. Return Value:
  632. ULONG - adapter index.
  633. --*/
  634. {
  635. ULONG AdapterIndex = (ULONG)-1;
  636. ULONG i;
  637. PMIB_IPADDRTABLE Table;
  638. PROFILE("NhMapAddressToAdapter");
  639. if (AllocateAndGetIpAddrTableFromStack(
  640. &Table, FALSE, GetProcessHeap(), 0
  641. ) == NO_ERROR) {
  642. for (i = 0; i < Table->dwNumEntries; i++) {
  643. if (Table->table[i].dwAddr != Address) { continue; }
  644. AdapterIndex = Table->table[i].dwIndex;
  645. break;
  646. }
  647. HeapFree(GetProcessHeap(), 0, Table);
  648. }
  649. return AdapterIndex;
  650. } // NhMapAddressToAdapter
  651. ULONG
  652. NhMapInterfaceToAdapter(
  653. ULONG Index
  654. )
  655. /*++
  656. Routine Description:
  657. This routine is invoked to map an interface to an adapter index.
  658. It does so by invoking the appropriate IP router-manager entry-point.
  659. Arguments:
  660. Index - the index of the interface to be mapped
  661. Return Value:
  662. ULONG - adapter index.
  663. --*/
  664. {
  665. MAPINTERFACETOADAPTER FarProc;
  666. PROFILE("NhMapInterfaceToAdapter");
  667. EnterCriticalSection(&NhLock);
  668. if (!NhpRtrmgrDll) { NhpRtrmgrDll = LoadLibraryA("IPRTRMGR.DLL"); }
  669. LeaveCriticalSection(&NhLock);
  670. if (!NhpRtrmgrDll) { return (ULONG)-1; }
  671. FarProc = (MAPINTERFACETOADAPTER)GetProcAddress(NhpRtrmgrDll, "MapInterfaceToAdapter");
  672. return (ULONG)(FarProc ? (*FarProc)(Index) : -1);
  673. } // NhMapInterfaceToAdapter
  674. VOID
  675. NhResetComponentMode(
  676. VOID
  677. )
  678. /*++
  679. Routine Description:
  680. This routine relinquishes control of the kernel-mode translation module,
  681. and returns this module to an uninitialized state.
  682. Arguments:
  683. none.
  684. Return Value:
  685. none.
  686. --*/
  687. {
  688. EnterCriticalSection(&NhLock);
  689. if (NhpComponentEvent) {
  690. CloseHandle(NhpComponentEvent); NhpComponentEvent = NULL;
  691. }
  692. NhComponentMode = NhUninitializedMode;
  693. LeaveCriticalSection(&NhLock);
  694. } // NhResetComponentMode
  695. BOOLEAN
  696. NhSetComponentMode(
  697. NH_COMPONENT_MODE ComponentMode
  698. )
  699. /*++
  700. Routine Description:
  701. This routine is invoked to atomically set the module into a particular mode
  702. in order to prevent conflict between shared-access and connection-sharing,
  703. both of which are implemented in this module, and both of which run
  704. in the 'netsvcs' instance of SVCHOST.EXE.
  705. In setting either mode, the routine first determines whether it is already
  706. executing in the alternate mode, in which case it fails.
  707. Otherwise, it attempts to create a named event, to claim exclusive control
  708. of the kernel-mode translation module. If the named event already exists,
  709. then the routine again fails.
  710. Otherwise, the kernel-mode translation module is claimed for this module
  711. and the module is set into the required mode.
  712. Arguments:
  713. ComponentMode - the mode into which the module is to be set.
  714. Return Value:
  715. BOOLEAN - TRUE if successful, FALSE if the module could not be set
  716. or if the kernel-mode translation module has already been claimed.
  717. --*/
  718. {
  719. EnterCriticalSection(&NhLock);
  720. if (NhpComponentEvent) {
  721. if (NhComponentMode != ComponentMode) {
  722. LeaveCriticalSection(&NhLock);
  723. NhErrorLog(
  724. (ComponentMode == NhRoutingProtocolMode)
  725. ? IP_NAT_LOG_ROUTING_PROTOCOL_CONFLICT
  726. : IP_NAT_LOG_SHARED_ACCESS_CONFLICT,
  727. 0,
  728. ""
  729. );
  730. return FALSE;
  731. }
  732. } else {
  733. NhpComponentEvent =
  734. CreateEventA(NULL, FALSE, FALSE, IP_NAT_SERVICE_NAME);
  735. if (!NhpComponentEvent) {
  736. LeaveCriticalSection(&NhLock);
  737. return FALSE;
  738. } else if (GetLastError() == ERROR_ALREADY_EXISTS) {
  739. CloseHandle(NhpComponentEvent); NhpComponentEvent = NULL;
  740. LeaveCriticalSection(&NhLock);
  741. NhErrorLog(
  742. (ComponentMode == NhRoutingProtocolMode)
  743. ? IP_NAT_LOG_ROUTING_PROTOCOL_CONFLICT
  744. : IP_NAT_LOG_SHARED_ACCESS_CONFLICT,
  745. 0,
  746. ""
  747. );
  748. return FALSE;
  749. }
  750. }
  751. NhComponentMode = ComponentMode;
  752. LeaveCriticalSection(&NhLock);
  753. return TRUE;
  754. } // NhSetComponentMode
  755. VOID
  756. NhSignalNatInterface(
  757. ULONG Index,
  758. BOOLEAN Boundary
  759. )
  760. /*++
  761. Routine Description:
  762. This routine is invoked upon reconfiguration of a NAT interface.
  763. It invokes the reconfiguration for the DHCP allocator and DNS proxy,
  764. neither of which are expected to operate on a NAT boundary interface.
  765. This notification gives either (or both) an opportunity to deactivate
  766. itself on NAT interfaces or reactivate itself on non-NAT interfaces.
  767. Arguments:
  768. Index - the interface whose configuration has changed
  769. Boundary - indicates whether the interface is now a boundary interface
  770. Return Value:
  771. none.
  772. Environment:
  773. Invoked from an arbitrary context.
  774. --*/
  775. {
  776. PROFILE("NhSignalNatInterface");
  777. //
  778. // Attempt to obtain the corresponding DHCP and DNS interfaces.
  779. // It is important that this works regardless of whether DHCP allocation,
  780. // DNS proxying or DirectPlay transparent proxying is enabled;
  781. // the interface lists are initialized minimally in 'DllMain' above.
  782. //
  783. DhcpSignalNatInterface(Index, Boundary);
  784. DnsSignalNatInterface(Index, Boundary);
  785. #ifndef NO_FTP_PROXY
  786. FtpSignalNatInterface(Index, Boundary);
  787. #endif
  788. // AlgSignalNatInterface(Index, Boundary);
  789. H323SignalNatInterface(Index, Boundary);
  790. } // NhSignalNatInterface
  791. VOID
  792. NhUpdateApplicationSettings(
  793. VOID
  794. )
  795. /*++
  796. Routine Description:
  797. This routine is invoked to (re)load the advanced application settings.
  798. Arguments:
  799. none.
  800. Return Value:
  801. none.
  802. --*/
  803. {
  804. HRESULT hr;
  805. PNAT_APP_ENTRY pAppEntry;
  806. IHNetCfgMgr *pCfgMgr = NULL;
  807. IHNetProtocolSettings *pProtocolSettings;
  808. IEnumHNetApplicationProtocols *pEnumApps;
  809. BOOLEAN ComInitialized = FALSE;
  810. ULONG ulCount;
  811. PROFILE("NhUpdateApplicationSettings");
  812. EnterCriticalSection(&NhLock);
  813. //
  814. // Free old settings list
  815. //
  816. NhFreeApplicationSettings();
  817. //
  818. // Free DHCP reservation list
  819. //
  820. NhFreeDhcpReservations();
  821. //
  822. // Make sure COM is initialized on this thread
  823. //
  824. hr = CoInitializeEx(NULL, COINIT_MULTITHREADED | COINIT_DISABLE_OLE1DDE );
  825. if (SUCCEEDED(hr))
  826. {
  827. ComInitialized = TRUE;
  828. }
  829. else if (RPC_E_CHANGED_MODE == hr)
  830. {
  831. hr = S_OK;
  832. }
  833. if (SUCCEEDED(hr))
  834. {
  835. //
  836. // Get the IHNetCfgMgr pointer out of the GIT
  837. //
  838. hr = NhGetHNetCfgMgr(&pCfgMgr);
  839. }
  840. if (SUCCEEDED(hr))
  841. {
  842. //
  843. // Get the IHNetProtocolSettings interface
  844. //
  845. hr = pCfgMgr->QueryInterface(
  846. IID_PPV_ARG(IHNetProtocolSettings, &pProtocolSettings)
  847. );
  848. }
  849. if (SUCCEEDED(hr))
  850. {
  851. //
  852. // Get the enumeration of enabled application protocols
  853. //
  854. hr = pProtocolSettings->EnumApplicationProtocols(TRUE, &pEnumApps);
  855. pProtocolSettings->Release();
  856. }
  857. if (SUCCEEDED(hr))
  858. {
  859. //
  860. // Process the items in the enum
  861. //
  862. do
  863. {
  864. IHNetApplicationProtocol *pAppProtocol;
  865. hr = pEnumApps->Next(1, &pAppProtocol, &ulCount);
  866. if (SUCCEEDED(hr) && 1 == ulCount)
  867. {
  868. //
  869. // Allocate a new app entry
  870. //
  871. pAppEntry = reinterpret_cast<PNAT_APP_ENTRY>(
  872. NH_ALLOCATE(sizeof(*pAppEntry))
  873. );
  874. if (NULL != pAppEntry)
  875. {
  876. ZeroMemory(pAppEntry, sizeof(*pAppEntry));
  877. //
  878. // Get protocol
  879. //
  880. hr = pAppProtocol->GetOutgoingIPProtocol(
  881. &pAppEntry->Protocol
  882. );
  883. if (SUCCEEDED(hr))
  884. {
  885. //
  886. // Get port
  887. //
  888. hr = pAppProtocol->GetOutgoingPort(
  889. &pAppEntry->Port
  890. );
  891. }
  892. if (SUCCEEDED(hr))
  893. {
  894. //
  895. // Get responses
  896. //
  897. hr = pAppProtocol->GetResponseRanges(
  898. &pAppEntry->ResponseCount,
  899. &pAppEntry->ResponseArray
  900. );
  901. }
  902. if (SUCCEEDED(hr))
  903. {
  904. //
  905. // Add entry to list
  906. //
  907. InsertTailList(&NhApplicationSettingsList, &pAppEntry->Link);
  908. }
  909. else
  910. {
  911. //
  912. // Free entry
  913. //
  914. NH_FREE(pAppEntry);
  915. }
  916. }
  917. else
  918. {
  919. hr = E_OUTOFMEMORY;
  920. }
  921. pAppProtocol->Release();
  922. }
  923. } while (SUCCEEDED(hr) && 1 == ulCount);
  924. pEnumApps->Release();
  925. }
  926. //
  927. // Build the DHCP reservation list
  928. //
  929. NhBuildDhcpReservations();
  930. LeaveCriticalSection(&NhLock);
  931. //
  932. // Free config manager
  933. //
  934. if (NULL != pCfgMgr)
  935. {
  936. pCfgMgr->Release();
  937. }
  938. //
  939. // Uninitialize COM
  940. //
  941. if (TRUE == ComInitialized)
  942. {
  943. CoUninitialize();
  944. }
  945. } // NhUpdateApplicationSettings
  946. ULONG
  947. APIENTRY
  948. RegisterProtocol(
  949. IN OUT PMPR_ROUTING_CHARACTERISTICS RoutingCharacteristics,
  950. IN OUT PMPR_SERVICE_CHARACTERISTICS ServiceCharacteristics
  951. )
  952. /*++
  953. Routine Description:
  954. This routine is invoked once for each protocol implemented in this module.
  955. On each invocation, the supplied 'RoutingCharacteristics' indicates
  956. the protocol to be registered in its 'dwProtocolId' field.
  957. Arguments:
  958. RoutingCharacteristics - on input, the protocol to be registered
  959. and the router-manager's supported functionality.
  960. ServiceCharacteristics - unused.
  961. Return Value:
  962. ULONG - status code.
  963. --*/
  964. {
  965. if (RoutingCharacteristics->dwVersion < MS_ROUTER_VERSION) {
  966. return ERROR_NOT_SUPPORTED;
  967. }
  968. if ((RoutingCharacteristics->fSupportedFunctionality &
  969. (RF_ROUTING|RF_ADD_ALL_INTERFACES)) !=
  970. (RF_ROUTING|RF_ADD_ALL_INTERFACES)) {
  971. return ERROR_NOT_SUPPORTED;
  972. }
  973. switch (RoutingCharacteristics->dwProtocolId) {
  974. case MS_IP_NAT: {
  975. //
  976. // Attempt to set the component into 'Connection Sharing' mode.
  977. // This module implements both shared-access and connection-sharing
  978. // which are mutually exclusive, so we need to ensure that
  979. // shared-access is not operational before proceeding.
  980. //
  981. if (!NhSetComponentMode(NhRoutingProtocolMode)) {
  982. return ERROR_CAN_NOT_COMPLETE;
  983. }
  984. CopyMemory(
  985. RoutingCharacteristics,
  986. &NatRoutingCharacteristics,
  987. sizeof(NatRoutingCharacteristics)
  988. );
  989. RoutingCharacteristics->fSupportedFunctionality = RF_ROUTING;
  990. break;
  991. }
  992. case MS_IP_DNS_PROXY: {
  993. CopyMemory(
  994. RoutingCharacteristics,
  995. &DnsRoutingCharacteristics,
  996. sizeof(DnsRoutingCharacteristics)
  997. );
  998. RoutingCharacteristics->fSupportedFunctionality =
  999. (RF_ROUTING|RF_ADD_ALL_INTERFACES);
  1000. break;
  1001. }
  1002. case MS_IP_DHCP_ALLOCATOR: {
  1003. CopyMemory(
  1004. RoutingCharacteristics,
  1005. &DhcpRoutingCharacteristics,
  1006. sizeof(DhcpRoutingCharacteristics)
  1007. );
  1008. RoutingCharacteristics->fSupportedFunctionality =
  1009. (RF_ROUTING|RF_ADD_ALL_INTERFACES);
  1010. break;
  1011. }
  1012. #ifndef NO_FTP_PROXY
  1013. case MS_IP_FTP: {
  1014. CopyMemory(
  1015. RoutingCharacteristics,
  1016. &FtpRoutingCharacteristics,
  1017. sizeof(FtpRoutingCharacteristics)
  1018. );
  1019. RoutingCharacteristics->fSupportedFunctionality =
  1020. (RF_ROUTING|RF_ADD_ALL_INTERFACES);
  1021. break;
  1022. }
  1023. #endif
  1024. case MS_IP_ALG: {
  1025. CopyMemory(
  1026. RoutingCharacteristics,
  1027. &AlgRoutingCharacteristics,
  1028. sizeof(AlgRoutingCharacteristics)
  1029. );
  1030. RoutingCharacteristics->fSupportedFunctionality =
  1031. (RF_ROUTING|RF_ADD_ALL_INTERFACES);
  1032. break;
  1033. }
  1034. case MS_IP_H323: {
  1035. CopyMemory(
  1036. RoutingCharacteristics,
  1037. &H323RoutingCharacteristics,
  1038. sizeof(H323RoutingCharacteristics)
  1039. );
  1040. RoutingCharacteristics->fSupportedFunctionality =
  1041. (RF_ROUTING|RF_ADD_ALL_INTERFACES);
  1042. break;
  1043. }
  1044. default: {
  1045. return ERROR_NOT_SUPPORTED;
  1046. }
  1047. }
  1048. ServiceCharacteristics->mscMpr40ServiceChars.fSupportedFunctionality = 0;
  1049. return NO_ERROR;
  1050. } // RegisterProtocol