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.

295 lines
7.8 KiB

  1. //#pragma title( "TService.cpp - SCM interface for MCS service" )
  2. /*
  3. Copyright (c) 1995-1998, Mission Critical Software, Inc. All rights reserved.
  4. ===============================================================================
  5. Module - TService.cpp
  6. System - Common
  7. Author - Rich Denham
  8. Created - 1997-08-17
  9. Description - Service Control Manager interface for MCS service
  10. Updates -
  11. ===============================================================================
  12. */
  13. #include <windows.h>
  14. #include <stdio.h>
  15. #include "TService.hpp"
  16. ///////////////////////////////////////////////////////////////////////////////
  17. // Private data declarations
  18. ///////////////////////////////////////////////////////////////////////////////
  19. #define WAIT_HINT_SECONDS (10)
  20. #define WAIT_HINT_MILLISECONDS (WAIT_HINT_SECONDS*1000)
  21. static
  22. TCHAR * gNameService;
  23. static
  24. SERVICE_STATUS gServiceStatus;
  25. static
  26. SERVICE_STATUS_HANDLE ghServiceStatus;
  27. static
  28. HANDLE ghServDoneEvent=INVALID_HANDLE_VALUE;
  29. static
  30. DWORD gArgc;
  31. static
  32. TCHAR ** gArgv;
  33. static
  34. TScmEpRc grcScmEp=TScmEpRc_Unknown; // TScmEp return code
  35. ///////////////////////////////////////////////////////////////////////////////
  36. // Private function prototypes
  37. ///////////////////////////////////////////////////////////////////////////////
  38. static
  39. void
  40. TScmServiceMain(
  41. DWORD argc ,// in -number of arguments
  42. TCHAR ** argv // in -string argument array
  43. );
  44. static
  45. void
  46. TScmServiceCtrl(
  47. DWORD dwCtrlCode
  48. );
  49. static
  50. DWORD WINAPI // ret-OS return code
  51. TScmServiceWorker(
  52. void * notUsed // i/o-not used
  53. );
  54. static
  55. BOOL // ret-TRUE if successful
  56. TScmReportStatusToSCMgr(
  57. DWORD dwCurrentState,
  58. DWORD dwWin32ExitCode,
  59. DWORD dwCheckPoint,
  60. DWORD dwWaitHint
  61. );
  62. ///////////////////////////////////////////////////////////////////////////////
  63. // Entry point from caller's 'main' function
  64. ///////////////////////////////////////////////////////////////////////////////
  65. TScmEpRc // TScmEp return code
  66. TScmEp(
  67. int argc ,// in -argument count
  68. char const ** argv ,// in -argument array
  69. TCHAR * nameService // in -name of service
  70. )
  71. {
  72. int argn; // argument number
  73. SERVICE_TABLE_ENTRY dispatchTable[] =
  74. {
  75. { nameService, (LPSERVICE_MAIN_FUNCTION) TScmServiceMain },
  76. { NULL, NULL }
  77. };
  78. gNameService = nameService;
  79. grcScmEp = TScmEpRc_Unknown;
  80. for ( argn = 1;
  81. argn < argc;
  82. argn++ )
  83. {
  84. if ( !UScmCmdLineArgs( argv[argn] ) )
  85. {
  86. grcScmEp = TScmEpRc_InvArgCli;
  87. }
  88. }
  89. if ( grcScmEp == TScmEpRc_Unknown )
  90. {
  91. if ( UScmForceCli() || !StartServiceCtrlDispatcher( dispatchTable ) )
  92. {
  93. // UScmEp( FALSE );
  94. UScmEp();
  95. grcScmEp = TScmEpRc_OkCli;
  96. }
  97. else
  98. {
  99. grcScmEp = TScmEpRc_OkSrv;
  100. }
  101. }
  102. return grcScmEp;
  103. }
  104. ///////////////////////////////////////////////////////////////////////////////
  105. // Mainline for service
  106. ///////////////////////////////////////////////////////////////////////////////
  107. static
  108. void
  109. TScmServiceMain(
  110. DWORD argc ,// in -number of arguments
  111. TCHAR ** argv // in -string argument array
  112. )
  113. {
  114. DWORD dwWait;
  115. DWORD idThread;
  116. HANDLE hThread=INVALID_HANDLE_VALUE;
  117. gArgc = argc;
  118. gArgv = argv;
  119. do // once or until break
  120. {
  121. ghServiceStatus = RegisterServiceCtrlHandler(
  122. gNameService,
  123. (LPHANDLER_FUNCTION) TScmServiceCtrl );
  124. if ( !ghServiceStatus )
  125. {
  126. break;
  127. }
  128. gServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
  129. gServiceStatus.dwServiceSpecificExitCode = 0;
  130. if ( !TScmReportStatusToSCMgr( SERVICE_START_PENDING, NO_ERROR, 1,
  131. WAIT_HINT_MILLISECONDS ) )
  132. {
  133. break;
  134. }
  135. ghServDoneEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
  136. if ( ghServDoneEvent == INVALID_HANDLE_VALUE )
  137. {
  138. break;
  139. }
  140. if ( !TScmReportStatusToSCMgr( SERVICE_START_PENDING, NO_ERROR, 2,
  141. WAIT_HINT_MILLISECONDS ) )
  142. {
  143. break;
  144. }
  145. hThread = CreateThread( NULL, 0, TScmServiceWorker, NULL, 0, &idThread );
  146. if ( hThread == INVALID_HANDLE_VALUE )
  147. {
  148. break;
  149. }
  150. if ( !TScmReportStatusToSCMgr( SERVICE_RUNNING, NO_ERROR, 0, 0 ) )
  151. {
  152. break;
  153. }
  154. dwWait = WaitForSingleObject( ghServDoneEvent, INFINITE );
  155. } while ( FALSE );
  156. if ( hThread != INVALID_HANDLE_VALUE )
  157. {
  158. CloseHandle( hThread );
  159. hThread = INVALID_HANDLE_VALUE;
  160. }
  161. if ( ghServDoneEvent != INVALID_HANDLE_VALUE )
  162. {
  163. CloseHandle( ghServDoneEvent );
  164. ghServDoneEvent = INVALID_HANDLE_VALUE;
  165. }
  166. if ( ghServiceStatus )
  167. {
  168. TScmReportStatusToSCMgr( SERVICE_STOPPED, 0, 0, 0 );
  169. }
  170. }
  171. ///////////////////////////////////////////////////////////////////////////////
  172. // Service control handler
  173. ///////////////////////////////////////////////////////////////////////////////
  174. static
  175. void
  176. TScmServiceCtrl(
  177. DWORD dwCtrlCode
  178. )
  179. {
  180. DWORD dwState = SERVICE_RUNNING;
  181. switch ( dwCtrlCode )
  182. {
  183. case SERVICE_CONTROL_STOP:
  184. case SERVICE_CONTROL_SHUTDOWN:
  185. dwState = SERVICE_STOP_PENDING;
  186. TScmReportStatusToSCMgr( SERVICE_STOP_PENDING, NO_ERROR, 1,
  187. WAIT_HINT_MILLISECONDS );
  188. SetEvent( ghServDoneEvent );
  189. return;
  190. case SERVICE_CONTROL_INTERROGATE:
  191. break;
  192. default:
  193. break;
  194. }
  195. TScmReportStatusToSCMgr( dwState, NO_ERROR, 0, 0 );
  196. }
  197. ///////////////////////////////////////////////////////////////////////////////
  198. // Service worker thread
  199. ///////////////////////////////////////////////////////////////////////////////
  200. static
  201. DWORD WINAPI // ret-OS return code
  202. TScmServiceWorker(
  203. void * notUsed // i/o-not used
  204. )
  205. {
  206. for ( DWORD i = 1;
  207. i < gArgc;
  208. i++ )
  209. {
  210. if ( !UScmCmdLineArgs( gArgv[i] ) )
  211. {
  212. grcScmEp = TScmEpRc_InvArgSrv;
  213. }
  214. }
  215. if ( grcScmEp != TScmEpRc_InvArgSrv )
  216. {
  217. // UScmEp( TRUE );
  218. UScmEp();
  219. }
  220. SetEvent( ghServDoneEvent );
  221. return 0;
  222. }
  223. ///////////////////////////////////////////////////////////////////////////////
  224. // Report status to Service Control Manager
  225. ///////////////////////////////////////////////////////////////////////////////
  226. static
  227. BOOL // ret-TRUE if successful
  228. TScmReportStatusToSCMgr(
  229. DWORD dwCurrentState,
  230. DWORD dwWin32ExitCode,
  231. DWORD dwCheckPoint,
  232. DWORD dwWaitHint
  233. )
  234. {
  235. BOOL bRc; // boolean return code
  236. if ( dwCurrentState == SERVICE_START_PENDING )
  237. {
  238. gServiceStatus.dwControlsAccepted = 0;
  239. }
  240. else
  241. {
  242. gServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
  243. }
  244. gServiceStatus.dwCurrentState = dwCurrentState;
  245. gServiceStatus.dwWin32ExitCode = dwWin32ExitCode;
  246. gServiceStatus.dwCheckPoint = dwCheckPoint;
  247. gServiceStatus.dwWaitHint = dwWaitHint;
  248. bRc = SetServiceStatus( ghServiceStatus, &gServiceStatus );
  249. if ( !bRc )
  250. {
  251. SetEvent( ghServDoneEvent );
  252. }
  253. return bRc;
  254. }
  255. // TService.cpp - end of file