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.

1172 lines
25 KiB

  1. /*++
  2. Copyright (c) 1997-2001 Microsoft Corporation
  3. Module Name:
  4. dnsrslvr.c
  5. Abstract:
  6. DNS Resolver Service
  7. Main service module.
  8. Author:
  9. Glenn Curtis (glennc) 25-Feb-1997
  10. Revision History:
  11. Jim Gilroy (jamesg) March 2000 cleanup
  12. Jim Gilroy (jamesg) Nov 2000 rewrite
  13. --*/
  14. #include "local.h"
  15. #ifdef BUILD_W2K
  16. #include <services.h>
  17. #else
  18. #include <svcs.h>
  19. #endif
  20. //
  21. // Service control
  22. //
  23. SERVICE_STATUS ServiceStatus;
  24. SERVICE_STATUS_HANDLE ServiceStatusHandle = (SERVICE_STATUS_HANDLE) 0;
  25. PSVCHOST_GLOBAL_DATA g_pSvchostData;
  26. HANDLE g_hStopEvent;
  27. BOOL g_StopFlag;
  28. BOOL g_fServiceControlHandled;
  29. //
  30. // Service state
  31. //
  32. #define RES_STATUS_BEGIN 0x0cc00000
  33. #define RES_STATUS_ZERO_INIT 0x0cc00001
  34. #define RES_STATUS_CREATED_CS 0x0cc00002
  35. #define RES_STATUS_CREATED_EVENT 0x0cc00003
  36. #define RES_STATUS_READ_REGISTRY 0x0cc00004
  37. #define RES_STATUS_ALLOC_CACHE 0x0cc00005
  38. #define RES_STATUS_START_NOTIFY 0x0cc00006
  39. #define RES_STATUS_START_IP_LIST 0x0cc00007
  40. #define RES_STATUS_START_RPC 0x0cc00008
  41. #define RES_STATUS_REG_CONTROL 0x0cc00009
  42. #define RES_STATUS_RUNNING 0x0cc00100
  43. #define RES_STATUS_STOPPING 0x0cc00300
  44. #define RES_STATUS_SIGNALED_STOP 0x0cc00301
  45. #define RES_STATUS_STOP_RPC 0x0cc00302
  46. #define RES_STATUS_STOP_NOTIFY 0x0cc00303
  47. #define RES_STATUS_STOP_IP_LIST 0x0cc00304
  48. #define RES_STATUS_FREE_CACHE 0x0cc00305
  49. #define RES_STATUS_FREE_NET_INFO 0x0cc00306
  50. #define RES_STATUS_FREE_IP_LIST 0x0cc00307
  51. #define RES_STATUS_FREE_SERVICE_NOTIFY 0x0cc00308
  52. #define RES_STATUS_DEL_EVENT 0x0cc00309
  53. #define RES_STATUS_DEL_CS 0x0cc00310
  54. #define RES_STATUS_END 0x0cc00400
  55. DWORD g_ResolverStatus = RES_STATUS_BEGIN;
  56. //
  57. // Initialization cleanup\state
  58. //
  59. // Track what we intialized for safer\faster cleanup
  60. //
  61. #define INITFLAG_CACHE_CS 0x00000001
  62. #define INITFLAG_NETINFO_CS 0x00000002
  63. #define INITFLAG_NETINFO_BUILD_LOCK 0x00000004
  64. #define INITFLAG_NETFAIL_CS 0x00000008
  65. #define INITFLAG_WINSOCK 0x00000010
  66. #define INITFLAG_EVENTS_CREATED 0x00000020
  67. #define INITFLAG_CACHE_CREATED 0x00000100
  68. #define INITFLAG_NOTIFY_STARTED 0x00001000
  69. #define INITFLAG_IP_LIST_CREATED 0x00002000
  70. #define INITFLAG_RPC_SERVER_STARTED 0x00010000
  71. DWORD g_InitState;
  72. //
  73. // Critical sections used
  74. //
  75. CRITICAL_SECTION CacheCS;
  76. CRITICAL_SECTION NetworkFailureCS;
  77. //
  78. // Logging control
  79. //
  80. BOOL g_LogTraceInfo = TRUE;
  81. //
  82. // Private protos
  83. //
  84. DWORD
  85. ResolverInitialize(
  86. VOID
  87. );
  88. VOID
  89. ResolverShutdown(
  90. IN DWORD ErrorCode
  91. );
  92. VOID
  93. ResolverControlHandler(
  94. IN DWORD Opcode
  95. );
  96. DWORD
  97. ResolverUpdateStatus(
  98. VOID
  99. );
  100. //
  101. // Service routines
  102. //
  103. VOID
  104. SvchostPushServiceGlobals(
  105. PSVCHOST_GLOBAL_DATA pGlobals
  106. )
  107. {
  108. g_pSvchostData = pGlobals;
  109. }
  110. VOID
  111. ServiceMain(
  112. IN DWORD NumArgs,
  113. IN LPTSTR * ArgsArray
  114. )
  115. /*++
  116. Routine Description:
  117. Main entry point of resolver service.
  118. Arguments:
  119. NumArgs - number of strings specified in ArgsArray.
  120. ArgsArray - array of ptrs to arguments in service start call
  121. Return Value:
  122. None
  123. --*/
  124. {
  125. //
  126. // Make sure svchost.exe gave us global data
  127. //
  128. ASSERT( g_pSvchostData != NULL );
  129. //
  130. // Startup service, then exit
  131. //
  132. ResolverInitialize();
  133. }
  134. VOID
  135. ResolverInitFailure(
  136. IN DNS_STATUS Status,
  137. IN DWORD EventId,
  138. IN DWORD MemEventId,
  139. IN PSTR pszDebugString
  140. )
  141. /*++
  142. Routine Description:
  143. Handle resolver init failure.
  144. Function exists to avoid duplicate code.
  145. Arguments:
  146. Return Value:
  147. None
  148. --*/
  149. {
  150. WCHAR numberString[16];
  151. PWSTR eventStrings[1];
  152. DNSLOG_TIME();
  153. DNSLOG_F1( "Resolver Init Failure" );
  154. DNSLOG_F2( " Failure = %s", pszDebugString );
  155. DNSLOG_F2( " Status = %d", Status );
  156. DNSLOG_F1( "" );
  157. DNSDBG( ANY, (
  158. "Resolver Init FAILED!\n"
  159. "\tname = %s\n"
  160. "\tstatus = %d\n"
  161. "\tevent id = %d\n"
  162. "\tmem event = %08x\n",
  163. pszDebugString,
  164. Status,
  165. EventId,
  166. MemEventId ));
  167. DnsDbg_PrintfToDebugger(
  168. "ResolverInitialize - Returning status %d 0x%08x\n"
  169. "\tname = %s\n",
  170. Status, Status,
  171. pszDebugString );
  172. //
  173. // log in memory event
  174. //
  175. LogEventInMemory( MemEventId, Status );
  176. //
  177. // log event
  178. // - convert status to string
  179. //
  180. wsprintfW( numberString, L"0x%.8X", Status );
  181. eventStrings[0] = numberString;
  182. ResolverLogEvent(
  183. EventId,
  184. EVENTLOG_ERROR_TYPE,
  185. 1,
  186. eventStrings,
  187. Status );
  188. // clean up
  189. ResolverShutdown( Status );
  190. }
  191. DWORD
  192. ResolverInitialize(
  193. VOID
  194. )
  195. /*++
  196. Routine Description:
  197. This function initializes the DNS Caching Resolver service.
  198. Arguments:
  199. InitState - Returns a flag to indicate how far we got with
  200. initializing the service before an error occurred.
  201. Return Value:
  202. ERROR_SUCCESS if successful.
  203. ErrorCode on failure.
  204. --*/
  205. {
  206. DNS_STATUS status = NO_ERROR;
  207. //
  208. // init service state
  209. //
  210. g_ResolverStatus = RES_STATUS_BEGIN;
  211. g_InitState = 0;
  212. g_StopFlag = FALSE;
  213. g_hStopEvent = NULL;
  214. g_fServiceControlHandled = FALSE;
  215. //
  216. // initialize logging
  217. //
  218. DNSLOG_INIT();
  219. DNSLOG_F1( "DNS Caching Resolver Service - ResolverInitialize" );
  220. #if DBG
  221. Dns_StartDebugEx(
  222. 0, // no flag value
  223. "dnsres.flag",
  224. NULL, // no external flag
  225. "dnsres.log",
  226. 0, // no wrap limit
  227. FALSE, // don't use existing global
  228. FALSE,
  229. TRUE // make this file global
  230. );
  231. #endif
  232. DNSDBG( INIT, ( "DNS resolver startup.\n" ));
  233. IF_DNSDBG( START_BREAK )
  234. {
  235. // since resolver moved to NetworkServices permissions do
  236. // not properly bring up ntsd; instead just give time
  237. // to attach debugger
  238. Sleep( 20000 );
  239. }
  240. //
  241. // initialize service status block
  242. //
  243. ServiceStatusHandle = (SERVICE_STATUS_HANDLE) 0;
  244. ServiceStatus.dwServiceType = SERVICE_WIN32_SHARE_PROCESS;
  245. ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
  246. ServiceStatus.dwControlsAccepted = 0;
  247. ServiceStatus.dwCheckPoint = 0;
  248. ServiceStatus.dwWaitHint = 5000;
  249. ServiceStatus.dwWin32ExitCode = NO_ERROR;
  250. ServiceStatus.dwServiceSpecificExitCode = 0;
  251. ResolverUpdateStatus();
  252. //
  253. // init globals to zero
  254. //
  255. ZeroInitIpListGlobals();
  256. ZeroNetworkConfigGlobals();
  257. g_ResolverStatus = RES_STATUS_ZERO_INIT;
  258. //
  259. // initialize all our critical sections as soon as we can
  260. //
  261. LogEventInMemory( RES_EVENT_INITCRIT_START, 0 );
  262. if ( RtlInitializeCriticalSection( &CacheCS ) != NO_ERROR )
  263. {
  264. goto Failed;
  265. }
  266. g_InitState |= INITFLAG_CACHE_CS;
  267. if ( RtlInitializeCriticalSection( &NetworkFailureCS ) != NO_ERROR )
  268. {
  269. goto Failed;
  270. }
  271. g_InitState |= INITFLAG_NETFAIL_CS;
  272. if ( RtlInitializeCriticalSection( &NetinfoCS ) != NO_ERROR )
  273. {
  274. goto Failed;
  275. }
  276. g_InitState |= INITFLAG_NETINFO_CS;
  277. if ( TimedLock_Initialize( &NetinfoBuildLock, 5000 ) != NO_ERROR )
  278. {
  279. goto Failed;
  280. }
  281. g_InitState |= INITFLAG_NETINFO_BUILD_LOCK;
  282. LogEventInMemory( RES_EVENT_INITCRIT_END,0 );
  283. //
  284. // init our dnslib heap to use dnsapi heap
  285. //
  286. // this is important because we currently mix and match records
  287. // created inside dnsapi (hosts file and query) with a few that
  288. // we roll on our own; need this to be common
  289. //
  290. Dns_LibHeapReset( DnsApiAlloc, DnsApiRealloc, DnsApiFree );
  291. //
  292. // init winsock
  293. //
  294. Socket_InitWinsock();
  295. g_InitState |= INITFLAG_WINSOCK;
  296. //
  297. // shutdown event
  298. //
  299. g_hStopEvent = CreateEvent(
  300. NULL, // no security descriptor
  301. TRUE, // do not use automatic reset
  302. FALSE, // initial state: not signalled
  303. NULL // no name
  304. );
  305. if ( !g_hStopEvent )
  306. {
  307. status = GetLastError();
  308. ResolverInitFailure(
  309. status,
  310. 0,
  311. 0,
  312. "CreateEvent() failed" );
  313. return status;
  314. }
  315. g_InitState |= INITFLAG_EVENTS_CREATED;
  316. g_ResolverStatus = RES_STATUS_CREATED_EVENT;
  317. ResolverUpdateStatus();
  318. //
  319. // initialize our global registry values
  320. // - force this just once on startup so we have the
  321. // relevant cache params; after that read only on
  322. // demand when building netinfo blobs
  323. ReadRegistryConfig();
  324. //
  325. // Set the query timeouts to be used from defaults or registry
  326. //
  327. Dns_InitQueryTimeouts();
  328. //
  329. // init socket caching
  330. // - improves perf and prevents socket DOS attack
  331. // - default cache to 10 sockets
  332. //
  333. // DCR: create global for socket caching
  334. //
  335. Socket_CacheInit( 10 );
  336. //
  337. // notification thread (host file and registry)
  338. //
  339. StartNotify();
  340. g_InitState |= INITFLAG_NOTIFY_STARTED;
  341. g_ResolverStatus = RES_STATUS_START_NOTIFY;
  342. ResolverUpdateStatus();
  343. //
  344. // IP notification thread
  345. //
  346. status = InitIpListAndNotification();
  347. if ( status != ERROR_SUCCESS )
  348. {
  349. ResolverInitFailure(
  350. status,
  351. 0,
  352. 0,
  353. "IP list init failed" );
  354. return status;
  355. }
  356. g_InitState |= INITFLAG_IP_LIST_CREATED;
  357. g_ResolverStatus = RES_STATUS_START_IP_LIST;
  358. ResolverUpdateStatus();
  359. //
  360. // register control handler
  361. // allows us to receive service requests
  362. //
  363. ServiceStatusHandle = RegisterServiceCtrlHandlerW(
  364. DNS_RESOLVER_SERVICE,
  365. ResolverControlHandler
  366. );
  367. if ( !ServiceStatusHandle )
  368. {
  369. status = GetLastError();
  370. ResolverInitFailure(
  371. status,
  372. EVENT_DNS_CACHE_START_FAILURE_LOW_MEMORY,
  373. RES_EVENT_REGISTER_SCH,
  374. "Call to RegisterServiceCtrlHandlerW failed!"
  375. );
  376. return status;
  377. }
  378. g_ResolverStatus = RES_STATUS_REG_CONTROL;
  379. ResolverUpdateStatus();
  380. //
  381. // initialize RPC interfaces
  382. // - bump our requested stack size up to 8K
  383. // (RPC uses 1800 bytes before we get the stack,
  384. // the new() operator followed by the heap code uses
  385. // another 1200 -- leaving only about a 1000 for
  386. // DNS)
  387. //
  388. LogEventInMemory( RES_EVENT_START_RPC, 0 );
  389. #if 0
  390. // should not be necessary
  391. // default for all svchost instances has been increased
  392. if ( status != NO_ERROR )
  393. {
  394. DNSDBG( ANY, (
  395. "RpcMgmtSetServerStackSize( 2000 ) = %d\n",
  396. status ));
  397. }
  398. #endif
  399. status = Rpc_Initialize();
  400. #if 0
  401. status = g_pSvchostData->StartRpcServer(
  402. SERVER_INTERFACE_NAME_W,
  403. DnsResolver_ServerIfHandle );
  404. #endif
  405. if ( status != NO_ERROR )
  406. {
  407. LogEventInMemory( RES_EVENT_STATUS, status );
  408. if ( status == RPC_S_TYPE_ALREADY_REGISTERED ||
  409. status == RPC_NT_TYPE_ALREADY_REGISTERED )
  410. {
  411. DNSLOG_TIME();
  412. DNSLOG_F1( " Call to StartRpcServer returned warning that" );
  413. DNSLOG_F1( " the service is already running!" );
  414. DNSLOG_F2( " RpcPipeName : %S", RESOLVER_INTERFACE_NAME_W );
  415. DNSLOG_F1( " Going to just continue running . . ." );
  416. DNSLOG_F1( "" );
  417. DnsDbg_PrintfToDebugger(
  418. "DNS Client (dnsrslvr.dll) - Call to StartRpcServer\n"
  419. "returned warning that the service is already running!\n"
  420. "RpcPipeName : %S"
  421. "Going to just continue running . . .\n",
  422. RESOLVER_INTERFACE_NAME_W );
  423. status = NO_ERROR;
  424. }
  425. else
  426. {
  427. DNSDBG( ANY, (
  428. "RPC init FAILED! status = %d\n"
  429. "\tpipe name = %s\n",
  430. status,
  431. RESOLVER_INTERFACE_NAME_W ));
  432. ResolverInitFailure(
  433. status,
  434. EVENT_DNS_CACHE_START_FAILURE_NO_RPC,
  435. 0,
  436. "Call to StartRpcServer failed!"
  437. );
  438. return status;
  439. }
  440. }
  441. g_ResolverStatus = RES_STATUS_START_RPC;
  442. g_InitState |= INITFLAG_RPC_SERVER_STARTED;
  443. //
  444. // successful startup
  445. // - indicate running
  446. // - indicate what service control messages we want to get
  447. //
  448. ServiceStatus.dwCurrentState = SERVICE_RUNNING;
  449. ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP |
  450. SERVICE_ACCEPT_PARAMCHANGE |
  451. SERVICE_ACCEPT_NETBINDCHANGE;
  452. ServiceStatus.dwWaitHint = 0;
  453. ServiceStatus.dwWin32ExitCode = NO_ERROR;
  454. ResolverUpdateStatus();
  455. g_ResolverStatus = RES_STATUS_RUNNING;
  456. LogEventInMemory( RES_EVENT_STARTED, 0 );
  457. DNSLOG_F1( "ResolverInitialize - Successful" );
  458. DNSLOG_F1( "" );
  459. return NO_ERROR;
  460. Failed:
  461. if ( status == NO_ERROR )
  462. {
  463. status = DNS_ERROR_NO_MEMORY;
  464. }
  465. return status;
  466. }
  467. VOID
  468. ResolverShutdown(
  469. IN DWORD ErrorCode
  470. )
  471. /*++
  472. Routine Description:
  473. This function shuts down the DNS cache service.
  474. Arguments:
  475. ErrorCode - Supplies the error code of the failure
  476. Return Value:
  477. None.
  478. --*/
  479. {
  480. DWORD status = NO_ERROR;
  481. LONG existingStopFlag;
  482. DNSLOG_TIME();
  483. DNSLOG_F1( "DNS Caching Resolver Service - ResolverShutdown" );
  484. DnsDbg_PrintfToDebugger( "DNS Client - ResolverShutdown!\n" );
  485. //
  486. // indicate shutdown
  487. // - but interlock to avoid dual shutdown
  488. //
  489. existingStopFlag = InterlockedExchange(
  490. &g_StopFlag,
  491. (LONG) TRUE );
  492. if ( existingStopFlag )
  493. {
  494. DNS_ASSERT( FALSE );
  495. return;
  496. }
  497. DNS_ASSERT( g_StopFlag );
  498. //
  499. // indicate stop in progress
  500. //
  501. ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
  502. ServiceStatus.dwCheckPoint = 1;
  503. ServiceStatus.dwWaitHint = 60000;
  504. ResolverUpdateStatus();
  505. g_ResolverStatus = RES_STATUS_STOPPING;
  506. //
  507. // wakeup threads to shut down
  508. //
  509. LogEventInMemory( RES_EVENT_STOPPING, 0 );
  510. g_StopFlag = TRUE;
  511. if ( g_hStopEvent )
  512. {
  513. if ( !SetEvent(g_hStopEvent) )
  514. {
  515. DnsDbg_PrintfToDebugger(
  516. "DNSCACHE: Error setting g_hStopEvent %lu\n",
  517. GetLastError());
  518. DNS_ASSERT( FALSE );
  519. }
  520. }
  521. g_ResolverStatus = RES_STATUS_SIGNALED_STOP;
  522. //
  523. // cleanup RPC
  524. //
  525. if ( g_InitState & INITFLAG_RPC_SERVER_STARTED )
  526. {
  527. LogEventInMemory( RES_EVENT_STOP_RPC, 0 );
  528. Rpc_Shutdown();
  529. #if 0
  530. //status = g_pSvchostData->StopRpcServer( DnsResolver_ServerIfHandle );
  531. #endif
  532. }
  533. g_ResolverStatus = RES_STATUS_STOP_RPC;
  534. //
  535. // re-signal stop within lock
  536. //
  537. LOCK_CACHE_NO_START();
  538. g_StopFlag = TRUE;
  539. if ( g_hStopEvent )
  540. {
  541. if ( !SetEvent(g_hStopEvent) )
  542. {
  543. DnsDbg_PrintfToDebugger(
  544. "DNSCACHE: Error setting g_hStopEvent %lu\n",
  545. GetLastError());
  546. DNS_ASSERT( FALSE );
  547. }
  548. }
  549. UNLOCK_CACHE();
  550. //
  551. // stop notify thread
  552. //
  553. if ( g_InitState & INITFLAG_NOTIFY_STARTED )
  554. {
  555. ShutdownNotify();
  556. }
  557. g_ResolverStatus = RES_STATUS_STOP_NOTIFY;
  558. //
  559. // stop IP notify thread
  560. //
  561. if ( g_InitState & INITFLAG_IP_LIST_CREATED )
  562. {
  563. ShutdownIpListAndNotify();
  564. }
  565. g_ResolverStatus = RES_STATUS_STOP_IP_LIST;
  566. //
  567. // cleanup cache
  568. //
  569. Cache_Shutdown();
  570. g_ResolverStatus = RES_STATUS_FREE_CACHE;
  571. //
  572. // cleanup service notification list
  573. //
  574. //CleanupServiceNotification();
  575. //g_ResolverStatus = RES_STATUS_FREE_SERVICE_NOTIFY;
  576. //
  577. // cleanup network info globals
  578. //
  579. CleanupNetworkInfo();
  580. g_ResolverStatus = RES_STATUS_FREE_NET_INFO;
  581. //
  582. // cleanup winsock
  583. // cleanup socket caching also
  584. // - this is irrelevant for other services running in
  585. // our process so we shouldn't leave the handles open
  586. //
  587. if ( g_InitState & INITFLAG_WINSOCK )
  588. {
  589. Socket_CacheCleanup();
  590. Socket_CleanupWinsock();
  591. }
  592. //
  593. // cleanup main shutdown event
  594. //
  595. if ( g_InitState & INITFLAG_EVENTS_CREATED )
  596. {
  597. if ( g_hStopEvent )
  598. {
  599. CloseHandle(g_hStopEvent);
  600. g_hStopEvent = NULL;
  601. }
  602. }
  603. g_ResolverStatus = RES_STATUS_DEL_EVENT;
  604. //
  605. // delete critical sections\locks
  606. //
  607. if ( g_InitState & INITFLAG_CACHE_CS )
  608. {
  609. DeleteCriticalSection( &CacheCS );
  610. }
  611. if ( g_InitState & INITFLAG_NETFAIL_CS )
  612. {
  613. DeleteCriticalSection( &NetworkFailureCS );
  614. }
  615. if ( g_InitState & INITFLAG_NETINFO_CS )
  616. {
  617. DeleteCriticalSection( &NetinfoCS );
  618. }
  619. if ( g_InitState & INITFLAG_NETINFO_BUILD_LOCK )
  620. {
  621. TimedLock_Cleanup( &NetinfoBuildLock );
  622. }
  623. g_ResolverStatus = RES_STATUS_DEL_CS;
  624. //
  625. // cleanup complete
  626. // tell Service Controller that we are stopped
  627. //
  628. ServiceStatus.dwCurrentState = SERVICE_STOPPED;
  629. ServiceStatus.dwControlsAccepted = 0;
  630. ServiceStatus.dwWin32ExitCode = ErrorCode;
  631. ServiceStatus.dwServiceSpecificExitCode = 0;
  632. ServiceStatus.dwCheckPoint = 0;
  633. ServiceStatus.dwWaitHint = 0;
  634. ResolverUpdateStatus();
  635. g_ResolverStatus = RES_STATUS_END;
  636. DNSLOG_F1( "ResolverShutdown - Finished" );
  637. DNSLOG_F1( "" );
  638. }
  639. BOOL
  640. GetServiceControlLock(
  641. VOID
  642. )
  643. /*++
  644. Routine Description:
  645. Get exclusive access handling service control message.
  646. Arguments:
  647. None
  648. Return Value:
  649. TRUE -- have exclusive access to handle SCM, other threads locked out
  650. FALSE -- another thread still handling SCM
  651. --*/
  652. {
  653. BOOL fresult;
  654. //
  655. // set handled flag, if not previously set
  656. // if not previous set -> we have exclusive access
  657. //
  658. fresult = InterlockedCompareExchange(
  659. &g_fServiceControlHandled,
  660. (LONG) TRUE, // new value
  661. (LONG) 0 // previous value to do exchange
  662. );
  663. return !fresult;
  664. }
  665. VOID
  666. ReleaseServiceControlLock(
  667. VOID
  668. )
  669. /*++
  670. Routine Description:
  671. Release service control exclusive access.
  672. Arguments:
  673. None
  674. Return Value:
  675. None
  676. --*/
  677. {
  678. //
  679. // clear handled flag
  680. // - since GetServiceControlLock() uses CompareExchange
  681. // we can just clear without interlock
  682. //
  683. DNS_ASSERT( g_fServiceControlHandled );
  684. g_fServiceControlHandled = FALSE;
  685. }
  686. VOID
  687. ResolverControlHandler(
  688. IN DWORD Opcode
  689. )
  690. /*++
  691. Routine Description:
  692. Service control handler for DNS cache service.
  693. Arguments:
  694. Opcode - specifies service action
  695. Return Value:
  696. None.
  697. --*/
  698. {
  699. LogEventInMemory( RES_EVENT_SERVICE_CONTROL, Opcode );
  700. DNSLOG_TIME();
  701. DNSLOG_F2( "ResolverControlHandler - Recieved opcode %d", Opcode );
  702. DNSDBG( ANY, (
  703. "\n\n"
  704. "ResolverControlHandler() Opcode = %d\n",
  705. Opcode ));
  706. //
  707. // handle various service control codes
  708. //
  709. switch( Opcode )
  710. {
  711. case SERVICE_CONTROL_STOP:
  712. //
  713. // shutdown
  714. // - ResolverShutdown() updates status with SCM, so we don't update
  715. // status here (as SCM will start invalidating stuff on stop)
  716. // but jump directly to exit
  717. //
  718. ResolverShutdown( NO_ERROR );
  719. goto Done;
  720. case SERVICE_CONTROL_PARAMCHANGE :
  721. DNSLOG_F1( " Handle Paramchange" );
  722. DNSLOG_F1( "" );
  723. if ( !GetServiceControlLock() )
  724. {
  725. return;
  726. }
  727. //
  728. // rebuild -- with cache flush
  729. //
  730. HandleConfigChange(
  731. "SC -- ParamChange",
  732. TRUE // flush cache
  733. );
  734. //
  735. // signal other services about PnP
  736. //
  737. // SendServiceNotifications();
  738. ReleaseServiceControlLock();
  739. break;
  740. case SERVICE_CONTROL_NETBINDENABLE:
  741. case SERVICE_CONTROL_NETBINDDISABLE:
  742. DNSLOG_F1( " Handle NetBindEnable\\Disable" );
  743. DNSLOG_F1( "" );
  744. if ( !GetServiceControlLock() )
  745. {
  746. return;
  747. }
  748. //
  749. // rebuild -- with cache flush
  750. //
  751. HandleConfigChange(
  752. "SC -- NetBind",
  753. TRUE // flush cache
  754. );
  755. ReleaseServiceControlLock();
  756. break;
  757. case SERVICE_CONTROL_INTERROGATE:
  758. case SERVICE_CONTROL_NETBINDADD:
  759. case SERVICE_CONTROL_NETBINDREMOVE:
  760. default:
  761. DNSLOG_F1( " This is an unknown opcode, ignoring ..." );
  762. DNSLOG_F1( "" );
  763. break;
  764. }
  765. //
  766. // update service status
  767. //
  768. ResolverUpdateStatus();
  769. Done:
  770. DNSLOG_F2( "Resolver Controll Handler (opcode = %d) -- returning", Opcode );
  771. DNSDBG( ANY, (
  772. "Leaving ResolverControlHandler( %d )\n\n\n",
  773. Opcode ));
  774. }
  775. DWORD
  776. ResolverUpdateStatus(
  777. VOID
  778. )
  779. /*++
  780. Routine Description:
  781. Update service controller with current service status.
  782. Arguments:
  783. None.
  784. Return Value:
  785. Return code from SetServiceStatus.
  786. --*/
  787. {
  788. DWORD status;
  789. DWORD logStatus;
  790. DNSDBG( TRACE, ( "ResolverUpdateStatus()\n" ));
  791. //
  792. // bump the checkpoint
  793. //
  794. ServiceStatus.dwCheckPoint++;
  795. if ( ServiceStatusHandle == (SERVICE_STATUS_HANDLE) 0 )
  796. {
  797. LogEventInMemory( RES_EVENT_UPDATE_STATUS, ERROR_INVALID_HANDLE );
  798. return ERROR_INVALID_HANDLE;
  799. }
  800. //
  801. // log memory event
  802. // - the current state
  803. // - the error, if exists
  804. LogEventInMemory( RES_EVENT_UPDATE_STATE, ServiceStatus.dwCurrentState );
  805. status = ServiceStatus.dwWin32ExitCode;
  806. if ( status != NO_ERROR )
  807. {
  808. LogEventInMemory( RES_EVENT_UPDATE_STATUS, status );
  809. }
  810. //
  811. // update service controller
  812. //
  813. if ( ! SetServiceStatus( ServiceStatusHandle, &ServiceStatus ) )
  814. {
  815. status = GetLastError();
  816. LogEventInMemory( RES_EVENT_UPDATE_STATUS, status );
  817. }
  818. return status;
  819. }
  820. //
  821. // Event logging
  822. //
  823. VOID
  824. ResolverLogEvent(
  825. IN DWORD MessageId,
  826. IN WORD EventType,
  827. IN DWORD StringCount,
  828. IN PWSTR * StringArray,
  829. IN DWORD ErrorCode
  830. )
  831. /*++
  832. Routine Description:
  833. Log to eventlog.
  834. Arguments:
  835. MessageId -- event message id
  836. EventType -- event type (error, warning, info, etc.)
  837. StringCount -- string arg count
  838. StringArray -- imbedded strings
  839. ErrorCode -- error code for data section of event
  840. Return Value:
  841. None
  842. --*/
  843. {
  844. HANDLE hlog;
  845. PVOID pdata = NULL;
  846. //
  847. // open resolver as event source
  848. //
  849. // note: we don't keep log open because events are few
  850. //
  851. hlog = RegisterEventSourceW(
  852. NULL,
  853. DNS_RESOLVER_SERVICE );
  854. if ( hlog == NULL )
  855. {
  856. return;
  857. }
  858. if ( ErrorCode != NO_ERROR )
  859. {
  860. pdata = &ErrorCode;
  861. }
  862. //
  863. // Write to event log
  864. //
  865. // DCR: should get suppression technology here
  866. //
  867. ReportEventW(
  868. hlog,
  869. EventType,
  870. 0, // event category
  871. MessageId,
  872. (PSID) NULL,
  873. (WORD) StringCount,
  874. sizeof(DWORD),
  875. StringArray,
  876. (PVOID) pdata );
  877. DeregisterEventSource( hlog );
  878. }
  879. //
  880. // End dnsrslvr.c
  881. //