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.

220 lines
4.5 KiB

  1. /*
  2. * Service.c
  3. *
  4. *
  5. * Service control interface to sumserve
  6. *
  7. * Geraint Davies, July 93
  8. */
  9. #include <windows.h>
  10. #include <sumserve.h> // public header for sumserve
  11. #include "errlog.h"
  12. #include <server.h> // private header for sumserve
  13. /*
  14. * this is the function (in some other module) that actually
  15. * does all the work (probably used to be main or WinMain until
  16. * we added all the service-control stuff in this file).
  17. */
  18. extern VOID MainLoop(DWORD dwArgc, LPTSTR *lpszArgv);
  19. // service status handle - used in SetServiceStatus calls.
  20. SERVICE_STATUS_HANDLE sshSumserve;
  21. //signaled when service completed
  22. HANDLE hServiceDoneEvent;
  23. SERVICE_STATUS gssStatus;
  24. /* structure to pass more than one parameter to the worker thread. */
  25. typedef struct _threadinitparams {
  26. DWORD dwArgc;
  27. LPTSTR *lpszArgv;
  28. } threadinitparams, * pthreadinitparams;
  29. /*
  30. * MainLoopCaller
  31. *
  32. * This function is called on the worker thread created to do all the
  33. * real work. It calls the main loop function for the service, and
  34. * when that exits, signals the completion event to tell the
  35. * SS_Main thread that it is time to exit the process.
  36. */
  37. DWORD
  38. MainLoopCaller(LPVOID lpgeneric)
  39. {
  40. pthreadinitparams pta;
  41. pta = (pthreadinitparams) lpgeneric;
  42. dprintf1(("calling main loop"));
  43. MainLoop(pta->dwArgc, pta->lpszArgv);
  44. SetEvent(hServiceDoneEvent);
  45. return(0);
  46. }
  47. /*
  48. * handler function called to perform start/stop
  49. * requests.
  50. */
  51. VOID
  52. SS_ServiceHandler(DWORD dwCtrlCode)
  53. {
  54. switch(dwCtrlCode) {
  55. case SERVICE_CONTROL_STOP:
  56. gssStatus.dwCurrentState = SERVICE_STOP_PENDING;
  57. gssStatus.dwControlsAccepted = 0;
  58. gssStatus.dwCheckPoint = 1;
  59. gssStatus.dwWaitHint = 3000;
  60. SetServiceStatus(sshSumserve, &gssStatus);
  61. SetEvent(hServiceDoneEvent);
  62. break;
  63. default:
  64. /*
  65. * we must always update the service status every time we are
  66. * called.
  67. */
  68. SetServiceStatus(sshSumserve, &gssStatus);
  69. break;
  70. }
  71. }
  72. /*
  73. * service main function - called by service controller
  74. * during StartServiceCtlDispatcher processing.
  75. *
  76. * Register our handler function, and initialise the service.
  77. * create a thread to do the work, and then wait for someone to
  78. * signal time to end. When this function exits, the call to
  79. * StartServiceCtlDispatcher will return, and the process will exit
  80. *
  81. * The args are passed from the program that called start service, and
  82. * are parameters that are passed to the main loop of the program.
  83. */
  84. VOID
  85. SS_Main(DWORD dwArgc, LPTSTR *lpszArgv)
  86. {
  87. threadinitparams ta;
  88. HANDLE thread;
  89. DWORD threadid;
  90. dprintf1(("in ss_main"));
  91. sshSumserve = RegisterServiceCtrlHandler(
  92. TEXT("SumServe"),
  93. (LPHANDLER_FUNCTION) SS_ServiceHandler);
  94. gssStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
  95. gssStatus.dwServiceSpecificExitCode = 0;
  96. gssStatus.dwCurrentState = SERVICE_START_PENDING;
  97. gssStatus.dwControlsAccepted = 0;
  98. gssStatus.dwWin32ExitCode = NO_ERROR;
  99. gssStatus.dwCheckPoint = 1;
  100. gssStatus.dwWaitHint = 3000;
  101. SetServiceStatus(sshSumserve, &gssStatus);
  102. hServiceDoneEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
  103. gssStatus.dwCheckPoint = 2;
  104. SetServiceStatus(sshSumserve, &gssStatus);
  105. // create a thread to do all the real work
  106. // init args
  107. ta.dwArgc = dwArgc;
  108. ta.lpszArgv = lpszArgv;
  109. thread = CreateThread(
  110. NULL,
  111. 0,
  112. (LPTHREAD_START_ROUTINE) MainLoopCaller,
  113. (LPVOID)&ta,
  114. 0,
  115. &threadid);
  116. if (thread != NULL) {
  117. CloseHandle(thread);
  118. gssStatus.dwCurrentState = SERVICE_RUNNING;
  119. gssStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
  120. gssStatus.dwCheckPoint = 0;
  121. gssStatus.dwWaitHint = 0;
  122. SetServiceStatus(sshSumserve, &gssStatus);
  123. WaitForSingleObject(hServiceDoneEvent, INFINITE);
  124. }
  125. CloseHandle(hServiceDoneEvent);
  126. gssStatus.dwCurrentState = SERVICE_STOPPED;
  127. gssStatus.dwControlsAccepted = 0;
  128. SetServiceStatus(sshSumserve, &gssStatus);
  129. }
  130. /*
  131. * main entry point.
  132. *
  133. * for a service, we need to call the service manager telling it our
  134. * main init function. It will then do everything. When the service
  135. * manager returns, it's time to exit.
  136. */
  137. int WINAPI
  138. WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdParam,
  139. int nCmdShow)
  140. {
  141. SERVICE_TABLE_ENTRY steDispatch[] = {
  142. { TEXT("SumServe"), (LPSERVICE_MAIN_FUNCTION) SS_Main },
  143. //end of table marker
  144. { NULL, NULL }
  145. };
  146. dprintf1(("in winmain"));
  147. StartServiceCtrlDispatcher(steDispatch);
  148. return(0);
  149. }