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.

2068 lines
49 KiB

  1. /*++
  2. Copyright (c) 1998, Microsoft Corporation
  3. Module Name:
  4. svcmain.c
  5. Abstract:
  6. This module contains code for the module's shared-access mode,
  7. in which the module runs as a service rather than as a routing component.
  8. Author:
  9. Abolade Gbadegesin (aboladeg) 31-Aug-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 <rasman.h>
  18. #include "beacon.h"
  19. HANDLE NhpAddressChangeEvent = NULL;
  20. OVERLAPPED NhpAddressChangeOverlapped;
  21. HANDLE NhpAddressChangeWaitHandle = NULL;
  22. SERVICE_STATUS NhpServiceStatus;
  23. SERVICE_STATUS_HANDLE NhpServiceStatusHandle = 0;
  24. PIP_ADAPTER_BINDING_INFO NhpSharedPrivateLanBindingInfo = NULL;
  25. GUID NhpSharedPrivateLanGuid;
  26. ULONG NhpSharedPrivateLanIndex = (ULONG)-1;
  27. HANDLE NhpStopDhcpEvent = NULL;
  28. HANDLE NhpStopDnsEvent = NULL;
  29. #ifndef NO_FTP_PROXY
  30. HANDLE NhpStopFtpEvent = NULL;
  31. #endif
  32. HANDLE NhpStopAlgEvent = NULL;
  33. HANDLE NhpStopH323Event = NULL;
  34. HANDLE NhpStopNatEvent = NULL;
  35. BOOLEAN NhpRasmanReferenced = FALSE;
  36. BOOLEAN NhpFwLoggingInitialized = FALSE;
  37. BOOL NhPolicyAllowsFirewall = TRUE;
  38. BOOL NhPolicyAllowsSharing = TRUE;
  39. BOOLEAN NoLocalDns = TRUE; //whether DNS server is running or going to run on local host
  40. BOOLEAN NhpNoLocalDhcp = TRUE; //whether DHCP server is running or goint to run on local host
  41. BOOLEAN NhpQoSEnabled = FALSE;
  42. IUdpBroadcastMapper *NhpUdpBroadcastMapper = NULL;
  43. BOOLEAN NhpClassObjectsRegistered = FALSE;
  44. //
  45. // Pointer to the GlobalInterfaceTable for the process
  46. //
  47. IGlobalInterfaceTable *NhGITp = NULL;
  48. //
  49. // GIT cookie for the IHNetCfgMgr instance
  50. //
  51. DWORD NhCfgMgrCookie = 0;
  52. const TCHAR c_szDnsServiceName[] = TEXT("DNS");
  53. const TCHAR c_szDhcpServiceName[] = TEXT("DHCPServer");
  54. ULONG
  55. NhpEnableQoSWindowSizeAdjustment(
  56. BOOLEAN fEnable
  57. );
  58. VOID
  59. NhpStartAddressChangeNotification(
  60. VOID
  61. );
  62. VOID
  63. NhpStopAddressChangeNotification(
  64. VOID
  65. );
  66. VOID
  67. NhpUpdateConnectionsFolder(
  68. VOID
  69. );
  70. VOID
  71. NhpUpdatePolicySettings(
  72. VOID
  73. );
  74. HRESULT
  75. NhGetHNetCfgMgr(
  76. IHNetCfgMgr **ppCfgMgr
  77. )
  78. /*++
  79. Routine Description:
  80. This routine obtains a pointer to the home networking configuration
  81. manager.
  82. Arguments:
  83. ppCfgMgr - receives the IHNetCfgMgr pointer. The caller must release
  84. this pointer.
  85. Return Value:
  86. standard HRESULT
  87. Environment:
  88. COM must be initialized on the calling thread
  89. --*/
  90. {
  91. HRESULT hr = S_OK;
  92. if (NULL == NhGITp)
  93. {
  94. EnterCriticalSection(&NhLock);
  95. if (NULL == NhGITp)
  96. {
  97. IHNetCfgMgr *pCfgMgr;
  98. //
  99. // Create the global interface table
  100. //
  101. hr = CoCreateInstance(
  102. CLSID_StdGlobalInterfaceTable,
  103. NULL,
  104. CLSCTX_INPROC_SERVER,
  105. IID_PPV_ARG(IGlobalInterfaceTable, &NhGITp)
  106. );
  107. if (SUCCEEDED(hr))
  108. {
  109. //
  110. // Create the homenet configuration manager
  111. //
  112. hr = CoCreateInstance(
  113. CLSID_HNetCfgMgr,
  114. NULL,
  115. CLSCTX_INPROC_SERVER,
  116. IID_PPV_ARG(IHNetCfgMgr, &pCfgMgr)
  117. );
  118. if (FAILED(hr))
  119. {
  120. NhTrace(
  121. TRACE_FLAG_INIT,
  122. "NhGetHNetCfgMgr: Unable to create HNetCfgMgr (0x%08x)",
  123. hr
  124. );
  125. }
  126. }
  127. else
  128. {
  129. NhTrace(
  130. TRACE_FLAG_INIT,
  131. "NhGetHNetCfgMgr: Unable to create GIT (0x%08x)",
  132. hr
  133. );
  134. }
  135. if (SUCCEEDED(hr))
  136. {
  137. //
  138. // Store the CfgMgr pointer in the GIT
  139. //
  140. hr = NhGITp->RegisterInterfaceInGlobal(
  141. pCfgMgr,
  142. IID_IHNetCfgMgr,
  143. &NhCfgMgrCookie
  144. );
  145. pCfgMgr->Release();
  146. if (FAILED(hr))
  147. {
  148. NhTrace(
  149. TRACE_FLAG_INIT,
  150. "NhGetHNetCfgMgr: Unable to register HNetCfgMgr (0x%08x)",
  151. hr
  152. );
  153. }
  154. }
  155. }
  156. LeaveCriticalSection(&NhLock);
  157. }
  158. if (SUCCEEDED(hr))
  159. {
  160. hr = NhGITp->GetInterfaceFromGlobal(
  161. NhCfgMgrCookie,
  162. IID_PPV_ARG(IHNetCfgMgr, ppCfgMgr)
  163. );
  164. }
  165. return hr;
  166. } // NhGetHNetCfgMgr
  167. ULONG
  168. NhMapGuidToAdapter(
  169. PWCHAR Guid
  170. )
  171. /*++
  172. Routine Description:
  173. This routine is invoked to map a GUID to an adapter index.
  174. It does so by querying 'GetInterfaceInfo' for the array of interfaces,
  175. which contains the GUID and adapter index for each interface.
  176. Arguments:
  177. Guid - the GUID to be mapped to an adapter index.
  178. Return Value:
  179. ULONG - the required adapter index
  180. --*/
  181. {
  182. ULONG AdapterIndex = (ULONG)-1;
  183. ULONG i;
  184. ULONG GuidLength;
  185. PIP_INTERFACE_INFO Info;
  186. PWCHAR Name;
  187. ULONG NameLength;
  188. ULONG Size;
  189. PROFILE("NhMapGuidToAdapter");
  190. Size = 0;
  191. GuidLength = lstrlenW(Guid);
  192. if (GetInterfaceInfo(NULL, &Size) == ERROR_INSUFFICIENT_BUFFER) {
  193. Info = reinterpret_cast<PIP_INTERFACE_INFO>(
  194. HeapAlloc(GetProcessHeap(), 0, Size)
  195. );
  196. if (Info) {
  197. if (GetInterfaceInfo(Info, &Size) == NO_ERROR) {
  198. for (i = 0; i < (ULONG)Info->NumAdapters; i++) {
  199. NameLength = lstrlenW(Info->Adapter[i].Name);
  200. if (NameLength < GuidLength) { continue; }
  201. Name = Info->Adapter[i].Name + (NameLength - GuidLength);
  202. if (lstrcmpiW(Guid, Name) == 0) {
  203. AdapterIndex = Info->Adapter[i].Index;
  204. break;
  205. }
  206. }
  207. }
  208. HeapFree(GetProcessHeap(), 0, Info);
  209. }
  210. }
  211. return AdapterIndex;
  212. } // NhMapGuidToAdapter
  213. VOID NTAPI
  214. NhpAddressChangeCallbackRoutine(
  215. PVOID Context,
  216. BOOLEAN TimedOut
  217. )
  218. /*++
  219. Routine Description:
  220. This routine is invoked when a change to a local address is signalled.
  221. It is responsible for updating the bindings of the private and public
  222. interfaces, and re-requesting change notification.
  223. Arguments:
  224. none used.
  225. Return Value:
  226. none.
  227. --*/
  228. {
  229. PROFILE("NhpAddressChangeCallbackRoutine");
  230. NtSetEvent(NatConnectionNotifyEvent, NULL);
  231. NhpStartAddressChangeNotification();
  232. } // NhpAddressChangeCallbackRoutine
  233. VOID
  234. NhpDeletePrivateInterface(
  235. VOID
  236. )
  237. /*++
  238. Routine Description:
  239. This routine is invoked to remove the private interface
  240. from each shared-access component.
  241. Arguments:
  242. none.
  243. Return Value:
  244. none.
  245. --*/
  246. {
  247. PROFILE("NhpDeletePrivateInterface");
  248. if (NhpStopDnsEvent) { DnsRmDeleteInterface(0); }
  249. if (NhpStopDhcpEvent) { DhcpRmDeleteInterface(0); }
  250. #ifndef NO_FTP_PROXY
  251. if (NhpStopFtpEvent) { FtpRmDeleteInterface(0); }
  252. #endif
  253. if (NhpStopAlgEvent) { AlgRmDeleteInterface(0); }
  254. if (NhpStopH323Event) { H323RmDeleteInterface(0); }
  255. if (NhpStopNatEvent) { NatRmDeleteInterface(0); }
  256. RtlZeroMemory(&NhpSharedPrivateLanGuid, sizeof(NhpSharedPrivateLanGuid));
  257. } // NhpDeletePrivateInterface
  258. ULONG
  259. NhpEnableQoSWindowSizeAdjustment(
  260. BOOLEAN fEnable
  261. )
  262. /*++
  263. Routine Description:
  264. Instructs PSCHED to enable or disable window size adjustment.
  265. Arguments:
  266. fEnable -- TRUE if adjustments are to be enabled; FALSE, to be disabled
  267. Return Value:
  268. ULONG -- Win32 error
  269. --*/
  270. {
  271. ULONG ulError = ERROR_SUCCESS;
  272. DWORD dwValue;
  273. WMIHANDLE hDataBlock = NULL;
  274. GUID qosGuid;
  275. PROFILE("NhpEnableQoSWindowSizeAdjustment");
  276. do
  277. {
  278. //
  279. // WmiOpenBlock doesn't take a const guid, se we need to
  280. // copy the defind value
  281. //
  282. CopyMemory(&qosGuid, &GUID_QOS_ENABLE_WINDOW_ADJUSTMENT, sizeof(GUID));
  283. //
  284. // Obtain a handle to the data block
  285. //
  286. ulError =
  287. WmiOpenBlock(
  288. &qosGuid,
  289. GENERIC_WRITE,
  290. &hDataBlock
  291. );
  292. if (ERROR_SUCCESS != ulError)
  293. {
  294. NhTrace(
  295. TRACE_FLAG_INIT,
  296. "NhpEnableQoSWindowSizeAdjustment: WmiOpenBlock = %u",
  297. ulError
  298. );
  299. break;
  300. }
  301. //
  302. // Set the value for the data block
  303. //
  304. dwValue = (fEnable ? 1 : 0);
  305. ulError =
  306. WmiSetSingleInstanceW(
  307. hDataBlock,
  308. L"PSCHED",
  309. 0,
  310. sizeof(dwValue),
  311. &dwValue
  312. );
  313. if (ERROR_SUCCESS != ulError)
  314. {
  315. NhTrace(
  316. TRACE_FLAG_INIT,
  317. "NhpEnableQoSWindowSizeAdjustment: WmiSetSingleInstanceW = %u",
  318. ulError
  319. );
  320. break;
  321. }
  322. } while (FALSE);
  323. if (NULL != hDataBlock)
  324. {
  325. WmiCloseBlock(hDataBlock);
  326. }
  327. return ulError;
  328. } // NhpEnableQoSWindowSizeAdjustment
  329. VOID
  330. NhpStartAddressChangeNotification(
  331. VOID
  332. )
  333. /*++
  334. Routine Description:
  335. This routine is invoked to request notifications of changes
  336. to local IP addresses. The notifications are signalled on an event
  337. which is created in this routine, and are acted on in a callback routine
  338. which is registered in this routine.
  339. Arguments:
  340. none.
  341. Return Value:
  342. none.
  343. --*/
  344. {
  345. ULONG Error;
  346. NTSTATUS status;
  347. HANDLE TcpipHandle;
  348. PROFILE("NhpStartAddressChangeNotification");
  349. //
  350. // Create an event on which to receive notifications
  351. // and register a callback routine to be invoked if the event is signalled.
  352. // Then request notification of address changes on the event.
  353. //
  354. do {
  355. EnterCriticalSection(&NhLock);
  356. if (!NhpAddressChangeEvent) {
  357. status =
  358. NtCreateEvent(
  359. &NhpAddressChangeEvent,
  360. EVENT_ALL_ACCESS,
  361. NULL,
  362. SynchronizationEvent,
  363. FALSE
  364. );
  365. if (!NT_SUCCESS(status)) { break; }
  366. status =
  367. RtlRegisterWait(
  368. &NhpAddressChangeWaitHandle,
  369. NhpAddressChangeEvent,
  370. NhpAddressChangeCallbackRoutine,
  371. NULL,
  372. INFINITE,
  373. 0
  374. );
  375. if (!NT_SUCCESS(status)) { break; }
  376. }
  377. ZeroMemory(&NhpAddressChangeOverlapped, sizeof(OVERLAPPED));
  378. NhpAddressChangeOverlapped.hEvent = NhpAddressChangeEvent;
  379. Error = NotifyAddrChange(&TcpipHandle, &NhpAddressChangeOverlapped);
  380. if (Error != ERROR_IO_PENDING) { break; }
  381. LeaveCriticalSection(&NhLock);
  382. return;
  383. } while(FALSE);
  384. //
  385. // A failure has occurred, so cleanup and quit.
  386. // We proceed in this case without notification of address changes.
  387. //
  388. NhpStopAddressChangeNotification();
  389. LeaveCriticalSection(&NhLock);
  390. } // NhpStartAddressChangeNotification
  391. VOID
  392. NhpStopAddressChangeNotification(
  393. VOID
  394. )
  395. /*++
  396. Routine Description:
  397. This routine is called to stop notification of local IP address changes,
  398. and to clean up resources used for handling notifications.
  399. Arguments:
  400. none.
  401. Return Value:
  402. none.
  403. --*/
  404. {
  405. EnterCriticalSection(&NhLock);
  406. if (NhpAddressChangeWaitHandle) {
  407. RtlDeregisterWait(NhpAddressChangeWaitHandle);
  408. NhpAddressChangeWaitHandle = NULL;
  409. }
  410. if (NhpAddressChangeEvent) {
  411. NtClose(NhpAddressChangeEvent);
  412. NhpAddressChangeEvent = NULL;
  413. }
  414. LeaveCriticalSection(&NhLock);
  415. } // NhpStopAddressChangeNotification
  416. VOID
  417. NhpUpdateConnectionsFolder(
  418. VOID
  419. )
  420. /*++
  421. Routine Description:
  422. This routine is called to refresh the connections folder UI.
  423. Arguments:
  424. None.
  425. Return Value:
  426. None.
  427. Environment:
  428. COM must be initialized on the calling thread.
  429. --*/
  430. {
  431. HRESULT hr;
  432. INetConnectionRefresh *pNetConnectionRefresh;
  433. hr = CoCreateInstance(
  434. CLSID_ConnectionManager,
  435. NULL,
  436. CLSCTX_SERVER | CLSCTX_NO_CODE_DOWNLOAD,
  437. IID_PPV_ARG(INetConnectionRefresh, &pNetConnectionRefresh)
  438. );
  439. if (SUCCEEDED(hr))
  440. {
  441. pNetConnectionRefresh->RefreshAll();
  442. pNetConnectionRefresh->Release();
  443. }
  444. } // NhpUpdateConnectionsFolder
  445. VOID
  446. NhpUpdatePolicySettings(
  447. VOID
  448. )
  449. {
  450. INetConnectionUiUtilities *pNetConnUiUtil;
  451. HRESULT hr;
  452. BOOL fPolicyAllowsFirewall;
  453. BOOL fPolicyAllowsSharing;
  454. hr = CoCreateInstance(
  455. CLSID_NetConnectionUiUtilities,
  456. NULL,
  457. CLSCTX_ALL,
  458. IID_PPV_ARG(INetConnectionUiUtilities, &pNetConnUiUtil)
  459. );
  460. if (SUCCEEDED(hr))
  461. {
  462. fPolicyAllowsFirewall =
  463. pNetConnUiUtil->UserHasPermission(NCPERM_PersonalFirewallConfig);
  464. fPolicyAllowsSharing =
  465. pNetConnUiUtil->UserHasPermission(NCPERM_ShowSharedAccessUi);
  466. pNetConnUiUtil->Release();
  467. }
  468. else
  469. {
  470. //
  471. // On failure assume that policy permits everything.
  472. //
  473. fPolicyAllowsFirewall = TRUE;
  474. fPolicyAllowsSharing = TRUE;
  475. NhTrace(
  476. TRACE_FLAG_INIT,
  477. "NhpUpdatePolicySettings: Unable to create INetConnectionUiUtilities (0x%08x)",
  478. hr
  479. );
  480. }
  481. //
  482. // Update global variables w/ new settings
  483. //
  484. InterlockedExchange(
  485. reinterpret_cast<LPLONG>(&NhPolicyAllowsFirewall),
  486. static_cast<LONG>(fPolicyAllowsFirewall)
  487. );
  488. InterlockedExchange(
  489. reinterpret_cast<LPLONG>(&NhPolicyAllowsSharing),
  490. static_cast<LONG>(fPolicyAllowsSharing)
  491. );
  492. NhTrace(
  493. TRACE_FLAG_INIT,
  494. "NhpUpdatePolicySettings: NhPolicyAllowsFirewall=%i, NhPolicyAllowsSharing=%i",
  495. NhPolicyAllowsFirewall,
  496. NhPolicyAllowsSharing
  497. );
  498. } // NhpUpdatePolicySettings
  499. BOOLEAN
  500. NhQueryScopeInformation(
  501. PULONG Address,
  502. PULONG Mask
  503. )
  504. /*++
  505. Routine Description:
  506. This routine is called to retrieve information about the current scope
  507. for automatic addressing.
  508. Arguments:
  509. Address - receives the address of the scope
  510. Mask - receives the network mask of the scope
  511. Return Value:
  512. BOOLEAN - TRUE if successful, FALSE otherwise.
  513. --*/
  514. {
  515. EnterCriticalSection(&NhLock);
  516. if (0 == NhDhcpScopeAddress) {
  517. LeaveCriticalSection(&NhLock);
  518. return FALSE;
  519. }
  520. *Address = NhDhcpScopeAddress;
  521. *Mask = NhDhcpScopeMask;
  522. LeaveCriticalSection(&NhLock);
  523. return TRUE;
  524. } // NhQueryScopeInformation
  525. ULONG NhpQueryServiceStartType(SC_HANDLE hService, DWORD * pdwStartType)
  526. {
  527. ASSERT(hService);
  528. ASSERT(pdwStartType);
  529. ULONG Error = ERROR_SUCCESS;
  530. DWORD cbBuf = sizeof (QUERY_SERVICE_CONFIG) +
  531. 5 * (32 * sizeof(WCHAR));
  532. LPQUERY_SERVICE_CONFIG pConfig = NULL;
  533. pConfig = (LPQUERY_SERVICE_CONFIG) NH_ALLOCATE(cbBuf);
  534. if (!pConfig)
  535. return ERROR_NOT_ENOUGH_MEMORY;
  536. do {
  537. if (!QueryServiceConfig(hService, pConfig, cbBuf, &cbBuf))
  538. {
  539. Error = GetLastError();
  540. if (ERROR_INSUFFICIENT_BUFFER == GetLastError())
  541. {
  542. NH_FREE(pConfig);
  543. pConfig = (LPQUERY_SERVICE_CONFIG) NH_ALLOCATE(cbBuf);
  544. if (NULL == pConfig)
  545. {
  546. Error = ERROR_NOT_ENOUGH_MEMORY;
  547. break;
  548. }
  549. if (!QueryServiceConfig(hService, pConfig, cbBuf, &cbBuf))
  550. {
  551. Error = GetLastError();
  552. break;
  553. }
  554. }
  555. else
  556. {
  557. break;
  558. }
  559. }
  560. Error = ERROR_SUCCESS;
  561. *pdwStartType = pConfig->dwStartType;
  562. } while(FALSE);
  563. if (pConfig)
  564. NH_FREE(pConfig);
  565. return Error;
  566. }
  567. BOOL NhpIsServiceRunningOrGoingToRun(SC_HANDLE hScm, LPCTSTR pSvcName)
  568. {
  569. BOOL bRet = FALSE;
  570. SC_HANDLE hService = NULL;
  571. DWORD dwStartType = 0;
  572. hService = OpenService(hScm, pSvcName, SERVICE_QUERY_STATUS | SERVICE_QUERY_CONFIG);
  573. if (hService)
  574. {
  575. SERVICE_STATUS Status;
  576. ZeroMemory(&Status, sizeof(Status));
  577. if (ERROR_SUCCESS == NhpQueryServiceStartType(hService, &dwStartType) &&
  578. SERVICE_AUTO_START == dwStartType)
  579. {
  580. bRet = TRUE;
  581. }
  582. else if (QueryServiceStatus(hService, &Status) &&
  583. (SERVICE_RUNNING == Status.dwCurrentState ||
  584. SERVICE_START_PENDING == Status.dwCurrentState))
  585. {
  586. bRet = TRUE;
  587. }
  588. CloseServiceHandle(hService);
  589. }
  590. return bRet;
  591. }
  592. ULONG
  593. NhStartICSProtocols(
  594. VOID
  595. )
  596. /*++
  597. Routine Description:
  598. This routine starts the DNS and DHCP modules.
  599. Arguments:
  600. Argument* - count and array of arguments specified to the service
  601. Return Value:
  602. none.
  603. --*/
  604. {
  605. ULONG Error;
  606. IP_AUTO_DHCP_GLOBAL_INFO DhcpInfo = {
  607. IPNATHLP_LOGGING_ERROR,
  608. 0,
  609. 7 * 24 * 60,
  610. DEFAULT_SCOPE_ADDRESS,
  611. DEFAULT_SCOPE_MASK,
  612. 0
  613. };
  614. IP_DNS_PROXY_GLOBAL_INFO DnsInfo = {
  615. IPNATHLP_LOGGING_ERROR,
  616. IP_DNS_PROXY_FLAG_ENABLE_DNS,
  617. 3
  618. };
  619. //
  620. // Get ICS settings to see if these should be started...
  621. //
  622. do {
  623. SC_HANDLE hScm = OpenSCManager(NULL, NULL, GENERIC_READ);
  624. //dont start the DNS module if DNS server is running on local host
  625. if (hScm)
  626. {
  627. NoLocalDns = !NhpIsServiceRunningOrGoingToRun(hScm, c_szDnsServiceName);
  628. }
  629. if (NoLocalDns)
  630. {
  631. if (!(NhpStopDnsEvent = CreateEvent(NULL, FALSE, FALSE, NULL))) {
  632. break;
  633. } else {
  634. Error =
  635. DnsRmStartProtocol(
  636. NhpStopDnsEvent,
  637. NULL,
  638. &DnsInfo,
  639. IP_NAT_VERSION,
  640. sizeof(DnsInfo),
  641. 1
  642. );
  643. if (Error) {
  644. NhTrace(
  645. TRACE_FLAG_INIT,
  646. "ServiceMain: DnsRmStartProtocol=%d",
  647. Error
  648. );
  649. CloseHandle(NhpStopDnsEvent); NhpStopDnsEvent = NULL; break;
  650. }
  651. }
  652. }
  653. //dont start the DHCP module if DNS server is running on local host
  654. if (hScm)
  655. {
  656. NhpNoLocalDhcp = !NhpIsServiceRunningOrGoingToRun(hScm, c_szDhcpServiceName);
  657. }
  658. if (NhpNoLocalDhcp)
  659. {
  660. if (!(NhpStopDhcpEvent = CreateEvent(NULL, FALSE, FALSE, NULL))) {
  661. break;
  662. } else {
  663. NhQueryScopeInformation(
  664. &DhcpInfo.ScopeNetwork, &DhcpInfo.ScopeMask
  665. );
  666. DhcpInfo.ScopeNetwork &= DhcpInfo.ScopeMask;
  667. Error =
  668. DhcpRmStartProtocol(
  669. NhpStopDhcpEvent,
  670. NULL,
  671. &DhcpInfo,
  672. IP_NAT_VERSION,
  673. sizeof(DhcpInfo),
  674. 1
  675. );
  676. if (Error) {
  677. NhTrace(
  678. TRACE_FLAG_INIT,
  679. "ServiceMain: DhcpRmStartProtocol=%d",
  680. Error
  681. );
  682. CloseHandle(NhpStopDhcpEvent); NhpStopDhcpEvent = NULL; break;
  683. }
  684. }
  685. }
  686. if (hScm)
  687. CloseServiceHandle(hScm);
  688. //
  689. // Instruct QoS to enable window size adjustments. Any error that
  690. // occurs here is not propagated, as ICS will still work correctly
  691. // if this fails.
  692. //
  693. ULONG Error2 = NhpEnableQoSWindowSizeAdjustment(TRUE);
  694. if (ERROR_SUCCESS == Error2)
  695. {
  696. NhpQoSEnabled = TRUE;
  697. }
  698. //
  699. // Create the UDP broadcast mapper
  700. //
  701. HRESULT hr;
  702. CComObject<CUdpBroadcastMapper> *pUdpBroadcast;
  703. hr = CComObject<CUdpBroadcastMapper>::CreateInstance(&pUdpBroadcast);
  704. if (SUCCEEDED(hr))
  705. {
  706. pUdpBroadcast->AddRef();
  707. hr = pUdpBroadcast->Initialize(&NatComponentReference);
  708. if (SUCCEEDED(hr))
  709. {
  710. hr = pUdpBroadcast->QueryInterface(
  711. IID_PPV_ARG(IUdpBroadcastMapper, &NhpUdpBroadcastMapper)
  712. );
  713. }
  714. pUdpBroadcast->Release();
  715. }
  716. if (FAILED(hr))
  717. {
  718. Error = ERROR_CAN_NOT_COMPLETE;
  719. break;
  720. }
  721. //
  722. // Start the Beaconing Service
  723. //
  724. StartBeaconSvr();
  725. return NO_ERROR;
  726. } while (FALSE);
  727. return Error;
  728. }
  729. ULONG
  730. NhStopICSProtocols(
  731. VOID
  732. )
  733. /*++
  734. Routine Description:
  735. This routine stops the "ICS" modules (DNS, DHCP, QoSWindow, Beacon etc.)
  736. Arguments:
  737. none.
  738. Return Value:
  739. none.
  740. --*/
  741. {
  742. ULONG Error = NO_ERROR;
  743. //
  744. // Stop the Beaconing Service
  745. //
  746. StopBeaconSvr();
  747. //
  748. // Cleanup the UDP broadcast mapper
  749. //
  750. if (NULL != NhpUdpBroadcastMapper)
  751. {
  752. NhpUdpBroadcastMapper->Shutdown();
  753. NhpUdpBroadcastMapper->Release();
  754. NhpUdpBroadcastMapper = NULL;
  755. }
  756. //
  757. // Instruct QoS to disable window size adjustments
  758. //
  759. if (NhpQoSEnabled) {
  760. NhpEnableQoSWindowSizeAdjustment(FALSE);
  761. NhpQoSEnabled = FALSE;
  762. }
  763. //
  764. // Remove the private interface from each shared-access component
  765. //
  766. NhpDeletePrivateInterface();
  767. //
  768. // Stop DHCP followed by DNS
  769. //
  770. if (NhpStopDhcpEvent) {
  771. DhcpRmStopProtocol();
  772. WaitForSingleObject(NhpStopDhcpEvent, INFINITE);
  773. CloseHandle(NhpStopDhcpEvent); NhpStopDhcpEvent = NULL;
  774. }
  775. if (NhpStopDnsEvent) {
  776. DnsRmStopProtocol();
  777. WaitForSingleObject(NhpStopDnsEvent, INFINITE);
  778. CloseHandle(NhpStopDnsEvent); NhpStopDnsEvent = NULL;
  779. }
  780. return Error;
  781. }
  782. ULONG
  783. NhUpdatePrivateInterface(
  784. VOID
  785. )
  786. /*++
  787. Routine Description:
  788. This routine is invoked to add the private interface to each
  789. shared-access component. It is also invoked when the private interface
  790. is already added, but some change has occurred which requires that it
  791. be updated (e.g. IP address change).
  792. Arguments:
  793. none.
  794. Return Value:
  795. Win32 error.
  796. --*/
  797. {
  798. ULONG AdapterIndex;
  799. PIP_ADAPTER_BINDING_INFO BindingInfo;
  800. ULONG Error;
  801. ULONG Count;
  802. GUID *pLanGuid;
  803. HRESULT hr;
  804. IHNetCfgMgr *pCfgMgr;
  805. IHNetIcsSettings *pIcsSettings;
  806. IEnumHNetIcsPrivateConnections *pEnum;
  807. IHNetIcsPrivateConnection *pIcsConn;
  808. IHNetConnection *pConn;
  809. IP_NAT_INTERFACE_INFO NatInfo =
  810. {
  811. 0,
  812. 0,
  813. { IP_NAT_VERSION, sizeof(RTR_INFO_BLOCK_HEADER), 0, { 0, 0, 0, 0 }}
  814. };
  815. UNICODE_STRING UnicodeString;
  816. PROFILE("NhUpdatePrivateInterface");
  817. //
  818. // We begin by reading the GUID from the configuration store,
  819. // and we then map that GUID to an adapter index.
  820. // Using that adapter index, we obtain the binding information
  821. // for the private interface.
  822. // We can then determine whether a change has occurred
  823. // by comparing the previous and new GUID and binding information.
  824. //
  825. //
  826. // Get the CfgMgr pointer out of the GIT
  827. //
  828. hr = NhGetHNetCfgMgr(&pCfgMgr);
  829. if (FAILED(hr))
  830. {
  831. NhTrace(
  832. TRACE_FLAG_INIT,
  833. "NhUpdatePrivateInterface: GetInterfaceFromGlobal=0x%08x",
  834. hr
  835. );
  836. return ERROR_CAN_NOT_COMPLETE;
  837. }
  838. //
  839. // Get the ICS settings interface
  840. //
  841. hr = pCfgMgr->QueryInterface(IID_PPV_ARG(IHNetIcsSettings, &pIcsSettings));
  842. pCfgMgr->Release();
  843. if (FAILED(hr))
  844. {
  845. NhTrace(
  846. TRACE_FLAG_INIT,
  847. "NhUpdatePrivateInterface: QI for IHNetIcsSettings=0x%08x",
  848. hr
  849. );
  850. return ERROR_CAN_NOT_COMPLETE;
  851. }
  852. //
  853. // Get the enumeration of the ICS private interfaces
  854. //
  855. hr = pIcsSettings->EnumIcsPrivateConnections(&pEnum);
  856. pIcsSettings->Release();
  857. if (FAILED(hr))
  858. {
  859. NhTrace(
  860. TRACE_FLAG_INIT,
  861. "NhUpdatePrivateInterface: EnumIcsPrivateConnections=0x%08x",
  862. hr
  863. );
  864. return ERROR_CAN_NOT_COMPLETE;
  865. }
  866. //
  867. // Get the private connection
  868. //
  869. hr = pEnum->Next(1, &pIcsConn, &Count);
  870. pEnum->Release();
  871. if (FAILED(hr) || 1 != Count)
  872. {
  873. NhTrace(
  874. TRACE_FLAG_INIT,
  875. "NhUpdatePrivateInterface: pEnum->Next=0x%08x, Count=%d",
  876. hr,
  877. Count
  878. );
  879. return ERROR_CAN_NOT_COMPLETE;
  880. }
  881. //
  882. // QI for the IHNetConnection
  883. //
  884. hr = pIcsConn->QueryInterface(IID_PPV_ARG(IHNetConnection, &pConn));
  885. pIcsConn->Release();
  886. if (FAILED(hr))
  887. {
  888. NhTrace(
  889. TRACE_FLAG_INIT,
  890. "NhUpdatePrivateInterface: QI for IHNetConnection=0x%08x",
  891. hr
  892. );
  893. return ERROR_CAN_NOT_COMPLETE;
  894. }
  895. //
  896. // Get the GUID for the connection
  897. //
  898. hr = pConn->GetGuid(&pLanGuid);
  899. pConn->Release();
  900. if (FAILED(hr))
  901. {
  902. NhTrace(
  903. TRACE_FLAG_INIT,
  904. "NhUpdatePrivateInterface: GetGuid=0x%08x",
  905. hr
  906. );
  907. return ERROR_CAN_NOT_COMPLETE;
  908. }
  909. //
  910. // Determine the adapter-index corresponding to the GUID
  911. //
  912. RtlStringFromGUID(*pLanGuid, &UnicodeString);
  913. AdapterIndex = NhMapGuidToAdapter(UnicodeString.Buffer);
  914. RtlFreeUnicodeString(&UnicodeString);
  915. if (AdapterIndex == (ULONG)-1) {
  916. NhTrace(
  917. TRACE_FLAG_INIT,
  918. "NhUpdatePrivateInterface: MapGuidToAdapter"
  919. );
  920. CoTaskMemFree(pLanGuid);
  921. return ERROR_CAN_NOT_COMPLETE;
  922. }
  923. //
  924. // Retrieve the binding information for the adapter
  925. //
  926. BindingInfo = NhQueryBindingInformation(AdapterIndex);
  927. if (!BindingInfo) {
  928. NhTrace(
  929. TRACE_FLAG_INIT,
  930. "NhUpdatePrivateInterface: QueryBindingInformation failed(2)\n"
  931. );
  932. CoTaskMemFree(pLanGuid);
  933. return ERROR_NO_SUCH_INTERFACE;
  934. }
  935. //
  936. // See if any change has occurred which requires an update.
  937. //
  938. if (RtlEqualMemory(pLanGuid, &NhpSharedPrivateLanGuid, sizeof(GUID)) &&
  939. AdapterIndex == NhpSharedPrivateLanIndex &&
  940. NhpSharedPrivateLanBindingInfo &&
  941. BindingInfo->AddressCount ==
  942. NhpSharedPrivateLanBindingInfo->AddressCount &&
  943. BindingInfo->AddressCount &&
  944. RtlEqualMemory(
  945. &BindingInfo->Address[0],
  946. &NhpSharedPrivateLanBindingInfo->Address[0],
  947. sizeof(IP_LOCAL_BINDING)
  948. )) {
  949. NhTrace(
  950. TRACE_FLAG_INIT,
  951. "NhUpdatePrivateInterface: no changes detected"
  952. );
  953. NH_FREE(BindingInfo);
  954. CoTaskMemFree(pLanGuid);
  955. return NO_ERROR;
  956. }
  957. //
  958. // A change has occurred which requires an update.
  959. // First we get rid of any existing private LAN interface,
  960. // then we add the new interface to each component (NAT, DHCP, DNS proxy)
  961. // and bind and enable the new interface.
  962. //
  963. NhpDeletePrivateInterface();
  964. do {
  965. Error =
  966. NatRmAddInterface(
  967. NULL,
  968. 0,
  969. PERMANENT,
  970. IF_TYPE_OTHER,
  971. IF_ACCESS_BROADCAST,
  972. IF_CONNECTION_DEDICATED,
  973. &NatInfo,
  974. IP_NAT_VERSION,
  975. sizeof(NatInfo),
  976. 1
  977. );
  978. if (Error) {
  979. NhTrace(
  980. TRACE_FLAG_INIT,
  981. "NhUpdatePrivateInterface: NatRmAddInterface=%d",
  982. Error
  983. );
  984. break;
  985. }
  986. if (NhpNoLocalDhcp)
  987. {
  988. Error =
  989. DhcpRmAddInterface(
  990. NULL,
  991. 0,
  992. PERMANENT,
  993. IF_TYPE_OTHER,
  994. IF_ACCESS_BROADCAST,
  995. IF_CONNECTION_DEDICATED,
  996. NULL,
  997. IP_NAT_VERSION,
  998. 0,
  999. 0
  1000. );
  1001. if (Error) {
  1002. NhTrace(
  1003. TRACE_FLAG_INIT,
  1004. "NhUpdatePrivateInterface: DhcpRmAddInterface=%d",
  1005. Error
  1006. );
  1007. break;
  1008. }
  1009. }
  1010. if (NoLocalDns)
  1011. {
  1012. Error =
  1013. DnsRmAddInterface(
  1014. NULL,
  1015. 0,
  1016. PERMANENT,
  1017. IF_TYPE_OTHER,
  1018. IF_ACCESS_BROADCAST,
  1019. IF_CONNECTION_DEDICATED,
  1020. NULL,
  1021. IP_NAT_VERSION,
  1022. 0,
  1023. 0
  1024. );
  1025. if (Error) {
  1026. NhTrace(
  1027. TRACE_FLAG_INIT,
  1028. "NhUpdatePrivateInterface: DnsRmAddInterface=%d",
  1029. Error
  1030. );
  1031. break;
  1032. }
  1033. }
  1034. #ifndef NO_FTP_PROXY
  1035. Error =
  1036. FtpRmAddInterface(
  1037. NULL,
  1038. 0,
  1039. PERMANENT,
  1040. IF_TYPE_OTHER,
  1041. IF_ACCESS_BROADCAST,
  1042. IF_CONNECTION_DEDICATED,
  1043. NULL,
  1044. IP_NAT_VERSION,
  1045. 0,
  1046. 0
  1047. );
  1048. if (Error) {
  1049. NhTrace(
  1050. TRACE_FLAG_INIT,
  1051. "NhUpdatePrivateInterface: FtpRmAddInterface=%d",
  1052. Error
  1053. );
  1054. break;
  1055. }
  1056. #endif
  1057. Error =
  1058. AlgRmAddInterface(
  1059. NULL,
  1060. 0,
  1061. PERMANENT,
  1062. IF_TYPE_OTHER,
  1063. IF_ACCESS_BROADCAST,
  1064. IF_CONNECTION_DEDICATED,
  1065. NULL,
  1066. IP_NAT_VERSION,
  1067. 0,
  1068. 0
  1069. );
  1070. if (Error) {
  1071. NhTrace(
  1072. TRACE_FLAG_INIT,
  1073. "NhUpdatePrivateInterface: AlgRmAddInterface=%d",
  1074. Error
  1075. );
  1076. break;
  1077. }
  1078. Error =
  1079. H323RmAddInterface(
  1080. NULL,
  1081. 0,
  1082. PERMANENT,
  1083. IF_TYPE_OTHER,
  1084. IF_ACCESS_BROADCAST,
  1085. IF_CONNECTION_DEDICATED,
  1086. NULL,
  1087. IP_NAT_VERSION,
  1088. 0,
  1089. 0
  1090. );
  1091. if (Error) {
  1092. NhTrace(
  1093. TRACE_FLAG_INIT,
  1094. "NhUpdatePrivateInterface: H323RmAddInterface=%d",
  1095. Error
  1096. );
  1097. break;
  1098. }
  1099. //
  1100. // Bind the private interface of each component
  1101. //
  1102. Error = NatBindInterface(0, NULL, BindingInfo, AdapterIndex);
  1103. if (Error) {
  1104. NhTrace(
  1105. TRACE_FLAG_INIT,
  1106. "NhUpdatePrivateInterface: NatRmBindInterface=%d",
  1107. Error
  1108. );
  1109. break;
  1110. }
  1111. if (NhpNoLocalDhcp)
  1112. {
  1113. Error = DhcpRmBindInterface(0, BindingInfo);
  1114. if (Error) {
  1115. NhTrace(
  1116. TRACE_FLAG_INIT,
  1117. "NhUpdatePrivateInterface: DhcpRmBindInterface=%d",
  1118. Error
  1119. );
  1120. break;
  1121. }
  1122. }
  1123. if (NoLocalDns)
  1124. {
  1125. Error = DnsRmBindInterface(0, BindingInfo);
  1126. if (Error) {
  1127. NhTrace(
  1128. TRACE_FLAG_INIT,
  1129. "NhUpdatePrivateInterface: DnsRmBindInterface=%d",
  1130. Error
  1131. );
  1132. break;
  1133. }
  1134. }
  1135. #ifndef NO_FTP_PROXY
  1136. Error = FtpRmBindInterface(0, BindingInfo);
  1137. if (Error) {
  1138. NhTrace(
  1139. TRACE_FLAG_INIT,
  1140. "NhUpdatePrivateInterface: FtpRmBindInterface=%d",
  1141. Error
  1142. );
  1143. break;
  1144. }
  1145. #endif
  1146. Error = AlgRmBindInterface(0, BindingInfo);
  1147. if (Error) {
  1148. NhTrace(
  1149. TRACE_FLAG_INIT,
  1150. "NhUpdatePrivateInterface: AlgRmBindInterface=%d",
  1151. Error
  1152. );
  1153. break;
  1154. }
  1155. Error = H323RmBindInterface(0, BindingInfo);
  1156. if (Error) {
  1157. NhTrace(
  1158. TRACE_FLAG_INIT,
  1159. "NhUpdatePrivateInterface: H323RmBindInterface=%d",
  1160. Error
  1161. );
  1162. break;
  1163. }
  1164. //
  1165. // Enable the private interface for the components.
  1166. // The NAT private interface is always enabled, and therefore
  1167. // requires no additional call.
  1168. //
  1169. if (NhpNoLocalDhcp)
  1170. {
  1171. Error = DhcpRmEnableInterface(0);
  1172. if (Error) {
  1173. NhTrace(
  1174. TRACE_FLAG_INIT,
  1175. "NhUpdatePrivateInterface: DhcpRmEnableInterface=%d",
  1176. Error
  1177. );
  1178. break;
  1179. }
  1180. }
  1181. if (NoLocalDns)
  1182. {
  1183. Error = DnsRmEnableInterface(0);
  1184. if (Error) {
  1185. NhTrace(
  1186. TRACE_FLAG_INIT,
  1187. "NhUpdatePrivateInterface: DnsRmEnableInterface=%d",
  1188. Error
  1189. );
  1190. break;
  1191. }
  1192. }
  1193. #ifndef NO_FTP_PROXY
  1194. Error = FtpRmEnableInterface(0);
  1195. if (Error) {
  1196. NhTrace(
  1197. TRACE_FLAG_INIT,
  1198. "NhUpdatePrivateInterface: FtpRmEnableInterface=%d",
  1199. Error
  1200. );
  1201. break;
  1202. }
  1203. #endif
  1204. Error = AlgRmEnableInterface(0);
  1205. if (Error) {
  1206. NhTrace(
  1207. TRACE_FLAG_INIT,
  1208. "NhUpdatePrivateInterface: AlgRmEnableInterface=%d",
  1209. Error
  1210. );
  1211. break;
  1212. }
  1213. Error = H323RmEnableInterface(0);
  1214. if (Error) {
  1215. NhTrace(
  1216. TRACE_FLAG_INIT,
  1217. "NhUpdatePrivateInterface: H323RmEnableInterface=%d",
  1218. Error
  1219. );
  1220. break;
  1221. }
  1222. //
  1223. // The interface was activated successfully.
  1224. //
  1225. RtlCopyMemory(&NhpSharedPrivateLanGuid, pLanGuid, sizeof(GUID));
  1226. NhpSharedPrivateLanIndex = AdapterIndex;
  1227. CoTaskMemFree(pLanGuid);
  1228. if (NhpSharedPrivateLanBindingInfo) {
  1229. NH_FREE(NhpSharedPrivateLanBindingInfo);
  1230. }
  1231. NhpSharedPrivateLanBindingInfo = BindingInfo;
  1232. return NO_ERROR;
  1233. } while(FALSE);
  1234. NH_FREE(BindingInfo);
  1235. CoTaskMemFree(pLanGuid);
  1236. return Error;
  1237. } // NhUpdatePrivateInterface
  1238. VOID
  1239. ServiceHandler(
  1240. ULONG ControlCode
  1241. )
  1242. /*++
  1243. Routine Description:
  1244. This routine is called to control the 'SharedAccess' service.
  1245. Arguments:
  1246. ControlCode - indicates the requested operation
  1247. Return Value:
  1248. none.
  1249. --*/
  1250. {
  1251. BOOLEAN ComInitialized = FALSE;
  1252. HRESULT hr;
  1253. PROFILE("ServiceHandler");
  1254. if (ControlCode == IPNATHLP_CONTROL_UPDATE_CONNECTION) {
  1255. //
  1256. // Update our policy settings
  1257. //
  1258. NhpUpdatePolicySettings();
  1259. //
  1260. // Signal the configuration-changed event
  1261. //
  1262. NtSetEvent(NatConfigurationChangedEvent, NULL);
  1263. SignalBeaconSvr();
  1264. } else if (ControlCode == IPNATHLP_CONTROL_UPDATE_SETTINGS) {
  1265. //
  1266. // Update all state which depends on shared access settings
  1267. //
  1268. NatRemoveApplicationSettings();
  1269. NhUpdateApplicationSettings();
  1270. NatInstallApplicationSettings();
  1271. } else if (ControlCode == IPNATHLP_CONTROL_UPDATE_FWLOGGER) {
  1272. FwUpdateLoggingSettings();
  1273. } else if (ControlCode == IPNATHLP_CONTROL_UPDATE_AUTODIAL) {
  1274. NtSetEvent(NatConnectionNotifyEvent, NULL);
  1275. } else if (ControlCode == SERVICE_CONTROL_STOP &&
  1276. NhpServiceStatus.dwCurrentState != SERVICE_STOPPED &&
  1277. NhpServiceStatus.dwCurrentState != SERVICE_STOP_PENDING) {
  1278. NhpServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
  1279. if (NhpServiceStatusHandle) {
  1280. SetServiceStatus(NhpServiceStatusHandle, &NhpServiceStatus);
  1281. }
  1282. if (NhpClassObjectsRegistered) {
  1283. _Module.RevokeClassObjects();
  1284. NhpClassObjectsRegistered = FALSE;
  1285. }
  1286. NhpStopAddressChangeNotification();
  1287. if (NhpStopNatEvent) {
  1288. NatRmStopProtocol();
  1289. WaitForSingleObject(NhpStopNatEvent, INFINITE);
  1290. CloseHandle(NhpStopNatEvent); NhpStopNatEvent = NULL;
  1291. }
  1292. if (NhpStopAlgEvent) {
  1293. AlgRmStopProtocol();
  1294. WaitForSingleObject(NhpStopAlgEvent, INFINITE);
  1295. CloseHandle(NhpStopAlgEvent); NhpStopAlgEvent = NULL;
  1296. }
  1297. #ifndef NO_FTP_PROXY
  1298. if (NhpStopFtpEvent) {
  1299. FtpRmStopProtocol();
  1300. WaitForSingleObject(NhpStopFtpEvent, INFINITE);
  1301. CloseHandle(NhpStopFtpEvent); NhpStopFtpEvent = NULL;
  1302. }
  1303. #endif
  1304. if (NhpStopH323Event) {
  1305. H323RmStopProtocol();
  1306. WaitForSingleObject(NhpStopH323Event, INFINITE);
  1307. CloseHandle(NhpStopH323Event); NhpStopH323Event = NULL;
  1308. }
  1309. EnterCriticalSection(&NhLock);
  1310. NhFreeApplicationSettings();
  1311. if (NhpSharedPrivateLanBindingInfo) {
  1312. NH_FREE(NhpSharedPrivateLanBindingInfo);
  1313. NhpSharedPrivateLanBindingInfo = NULL;
  1314. }
  1315. LeaveCriticalSection(&NhLock);
  1316. NhpServiceStatus.dwCurrentState = SERVICE_STOPPED;
  1317. NhResetComponentMode();
  1318. //
  1319. // Shutdown the firewall logging subsystem
  1320. //
  1321. if (NhpFwLoggingInitialized) {
  1322. FwCleanupLogger();
  1323. NhpFwLoggingInitialized = FALSE;
  1324. }
  1325. //
  1326. // Release our reference to RasMan
  1327. //
  1328. if (NhpRasmanReferenced) {
  1329. RasReferenceRasman(FALSE);
  1330. NhpRasmanReferenced = FALSE;
  1331. }
  1332. //
  1333. // Update the network connections folder (so that the firewall icons
  1334. // will disappear as necessary).
  1335. //
  1336. hr = CoInitializeEx(NULL, COINIT_MULTITHREADED | COINIT_DISABLE_OLE1DDE );
  1337. if (SUCCEEDED(hr)) {
  1338. ComInitialized = TRUE;
  1339. } else if (RPC_E_CHANGED_MODE == hr) {
  1340. hr = S_OK;
  1341. }
  1342. if (SUCCEEDED(hr)) {
  1343. NhpUpdateConnectionsFolder();
  1344. }
  1345. if (TRUE == ComInitialized) {
  1346. CoUninitialize();
  1347. }
  1348. }
  1349. if (NhpServiceStatusHandle) {
  1350. SetServiceStatus(NhpServiceStatusHandle, &NhpServiceStatus);
  1351. }
  1352. } // ServiceHandler
  1353. VOID
  1354. ServiceMain(
  1355. ULONG ArgumentCount,
  1356. PWCHAR ArgumentArray[]
  1357. )
  1358. /*++
  1359. Routine Description:
  1360. This routine is the entrypoint for the connection-sharing service.
  1361. It is responsible for initializing the module and starting operation.
  1362. Arguments:
  1363. Argument* - count and array of arguments specified to the service
  1364. Return Value:
  1365. none.
  1366. --*/
  1367. {
  1368. HRESULT hr;
  1369. ULONG Error;
  1370. BOOLEAN ComInitialized = FALSE;
  1371. #ifndef NO_FTP_PROXY
  1372. IP_FTP_GLOBAL_INFO FtpInfo = {
  1373. IPNATHLP_LOGGING_ERROR,
  1374. 0
  1375. };
  1376. #endif
  1377. IP_ALG_GLOBAL_INFO AlgInfo = {
  1378. IPNATHLP_LOGGING_ERROR,
  1379. 0
  1380. };
  1381. IP_H323_GLOBAL_INFO H323Info = {
  1382. IPNATHLP_LOGGING_ERROR,
  1383. 0
  1384. };
  1385. IP_NAT_GLOBAL_INFO NatInfo = {
  1386. IPNATHLP_LOGGING_ERROR,
  1387. 0,
  1388. { IP_NAT_VERSION, FIELD_OFFSET(RTR_INFO_BLOCK_HEADER, TocEntry), 0,
  1389. { 0, 0, 0, 0 }}
  1390. };
  1391. PROFILE("ServiceMain");
  1392. do {
  1393. //
  1394. // Initialize service status, register a service control handler,
  1395. // and indicate that the service is starting
  1396. //
  1397. ZeroMemory(&NhpServiceStatus, sizeof(NhpServiceStatus));
  1398. NhpServiceStatus.dwServiceType = SERVICE_WIN32_SHARE_PROCESS;
  1399. NhpServiceStatus.dwCurrentState = SERVICE_START_PENDING;
  1400. NhpServiceStatusHandle =
  1401. RegisterServiceCtrlHandler(
  1402. TEXT("SharedAccess"), ServiceHandler
  1403. );
  1404. if (!NhpServiceStatusHandle) { break; }
  1405. //
  1406. // Attempt to set the component into 'Shared Access' mode.
  1407. // This module implements both shared-access and connection-sharing
  1408. // which are mutually exclusive, so we need to ensure that
  1409. // connection-sharing is not operational before proceeding.
  1410. //
  1411. if (!NhSetComponentMode(NhSharedAccessMode)) {
  1412. NhTrace(
  1413. TRACE_FLAG_INIT,
  1414. "ServiceMain: cannot enable Shared Access mode"
  1415. );
  1416. break;
  1417. }
  1418. //
  1419. // Make sure COM is initialized on this thread
  1420. //
  1421. hr = CoInitializeEx(NULL, COINIT_MULTITHREADED | COINIT_DISABLE_OLE1DDE );
  1422. if (SUCCEEDED(hr))
  1423. {
  1424. ComInitialized = TRUE;
  1425. }
  1426. else
  1427. {
  1428. if (RPC_E_CHANGED_MODE != hr)
  1429. {
  1430. NhTrace(
  1431. TRACE_FLAG_INIT,
  1432. "ServiceMain: Unable to initialize COM (0x%08x)",
  1433. hr
  1434. );
  1435. break;
  1436. }
  1437. else
  1438. {
  1439. ASSERT(FALSE);
  1440. NhTrace(
  1441. TRACE_FLAG_INIT,
  1442. "ServiceMain: Unexpectedly in STA!"
  1443. );
  1444. }
  1445. }
  1446. //
  1447. // Obtain the current policy settings.
  1448. //
  1449. NhpServiceStatus.dwCheckPoint++;
  1450. SetServiceStatus(NhpServiceStatusHandle, &NhpServiceStatus);
  1451. NhpUpdatePolicySettings();
  1452. //
  1453. // Reference RasMan. As we live in the same process as rasman, the
  1454. // normal SC dependency mechanism won't necessarily keep the rasman
  1455. // service alive (119042)
  1456. //
  1457. NhpServiceStatus.dwCheckPoint++;
  1458. SetServiceStatus(NhpServiceStatusHandle, &NhpServiceStatus);
  1459. if (ERROR_SUCCESS != (Error = RasReferenceRasman(TRUE))) {
  1460. NhTrace(
  1461. TRACE_FLAG_INIT,
  1462. "ServiceMain: Unable to reference RasMan (0x%08x)",
  1463. Error
  1464. );
  1465. break;
  1466. }
  1467. NhpRasmanReferenced = TRUE;
  1468. //
  1469. // Initialize the firewall logging subsystem
  1470. //
  1471. Error = FwInitializeLogger();
  1472. if (ERROR_SUCCESS != Error) {
  1473. NhTrace(
  1474. TRACE_FLAG_INIT,
  1475. "ServiceMain: FwInitializeLogger=%d",
  1476. Error
  1477. );
  1478. break;
  1479. }
  1480. NhpFwLoggingInitialized = TRUE;
  1481. //
  1482. // Register the class object for our notification sink
  1483. //
  1484. hr = _Module.RegisterClassObjects(
  1485. CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
  1486. REGCLS_MULTIPLEUSE
  1487. );
  1488. if (FAILED(hr)) {
  1489. NhTrace(
  1490. TRACE_FLAG_INIT,
  1491. "ServiceMain: _Module.RegisterClassObjects=0x%08x",
  1492. hr
  1493. );
  1494. break;
  1495. }
  1496. NhpClassObjectsRegistered = TRUE;
  1497. //
  1498. // Start operations by loading the NAT, Ftp, ALG, and H.323 modules
  1499. //
  1500. NhpServiceStatus.dwWaitHint = 30000;
  1501. SetServiceStatus(NhpServiceStatusHandle, &NhpServiceStatus);
  1502. if (!(NhpStopNatEvent = CreateEvent(NULL, FALSE, FALSE, NULL))) {
  1503. break;
  1504. } else {
  1505. Error =
  1506. NatRmStartProtocol(
  1507. NhpStopNatEvent,
  1508. NULL,
  1509. &NatInfo,
  1510. IP_NAT_VERSION,
  1511. sizeof(NatInfo),
  1512. 1
  1513. );
  1514. if (Error) {
  1515. NhTrace(
  1516. TRACE_FLAG_INIT,
  1517. "ServiceMain: NatRmStartProtocol=%d",
  1518. Error
  1519. );
  1520. CloseHandle(NhpStopNatEvent); NhpStopNatEvent = NULL; break;
  1521. }
  1522. }
  1523. #ifndef NO_FTP_PROXY
  1524. NhpServiceStatus.dwCheckPoint++;
  1525. SetServiceStatus(NhpServiceStatusHandle, &NhpServiceStatus);
  1526. if (!(NhpStopFtpEvent = CreateEvent(NULL, FALSE, FALSE, NULL))) {
  1527. break;
  1528. } else {
  1529. Error =
  1530. FtpRmStartProtocol(
  1531. NhpStopFtpEvent,
  1532. NULL,
  1533. &FtpInfo,
  1534. IP_NAT_VERSION,
  1535. sizeof(FtpInfo),
  1536. 1
  1537. );
  1538. if (Error) {
  1539. NhTrace(
  1540. TRACE_FLAG_INIT,
  1541. "ServiceMain: FtpRmStartProtocol=%d",
  1542. Error
  1543. );
  1544. CloseHandle(NhpStopFtpEvent); NhpStopFtpEvent = NULL; break;
  1545. }
  1546. }
  1547. #endif
  1548. NhpServiceStatus.dwCheckPoint++;
  1549. SetServiceStatus(NhpServiceStatusHandle, &NhpServiceStatus);
  1550. if (!(NhpStopAlgEvent = CreateEvent(NULL, FALSE, FALSE, NULL))) {
  1551. break;
  1552. } else {
  1553. Error =
  1554. AlgRmStartProtocol(
  1555. NhpStopAlgEvent,
  1556. NULL,
  1557. &AlgInfo,
  1558. IP_NAT_VERSION,
  1559. sizeof(AlgInfo),
  1560. 1
  1561. );
  1562. if (Error) {
  1563. NhTrace(
  1564. TRACE_FLAG_INIT,
  1565. "ServiceMain: AlgRmStartProtocol=%d",
  1566. Error
  1567. );
  1568. CloseHandle(NhpStopAlgEvent); NhpStopAlgEvent = NULL; break;
  1569. }
  1570. }
  1571. NhpServiceStatus.dwCheckPoint++;
  1572. SetServiceStatus(NhpServiceStatusHandle, &NhpServiceStatus);
  1573. if (!(NhpStopH323Event = CreateEvent(NULL, FALSE, FALSE, NULL))) {
  1574. break;
  1575. } else {
  1576. Error =
  1577. H323RmStartProtocol(
  1578. NhpStopH323Event,
  1579. NULL,
  1580. &H323Info,
  1581. IP_NAT_VERSION,
  1582. sizeof(H323Info),
  1583. 1
  1584. );
  1585. if (Error) {
  1586. NhTrace(
  1587. TRACE_FLAG_INIT,
  1588. "ServiceMain: H323RmStartProtocol=%d",
  1589. Error
  1590. );
  1591. CloseHandle(NhpStopH323Event); NhpStopH323Event = NULL; break;
  1592. }
  1593. }
  1594. //
  1595. // Start connection management. If needed, this will load the DNS and
  1596. // DHCP modules. The Beacon Service is also started.
  1597. //
  1598. NhpServiceStatus.dwCheckPoint++;
  1599. SetServiceStatus(NhpServiceStatusHandle, &NhpServiceStatus);
  1600. Error = NatStartConnectionManagement();
  1601. if (Error) {
  1602. NhTrace(
  1603. TRACE_FLAG_INIT,
  1604. "ServiceMain: NatStartConnectionManagement=%d",
  1605. Error
  1606. );
  1607. break;
  1608. }
  1609. NhpServiceStatus.dwCheckPoint++;
  1610. SetServiceStatus(NhpServiceStatusHandle, &NhpServiceStatus);
  1611. NhpStartAddressChangeNotification();
  1612. //
  1613. // Indicate that the service is now up and running.
  1614. //
  1615. NhpServiceStatus.dwCurrentState = SERVICE_RUNNING;
  1616. NhpServiceStatus.dwWaitHint = 0;
  1617. NhpServiceStatus.dwCheckPoint = 0;
  1618. NhpServiceStatus.dwControlsAccepted =
  1619. SERVICE_ACCEPT_STOP|SERVICE_ACCEPT_PARAMCHANGE;
  1620. SetServiceStatus(NhpServiceStatusHandle, &NhpServiceStatus);
  1621. NhTrace(TRACE_FLAG_INIT, "ServiceMain: service started successfully");
  1622. //
  1623. // Ask the connections folder to update itself.
  1624. //
  1625. NhpUpdateConnectionsFolder();
  1626. //
  1627. // Uninitialize COM
  1628. //
  1629. if (TRUE == ComInitialized)
  1630. {
  1631. CoUninitialize();
  1632. }
  1633. return;
  1634. } while(FALSE);
  1635. //
  1636. // A failure occurred; do cleanup
  1637. //
  1638. NhpServiceStatus.dwWaitHint = 0;
  1639. NhpServiceStatus.dwCheckPoint = 0;
  1640. NhTrace(TRACE_FLAG_INIT, "ServiceMain: service could not start");
  1641. StopBeaconSvr();
  1642. //
  1643. // Uninitialize COM
  1644. //
  1645. if (TRUE == ComInitialized)
  1646. {
  1647. CoUninitialize();
  1648. }
  1649. ServiceHandler(SERVICE_CONTROL_STOP);
  1650. } // ServiceMain