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.

1628 lines
40 KiB

  1. //+--------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1996-1998
  5. //
  6. // File: service.c
  7. //
  8. // Contents: Hydra License Server Service Control Manager Interface
  9. //
  10. // History: 12-09-97 HueiWang Modified from MSDN RPC Service Sample
  11. //
  12. //---------------------------------------------------------------------------
  13. #include "pch.cpp"
  14. #include <winsock2.h>
  15. #include <ws2tcpip.h>
  16. #include "server.h"
  17. #include "globals.h"
  18. #include "init.h"
  19. #include "postsrv.h"
  20. #include "tlsbkup.h"
  21. #define SERVICE_WAITHINT 60*1000 // WaitHint 1 mins.
  22. #define SERVICE_SHUTDOWN_WAITTIME 15*60*1000 // must have shutdown already.
  23. //---------------------------------------------------------------------------
  24. //
  25. // internal function prototypes
  26. //
  27. BOOL
  28. ReportStatusToSCMgr(
  29. DWORD,
  30. DWORD,
  31. DWORD
  32. );
  33. DWORD
  34. ServiceStart(
  35. DWORD,
  36. LPTSTR *,
  37. BOOL bDebug=FALSE
  38. );
  39. VOID WINAPI
  40. ServiceCtrl(
  41. DWORD
  42. );
  43. VOID WINAPI
  44. ServiceMain(
  45. DWORD,
  46. LPTSTR *
  47. );
  48. VOID
  49. CmdDebugService(
  50. int,
  51. char **,
  52. BOOL
  53. );
  54. BOOL WINAPI
  55. ControlHandler(
  56. DWORD
  57. );
  58. extern "C" VOID
  59. ServiceStop();
  60. VOID
  61. ServicePause();
  62. VOID
  63. ServiceContinue();
  64. HANDLE hRpcPause=NULL;
  65. ///////////////////////////////////////////////////////////
  66. //
  67. // internal variables
  68. //
  69. SERVICE_STATUS_HANDLE sshStatusHandle;
  70. DWORD ssCurrentStatus; // current status of the service
  71. BOOL g_bReportToSCM = TRUE;
  72. HANDLE gSafeToTerminate=NULL;
  73. HRESULT hrStatus = NULL;
  74. DEFINE_GUID(TLS_WRITER_GUID, 0x5382579c, 0x98df, 0x47a7, 0xac, 0x6c, 0x98, 0xa6, 0xd7, 0x10, 0x6e, 0x9);
  75. GUID idWriter = TLS_WRITER_GUID;
  76. CVssJetWriter *g_pWriter = NULL;
  77. SERVICE_TABLE_ENTRY dispatchTable[] =
  78. {
  79. { _TEXT(SZSERVICENAME), (LPSERVICE_MAIN_FUNCTION)ServiceMain },
  80. { NULL, NULL }
  81. };
  82. //-----------------------------------------------------------------
  83. // Internal routine
  84. //-----------------------------------------------------------------
  85. void print_usage()
  86. {
  87. _ftprintf(
  88. stdout,
  89. _TEXT("Usage : %s can't be run as a console app\n"),
  90. _TEXT(SZAPPNAME)
  91. );
  92. return;
  93. }
  94. //-----------------------------------------------------------------
  95. DWORD
  96. AddNullSessionPipe(
  97. IN LPTSTR szPipeName
  98. )
  99. /*++
  100. Abstract:
  101. Add our RPC namedpipe into registry to allow unrestricted access.
  102. Parameter:
  103. szPipeName : name of the pipe to append.
  104. Returns:
  105. ERROR_SUCCESS or error code
  106. --*/
  107. {
  108. LPTSTR lpszKey=L"SYSTEM\\CurrentControlSet\\Services\\LanmanServer\\Parameters";
  109. LPTSTR lpszValue=L"NullSessionPipes";
  110. HKEY hKey;
  111. DWORD dwStatus;
  112. LPTSTR pbData=NULL, pbOrg=NULL;
  113. DWORD cbData = 0;
  114. dwStatus = RegOpenKeyEx(
  115. HKEY_LOCAL_MACHINE,
  116. lpszKey,
  117. 0,
  118. KEY_ALL_ACCESS,
  119. &hKey
  120. );
  121. if(dwStatus != ERROR_SUCCESS)
  122. return dwStatus;
  123. dwStatus = RegQueryValueEx(
  124. hKey,
  125. lpszValue,
  126. NULL,
  127. NULL,
  128. NULL,
  129. &cbData
  130. );
  131. if(dwStatus != ERROR_MORE_DATA && dwStatus != ERROR_SUCCESS)
  132. return dwStatus;
  133. // pre-allocate our pipe name
  134. if(!(pbData = (LPTSTR)AllocateMemory(cbData + (_tcslen(szPipeName) + 1) * sizeof(TCHAR))))
  135. return GetLastError();
  136. dwStatus = RegQueryValueEx(
  137. hKey,
  138. lpszValue,
  139. NULL,
  140. NULL,
  141. (LPBYTE)pbData,
  142. &cbData
  143. );
  144. BOOL bAddPipe=TRUE;
  145. pbOrg = pbData;
  146. // check pipe name
  147. while(*pbData)
  148. {
  149. if(!_tcsicmp(pbData, szPipeName))
  150. {
  151. bAddPipe=FALSE;
  152. break;
  153. }
  154. pbData += _tcslen(pbData) + 1;
  155. }
  156. if(bAddPipe)
  157. {
  158. _tcscat(pbData, szPipeName);
  159. cbData += (_tcslen(szPipeName) + 1) * sizeof(TCHAR);
  160. dwStatus = RegSetValueEx(
  161. hKey,
  162. lpszValue,
  163. 0,
  164. REG_MULTI_SZ,
  165. (PBYTE)pbOrg,
  166. cbData
  167. );
  168. }
  169. FreeMemory(pbOrg);
  170. RegCloseKey(hKey);
  171. return dwStatus;
  172. }
  173. //-----------------------------------------------------------------
  174. void __cdecl
  175. trans_se_func(
  176. unsigned int u,
  177. _EXCEPTION_POINTERS* pExp
  178. )
  179. /*++
  180. --*/
  181. {
  182. #if DBG
  183. OutputDebugString(_TEXT("Translating SE exception...\n"));
  184. #endif
  185. throw SE_Exception( u );
  186. }
  187. //-----------------------------------------------------------------
  188. int __cdecl
  189. handle_new_failed(
  190. size_t size
  191. )
  192. /*++
  193. --*/
  194. {
  195. #if DBG
  196. OutputDebugString(_TEXT("handle_new_failed() invoked...\n"));
  197. #endif
  198. //
  199. // Raise exception here, STL does not check return pointer
  200. //
  201. RaiseException(
  202. ERROR_OUTOFMEMORY,
  203. 0,
  204. 0,
  205. NULL
  206. );
  207. //
  208. // stop memory allocation attemp.
  209. //
  210. return 0;
  211. }
  212. //-----------------------------------------------------------------
  213. void _cdecl
  214. main(
  215. int argc,
  216. char **argv
  217. )
  218. /*++
  219. Abstract
  220. Entry point.
  221. ++*/
  222. {
  223. // LARGE_INTEGER Time = USER_SHARED_DATA->SystemExpirationDate;
  224. _set_new_handler(handle_new_failed);
  225. _set_new_mode(1);
  226. gSafeToTerminate = CreateEvent(
  227. NULL,
  228. TRUE,
  229. FALSE,
  230. NULL
  231. );
  232. if(gSafeToTerminate == NULL)
  233. {
  234. TLSLogErrorEvent(TLS_E_ALLOCATE_RESOURCE);
  235. // out of resource.
  236. return;
  237. }
  238. for(int i=1; i < argc; i++)
  239. {
  240. if(*argv[i] == '-' || *argv[i] == '/')
  241. {
  242. if(!_stricmp("noservice", argv[i]+1))
  243. {
  244. g_bReportToSCM = FALSE;
  245. }
  246. else if(!_stricmp("cleanup", argv[i]+1))
  247. {
  248. CleanSetupLicenseServer();
  249. exit(0);
  250. }
  251. else
  252. {
  253. print_usage();
  254. exit(0);
  255. }
  256. }
  257. }
  258. if(g_bReportToSCM == FALSE)
  259. {
  260. CmdDebugService(
  261. argc,
  262. argv,
  263. !g_bReportToSCM
  264. );
  265. }
  266. else if(!StartServiceCtrlDispatcher(dispatchTable))
  267. {
  268. TLSLogErrorEvent(TLS_E_SC_CONNECT);
  269. }
  270. WaitForSingleObject(gSafeToTerminate, INFINITE);
  271. CloseHandle(gSafeToTerminate);
  272. }
  273. //-----------------------------------------------------------------
  274. void WINAPI
  275. ServiceMain(
  276. IN DWORD dwArgc,
  277. IN LPTSTR *lpszArgv
  278. )
  279. /*++
  280. Abstract:
  281. To perform actual initialization of the service
  282. Parameter:
  283. dwArgc - number of command line arguments
  284. lpszArgv - array of command line arguments
  285. Returns:
  286. none
  287. ++*/
  288. {
  289. DWORD dwStatus;
  290. // register our service control handler:
  291. sshStatusHandle = RegisterServiceCtrlHandler(
  292. _TEXT(SZSERVICENAME),
  293. ServiceCtrl
  294. );
  295. if (sshStatusHandle)
  296. {
  297. ssCurrentStatus=SERVICE_START_PENDING;
  298. // report the status to the service control manager.
  299. //
  300. if(ReportStatusToSCMgr(
  301. SERVICE_START_PENDING, // service state
  302. NO_ERROR, // exit code
  303. SERVICE_WAITHINT)) // wait hint
  304. {
  305. dwStatus = ServiceStart(
  306. dwArgc,
  307. lpszArgv
  308. );
  309. if(dwStatus != ERROR_SUCCESS)
  310. {
  311. ReportStatusToSCMgr(
  312. SERVICE_STOPPED,
  313. dwStatus,
  314. 0
  315. );
  316. }
  317. else
  318. {
  319. ReportStatusToSCMgr(
  320. SERVICE_STOPPED,
  321. NO_ERROR,
  322. 0
  323. );
  324. }
  325. }
  326. }
  327. else
  328. {
  329. dwStatus = GetLastError();
  330. TLSLogErrorEvent(TLS_E_SC_CONNECT);
  331. }
  332. DBGPrintf(
  333. DBG_INFORMATION,
  334. DBG_FACILITY_INIT,
  335. DBGLEVEL_FUNCTION_TRACE,
  336. _TEXT("Service terminated...\n")
  337. );
  338. return;
  339. }
  340. //-------------------------------------------------------------
  341. VOID WINAPI
  342. ServiceCtrl(
  343. IN DWORD dwCtrlCode
  344. )
  345. /*+++
  346. Abstract:
  347. This function is called by the SCM whenever
  348. ControlService() is called on this service.
  349. Parameter:
  350. dwCtrlCode - type of control requested from SCM.
  351. +++*/
  352. {
  353. // Handle the requested control code.
  354. //
  355. switch(dwCtrlCode)
  356. {
  357. // Stop the service.
  358. //
  359. case SERVICE_CONTROL_SHUTDOWN:
  360. case SERVICE_CONTROL_STOP:
  361. ReportStatusToSCMgr(
  362. SERVICE_STOP_PENDING,
  363. NO_ERROR,
  364. 0
  365. );
  366. ServiceStop();
  367. break;
  368. // We don't really accept pause and continue
  369. case SERVICE_CONTROL_PAUSE:
  370. ReportStatusToSCMgr(
  371. SERVICE_PAUSED,
  372. NO_ERROR,
  373. 0
  374. );
  375. ServicePause();
  376. break;
  377. case SERVICE_CONTROL_CONTINUE:
  378. ReportStatusToSCMgr(
  379. SERVICE_RUNNING,
  380. NO_ERROR,
  381. 0
  382. );
  383. ServiceContinue();
  384. break;
  385. // Update the service status.
  386. case SERVICE_CONTROL_INTERROGATE:
  387. ReportStatusToSCMgr(
  388. ssCurrentStatus,
  389. NO_ERROR,
  390. 0
  391. );
  392. break;
  393. // invalid control code
  394. default:
  395. break;
  396. }
  397. }
  398. //------------------------------------------------------------------
  399. DWORD
  400. ServiceShutdownThread(
  401. void *p
  402. )
  403. /*++
  404. Abstract:
  405. Entry point into thread that shutdown server (mainly database).
  406. Parameter:
  407. Ignore
  408. ++*/
  409. {
  410. ServerShutdown();
  411. ExitThread(ERROR_SUCCESS);
  412. return ERROR_SUCCESS;
  413. }
  414. //------------------------------------------------------------------
  415. DWORD
  416. RPCServiceStartThread(
  417. void *p
  418. )
  419. /*++
  420. Abstract:
  421. Entry point to thread that startup RPC.
  422. Parameter:
  423. None.
  424. Return:
  425. Thread exit code.
  426. ++*/
  427. {
  428. RPC_BINDING_VECTOR *pbindingVector = NULL;
  429. RPC_STATUS status = RPC_S_OK;
  430. WCHAR *pszEntryName = _TEXT(RPC_ENTRYNAME);
  431. DWORD dwNumSuccessRpcPro=0;
  432. do {
  433. //
  434. // local procedure call
  435. //
  436. status = RpcServerUseProtseq(
  437. _TEXT(RPC_PROTOSEQLPC),
  438. RPC_C_PROTSEQ_MAX_REQS_DEFAULT,
  439. NULL // &SecurityDescriptor
  440. );
  441. if(status == RPC_S_OK)
  442. {
  443. dwNumSuccessRpcPro++;
  444. }
  445. //
  446. // NT4 backward compatible issue, let NT4 termsrv serivce
  447. // client connect so still set security descriptor
  448. //
  449. // 11/10/98 Tested on NT4 and NT5
  450. //
  451. //
  452. // Namedpipe
  453. //
  454. status = RpcServerUseProtseqEp(
  455. _TEXT(RPC_PROTOSEQNP),
  456. RPC_C_PROTSEQ_MAX_REQS_DEFAULT,
  457. _TEXT(LSNAMEPIPE),
  458. NULL //&SecurityDescriptor
  459. );
  460. if(status == RPC_S_OK)
  461. {
  462. dwNumSuccessRpcPro++;
  463. }
  464. //
  465. // TCP/IP
  466. //
  467. status = RpcServerUseProtseq(
  468. _TEXT(RPC_PROTOSEQTCP),
  469. RPC_C_PROTSEQ_MAX_REQS_DEFAULT,
  470. NULL //&SecurityDescriptor
  471. );
  472. if(status == RPC_S_OK)
  473. {
  474. dwNumSuccessRpcPro++;
  475. }
  476. // Must have at least one protocol.
  477. if(dwNumSuccessRpcPro == 0)
  478. {
  479. status = TLS_E_RPC_PROTOCOL;
  480. break;
  481. }
  482. // Get server binding handles
  483. status = RpcServerInqBindings(&pbindingVector);
  484. if (status != RPC_S_OK)
  485. {
  486. status = TLS_E_RPC_INQ_BINDING;
  487. break;
  488. }
  489. // Register interface(s) and binding(s) (endpoints) with
  490. // the endpoint mapper.
  491. status = RpcEpRegister(
  492. TermServLicensing_v1_0_s_ifspec, // from rpcsvc.h
  493. pbindingVector,
  494. NULL, // &export_uuid,
  495. L""
  496. );
  497. if (status != RPC_S_OK)
  498. {
  499. status = TLS_E_RPC_EP_REGISTER;
  500. break;
  501. }
  502. status = RpcServerRegisterIf(
  503. TermServLicensing_v1_0_s_ifspec,
  504. NULL,
  505. NULL);
  506. if(status != RPC_S_OK)
  507. {
  508. status = TLS_E_RPC_REG_INTERFACE;
  509. break;
  510. }
  511. // Register interface(s) and binding(s) (endpoints) with
  512. // the endpoint mapper.
  513. status = RpcEpRegister(
  514. HydraLicenseService_v1_0_s_ifspec, // from rpcsvc.h
  515. pbindingVector,
  516. NULL, // &export_uuid,
  517. L"");
  518. if (status != RPC_S_OK)
  519. {
  520. status = TLS_E_RPC_EP_REGISTER;
  521. break;
  522. }
  523. status = RpcServerRegisterIf(
  524. HydraLicenseService_v1_0_s_ifspec,
  525. NULL,
  526. NULL);
  527. if(status != RPC_S_OK)
  528. {
  529. status = TLS_E_RPC_REG_INTERFACE;
  530. break;
  531. }
  532. // Register interface(s) and binding(s) (endpoints) with
  533. // the endpoint mapper.
  534. status = RpcEpRegister(
  535. TermServLicensingBackup_v1_0_s_ifspec, // from rpcsvc.h
  536. pbindingVector,
  537. NULL, // &export_uuid,
  538. L"");
  539. if (status != RPC_S_OK)
  540. {
  541. status = TLS_E_RPC_EP_REGISTER;
  542. break;
  543. }
  544. status = RpcServerRegisterIf(
  545. TermServLicensingBackup_v1_0_s_ifspec,
  546. NULL,
  547. NULL);
  548. if(status != RPC_S_OK)
  549. {
  550. status = TLS_E_RPC_REG_INTERFACE;
  551. break;
  552. }
  553. // Enable NT LM Security Support Provider (NtLmSsp service)
  554. status = RpcServerRegisterAuthInfo(0,
  555. RPC_C_AUTHN_WINNT,
  556. 0,
  557. 0);
  558. if (status != RPC_S_OK)
  559. {
  560. status = TLS_E_RPC_SET_AUTHINFO;
  561. break;
  562. }
  563. } while(FALSE);
  564. if(status != RPC_S_OK)
  565. {
  566. TLSLogEvent(
  567. EVENTLOG_ERROR_TYPE,
  568. TLS_E_SERVICEINIT,
  569. TLS_E_INITRPC,
  570. status
  571. );
  572. status = TLS_E_SERVICE_STARTUP;
  573. }
  574. ExitThread(status);
  575. return status;
  576. }
  577. //------------------------------------------------------------------------
  578. unsigned int __stdcall
  579. GetLServerRoleInDomain(
  580. PVOID pData
  581. )
  582. /*++
  583. --*/
  584. {
  585. SERVER_ROLE_IN_DOMAIN* srvRole = (SERVER_ROLE_IN_DOMAIN *)pData;
  586. if(pData != NULL)
  587. {
  588. *srvRole = GetServerRoleInDomain(NULL);
  589. }
  590. _endthreadex(0);
  591. return 0;
  592. }
  593. //------------------------------------------------------------------------
  594. DWORD
  595. ServiceStart(
  596. IN DWORD dwArgc,
  597. IN LPTSTR *lpszArgv,
  598. IN BOOL bDebug
  599. )
  600. /*
  601. */
  602. {
  603. RPC_BINDING_VECTOR *pbindingVector = NULL;
  604. WCHAR *pszEntryName = _TEXT(RPC_ENTRYNAME);
  605. HANDLE hInitThread=NULL;
  606. HANDLE hRpcThread=NULL;
  607. HANDLE hMailslotThread=NULL;
  608. HANDLE hShutdownThread=NULL;
  609. DWORD dump;
  610. HANDLE hEvent=NULL;
  611. DWORD dwStatus=ERROR_SUCCESS;
  612. WORD wVersionRequested;
  613. WSADATA wsaData;
  614. int err;
  615. if (!ReportStatusToSCMgr(
  616. SERVICE_START_PENDING,
  617. NO_ERROR,
  618. SERVICE_WAITHINT))
  619. {
  620. // resource leak but something went wrong already.
  621. dwStatus = TLS_E_SC_REPORT_STATUS;
  622. goto cleanup;
  623. }
  624. hrStatus = CoInitializeEx (NULL, COINIT_MULTITHREADED);
  625. if (FAILED (hrStatus))
  626. {
  627. DBGPrintf(
  628. DBG_INFORMATION,
  629. DBG_FACILITY_INIT,
  630. DBGLEVEL_FUNCTION_DETAILSIMPLE,
  631. _TEXT("CoInitializeEx failed with error code %08x...\n"),
  632. hrStatus
  633. );
  634. }
  635. if (!ReportStatusToSCMgr(
  636. SERVICE_START_PENDING,
  637. NO_ERROR,
  638. SERVICE_WAITHINT))
  639. {
  640. // resource leak but something went wrong already.
  641. dwStatus = TLS_E_SC_REPORT_STATUS;
  642. goto cleanup;
  643. }
  644. if (SUCCEEDED (hrStatus))
  645. {
  646. hrStatus = CoInitializeSecurity(
  647. NULL,
  648. -1,
  649. NULL,
  650. NULL,
  651. RPC_C_AUTHN_LEVEL_CONNECT,
  652. RPC_C_IMP_LEVEL_IDENTIFY,
  653. NULL,
  654. EOAC_NONE,
  655. NULL
  656. );
  657. }
  658. if (!ReportStatusToSCMgr(
  659. SERVICE_START_PENDING,
  660. NO_ERROR,
  661. SERVICE_WAITHINT))
  662. {
  663. // resource leak but something went wrong already.
  664. dwStatus = TLS_E_SC_REPORT_STATUS;
  665. goto cleanup;
  666. }
  667. if (SUCCEEDED (hrStatus))
  668. {
  669. g_pWriter = new CVssJetWriter;
  670. if (NULL == g_pWriter)
  671. {
  672. DBGPrintf(
  673. DBG_INFORMATION,
  674. DBG_FACILITY_INIT,
  675. DBGLEVEL_FUNCTION_DETAILSIMPLE,
  676. _TEXT("new CVssJetWriter failed...\n")
  677. );
  678. hrStatus = HRESULT_FROM_WIN32 (ERROR_NOT_ENOUGH_MEMORY);
  679. }
  680. }
  681. // Report the status to the service control manager.
  682. if (!ReportStatusToSCMgr(
  683. SERVICE_START_PENDING,
  684. NO_ERROR,
  685. SERVICE_WAITHINT))
  686. {
  687. // resource leak but something went wrong already.
  688. dwStatus = TLS_E_SC_REPORT_STATUS;
  689. goto cleanup;
  690. }
  691. {
  692. DWORD dwConsole;
  693. DWORD dwDbLevel;
  694. DWORD dwType;
  695. DWORD dwSize = sizeof(dwConsole);
  696. DWORD status;
  697. HKEY hKey=NULL;
  698. status = RegOpenKeyEx(
  699. HKEY_LOCAL_MACHINE,
  700. LSERVER_PARAMETERS_KEY,
  701. 0,
  702. KEY_ALL_ACCESS,
  703. &hKey);
  704. if(status == ERROR_SUCCESS)
  705. {
  706. if(RegQueryValueEx(
  707. hKey,
  708. LSERVER_PARAMETERS_CONSOLE,
  709. NULL,
  710. &dwType,
  711. (LPBYTE)&dwConsole,
  712. &dwSize
  713. ) != ERROR_SUCCESS)
  714. {
  715. dwConsole = 0;
  716. }
  717. dwSize = sizeof(dwDbLevel);
  718. if(RegQueryValueEx(
  719. hKey,
  720. LSERVER_PARAMETERS_LOGLEVEL,
  721. NULL,
  722. &dwType,
  723. (LPBYTE)&dwDbLevel,
  724. &dwSize
  725. ) == ERROR_SUCCESS)
  726. {
  727. InitDBGPrintf(
  728. dwConsole != 0,
  729. _TEXT(SZSERVICENAME),
  730. dwDbLevel
  731. );
  732. }
  733. RegCloseKey(hKey);
  734. }
  735. }
  736. // Report the status to the service control manager.
  737. if (!ReportStatusToSCMgr(
  738. SERVICE_START_PENDING,
  739. NO_ERROR,
  740. SERVICE_WAITHINT))
  741. {
  742. // resource leak but something went wrong already.
  743. dwStatus = TLS_E_SC_REPORT_STATUS;
  744. goto cleanup;
  745. }
  746. do {
  747. // setup should have done this but just to make sure we have our
  748. // pipe in NullSessionPipe to allow service to connect
  749. AddNullSessionPipe(_TEXT(HLSPIPENAME));
  750. AddNullSessionPipe(_TEXT(SZSERVICENAME));
  751. wVersionRequested = MAKEWORD( 1, 1 );
  752. err = WSAStartup(
  753. wVersionRequested,
  754. &wsaData
  755. );
  756. if(err != 0)
  757. {
  758. // None critical error
  759. TLSLogWarningEvent(
  760. TLS_E_SERVICE_WSASTARTUP
  761. );
  762. }
  763. else
  764. {
  765. char hostname[(MAXTCPNAME+1)*sizeof(TCHAR)];
  766. err=gethostname(hostname, MAXTCPNAME*sizeof(TCHAR));
  767. if(err == 0)
  768. {
  769. struct addrinfo *paddrinfo;
  770. struct addrinfo hints;
  771. memset(&hints,0,sizeof(hints));
  772. hints.ai_flags = AI_CANONNAME;
  773. hints.ai_family = PF_UNSPEC;
  774. if (0 == getaddrinfo(hostname,NULL,&hints,&paddrinfo))
  775. {
  776. err = (MultiByteToWideChar(
  777. GetACP(),
  778. MB_ERR_INVALID_CHARS,
  779. paddrinfo->ai_canonname,
  780. -1,
  781. g_szHostName,
  782. g_cbHostName) == 0) ? -1 : 0;
  783. }
  784. else
  785. {
  786. err = -1;
  787. }
  788. freeaddrinfo(paddrinfo);
  789. }
  790. }
  791. if(err != 0)
  792. {
  793. if(GetComputerName(g_szHostName, &g_cbHostName) == FALSE)
  794. {
  795. dwStatus = GetLastError();
  796. DBGPrintf(
  797. DBG_INFORMATION,
  798. DBG_FACILITY_INIT,
  799. DBGLEVEL_FUNCTION_DETAILSIMPLE,
  800. _TEXT("GetComputerName() failed with %d...\n"),
  801. dwStatus
  802. );
  803. // this shoule not happen...
  804. TLSLogErrorEvent(TLS_E_INIT_GENERAL);
  805. break;
  806. }
  807. }
  808. if(GetComputerName(g_szComputerName, &g_cbComputerName) == FALSE)
  809. {
  810. dwStatus = GetLastError();
  811. DBGPrintf(
  812. DBG_INFORMATION,
  813. DBG_FACILITY_INIT,
  814. DBGLEVEL_FUNCTION_DETAILSIMPLE,
  815. _TEXT("GetComputerName() failed with %d...\n"),
  816. dwStatus
  817. );
  818. // this shoule not happen...
  819. TLSLogErrorEvent(TLS_E_INIT_GENERAL);
  820. break;
  821. }
  822. hRpcPause=CreateEvent(NULL, TRUE, TRUE, NULL);
  823. if(!hRpcPause)
  824. {
  825. TLSLogErrorEvent(TLS_E_ALLOCATE_RESOURCE);
  826. dwStatus = TLS_E_ALLOCATE_RESOURCE;
  827. break;
  828. }
  829. //
  830. // start up general server and RPC initialization thread
  831. //
  832. hInitThread=ServerInit(bDebug);
  833. if(hInitThread==NULL)
  834. {
  835. TLSLogErrorEvent(TLS_E_SERVICE_STARTUP_CREATE_THREAD);
  836. dwStatus = TLS_E_SERVICE_STARTUP_CREATE_THREAD;
  837. break;
  838. }
  839. dwStatus = ERROR_SUCCESS;
  840. //
  841. // Wait for general server init. thread to terminate
  842. //
  843. while(WaitForSingleObject( hInitThread, 100 ) == WAIT_TIMEOUT)
  844. {
  845. // Report the status to the service control manager.
  846. if (!ReportStatusToSCMgr(
  847. SERVICE_START_PENDING,
  848. NO_ERROR,
  849. SERVICE_WAITHINT))
  850. {
  851. // resource leak but something went wrong already.
  852. dwStatus = TLS_E_SC_REPORT_STATUS;
  853. break;
  854. }
  855. }
  856. if(dwStatus != ERROR_SUCCESS)
  857. {
  858. break;
  859. }
  860. // Check thread exit code.
  861. GetExitCodeThread(
  862. hInitThread,
  863. &dwStatus
  864. );
  865. if(dwStatus != ERROR_SUCCESS)
  866. {
  867. //
  868. // Server init. thread logs its own error
  869. //
  870. dwStatus = TLS_E_SERVICE_STARTUP_INIT_THREAD_ERROR;
  871. break;
  872. }
  873. CloseHandle(hInitThread);
  874. hInitThread=NULL;
  875. // timing, if we startup RPC init thread but database init thread
  876. // can't initialize, service will be in forever stop state.
  877. hRpcThread=CreateThread(
  878. NULL,
  879. 0,
  880. RPCServiceStartThread,
  881. ULongToPtr(bDebug),
  882. 0,
  883. &dump
  884. );
  885. if(hRpcThread == NULL)
  886. {
  887. TLSLogErrorEvent(TLS_E_SERVICE_STARTUP_CREATE_THREAD);
  888. dwStatus=TLS_E_SERVICE_STARTUP_CREATE_THREAD;
  889. break;
  890. }
  891. dwStatus = ERROR_SUCCESS;
  892. //
  893. // Wait for RPC init. thread to terminate
  894. //
  895. while(WaitForSingleObject( hRpcThread, 100 ) == WAIT_TIMEOUT)
  896. {
  897. // Report the status to the service control manager.
  898. if (!ReportStatusToSCMgr(SERVICE_START_PENDING, // service state
  899. NO_ERROR, // exit code
  900. SERVICE_WAITHINT)) // wait hint
  901. {
  902. dwStatus = TLS_E_SC_REPORT_STATUS;
  903. break;
  904. }
  905. }
  906. if(dwStatus != ERROR_SUCCESS)
  907. {
  908. break;
  909. }
  910. // Check thread exit code.
  911. GetExitCodeThread(hRpcThread, &dwStatus);
  912. if(dwStatus != ERROR_SUCCESS)
  913. {
  914. dwStatus = TLS_E_SERVICE_STARTUP_RPC_THREAD_ERROR;
  915. break;
  916. }
  917. CloseHandle(hRpcThread);
  918. hRpcThread=NULL;
  919. //
  920. // Tell server control manager that we are ready.
  921. //
  922. if (!ReportStatusToSCMgr(
  923. SERVICE_RUNNING, // service state
  924. NO_ERROR, // exit code
  925. SERVICE_WAITHINT // wait hint
  926. ))
  927. {
  928. dwStatus = TLS_E_SC_REPORT_STATUS;
  929. break;
  930. }
  931. //
  932. // Post service init. load self-signed certificate and init. crypt.
  933. // this is needed after reporting service running status back to
  934. // service control manager because it may need to manually call
  935. // StartService() to startup protected storage service.
  936. //
  937. if(InitCryptoAndCertificate() != ERROR_SUCCESS)
  938. {
  939. dwStatus = TLS_E_SERVICE_STARTUP_POST_INIT;
  940. break;
  941. }
  942. TLSLogInfoEvent(TLS_I_SERVICE_START);
  943. // RpcMgmtWaitServerListen() will block until the server has
  944. // stopped listening. If this service had something better to
  945. // do with this thread, it would delay this call until
  946. // ServiceStop() had been called. (Set an event in ServiceStop()).
  947. //
  948. BOOL bOtherServiceStarted = FALSE;
  949. do {
  950. WaitForSingleObject(hRpcPause, INFINITE);
  951. if(ssCurrentStatus == SERVICE_STOP_PENDING)
  952. {
  953. break;
  954. }
  955. // Start accepting client calls.PostServiceInit
  956. dwStatus = RpcServerListen(
  957. RPC_MINIMUMCALLTHREADS,
  958. RPC_MAXIMUMCALLTHREADS,
  959. TRUE
  960. );
  961. if(dwStatus != RPC_S_OK)
  962. {
  963. TLSLogErrorEvent(TLS_E_RPC_LISTEN);
  964. dwStatus = TLS_E_SERVICE_RPC_LISTEN;
  965. break;
  966. }
  967. //
  968. // Initialize all policy module
  969. //
  970. if(bOtherServiceStarted == FALSE)
  971. {
  972. dwStatus = PostServiceInit();
  973. if(dwStatus != ERROR_SUCCESS)
  974. {
  975. // faild to initialize.
  976. break;
  977. }
  978. //ServiceInitPolicyModule();
  979. }
  980. bOtherServiceStarted = TRUE;
  981. DBGPrintf(
  982. DBG_INFORMATION,
  983. DBG_FACILITY_INIT,
  984. DBGLEVEL_FUNCTION_DETAILSIMPLE,
  985. _TEXT("Ready to accept request...\n")
  986. );
  987. dwStatus = RpcMgmtWaitServerListen();
  988. assert(dwStatus == RPC_S_OK);
  989. } while(TRUE);
  990. // tell service control manager we are stopping
  991. ReportStatusToSCMgr(
  992. SERVICE_STOP_PENDING,
  993. NO_ERROR,
  994. SERVICE_WAITHINT
  995. );
  996. //
  997. // Terminate - ignore all error here on
  998. //
  999. dwStatus = RpcServerUnregisterIf(
  1000. TermServLicensingBackup_v1_0_s_ifspec,
  1001. NULL,
  1002. TRUE
  1003. );
  1004. // tell service control manager we are stopping
  1005. ReportStatusToSCMgr(
  1006. SERVICE_STOP_PENDING,
  1007. NO_ERROR,
  1008. SERVICE_WAITHINT
  1009. );
  1010. dwStatus = RpcServerUnregisterIf(
  1011. HydraLicenseService_v1_0_s_ifspec,
  1012. NULL,
  1013. TRUE
  1014. );
  1015. // tell service control manager we are stopping
  1016. ReportStatusToSCMgr(
  1017. SERVICE_STOP_PENDING,
  1018. NO_ERROR,
  1019. SERVICE_WAITHINT
  1020. );
  1021. dwStatus = RpcServerUnregisterIf(
  1022. TermServLicensing_v1_0_s_ifspec, // from rpcsvc.h
  1023. NULL,
  1024. TRUE
  1025. );
  1026. // tell service control manager we are stopping
  1027. ReportStatusToSCMgr(
  1028. SERVICE_STOP_PENDING,
  1029. NO_ERROR,
  1030. SERVICE_WAITHINT
  1031. );
  1032. // Remove entries from the endpoint mapper database.
  1033. dwStatus = RpcEpUnregister(
  1034. HydraLicenseService_v1_0_s_ifspec, // from rpcsvc.h
  1035. pbindingVector,
  1036. NULL
  1037. );
  1038. // tell service control manager we are stopping
  1039. ReportStatusToSCMgr(
  1040. SERVICE_STOP_PENDING,
  1041. NO_ERROR,
  1042. SERVICE_WAITHINT
  1043. );
  1044. // Remove entries from the endpoint mapper database.
  1045. dwStatus = RpcEpUnregister(
  1046. TermServLicensing_v1_0_s_ifspec, // from rpcsvc.h
  1047. pbindingVector,
  1048. NULL
  1049. );
  1050. // tell service control manager we are stopping
  1051. ReportStatusToSCMgr(
  1052. SERVICE_STOP_PENDING,
  1053. NO_ERROR,
  1054. SERVICE_WAITHINT
  1055. );
  1056. // Remove entries from the endpoint mapper database.
  1057. dwStatus = RpcEpUnregister(
  1058. TermServLicensingBackup_v1_0_s_ifspec, // from rpcsvc.h
  1059. pbindingVector,
  1060. NULL
  1061. );
  1062. // Get server binding handles
  1063. dwStatus = RpcServerInqBindings(
  1064. &pbindingVector
  1065. );
  1066. if(dwStatus == ERROR_SUCCESS)
  1067. {
  1068. dwStatus = RpcBindingVectorFree(
  1069. &pbindingVector
  1070. );
  1071. }
  1072. // Create entry name in name database first
  1073. // Only work for NT 5.0
  1074. // status = RpcNsMgmtEntryDelete(RPC_C_NS_SYNTAX_DEFAULT, pszEntryName);
  1075. // try to report the stopped status to the service control manager.
  1076. //
  1077. // Initialize Crypto.
  1078. } while(FALSE);
  1079. if(hInitThread != NULL)
  1080. {
  1081. CloseHandle(hInitThread);
  1082. }
  1083. if(hRpcThread != NULL)
  1084. {
  1085. CloseHandle(hRpcThread);
  1086. }
  1087. if(hMailslotThread != NULL)
  1088. {
  1089. CloseHandle(hMailslotThread);
  1090. }
  1091. if(hEvent != NULL)
  1092. {
  1093. CloseHandle(hEvent);
  1094. }
  1095. if(hRpcPause != NULL)
  1096. {
  1097. CloseHandle(hRpcPause);
  1098. }
  1099. if(err == 0)
  1100. {
  1101. WSACleanup();
  1102. }
  1103. ReportStatusToSCMgr(
  1104. SERVICE_STOP_PENDING,
  1105. dwStatus, //NO_ERROR,
  1106. SERVICE_WAITHINT
  1107. );
  1108. //
  1109. // Create another thread to shutdown server.
  1110. //
  1111. hShutdownThread=CreateThread(
  1112. NULL,
  1113. 0,
  1114. ServiceShutdownThread,
  1115. (VOID *)NULL,
  1116. 0,
  1117. &dump
  1118. );
  1119. if(hShutdownThread == NULL)
  1120. {
  1121. // Report the status to the service control manager with
  1122. // long wait hint time.
  1123. ReportStatusToSCMgr(
  1124. SERVICE_STOP_PENDING,
  1125. NO_ERROR,
  1126. SERVICE_SHUTDOWN_WAITTIME
  1127. );
  1128. //
  1129. // can't create thread, just call shutdown directory
  1130. //
  1131. ServerShutdown();
  1132. }
  1133. else
  1134. {
  1135. //
  1136. // report in 5 second interval to SC.
  1137. //
  1138. DWORD dwMaxWaitTime = SERVICE_SHUTDOWN_WAITTIME / 5000;
  1139. DWORD dwTimes=0;
  1140. //
  1141. // Wait for general server shutdown thread to terminate
  1142. // Gives max 1 mins to shutdown
  1143. //
  1144. while(WaitForSingleObject( hShutdownThread, SC_WAITHINT ) == WAIT_TIMEOUT &&
  1145. dwTimes++ < dwMaxWaitTime)
  1146. {
  1147. // Report the status to the service control manager.
  1148. ReportStatusToSCMgr(
  1149. SERVICE_STOP_PENDING,
  1150. NO_ERROR,
  1151. SERVICE_WAITHINT
  1152. );
  1153. }
  1154. CloseHandle(hShutdownThread);
  1155. }
  1156. cleanup:
  1157. if (NULL != g_pWriter)
  1158. {
  1159. g_pWriter->Uninitialize();
  1160. delete g_pWriter;
  1161. g_pWriter = NULL;
  1162. }
  1163. CoUninitialize( );
  1164. // Signal we are safe to shutting down
  1165. SetEvent(gSafeToTerminate);
  1166. return dwStatus;
  1167. }
  1168. //-----------------------------------------------------------------
  1169. VOID
  1170. ServiceStop()
  1171. /*++
  1172. ++*/
  1173. {
  1174. ReportStatusToSCMgr(
  1175. SERVICE_STOP_PENDING,
  1176. NO_ERROR,
  1177. 0
  1178. );
  1179. // Stop's the server, wakes the main thread.
  1180. SetEvent(hRpcPause);
  1181. //
  1182. // Signal currently waiting RPC call to terminate
  1183. //
  1184. ServiceSignalShutdown();
  1185. // this is the actual time we receive shutdown request.
  1186. SetServiceLastShutdownTime();
  1187. (VOID)RpcMgmtStopServerListening(NULL);
  1188. TLSLogInfoEvent(TLS_I_SERVICE_STOP);
  1189. }
  1190. //-----------------------------------------------------------------
  1191. VOID
  1192. ServicePause()
  1193. /*++
  1194. ++*/
  1195. {
  1196. ResetEvent(hRpcPause);
  1197. (VOID)RpcMgmtStopServerListening(NULL);
  1198. TLSLogInfoEvent(TLS_I_SERVICE_PAUSED);
  1199. }
  1200. //-----------------------------------------------------------------
  1201. VOID
  1202. ServiceContinue()
  1203. /*++
  1204. ++*/
  1205. {
  1206. SetEvent(hRpcPause);
  1207. TLSLogInfoEvent(TLS_I_SERVICE_CONTINUE);
  1208. }
  1209. //-----------------------------------------------------------------
  1210. BOOL
  1211. ReportStatusToSCMgr(
  1212. IN DWORD dwCurrentState,
  1213. IN DWORD dwExitCode,
  1214. IN DWORD dwWaitHint
  1215. )
  1216. /*++
  1217. Abstract:
  1218. Sets the current status of the service and reports it
  1219. to the Service Control Manager
  1220. Parameter:
  1221. dwCurrentState - the state of the service
  1222. dwWin32ExitCode - error code to report
  1223. dwWaitHint - worst case estimate to next checkpoint
  1224. Returns:
  1225. TRUE if success, FALSE otherwise
  1226. */
  1227. {
  1228. BOOL fResult=TRUE;
  1229. if(g_bReportToSCM == TRUE)
  1230. {
  1231. SERVICE_STATUS ssStatus;
  1232. static DWORD dwCheckPoint = 1;
  1233. ssStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
  1234. //
  1235. // global - current status of process
  1236. //
  1237. ssCurrentStatus = dwCurrentState;
  1238. if (dwCurrentState == SERVICE_START_PENDING)
  1239. {
  1240. ssStatus.dwControlsAccepted = 0;
  1241. }
  1242. else
  1243. {
  1244. ssStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PAUSE_CONTINUE | SERVICE_CONTROL_SHUTDOWN;
  1245. }
  1246. ssStatus.dwCurrentState = dwCurrentState;
  1247. if(dwExitCode != NO_ERROR)
  1248. {
  1249. ssStatus.dwWin32ExitCode = ERROR_SERVICE_SPECIFIC_ERROR;
  1250. ssStatus.dwServiceSpecificExitCode = dwExitCode;
  1251. }
  1252. else
  1253. {
  1254. ssStatus.dwWin32ExitCode = dwExitCode;
  1255. }
  1256. ssStatus.dwWaitHint = dwWaitHint;
  1257. if(dwCurrentState == SERVICE_RUNNING || dwCurrentState == SERVICE_STOPPED)
  1258. {
  1259. ssStatus.dwCheckPoint = 0;
  1260. }
  1261. else
  1262. {
  1263. ssStatus.dwCheckPoint = dwCheckPoint++;
  1264. }
  1265. // Report the status of the service to the service control manager.
  1266. //
  1267. fResult = SetServiceStatus(
  1268. sshStatusHandle,
  1269. &ssStatus
  1270. );
  1271. if(fResult == FALSE)
  1272. {
  1273. DBGPrintf(
  1274. DBG_INFORMATION,
  1275. DBG_FACILITY_INIT,
  1276. DBGLEVEL_FUNCTION_TRACE,
  1277. _TEXT("Failed to set service status %d...\n"),
  1278. GetLastError()
  1279. );
  1280. TLSLogErrorEvent(TLS_E_SC_REPORT_STATUS);
  1281. }
  1282. }
  1283. return fResult;
  1284. }
  1285. ///////////////////////////////////////////////////////////////////
  1286. //
  1287. // The following code is for running the service as a console app
  1288. //
  1289. void
  1290. CmdDebugService(
  1291. IN int argc,
  1292. IN char ** argv,
  1293. IN BOOL bDebug
  1294. )
  1295. /*
  1296. */
  1297. {
  1298. int dwArgc;
  1299. LPTSTR *lpszArgv;
  1300. #ifdef UNICODE
  1301. lpszArgv = CommandLineToArgvW(GetCommandLineW(), &(dwArgc) );
  1302. #else
  1303. dwArgc = (DWORD) argc;
  1304. lpszArgv = argv;
  1305. #endif
  1306. _tprintf(
  1307. _TEXT("Debugging %s.\n"),
  1308. _TEXT(SZSERVICEDISPLAYNAME)
  1309. );
  1310. SetConsoleCtrlHandler(
  1311. ControlHandler,
  1312. TRUE
  1313. );
  1314. ServiceStart(
  1315. dwArgc,
  1316. lpszArgv,
  1317. bDebug
  1318. );
  1319. }
  1320. //------------------------------------------------------------------
  1321. BOOL WINAPI
  1322. ControlHandler(
  1323. IN DWORD dwCtrlType
  1324. )
  1325. /*++
  1326. Abstract:
  1327. Parameter:
  1328. IN dwCtrlType : control type
  1329. Return:
  1330. ++*/
  1331. {
  1332. switch( dwCtrlType )
  1333. {
  1334. case CTRL_BREAK_EVENT: // use Ctrl+C or Ctrl+Break to simulate
  1335. case CTRL_C_EVENT: // SERVICE_CONTROL_STOP in debug mode
  1336. _tprintf(
  1337. _TEXT("Stopping %s.\n"),
  1338. _TEXT(SZSERVICEDISPLAYNAME)
  1339. );
  1340. ssCurrentStatus = SERVICE_STOP_PENDING;
  1341. ServiceStop();
  1342. return TRUE;
  1343. break;
  1344. }
  1345. return FALSE;
  1346. }