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.

237 lines
7.0 KiB

  1. /*---------------------------------------------------------------------------
  2. THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
  3. ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED
  4. TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
  5. PARTICULAR PURPOSE.
  6. Copyright (C) 1993-2001. Microsoft Corporation. All rights reserved.
  7. MODULE: service.c
  8. PURPOSE: Implements functions required by all Windows NT services
  9. FUNCTIONS:
  10. DllMain(PVOID hModule, ULONG Reason, PCONTEXT pContext)
  11. ServiceCtrl(DWORD dwCtrlCode, DWORD dwEventType, LPVOID lpEventData, LPVOID lpContext);
  12. ServiceMain(DWORD dwArgc, LPTSTR *lpszArgv);
  13. ---------------------------------------------------------------------------*/
  14. #include <windows.h>
  15. #include <shellapi.h>
  16. #include <stdio.h>
  17. #include <stdlib.h>
  18. #include <process.h>
  19. #include <tchar.h>
  20. #include "debug.h"
  21. #include "service.h"
  22. // internal variables
  23. SERVICE_STATUS ssStatus; // current status of the service
  24. SERVICE_STATUS_HANDLE sshStatusHandle;
  25. DWORD dwErr = 0;
  26. // internal function prototypes
  27. DWORD WINAPI ServiceCtrl(DWORD dwCtrlCode, DWORD dwEventType, LPVOID lpEventData, LPVOID lpContext);
  28. VOID WINAPI ServiceMain(DWORD dwArgc, LPTSTR *lpszArgv);
  29. //
  30. // FUNCTION: ServiceMain
  31. //
  32. // PURPOSE: To perform actual initialization of the service
  33. //
  34. // PARAMETERS:
  35. // dwArgc - number of command line arguments
  36. // lpszArgv - array of command line arguments
  37. //
  38. // RETURN VALUE:
  39. // none
  40. //
  41. // COMMENTS:
  42. // This routine performs the service initialization and then calls
  43. // the user defined ServiceStart() routine to perform majority
  44. // of the work.
  45. //
  46. void WINAPI ServiceMain(DWORD dwArgc, LPTSTR *lpszArgv)
  47. {
  48. dprintf(TEXT("pid=%d\n"), GetCurrentProcessId());
  49. // register our service control handler:
  50. //
  51. sshStatusHandle = RegisterServiceCtrlHandlerEx(TEXT(SZSERVICENAME), ServiceCtrl, NULL);
  52. if (sshStatusHandle)
  53. {
  54. // SERVICE_STATUS members that don't change
  55. //
  56. ssStatus.dwServiceType = SERVICE_WIN32_SHARE_PROCESS;
  57. ssStatus.dwServiceSpecificExitCode = 0;
  58. // report the status to the service control manager.
  59. // ISSUE-2000/10/17-FrankYe reduce the wait hint
  60. if (ReportStatusToSCMgr(SERVICE_START_PENDING, // service state
  61. NO_ERROR, // exit code
  62. 60000)) // wait hint
  63. {
  64. ServiceStart( sshStatusHandle, dwArgc, lpszArgv );
  65. }
  66. }
  67. return;
  68. }
  69. //
  70. // FUNCTION: ServiceCtrl
  71. //
  72. // PURPOSE: This function is called by the SCM whenever
  73. // ControlService() is called on this service.
  74. //
  75. // PARAMETERS:
  76. // dwCtrlCode - The requested control code.
  77. // dwEventType - The type of event that has occurred.
  78. // lpEventData - Additional device information, if required. The
  79. // format of this data depends on the value of the dwControl
  80. // and dwEventType parameters.
  81. // lpContext - The user-defined data passed from
  82. // RegisterServiceCtrlHandlerEx.
  83. //
  84. // RETURN VALUE:
  85. // The return value for this function depends on the control code received.
  86. //
  87. // COMMENTS:
  88. //
  89. DWORD WINAPI ServiceCtrl(DWORD dwCtrlCode, DWORD dwEventType, LPVOID lpEventData, LPVOID lpContext)
  90. {
  91. // Handle the requested control code.
  92. //
  93. switch (dwCtrlCode)
  94. {
  95. // Stop the service.
  96. //
  97. // SERVICE_STOP_PENDING should be reported before
  98. // setting the Stop Event - hServerStopEvent - in
  99. // ServiceStop(). This avoids a race condition
  100. // which may result in a 1053 - The Service did not respond...
  101. // error.
  102. case SERVICE_CONTROL_STOP:
  103. ReportStatusToSCMgr(SERVICE_STOP_PENDING, NO_ERROR, 0);
  104. ServiceStop();
  105. return NO_ERROR;
  106. case SERVICE_CONTROL_DEVICEEVENT:
  107. return ServiceDeviceEvent(dwEventType, lpEventData);
  108. case SERVICE_CONTROL_INTERROGATE:
  109. ReportStatusToSCMgr(ssStatus.dwCurrentState, NO_ERROR, 0);
  110. return NO_ERROR;
  111. case SERVICE_CONTROL_SESSIONCHANGE:
  112. return ServiceSessionChange(dwEventType, lpEventData);
  113. // invalid control code
  114. default:
  115. return ERROR_CALL_NOT_IMPLEMENTED;
  116. }
  117. return ERROR_CALL_NOT_IMPLEMENTED;
  118. }
  119. //
  120. // FUNCTION: AddToMessageLog(LPTSTR lpszMsg)
  121. //
  122. // PURPOSE: Allows any thread to log an error message
  123. //
  124. // PARAMETERS:
  125. // lpszMsg - text for message
  126. //
  127. // RETURN VALUE:
  128. // none
  129. //
  130. // COMMENTS:
  131. //
  132. VOID AddToMessageLog(LPTSTR lpszMsg)
  133. {
  134. TCHAR szMsg[256];
  135. HANDLE hEventSource;
  136. LPTSTR lpszStrings[2];
  137. dwErr = GetLastError();
  138. // Use event logging to log the error.
  139. //
  140. hEventSource = RegisterEventSource(NULL, TEXT(SZSERVICENAME));
  141. wsprintf(szMsg, TEXT("%s error: %d"), TEXT(SZSERVICENAME), dwErr);
  142. lpszStrings[0] = szMsg;
  143. lpszStrings[1] = lpszMsg;
  144. if (hEventSource != NULL)
  145. {
  146. ReportEvent(hEventSource, // handle of event source
  147. EVENTLOG_ERROR_TYPE, // event type
  148. 0, // event category
  149. 0, // event ID
  150. NULL, // current user's SID
  151. 2, // strings in lpszStrings
  152. 0, // no bytes of raw data
  153. lpszStrings, // array of error strings
  154. NULL); // no raw data
  155. (VOID) DeregisterEventSource(hEventSource);
  156. }
  157. }
  158. //
  159. // FUNCTION: ReportStatusToSCMgr()
  160. //
  161. // PURPOSE: Sets the current status of the service and
  162. // reports it to the Service Control Manager
  163. //
  164. // PARAMETERS:
  165. // dwCurrentState - the state of the service
  166. // dwWin32ExitCode - error code to report
  167. // dwWaitHint - worst case estimate to next checkpoint
  168. //
  169. // RETURN VALUE:
  170. // TRUE - success
  171. // FALSE - failure
  172. //
  173. // COMMENTS:
  174. //
  175. BOOL ReportStatusToSCMgr(DWORD dwCurrentState,
  176. DWORD dwWin32ExitCode,
  177. DWORD dwWaitHint)
  178. {
  179. static DWORD dwCheckPoint = 1;
  180. BOOL fResult = TRUE;
  181. // Accept only session notifications (no pause, stop, etc)
  182. ssStatus.dwControlsAccepted = SERVICE_ACCEPT_SESSIONCHANGE;
  183. ssStatus.dwCurrentState = dwCurrentState;
  184. ssStatus.dwWin32ExitCode = dwWin32ExitCode;
  185. ssStatus.dwWaitHint = dwWaitHint;
  186. if ( ( dwCurrentState == SERVICE_RUNNING ) ||
  187. ( dwCurrentState == SERVICE_STOPPED ) )
  188. ssStatus.dwCheckPoint = 0;
  189. else
  190. ssStatus.dwCheckPoint = dwCheckPoint++;
  191. // Report the status of the service to the service control manager.
  192. //
  193. if (!(fResult = SetServiceStatus( sshStatusHandle, &ssStatus)))
  194. {
  195. AddToMessageLog(TEXT("SetServiceStatus"));
  196. }
  197. return fResult;
  198. }