Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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