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.

2025 lines
52 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. #include "Lmaccess.h"
  22. #include "Dsgetdc.h"
  23. #define NULL_SESSION_KEY_NAME _TEXT("SYSTEM\\CurrentControlSet\\Services\\LanmanServer\\Parameters")
  24. #define NULL_SESSION_VALUE_NAME _TEXT("NullSessionPipes")
  25. #define SERVICE_WAITHINT 60*1000 // WaitHint 1 mins.
  26. #define SERVICE_SHUTDOWN_WAITTIME 15*60*1000 // must have shutdown already.
  27. #define TSLSLOCALGROUPNAMELENGTH 64
  28. #define TSLSLOCALGROUPDESLENGTH 128
  29. #define ALLDOMAINCOMPUTERS L"Domain Computers"
  30. PSECURITY_DESCRIPTOR g_pSecDes = NULL; //Security Descriptor for local group
  31. PSID g_pSid = NULL; //Sid for local group
  32. PACL g_Dacl = NULL; //Dacl for local group
  33. //---------------------------------------------------------------------------
  34. //
  35. // internal function prototypes
  36. //
  37. BOOL
  38. ReportStatusToSCMgr(
  39. DWORD,
  40. DWORD,
  41. DWORD
  42. );
  43. DWORD
  44. ServiceStart(
  45. DWORD,
  46. LPTSTR *,
  47. BOOL bDebug=FALSE
  48. );
  49. VOID WINAPI
  50. ServiceCtrl(
  51. DWORD
  52. );
  53. VOID WINAPI
  54. ServiceMain(
  55. DWORD,
  56. LPTSTR *
  57. );
  58. VOID
  59. CmdDebugService(
  60. int,
  61. char **,
  62. BOOL
  63. );
  64. BOOL WINAPI
  65. ControlHandler(
  66. DWORD
  67. );
  68. extern "C" VOID
  69. ServiceStop();
  70. VOID
  71. ServicePause();
  72. VOID
  73. ServiceContinue();
  74. HANDLE hRpcPause=NULL;
  75. ///////////////////////////////////////////////////////////
  76. //
  77. // internal variables
  78. //
  79. SERVICE_STATUS_HANDLE sshStatusHandle;
  80. DWORD ssCurrentStatus; // current status of the service
  81. BOOL g_bReportToSCM = TRUE;
  82. HANDLE gSafeToTerminate=NULL;
  83. HRESULT hrStatus = NULL;
  84. DEFINE_GUID(TLS_WRITER_GUID, 0x5382579c, 0x98df, 0x47a7, 0xac, 0x6c, 0x98, 0xa6, 0xd7, 0x10, 0x6e, 0x9);
  85. GUID idWriter = TLS_WRITER_GUID;
  86. CTlsVssJetWriter *g_pWriter = NULL;
  87. CTlsVssJetWriter::CTlsVssJetWriter() : CVssJetWriter()
  88. {
  89. }
  90. CTlsVssJetWriter::~CTlsVssJetWriter()
  91. {
  92. }
  93. HRESULT CTlsVssJetWriter::Initialize()
  94. {
  95. return CVssJetWriter::Initialize(idWriter, L"TermServLicensing", TRUE, FALSE, L"", L"");
  96. }
  97. void CTlsVssJetWriter::Uninitialize()
  98. {
  99. return CVssJetWriter::Uninitialize();
  100. }
  101. bool STDMETHODCALLTYPE CTlsVssJetWriter::OnIdentify(IN IVssCreateWriterMetadata *pMetadata)
  102. {
  103. HRESULT hr= E_FAIL;
  104. hr = pMetadata->SetRestoreMethod(
  105. VSS_RME_RESTORE_AT_REBOOT,
  106. NULL,
  107. NULL,
  108. VSS_WRE_NEVER,
  109. true);
  110. if(ERROR_SUCCESS == hr)
  111. return CVssJetWriter::OnIdentify(pMetadata);
  112. else
  113. return FALSE;
  114. }
  115. SERVICE_TABLE_ENTRY dispatchTable[] =
  116. {
  117. { _TEXT(SZSERVICENAME), (LPSERVICE_MAIN_FUNCTION)ServiceMain },
  118. { NULL, NULL }
  119. };
  120. //-----------------------------------------------------------------
  121. // Internal routine
  122. //-----------------------------------------------------------------
  123. void print_usage()
  124. {
  125. _ftprintf(
  126. stdout,
  127. _TEXT("Usage : %s can't be run as a console app\n"),
  128. _TEXT(SZAPPNAME)
  129. );
  130. return;
  131. }
  132. #ifdef DISALLOW_ANONYMOUS_RPC
  133. DWORD
  134. RemoveStringFromMultiSz(
  135. LPTSTR pszRemoveString1,
  136. LPTSTR pszRemoveString2,
  137. HKEY hKey,
  138. LPCTSTR pszValueName)
  139. {
  140. DWORD dwErr;
  141. LPTSTR wszData = NULL, pwsz;
  142. DWORD cbData, cbDataRemaining;
  143. BOOL fFound = FALSE;
  144. if ((NULL == pszRemoveString1) || (NULL == pszRemoveString2)
  145. || (NULL == pszValueName) || (NULL == hKey))
  146. {
  147. return ERROR_INVALID_PARAMETER;
  148. }
  149. //
  150. // Retrieve existing MULTI_SZ
  151. //
  152. dwErr = RegQueryValueEx(hKey,
  153. pszValueName,
  154. NULL,
  155. NULL,
  156. NULL,
  157. &cbData);
  158. if (dwErr != ERROR_SUCCESS)
  159. {
  160. if (dwErr == ERROR_FILE_NOT_FOUND)
  161. {
  162. //
  163. // Value isn't there
  164. //
  165. return ERROR_SUCCESS;
  166. }
  167. else
  168. {
  169. return dwErr;
  170. }
  171. }
  172. wszData = (LPTSTR) LocalAlloc(LPTR, cbData);
  173. if (NULL == wszData)
  174. {
  175. return ERROR_OUTOFMEMORY;
  176. }
  177. dwErr = RegQueryValueEx(hKey,
  178. pszValueName,
  179. NULL,
  180. NULL,
  181. (LPBYTE) wszData,
  182. &cbData);
  183. if (dwErr != ERROR_SUCCESS)
  184. {
  185. LocalFree(wszData);
  186. return dwErr;
  187. }
  188. pwsz = wszData;
  189. cbDataRemaining = cbData;
  190. while (*pwsz)
  191. {
  192. DWORD cchDataToMove = _tcslen (pwsz) + 1;
  193. if ((0 == _tcsicmp(pwsz,pszRemoveString1))
  194. || (0 == _tcsicmp(pwsz,pszRemoveString2)))
  195. {
  196. LPTSTR pwszRemain = pwsz + cchDataToMove;
  197. MoveMemory(pwsz, pwszRemain, cbDataRemaining - (cchDataToMove * sizeof(TCHAR)));
  198. cbData -= cchDataToMove * sizeof(TCHAR);
  199. fFound = TRUE;
  200. }
  201. else
  202. {
  203. pwsz += cchDataToMove;
  204. }
  205. cbDataRemaining -= cchDataToMove * sizeof(TCHAR);
  206. }
  207. if (fFound)
  208. {
  209. dwErr = RegSetValueEx(
  210. hKey,
  211. wszData,
  212. 0,
  213. REG_MULTI_SZ,
  214. (LPBYTE) wszData,
  215. cbData);
  216. }
  217. LocalFree(wszData);
  218. return dwErr;
  219. }
  220. DWORD
  221. RemoveNullSessions()
  222. {
  223. HKEY hKey;
  224. DWORD dwErr;
  225. dwErr = RegOpenKeyEx(
  226. HKEY_LOCAL_MACHINE,
  227. NULL_SESSION_KEY_NAME,
  228. 0,
  229. KEY_READ | KEY_WRITE,
  230. &hKey
  231. );
  232. if (dwErr != ERROR_SUCCESS) {
  233. //
  234. // Key doesn't exist - success
  235. //
  236. return ERROR_SUCCESS;
  237. }
  238. dwErr = RemoveStringFromMultiSz(_TEXT(HLSPIPENAME),
  239. _TEXT(SZSERVICENAME),
  240. hKey,
  241. NULL_SESSION_VALUE_NAME);
  242. RegCloseKey(hKey);
  243. return dwErr;
  244. }
  245. #endif // DISALLOW_ANONYMOUS_RPC
  246. //-----------------------------------------------------------------
  247. DWORD
  248. AddNullSessionPipe(
  249. IN LPTSTR szPipeName
  250. )
  251. /*++
  252. Abstract:
  253. Add our RPC namedpipe into registry to allow unrestricted access.
  254. Parameter:
  255. szPipeName : name of the pipe to append.
  256. Returns:
  257. ERROR_SUCCESS or error code
  258. --*/
  259. {
  260. HKEY hKey;
  261. DWORD dwStatus;
  262. LPTSTR pbData=NULL, pbOrg=NULL;
  263. DWORD cbData = 0;
  264. dwStatus = RegOpenKeyEx(
  265. HKEY_LOCAL_MACHINE,
  266. NULL_SESSION_KEY_NAME,
  267. 0,
  268. KEY_ALL_ACCESS,
  269. &hKey
  270. );
  271. if(dwStatus != ERROR_SUCCESS)
  272. return dwStatus;
  273. dwStatus = RegQueryValueEx(
  274. hKey,
  275. NULL_SESSION_VALUE_NAME,
  276. NULL,
  277. NULL,
  278. NULL,
  279. &cbData
  280. );
  281. if(dwStatus != ERROR_MORE_DATA && dwStatus != ERROR_SUCCESS)
  282. return dwStatus;
  283. // pre-allocate our pipe name
  284. if(!(pbData = (LPTSTR)AllocateMemory(cbData + (_tcslen(szPipeName) + 1) * sizeof(TCHAR))))
  285. return GetLastError();
  286. dwStatus = RegQueryValueEx(
  287. hKey,
  288. NULL_SESSION_VALUE_NAME,
  289. NULL,
  290. NULL,
  291. (LPBYTE)pbData,
  292. &cbData
  293. );
  294. BOOL bAddPipe=TRUE;
  295. pbOrg = pbData;
  296. // check pipe name
  297. while(*pbData)
  298. {
  299. if(!_tcsicmp(pbData, szPipeName))
  300. {
  301. bAddPipe=FALSE;
  302. break;
  303. }
  304. pbData += _tcslen(pbData) + 1;
  305. }
  306. if(bAddPipe)
  307. {
  308. _tcscat(pbData, szPipeName);
  309. cbData += (_tcslen(szPipeName) + 1) * sizeof(TCHAR);
  310. dwStatus = RegSetValueEx(
  311. hKey,
  312. NULL_SESSION_VALUE_NAME,
  313. 0,
  314. REG_MULTI_SZ,
  315. (PBYTE)pbOrg,
  316. cbData
  317. );
  318. }
  319. FreeMemory(pbOrg);
  320. RegCloseKey(hKey);
  321. return dwStatus;
  322. }
  323. //-----------------------------------------------------------------
  324. void _cdecl
  325. main(
  326. int argc,
  327. char **argv
  328. )
  329. /*++
  330. Abstract
  331. Entry point.
  332. ++*/
  333. {
  334. // LARGE_INTEGER Time = USER_SHARED_DATA->SystemExpirationDate;
  335. gSafeToTerminate = CreateEvent(
  336. NULL,
  337. TRUE,
  338. FALSE,
  339. NULL
  340. );
  341. if(gSafeToTerminate == NULL)
  342. {
  343. TLSLogErrorEvent(TLS_E_ALLOCATE_RESOURCE);
  344. // out of resource.
  345. return;
  346. }
  347. if(g_bReportToSCM == FALSE)
  348. {
  349. CmdDebugService(
  350. argc,
  351. argv,
  352. !g_bReportToSCM
  353. );
  354. }
  355. else if(!StartServiceCtrlDispatcher(dispatchTable))
  356. {
  357. TLSLogErrorEvent(TLS_E_SC_CONNECT);
  358. }
  359. WaitForSingleObject(gSafeToTerminate, INFINITE);
  360. CloseHandle(gSafeToTerminate);
  361. }
  362. //-----------------------------------------------------------------
  363. void WINAPI
  364. ServiceMain(
  365. IN DWORD dwArgc,
  366. IN LPTSTR *lpszArgv
  367. )
  368. /*++
  369. Abstract:
  370. To perform actual initialization of the service
  371. Parameter:
  372. dwArgc - number of command line arguments
  373. lpszArgv - array of command line arguments
  374. Returns:
  375. none
  376. ++*/
  377. {
  378. DWORD dwStatus;
  379. // register our service control handler:
  380. sshStatusHandle = RegisterServiceCtrlHandler(
  381. _TEXT(SZSERVICENAME),
  382. ServiceCtrl
  383. );
  384. if (sshStatusHandle)
  385. {
  386. ssCurrentStatus=SERVICE_START_PENDING;
  387. // report the status to the service control manager.
  388. //
  389. if(ReportStatusToSCMgr(
  390. SERVICE_START_PENDING, // service state
  391. NO_ERROR, // exit code
  392. SERVICE_WAITHINT)) // wait hint
  393. {
  394. dwStatus = ServiceStart(
  395. dwArgc,
  396. lpszArgv
  397. );
  398. if(dwStatus != ERROR_SUCCESS)
  399. {
  400. ReportStatusToSCMgr(
  401. SERVICE_STOPPED,
  402. dwStatus,
  403. 0
  404. );
  405. }
  406. else
  407. {
  408. ReportStatusToSCMgr(
  409. SERVICE_STOPPED,
  410. NO_ERROR,
  411. 0
  412. );
  413. }
  414. }
  415. }
  416. else
  417. {
  418. dwStatus = GetLastError();
  419. TLSLogErrorEvent(TLS_E_SC_CONNECT);
  420. }
  421. DBGPrintf(
  422. DBG_INFORMATION,
  423. DBG_FACILITY_INIT,
  424. DBGLEVEL_FUNCTION_TRACE,
  425. _TEXT("Service terminated...\n")
  426. );
  427. return;
  428. }
  429. //-------------------------------------------------------------
  430. VOID WINAPI
  431. ServiceCtrl(
  432. IN DWORD dwCtrlCode
  433. )
  434. /*+++
  435. Abstract:
  436. This function is called by the SCM whenever
  437. ControlService() is called on this service.
  438. Parameter:
  439. dwCtrlCode - type of control requested from SCM.
  440. +++*/
  441. {
  442. // Handle the requested control code.
  443. //
  444. switch(dwCtrlCode)
  445. {
  446. // Stop the service.
  447. //
  448. case SERVICE_CONTROL_SHUTDOWN:
  449. case SERVICE_CONTROL_STOP:
  450. ReportStatusToSCMgr(
  451. SERVICE_STOP_PENDING,
  452. NO_ERROR,
  453. 0
  454. );
  455. ServiceStop();
  456. break;
  457. // We don't really accept pause and continue
  458. case SERVICE_CONTROL_PAUSE:
  459. ReportStatusToSCMgr(
  460. SERVICE_PAUSED,
  461. NO_ERROR,
  462. 0
  463. );
  464. ServicePause();
  465. break;
  466. case SERVICE_CONTROL_CONTINUE:
  467. ReportStatusToSCMgr(
  468. SERVICE_RUNNING,
  469. NO_ERROR,
  470. 0
  471. );
  472. ServiceContinue();
  473. break;
  474. // Update the service status.
  475. case SERVICE_CONTROL_INTERROGATE:
  476. ReportStatusToSCMgr(
  477. ssCurrentStatus,
  478. NO_ERROR,
  479. 0
  480. );
  481. break;
  482. // invalid control code
  483. default:
  484. break;
  485. }
  486. }
  487. //------------------------------------------------------------------
  488. DWORD
  489. ServiceShutdownThread(
  490. void *p
  491. )
  492. /*++
  493. Abstract:
  494. Entry point into thread that shutdown server (mainly database).
  495. Parameter:
  496. Ignore
  497. ++*/
  498. {
  499. ServerShutdown();
  500. ExitThread(ERROR_SUCCESS);
  501. return ERROR_SUCCESS;
  502. }
  503. //------------------------------------------------------------------
  504. DWORD
  505. RPCServiceStartThread(
  506. void *p
  507. )
  508. /*++
  509. Abstract:
  510. Entry point to thread that startup RPC.
  511. Parameter:
  512. None.
  513. Return:
  514. Thread exit code.
  515. ++*/
  516. {
  517. RPC_BINDING_VECTOR *pbindingVector = NULL;
  518. RPC_STATUS status = RPC_S_OK;
  519. WCHAR *pszEntryName = _TEXT(RPC_ENTRYNAME);
  520. DWORD dwNumSuccessRpcPro=0;
  521. do {
  522. //
  523. // local procedure call
  524. //
  525. status = RpcServerUseProtseq(
  526. _TEXT(RPC_PROTOSEQLPC),
  527. RPC_C_PROTSEQ_MAX_REQS_DEFAULT,
  528. NULL // &SecurityDescriptor
  529. );
  530. if(status == RPC_S_OK)
  531. {
  532. dwNumSuccessRpcPro++;
  533. }
  534. //
  535. // NT4 backward compatible issue, let NT4 termsrv serivce
  536. // client connect so still set security descriptor
  537. //
  538. // 11/10/98 Tested on NT4 and NT5
  539. //
  540. //
  541. // Namedpipe
  542. //
  543. status = RpcServerUseProtseqEp(
  544. _TEXT(RPC_PROTOSEQNP),
  545. RPC_C_PROTSEQ_MAX_REQS_DEFAULT,
  546. _TEXT(LSNAMEPIPE),
  547. NULL //&SecurityDescriptor
  548. );
  549. if(status == RPC_S_OK)
  550. {
  551. dwNumSuccessRpcPro++;
  552. }
  553. //
  554. // TCP/IP
  555. //
  556. status = RpcServerUseProtseq(
  557. _TEXT(RPC_PROTOSEQTCP),
  558. RPC_C_PROTSEQ_MAX_REQS_DEFAULT,
  559. NULL //&SecurityDescriptor
  560. );
  561. if(status == RPC_S_OK)
  562. {
  563. dwNumSuccessRpcPro++;
  564. }
  565. // Must have at least one protocol.
  566. if(dwNumSuccessRpcPro == 0)
  567. {
  568. status = TLS_E_RPC_PROTOCOL;
  569. break;
  570. }
  571. // Get server binding handles
  572. status = RpcServerInqBindings(&pbindingVector);
  573. if (status != RPC_S_OK)
  574. {
  575. status = TLS_E_RPC_INQ_BINDING;
  576. break;
  577. }
  578. // Register interface(s) and binding(s) (endpoints) with
  579. // the endpoint mapper.
  580. status = RpcEpRegister(
  581. TermServLicensing_v1_0_s_ifspec, // from rpcsvc.h
  582. pbindingVector,
  583. NULL, // &export_uuid,
  584. L""
  585. );
  586. if (status != RPC_S_OK)
  587. {
  588. status = TLS_E_RPC_EP_REGISTER;
  589. break;
  590. }
  591. status = RpcServerRegisterIf(
  592. TermServLicensing_v1_0_s_ifspec,
  593. NULL,
  594. NULL);
  595. if(status != RPC_S_OK)
  596. {
  597. status = TLS_E_RPC_REG_INTERFACE;
  598. break;
  599. }
  600. // Register interface(s) and binding(s) (endpoints) with
  601. // the endpoint mapper.
  602. status = RpcEpRegister(
  603. HydraLicenseService_v1_0_s_ifspec, // from rpcsvc.h
  604. pbindingVector,
  605. NULL, // &export_uuid,
  606. L"");
  607. if (status != RPC_S_OK)
  608. {
  609. status = TLS_E_RPC_EP_REGISTER;
  610. break;
  611. }
  612. status = RpcServerRegisterIf(
  613. HydraLicenseService_v1_0_s_ifspec,
  614. NULL,
  615. NULL);
  616. if(status != RPC_S_OK)
  617. {
  618. status = TLS_E_RPC_REG_INTERFACE;
  619. break;
  620. }
  621. // Register interface(s) and binding(s) (endpoints) with
  622. // the endpoint mapper.
  623. status = RpcEpRegister(
  624. TermServLicensingBackup_v1_0_s_ifspec, // from rpcsvc.h
  625. pbindingVector,
  626. NULL, // &export_uuid,
  627. L"");
  628. if (status != RPC_S_OK)
  629. {
  630. status = TLS_E_RPC_EP_REGISTER;
  631. break;
  632. }
  633. status = RpcServerRegisterIf(
  634. TermServLicensingBackup_v1_0_s_ifspec,
  635. NULL,
  636. NULL);
  637. if(status != RPC_S_OK)
  638. {
  639. status = TLS_E_RPC_REG_INTERFACE;
  640. break;
  641. }
  642. // Enable NT LM Security Support Provider (NtLmSsp service)
  643. status = RpcServerRegisterAuthInfo(0,
  644. RPC_C_AUTHN_GSS_NEGOTIATE,
  645. 0,
  646. 0);
  647. if (status != RPC_S_OK)
  648. {
  649. status = TLS_E_RPC_SET_AUTHINFO;
  650. break;
  651. }
  652. } while(FALSE);
  653. if(status != RPC_S_OK)
  654. {
  655. TLSLogEvent(
  656. EVENTLOG_ERROR_TYPE,
  657. TLS_E_SERVICEINIT,
  658. TLS_E_INITRPC,
  659. status
  660. );
  661. status = TLS_E_SERVICE_STARTUP;
  662. }
  663. ExitThread(status);
  664. return status;
  665. }
  666. //------------------------------------------------------------------------
  667. DWORD SetupNamedPipes()
  668. {
  669. DWORD dwStatus = ERROR_SUCCESS;
  670. #ifdef DISALLOW_ANONYMOUS_RPC
  671. BOOL fInDomain = FALSE;
  672. TLSInDomain(&fInDomain,NULL);
  673. if (!fInDomain)
  674. {
  675. #endif
  676. dwStatus = AddNullSessionPipe(_TEXT(HLSPIPENAME));
  677. if (dwStatus != ERROR_SUCCESS)
  678. {
  679. return dwStatus;
  680. }
  681. dwStatus = AddNullSessionPipe(_TEXT(SZSERVICENAME));
  682. #ifdef DISALLOW_ANONYMOUS_RPC
  683. }
  684. else
  685. {
  686. dwStatus = RemoveNullSessions();
  687. }
  688. #endif
  689. return dwStatus;
  690. }
  691. //---------------------------------------------------------------------------
  692. /****************************************************************************/
  693. // LSCreateLocalGroup
  694. //
  695. // Create Terminal Server Computers local group if not exist
  696. // and create the security descriptor of this local group
  697. /****************************************************************************/
  698. BOOL TSLSCreateLocalGroupSecDes(BOOL fEnterpriseServer)
  699. {
  700. DWORD dwStatus;
  701. LPWSTR ReferencedDomainName = NULL;
  702. ULONG SidSize, ReferencedDomainNameSize;
  703. SID_NAME_USE SidNameUse;
  704. WCHAR TSLSLocalGroupName[TSLSLOCALGROUPNAMELENGTH];
  705. WCHAR TSLSLocalGroupDes[TSLSLOCALGROUPDESLENGTH];
  706. GROUP_INFO_1 TSLSGroupInfo = {TSLSLocalGroupName, TSLSLocalGroupDes};
  707. HMODULE HModule = NULL;
  708. LOCALGROUP_MEMBERS_INFO_3 DomainComputers = {ALLDOMAINCOMPUTERS};
  709. DWORD cbAcl;
  710. DWORD SecurityDescriptorSize;
  711. NET_API_STATUS NetStatus;
  712. HModule = GetModuleHandle(NULL);
  713. if (HModule == NULL)
  714. {
  715. dwStatus = GetLastError();
  716. if(dwStatus != ERROR_SUCCESS)
  717. {
  718. TLSLogEvent(
  719. EVENTLOG_ERROR_TYPE,
  720. TLS_E_SERVICEINIT,
  721. TLS_E_CREATETSLSGROUP
  722. );
  723. }
  724. goto cleanup;
  725. }
  726. LoadString(HModule, IDS_TSLSLOCALGROUP_NAME, TSLSLocalGroupName, sizeof(TSLSLocalGroupName) / sizeof(WCHAR));
  727. LoadString(HModule, IDS_TSLSLOCALGROUP_DES, TSLSLocalGroupDes, sizeof(TSLSLocalGroupDes) / sizeof(WCHAR));
  728. for( int i = 0; i < 3; i++)
  729. {
  730. // Create local group if not exist
  731. NetStatus = NetLocalGroupAdd(
  732. NULL,
  733. 1,
  734. (LPBYTE)&TSLSGroupInfo,
  735. NULL
  736. );
  737. if(NERR_Success == NetStatus || NERR_GroupExists == NetStatus || ERROR_ALIAS_EXISTS == NetStatus )
  738. break;
  739. Sleep (5000);
  740. }
  741. if(NERR_Success != NetStatus)
  742. {
  743. if((NERR_GroupExists != NetStatus)
  744. && (ERROR_ALIAS_EXISTS != NetStatus))
  745. {
  746. dwStatus = ERROR_ACCESS_DENIED;
  747. //
  748. // Didn't create the group and group doesn't exist either.
  749. //
  750. TLSLogEvent(
  751. EVENTLOG_ERROR_TYPE,
  752. TLS_E_SERVICEINIT,
  753. TLS_E_CREATETSLSGROUP
  754. );
  755. goto cleanup;
  756. }
  757. }
  758. //
  759. // Group created. Now lookup the SID.
  760. //
  761. SidSize = ReferencedDomainNameSize = 0;
  762. ReferencedDomainName = NULL;
  763. NetStatus = LookupAccountName(
  764. NULL,
  765. TSLSGroupInfo.grpi1_name,
  766. NULL,
  767. &SidSize,
  768. NULL,
  769. &ReferencedDomainNameSize,
  770. &SidNameUse);
  771. if( NetStatus )
  772. {
  773. dwStatus = GetLastError();
  774. if( ERROR_INSUFFICIENT_BUFFER != dwStatus )
  775. goto cleanup;
  776. }
  777. g_pSid = (PSID)LocalAlloc(LMEM_FIXED, SidSize);
  778. if (NULL == g_pSid)
  779. {
  780. goto cleanup;
  781. }
  782. ReferencedDomainName = (LPWSTR)LocalAlloc(LMEM_FIXED,
  783. sizeof(WCHAR)*(1+ReferencedDomainNameSize));
  784. if (NULL == ReferencedDomainName) {
  785. goto cleanup;
  786. }
  787. NetStatus = LookupAccountName(
  788. NULL,
  789. TSLSGroupInfo.grpi1_name,
  790. g_pSid,
  791. &SidSize,
  792. ReferencedDomainName,
  793. &ReferencedDomainNameSize,
  794. &SidNameUse
  795. );
  796. if( 0 == NetStatus )
  797. {
  798. //
  799. // Failed.
  800. //
  801. dwStatus = GetLastError();
  802. if(dwStatus != ERROR_SUCCESS)
  803. {
  804. TLSLogEvent(
  805. EVENTLOG_ERROR_TYPE,
  806. TLS_E_SERVICEINIT,
  807. TLS_E_CREATETSLSGROUP
  808. );
  809. }
  810. goto cleanup;
  811. }
  812. // Create Security Descriptor
  813. // The size is equal to the size of an SD + twice the length of the SID
  814. // (for owner and group) + size of the DACL = sizeof ACL + size of the
  815. // ACE, which is an ACE + length of the SID.
  816. SecurityDescriptorSize = sizeof(SECURITY_DESCRIPTOR) +
  817. sizeof(ACCESS_ALLOWED_ACE) +
  818. sizeof(ACL) +
  819. 3 * GetLengthSid(g_pSid);
  820. g_pSecDes = (PSECURITY_DESCRIPTOR)LocalAlloc(LMEM_FIXED, SecurityDescriptorSize);
  821. if (NULL == g_pSecDes)
  822. {
  823. goto cleanup;
  824. }
  825. if (!InitializeSecurityDescriptor(g_pSecDes, SECURITY_DESCRIPTOR_REVISION))
  826. {
  827. dwStatus = GetLastError();
  828. if(dwStatus != ERROR_SUCCESS)
  829. {
  830. TLSLogEvent(
  831. EVENTLOG_ERROR_TYPE,
  832. TLS_E_SERVICEINIT,
  833. TLS_E_CREATETSLSGROUP
  834. );
  835. }
  836. goto cleanup;
  837. }
  838. SetSecurityDescriptorOwner(g_pSecDes, g_pSid, FALSE);
  839. SetSecurityDescriptorGroup(g_pSecDes, g_pSid, FALSE);
  840. // Add acl to security descriptor
  841. cbAcl = sizeof(ACL) + sizeof (ACCESS_ALLOWED_ACE) - sizeof (DWORD)+ GetLengthSid(g_pSid);
  842. g_Dacl = (PACL) LocalAlloc(LMEM_FIXED, cbAcl);
  843. if (NULL == g_Dacl)
  844. {
  845. goto cleanup;
  846. }
  847. if(!InitializeAcl(g_Dacl,
  848. cbAcl,
  849. ACL_REVISION))
  850. {
  851. dwStatus = GetLastError();
  852. if(dwStatus != ERROR_SUCCESS)
  853. {
  854. TLSLogEvent(
  855. EVENTLOG_ERROR_TYPE,
  856. TLS_E_SERVICEINIT,
  857. TLS_E_CREATETSLSGROUP
  858. );
  859. }
  860. goto cleanup;
  861. }
  862. if(!AddAccessAllowedAce(g_Dacl, ACL_REVISION, STANDARD_RIGHTS_READ, g_pSid))
  863. {
  864. dwStatus = GetLastError();
  865. if(dwStatus != ERROR_SUCCESS)
  866. {
  867. TLSLogEvent(
  868. EVENTLOG_ERROR_TYPE,
  869. TLS_E_SERVICEINIT,
  870. TLS_E_CREATETSLSGROUP
  871. );
  872. }
  873. goto cleanup;
  874. }
  875. if(!SetSecurityDescriptorDacl(g_pSecDes, TRUE, g_Dacl, FALSE))
  876. {
  877. dwStatus = GetLastError();
  878. if(dwStatus != ERROR_SUCCESS)
  879. {
  880. TLSLogEvent(
  881. EVENTLOG_ERROR_TYPE,
  882. TLS_E_SERVICEINIT,
  883. TLS_E_CREATETSLSGROUP
  884. );
  885. }
  886. goto cleanup;
  887. }
  888. return TRUE;
  889. cleanup:
  890. if (ReferencedDomainName)
  891. LocalFree(ReferencedDomainName);
  892. if (g_pSid)
  893. LocalFree(g_pSid);
  894. if (g_Dacl)
  895. LocalFree(g_Dacl);
  896. if (g_pSecDes)
  897. LocalFree(g_pSecDes);
  898. return FALSE;
  899. }
  900. //------------------------------------------------------------------------------
  901. DWORD
  902. ServiceStart(
  903. IN DWORD dwArgc,
  904. IN LPTSTR *lpszArgv,
  905. IN BOOL bDebug
  906. )
  907. /*
  908. */
  909. {
  910. RPC_BINDING_VECTOR *pbindingVector = NULL;
  911. WCHAR *pszEntryName = _TEXT(RPC_ENTRYNAME);
  912. HANDLE hInitThread=NULL;
  913. HANDLE hRpcThread=NULL;
  914. HANDLE hMailslotThread=NULL;
  915. HANDLE hShutdownThread=NULL;
  916. DWORD dump;
  917. HANDLE hEvent=NULL;
  918. DWORD dwStatus=ERROR_SUCCESS;
  919. WORD wVersionRequested;
  920. WSADATA wsaData;
  921. int err;
  922. if (!ReportStatusToSCMgr(
  923. SERVICE_START_PENDING,
  924. NO_ERROR,
  925. SERVICE_WAITHINT))
  926. {
  927. // resource leak but something went wrong already.
  928. dwStatus = TLS_E_SC_REPORT_STATUS;
  929. goto cleanup;
  930. }
  931. hrStatus = CoInitializeEx (NULL, COINIT_MULTITHREADED);
  932. if (FAILED (hrStatus))
  933. {
  934. DBGPrintf(
  935. DBG_INFORMATION,
  936. DBG_FACILITY_INIT,
  937. DBGLEVEL_FUNCTION_DETAILSIMPLE,
  938. _TEXT("CoInitializeEx failed with error code %08x...\n"),
  939. hrStatus
  940. );
  941. }
  942. if (!ReportStatusToSCMgr(
  943. SERVICE_START_PENDING,
  944. NO_ERROR,
  945. SERVICE_WAITHINT))
  946. {
  947. // resource leak but something went wrong already.
  948. dwStatus = TLS_E_SC_REPORT_STATUS;
  949. goto cleanup;
  950. }
  951. if (SUCCEEDED (hrStatus))
  952. {
  953. hrStatus = CoInitializeSecurity(
  954. NULL,
  955. -1,
  956. NULL,
  957. NULL,
  958. RPC_C_AUTHN_LEVEL_CONNECT,
  959. RPC_C_IMP_LEVEL_IDENTIFY,
  960. NULL,
  961. EOAC_NONE,
  962. NULL
  963. );
  964. }
  965. if (!ReportStatusToSCMgr(
  966. SERVICE_START_PENDING,
  967. NO_ERROR,
  968. SERVICE_WAITHINT))
  969. {
  970. // resource leak but something went wrong already.
  971. dwStatus = TLS_E_SC_REPORT_STATUS;
  972. goto cleanup;
  973. }
  974. if (SUCCEEDED (hrStatus))
  975. {
  976. g_pWriter = new CTlsVssJetWriter;
  977. if (NULL == g_pWriter)
  978. {
  979. DBGPrintf(
  980. DBG_INFORMATION,
  981. DBG_FACILITY_INIT,
  982. DBGLEVEL_FUNCTION_DETAILSIMPLE,
  983. _TEXT("new CVssJetWriter failed...\n")
  984. );
  985. hrStatus = HRESULT_FROM_WIN32 (ERROR_NOT_ENOUGH_MEMORY);
  986. }
  987. }
  988. // Report the status to the service control manager.
  989. if (!ReportStatusToSCMgr(
  990. SERVICE_START_PENDING,
  991. NO_ERROR,
  992. SERVICE_WAITHINT))
  993. {
  994. // resource leak but something went wrong already.
  995. dwStatus = TLS_E_SC_REPORT_STATUS;
  996. goto cleanup;
  997. }
  998. {
  999. DWORD dwConsole;
  1000. DWORD dwDbLevel;
  1001. DWORD dwType;
  1002. DWORD dwSize = sizeof(dwConsole);
  1003. DWORD status;
  1004. HKEY hKey=NULL;
  1005. status = RegOpenKeyEx(
  1006. HKEY_LOCAL_MACHINE,
  1007. LSERVER_PARAMETERS_KEY,
  1008. 0,
  1009. KEY_ALL_ACCESS,
  1010. &hKey);
  1011. if(status == ERROR_SUCCESS)
  1012. {
  1013. if(RegQueryValueEx(
  1014. hKey,
  1015. LSERVER_PARAMETERS_CONSOLE,
  1016. NULL,
  1017. &dwType,
  1018. (LPBYTE)&dwConsole,
  1019. &dwSize
  1020. ) != ERROR_SUCCESS)
  1021. {
  1022. dwConsole = 0;
  1023. }
  1024. dwSize = sizeof(dwDbLevel);
  1025. if(RegQueryValueEx(
  1026. hKey,
  1027. LSERVER_PARAMETERS_LOGLEVEL,
  1028. NULL,
  1029. &dwType,
  1030. (LPBYTE)&dwDbLevel,
  1031. &dwSize
  1032. ) == ERROR_SUCCESS)
  1033. {
  1034. InitDBGPrintf(
  1035. dwConsole != 0,
  1036. _TEXT(SZSERVICENAME),
  1037. dwDbLevel
  1038. );
  1039. }
  1040. RegCloseKey(hKey);
  1041. }
  1042. }
  1043. // Report the status to the service control manager.
  1044. if (!ReportStatusToSCMgr(
  1045. SERVICE_START_PENDING,
  1046. NO_ERROR,
  1047. SERVICE_WAITHINT))
  1048. {
  1049. // resource leak but something went wrong already.
  1050. dwStatus = TLS_E_SC_REPORT_STATUS;
  1051. goto cleanup;
  1052. }
  1053. do {
  1054. dwStatus = SetupNamedPipes();
  1055. if (dwStatus != ERROR_SUCCESS)
  1056. {
  1057. break;
  1058. }
  1059. wVersionRequested = MAKEWORD( 1, 1 );
  1060. err = WSAStartup(
  1061. wVersionRequested,
  1062. &wsaData
  1063. );
  1064. if(err != 0)
  1065. {
  1066. // None critical error
  1067. TLSLogWarningEvent(
  1068. TLS_E_SERVICE_WSASTARTUP
  1069. );
  1070. }
  1071. else
  1072. {
  1073. char hostname[(MAXTCPNAME+1)*sizeof(TCHAR)];
  1074. err=gethostname(hostname, MAXTCPNAME*sizeof(TCHAR));
  1075. if(err == 0)
  1076. {
  1077. struct addrinfo *paddrinfo;
  1078. struct addrinfo hints;
  1079. memset(&hints,0,sizeof(hints));
  1080. hints.ai_flags = AI_CANONNAME;
  1081. hints.ai_family = PF_UNSPEC;
  1082. if (0 == getaddrinfo(hostname,NULL,&hints,&paddrinfo) && paddrinfo && paddrinfo->ai_canonname)
  1083. {
  1084. err = (MultiByteToWideChar(
  1085. GetACP(),
  1086. MB_ERR_INVALID_CHARS,
  1087. paddrinfo->ai_canonname,
  1088. -1,
  1089. g_szHostName,
  1090. g_cbHostName) == 0) ? -1 : 0;
  1091. }
  1092. else
  1093. {
  1094. err = -1;
  1095. }
  1096. freeaddrinfo(paddrinfo);
  1097. }
  1098. }
  1099. if(err != 0)
  1100. {
  1101. if(GetComputerName(g_szHostName, &g_cbHostName) == FALSE)
  1102. {
  1103. dwStatus = GetLastError();
  1104. DBGPrintf(
  1105. DBG_INFORMATION,
  1106. DBG_FACILITY_INIT,
  1107. DBGLEVEL_FUNCTION_DETAILSIMPLE,
  1108. _TEXT("GetComputerName() failed with %d...\n"),
  1109. dwStatus
  1110. );
  1111. // this shoule not happen...
  1112. TLSLogErrorEvent(TLS_E_INIT_GENERAL);
  1113. break;
  1114. }
  1115. }
  1116. if(GetComputerName(g_szComputerName, &g_cbComputerName) == FALSE)
  1117. {
  1118. dwStatus = GetLastError();
  1119. DBGPrintf(
  1120. DBG_INFORMATION,
  1121. DBG_FACILITY_INIT,
  1122. DBGLEVEL_FUNCTION_DETAILSIMPLE,
  1123. _TEXT("GetComputerName() failed with %d...\n"),
  1124. dwStatus
  1125. );
  1126. // this shoule not happen...
  1127. TLSLogErrorEvent(TLS_E_INIT_GENERAL);
  1128. break;
  1129. }
  1130. hRpcPause=CreateEvent(NULL, TRUE, TRUE, NULL);
  1131. if(!hRpcPause)
  1132. {
  1133. TLSLogErrorEvent(TLS_E_ALLOCATE_RESOURCE);
  1134. dwStatus = TLS_E_ALLOCATE_RESOURCE;
  1135. break;
  1136. }
  1137. //
  1138. // start up general server and RPC initialization thread
  1139. //
  1140. hInitThread=ServerInit(bDebug);
  1141. if(hInitThread==NULL)
  1142. {
  1143. TLSLogErrorEvent(TLS_E_SERVICE_STARTUP_CREATE_THREAD);
  1144. dwStatus = TLS_E_SERVICE_STARTUP_CREATE_THREAD;
  1145. break;
  1146. }
  1147. dwStatus = ERROR_SUCCESS;
  1148. //
  1149. // Wait for general server init. thread to terminate
  1150. //
  1151. while(WaitForSingleObject( hInitThread, 100 ) == WAIT_TIMEOUT)
  1152. {
  1153. // Report the status to the service control manager.
  1154. if (!ReportStatusToSCMgr(
  1155. SERVICE_START_PENDING,
  1156. NO_ERROR,
  1157. SERVICE_WAITHINT))
  1158. {
  1159. // resource leak but something went wrong already.
  1160. dwStatus = TLS_E_SC_REPORT_STATUS;
  1161. break;
  1162. }
  1163. }
  1164. if(dwStatus != ERROR_SUCCESS)
  1165. {
  1166. break;
  1167. }
  1168. // Check thread exit code.
  1169. GetExitCodeThread(
  1170. hInitThread,
  1171. &dwStatus
  1172. );
  1173. if(dwStatus != ERROR_SUCCESS)
  1174. {
  1175. //
  1176. // Server init. thread logs its own error
  1177. //
  1178. dwStatus = TLS_E_SERVICE_STARTUP_INIT_THREAD_ERROR;
  1179. break;
  1180. }
  1181. CloseHandle(hInitThread);
  1182. hInitThread=NULL;
  1183. // Create the Terminal Servers group in case of Domain a/ Enterprise LS
  1184. BOOL fInDomain;
  1185. DWORD dwErr;
  1186. BOOL fEnterprise = FALSE;
  1187. if(GetLicenseServerRole() & TLSERVER_ENTERPRISE_SERVER)
  1188. {
  1189. fEnterprise = TRUE;
  1190. }
  1191. else
  1192. {
  1193. dwErr = TLSInDomain(&fInDomain,NULL);
  1194. }
  1195. if(fEnterprise == TRUE || ( dwErr == ERROR_SUCCESS && fInDomain == TRUE))
  1196. {
  1197. // Create the License Server group that contains the list of Terminal servers that have access to it.
  1198. if (!TSLSCreateLocalGroupSecDes(fEnterprise))
  1199. {
  1200. TLSLogErrorEvent(TLS_E_CREATETSLSGROUP);
  1201. goto cleanup;
  1202. }
  1203. }
  1204. // timing, if we startup RPC init thread but database init thread
  1205. // can't initialize, service will be in forever stop state.
  1206. hRpcThread=CreateThread(
  1207. NULL,
  1208. 0,
  1209. RPCServiceStartThread,
  1210. ULongToPtr(bDebug),
  1211. 0,
  1212. &dump
  1213. );
  1214. if(hRpcThread == NULL)
  1215. {
  1216. TLSLogErrorEvent(TLS_E_SERVICE_STARTUP_CREATE_THREAD);
  1217. dwStatus=TLS_E_SERVICE_STARTUP_CREATE_THREAD;
  1218. break;
  1219. }
  1220. dwStatus = ERROR_SUCCESS;
  1221. //
  1222. // Wait for RPC init. thread to terminate
  1223. //
  1224. while(WaitForSingleObject( hRpcThread, 100 ) == WAIT_TIMEOUT)
  1225. {
  1226. // Report the status to the service control manager.
  1227. if (!ReportStatusToSCMgr(SERVICE_START_PENDING, // service state
  1228. NO_ERROR, // exit code
  1229. SERVICE_WAITHINT)) // wait hint
  1230. {
  1231. dwStatus = TLS_E_SC_REPORT_STATUS;
  1232. break;
  1233. }
  1234. }
  1235. if(dwStatus != ERROR_SUCCESS)
  1236. {
  1237. break;
  1238. }
  1239. // Check thread exit code.
  1240. GetExitCodeThread(hRpcThread, &dwStatus);
  1241. if(dwStatus != ERROR_SUCCESS)
  1242. {
  1243. dwStatus = TLS_E_SERVICE_STARTUP_RPC_THREAD_ERROR;
  1244. break;
  1245. }
  1246. CloseHandle(hRpcThread);
  1247. hRpcThread=NULL;
  1248. //
  1249. // Tell server control manager that we are ready.
  1250. //
  1251. if (!ReportStatusToSCMgr(
  1252. SERVICE_RUNNING, // service state
  1253. NO_ERROR, // exit code
  1254. SERVICE_WAITHINT // wait hint
  1255. ))
  1256. {
  1257. dwStatus = TLS_E_SC_REPORT_STATUS;
  1258. break;
  1259. }
  1260. //
  1261. // Post service init. load self-signed certificate and init. crypt.
  1262. // this is needed after reporting service running status back to
  1263. // service control manager because it may need to manually call
  1264. // StartService() to startup protected storage service.
  1265. //
  1266. if(InitCryptoAndCertificate() != ERROR_SUCCESS)
  1267. {
  1268. dwStatus = TLS_E_SERVICE_STARTUP_POST_INIT;
  1269. break;
  1270. }
  1271. TLSLogInfoEvent(TLS_I_SERVICE_START);
  1272. // RpcMgmtWaitServerListen() will block until the server has
  1273. // stopped listening. If this service had something better to
  1274. // do with this thread, it would delay this call until
  1275. // ServiceStop() had been called. (Set an event in ServiceStop()).
  1276. //
  1277. BOOL bOtherServiceStarted = FALSE;
  1278. do {
  1279. WaitForSingleObject(hRpcPause, INFINITE);
  1280. if(ssCurrentStatus == SERVICE_STOP_PENDING)
  1281. {
  1282. break;
  1283. }
  1284. // Start accepting client calls.PostServiceInit
  1285. dwStatus = RpcServerListen(
  1286. RPC_MINIMUMCALLTHREADS,
  1287. RPC_MAXIMUMCALLTHREADS,
  1288. TRUE
  1289. );
  1290. if(dwStatus != RPC_S_OK)
  1291. {
  1292. TLSLogErrorEvent(TLS_E_RPC_LISTEN);
  1293. dwStatus = TLS_E_SERVICE_RPC_LISTEN;
  1294. break;
  1295. }
  1296. //
  1297. // Initialize all policy module
  1298. //
  1299. if(bOtherServiceStarted == FALSE)
  1300. {
  1301. dwStatus = PostServiceInit();
  1302. if(dwStatus != ERROR_SUCCESS)
  1303. {
  1304. // faild to initialize.
  1305. break;
  1306. }
  1307. //ServiceInitPolicyModule();
  1308. }
  1309. bOtherServiceStarted = TRUE;
  1310. DBGPrintf(
  1311. DBG_INFORMATION,
  1312. DBG_FACILITY_INIT,
  1313. DBGLEVEL_FUNCTION_DETAILSIMPLE,
  1314. _TEXT("Ready to accept request...\n")
  1315. );
  1316. dwStatus = RpcMgmtWaitServerListen();
  1317. assert(dwStatus == RPC_S_OK);
  1318. } while(TRUE);
  1319. // tell service control manager we are stopping
  1320. ReportStatusToSCMgr(
  1321. SERVICE_STOP_PENDING,
  1322. NO_ERROR,
  1323. SERVICE_WAITHINT
  1324. );
  1325. //
  1326. // Terminate - ignore all error here on
  1327. //
  1328. dwStatus = RpcServerUnregisterIf(
  1329. TermServLicensingBackup_v1_0_s_ifspec,
  1330. NULL,
  1331. TRUE
  1332. );
  1333. // tell service control manager we are stopping
  1334. ReportStatusToSCMgr(
  1335. SERVICE_STOP_PENDING,
  1336. NO_ERROR,
  1337. SERVICE_WAITHINT
  1338. );
  1339. dwStatus = RpcServerUnregisterIf(
  1340. HydraLicenseService_v1_0_s_ifspec,
  1341. NULL,
  1342. TRUE
  1343. );
  1344. // tell service control manager we are stopping
  1345. ReportStatusToSCMgr(
  1346. SERVICE_STOP_PENDING,
  1347. NO_ERROR,
  1348. SERVICE_WAITHINT
  1349. );
  1350. dwStatus = RpcServerUnregisterIf(
  1351. TermServLicensing_v1_0_s_ifspec, // from rpcsvc.h
  1352. NULL,
  1353. TRUE
  1354. );
  1355. // tell service control manager we are stopping
  1356. ReportStatusToSCMgr(
  1357. SERVICE_STOP_PENDING,
  1358. NO_ERROR,
  1359. SERVICE_WAITHINT
  1360. );
  1361. // Remove entries from the endpoint mapper database.
  1362. dwStatus = RpcEpUnregister(
  1363. HydraLicenseService_v1_0_s_ifspec, // from rpcsvc.h
  1364. pbindingVector,
  1365. NULL
  1366. );
  1367. // tell service control manager we are stopping
  1368. ReportStatusToSCMgr(
  1369. SERVICE_STOP_PENDING,
  1370. NO_ERROR,
  1371. SERVICE_WAITHINT
  1372. );
  1373. // Remove entries from the endpoint mapper database.
  1374. dwStatus = RpcEpUnregister(
  1375. TermServLicensing_v1_0_s_ifspec, // from rpcsvc.h
  1376. pbindingVector,
  1377. NULL
  1378. );
  1379. // tell service control manager we are stopping
  1380. ReportStatusToSCMgr(
  1381. SERVICE_STOP_PENDING,
  1382. NO_ERROR,
  1383. SERVICE_WAITHINT
  1384. );
  1385. // Remove entries from the endpoint mapper database.
  1386. dwStatus = RpcEpUnregister(
  1387. TermServLicensingBackup_v1_0_s_ifspec, // from rpcsvc.h
  1388. pbindingVector,
  1389. NULL
  1390. );
  1391. // Get server binding handles
  1392. dwStatus = RpcServerInqBindings(
  1393. &pbindingVector
  1394. );
  1395. if(dwStatus == ERROR_SUCCESS)
  1396. {
  1397. dwStatus = RpcBindingVectorFree(
  1398. &pbindingVector
  1399. );
  1400. }
  1401. // Create entry name in name database first
  1402. // Only work for NT 5.0
  1403. // status = RpcNsMgmtEntryDelete(RPC_C_NS_SYNTAX_DEFAULT, pszEntryName);
  1404. // try to report the stopped status to the service control manager.
  1405. //
  1406. // Initialize Crypto.
  1407. } while(FALSE);
  1408. if(hInitThread != NULL)
  1409. {
  1410. CloseHandle(hInitThread);
  1411. }
  1412. if(hRpcThread != NULL)
  1413. {
  1414. CloseHandle(hRpcThread);
  1415. }
  1416. if(hMailslotThread != NULL)
  1417. {
  1418. CloseHandle(hMailslotThread);
  1419. }
  1420. if(hEvent != NULL)
  1421. {
  1422. CloseHandle(hEvent);
  1423. }
  1424. if(hRpcPause != NULL)
  1425. {
  1426. CloseHandle(hRpcPause);
  1427. }
  1428. if(err == 0)
  1429. {
  1430. WSACleanup();
  1431. }
  1432. ReportStatusToSCMgr(
  1433. SERVICE_STOP_PENDING,
  1434. dwStatus, //NO_ERROR,
  1435. SERVICE_WAITHINT
  1436. );
  1437. //
  1438. // Create another thread to shutdown server.
  1439. //
  1440. hShutdownThread=CreateThread(
  1441. NULL,
  1442. 0,
  1443. ServiceShutdownThread,
  1444. (VOID *)NULL,
  1445. 0,
  1446. &dump
  1447. );
  1448. if(hShutdownThread == NULL)
  1449. {
  1450. // Report the status to the service control manager with
  1451. // long wait hint time.
  1452. ReportStatusToSCMgr(
  1453. SERVICE_STOP_PENDING,
  1454. NO_ERROR,
  1455. SERVICE_SHUTDOWN_WAITTIME
  1456. );
  1457. //
  1458. // can't create thread, just call shutdown directory
  1459. //
  1460. ServerShutdown();
  1461. }
  1462. else
  1463. {
  1464. //
  1465. // report in 5 second interval to SC.
  1466. //
  1467. DWORD dwMaxWaitTime = SERVICE_SHUTDOWN_WAITTIME / 5000;
  1468. DWORD dwTimes=0;
  1469. //
  1470. // Wait for general server shutdown thread to terminate
  1471. // Gives max 1 mins to shutdown
  1472. //
  1473. while(WaitForSingleObject( hShutdownThread, SC_WAITHINT ) == WAIT_TIMEOUT &&
  1474. dwTimes++ < dwMaxWaitTime)
  1475. {
  1476. // Report the status to the service control manager.
  1477. ReportStatusToSCMgr(
  1478. SERVICE_STOP_PENDING,
  1479. NO_ERROR,
  1480. SERVICE_WAITHINT
  1481. );
  1482. }
  1483. CloseHandle(hShutdownThread);
  1484. }
  1485. cleanup:
  1486. if (NULL != g_pWriter)
  1487. {
  1488. g_pWriter->Uninitialize();
  1489. delete g_pWriter;
  1490. g_pWriter = NULL;
  1491. }
  1492. CoUninitialize( );
  1493. // Signal we are safe to shutting down
  1494. SetEvent(gSafeToTerminate);
  1495. return dwStatus;
  1496. }
  1497. //-----------------------------------------------------------------
  1498. VOID
  1499. ServiceStop()
  1500. /*++
  1501. ++*/
  1502. {
  1503. ReportStatusToSCMgr(
  1504. SERVICE_STOP_PENDING,
  1505. NO_ERROR,
  1506. 0
  1507. );
  1508. // Stop's the server, wakes the main thread.
  1509. SetEvent(hRpcPause);
  1510. //
  1511. // Signal currently waiting RPC call to terminate
  1512. //
  1513. ServiceSignalShutdown();
  1514. // this is the actual time we receive shutdown request.
  1515. SetServiceLastShutdownTime();
  1516. (VOID)RpcMgmtStopServerListening(NULL);
  1517. TLSLogInfoEvent(TLS_I_SERVICE_STOP);
  1518. }
  1519. //-----------------------------------------------------------------
  1520. VOID
  1521. ServicePause()
  1522. /*++
  1523. ++*/
  1524. {
  1525. ResetEvent(hRpcPause);
  1526. (VOID)RpcMgmtStopServerListening(NULL);
  1527. TLSLogInfoEvent(TLS_I_SERVICE_PAUSED);
  1528. }
  1529. //-----------------------------------------------------------------
  1530. VOID
  1531. ServiceContinue()
  1532. /*++
  1533. ++*/
  1534. {
  1535. SetEvent(hRpcPause);
  1536. TLSLogInfoEvent(TLS_I_SERVICE_CONTINUE);
  1537. }
  1538. //-----------------------------------------------------------------
  1539. BOOL
  1540. ReportStatusToSCMgr(
  1541. IN DWORD dwCurrentState,
  1542. IN DWORD dwExitCode,
  1543. IN DWORD dwWaitHint
  1544. )
  1545. /*++
  1546. Abstract:
  1547. Sets the current status of the service and reports it
  1548. to the Service Control Manager
  1549. Parameter:
  1550. dwCurrentState - the state of the service
  1551. dwWin32ExitCode - error code to report
  1552. dwWaitHint - worst case estimate to next checkpoint
  1553. Returns:
  1554. TRUE if success, FALSE otherwise
  1555. */
  1556. {
  1557. BOOL fResult=TRUE;
  1558. if(g_bReportToSCM == TRUE)
  1559. {
  1560. SERVICE_STATUS ssStatus;
  1561. static DWORD dwCheckPoint = 1;
  1562. ssStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
  1563. //
  1564. // global - current status of process
  1565. //
  1566. ssCurrentStatus = dwCurrentState;
  1567. if (dwCurrentState == SERVICE_START_PENDING)
  1568. {
  1569. ssStatus.dwControlsAccepted = 0;
  1570. }
  1571. else
  1572. {
  1573. ssStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PAUSE_CONTINUE | SERVICE_CONTROL_SHUTDOWN;
  1574. }
  1575. ssStatus.dwCurrentState = dwCurrentState;
  1576. if(dwExitCode != NO_ERROR)
  1577. {
  1578. ssStatus.dwWin32ExitCode = ERROR_SERVICE_SPECIFIC_ERROR;
  1579. ssStatus.dwServiceSpecificExitCode = dwExitCode;
  1580. }
  1581. else
  1582. {
  1583. ssStatus.dwWin32ExitCode = dwExitCode;
  1584. }
  1585. ssStatus.dwWaitHint = dwWaitHint;
  1586. if(dwCurrentState == SERVICE_RUNNING || dwCurrentState == SERVICE_STOPPED)
  1587. {
  1588. ssStatus.dwCheckPoint = 0;
  1589. }
  1590. else
  1591. {
  1592. ssStatus.dwCheckPoint = dwCheckPoint++;
  1593. }
  1594. // Report the status of the service to the service control manager.
  1595. //
  1596. fResult = SetServiceStatus(
  1597. sshStatusHandle,
  1598. &ssStatus
  1599. );
  1600. if(fResult == FALSE)
  1601. {
  1602. DBGPrintf(
  1603. DBG_INFORMATION,
  1604. DBG_FACILITY_INIT,
  1605. DBGLEVEL_FUNCTION_TRACE,
  1606. _TEXT("Failed to set service status %d...\n"),
  1607. GetLastError()
  1608. );
  1609. TLSLogErrorEvent(TLS_E_SC_REPORT_STATUS);
  1610. }
  1611. }
  1612. return fResult;
  1613. }
  1614. ///////////////////////////////////////////////////////////////////
  1615. //
  1616. // The following code is for running the service as a console app
  1617. //
  1618. void
  1619. CmdDebugService(
  1620. IN int argc,
  1621. IN char ** argv,
  1622. IN BOOL bDebug
  1623. )
  1624. /*
  1625. */
  1626. {
  1627. int dwArgc;
  1628. LPTSTR *lpszArgv;
  1629. #ifdef UNICODE
  1630. lpszArgv = CommandLineToArgvW(GetCommandLineW(), &(dwArgc) );
  1631. #else
  1632. dwArgc = (DWORD) argc;
  1633. lpszArgv = argv;
  1634. #endif
  1635. _tprintf(
  1636. _TEXT("Debugging %s.\n"),
  1637. _TEXT(SZSERVICEDISPLAYNAME)
  1638. );
  1639. SetConsoleCtrlHandler(
  1640. ControlHandler,
  1641. TRUE
  1642. );
  1643. ServiceStart(
  1644. dwArgc,
  1645. lpszArgv,
  1646. bDebug
  1647. );
  1648. }
  1649. //------------------------------------------------------------------
  1650. BOOL WINAPI
  1651. ControlHandler(
  1652. IN DWORD dwCtrlType
  1653. )
  1654. /*++
  1655. Abstract:
  1656. Parameter:
  1657. IN dwCtrlType : control type
  1658. Return:
  1659. ++*/
  1660. {
  1661. switch( dwCtrlType )
  1662. {
  1663. case CTRL_BREAK_EVENT: // use Ctrl+C or Ctrl+Break to simulate
  1664. case CTRL_C_EVENT: // SERVICE_CONTROL_STOP in debug mode
  1665. _tprintf(
  1666. _TEXT("Stopping %s.\n"),
  1667. _TEXT(SZSERVICEDISPLAYNAME)
  1668. );
  1669. ssCurrentStatus = SERVICE_STOP_PENDING;
  1670. ServiceStop();
  1671. return TRUE;
  1672. break;
  1673. }
  1674. return FALSE;
  1675. }