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.

248 lines
5.8 KiB

  1. /* Copyright 1999 American Power Conversion, All Rights Reserved
  2. *
  3. * Description:
  4. * The file implements the main portion of the native NT UPS
  5. * service for Windows 2000. It implements all of the functions
  6. * required by all Windows NT services.
  7. *
  8. * Revision History:
  9. * sberard 25Mar1999 initial revision.
  10. *
  11. */
  12. #include <windows.h>
  13. #include <stdio.h>
  14. #include <stdlib.h>
  15. #include <process.h>
  16. #include <tchar.h>
  17. #include "service.h"
  18. #include "polmgr.h"
  19. #include "shutdown.h"
  20. #include "notifier.h"
  21. #include "eventlog.h"
  22. #include "cmdexe.h"
  23. #include "upsmsg.h"
  24. #ifdef __cplusplus
  25. extern "C" {
  26. #endif
  27. // global variables
  28. SERVICE_STATUS _theServiceStatus;
  29. SERVICE_STATUS_HANDLE _theServiceStatusHandle;
  30. // Internal function prototypes
  31. VOID ServiceMain(DWORD anArgCount, LPTSTR *anArgList);
  32. static VOID WINAPI ServiceControl(DWORD aControlCode);
  33. static BOOL ConsoleHandler (DWORD aControlType);
  34. static BOOL ServiceInit();
  35. static BOOL SetServiceState(DWORD aNewState);
  36. /**
  37. * main
  38. *
  39. * Description:
  40. * This is the entrypoint for the service. StartServiceCtrlDispatcher
  41. * is called to register the main service thread. If this call returns
  42. * the service has been stopped.
  43. *
  44. * Parameters:
  45. * argc - number of command line arguments
  46. * argv - array of command line arguments
  47. *
  48. * Returns:
  49. * void
  50. */
  51. void __cdecl main(int argc, char **argv) {
  52. // Initialize the service table
  53. SERVICE_TABLE_ENTRY dispatch_table[] = {
  54. { SZSERVICENAME, ServiceMain},
  55. { NULL, NULL}
  56. };
  57. if (!StartServiceCtrlDispatcher(dispatch_table)) {
  58. LogEvent(NERR_UPSInvalidConfig, NULL, GetLastError());
  59. }
  60. ExitProcess(0);
  61. }
  62. /**
  63. * ServiceMain
  64. *
  65. * Description:
  66. * Implements the core functionality of the service.
  67. *
  68. * Returns:
  69. * VOID
  70. */
  71. VOID ServiceMain(DWORD anArgCount, LPTSTR *anArgList) {
  72. // Initialize service parameters
  73. if (ServiceInit()) {
  74. // Update the service state
  75. SetServiceState(SERVICE_RUNNING);
  76. PolicyManagerRun();
  77. }
  78. // Tell the SCM that the service is stopped
  79. if (_theServiceStatusHandle) {
  80. // TBD
  81. }
  82. // Do any termination stuff
  83. // Tell the SCM that we are stopped
  84. SetServiceState(SERVICE_STOPPED);
  85. }
  86. /**
  87. * ServiceControl
  88. *
  89. * Description:
  90. * This function is called by the SCM whenever ControlService() is called.
  91. * It is responsible for communicating service control requests to the service.
  92. *
  93. * Parameters:
  94. * aControlCode - type of control requested
  95. *
  96. * Returns:
  97. * VOID
  98. */
  99. static VOID WINAPI ServiceControl(DWORD aControlCode) {
  100. // Handle the requested control code.
  101. //
  102. switch (aControlCode) {
  103. // Requests the service to stop.
  104. case SERVICE_CONTROL_STOP:
  105. // Requests the service to perform cleanup tasks, due to shutdown
  106. case SERVICE_CONTROL_SHUTDOWN:
  107. // Tell the SCM that we are stopping
  108. SetServiceState(SERVICE_STOP_PENDING);
  109. // Call stop on the policy manager
  110. PolicyManagerStop();
  111. break;
  112. // Requests the service to pause.
  113. case SERVICE_CONTROL_PAUSE:
  114. break;
  115. // Requests the paused service to resume.
  116. case SERVICE_CONTROL_CONTINUE:
  117. break;
  118. // Requests the service to update immediately
  119. // its current status information to the service control manager.
  120. case SERVICE_CONTROL_INTERROGATE:
  121. break;
  122. // Invalid control code
  123. default:
  124. // Ignore the request
  125. break;
  126. }
  127. }
  128. /**
  129. * ServiceInit
  130. *
  131. * Description:
  132. * This function is responsible the service with the SCM.
  133. *
  134. * Parameters:
  135. * none
  136. *
  137. * Returns:
  138. * TRUE - if there are no errors in initialization
  139. * FALSE - if errors occur during initialization
  140. */
  141. static BOOL ServiceInit() {
  142. BOOL ret_val = TRUE;
  143. DWORD result;
  144. // Register a service control handler with the SCM
  145. _theServiceStatusHandle = RegisterServiceCtrlHandler( SZSERVICENAME, ServiceControl);
  146. if (_theServiceStatusHandle) {
  147. _theServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
  148. _theServiceStatus.dwCurrentState = SERVICE_START_PENDING;
  149. _theServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP |
  150. // sberard - Removed. Pause/Continue is not supported
  151. // SERVICE_ACCEPT_PAUSE_CONTINUE |
  152. SERVICE_ACCEPT_SHUTDOWN;
  153. _theServiceStatus.dwCheckPoint = 1; // This service only has 1 initialization step
  154. _theServiceStatus.dwWaitHint = UPS_SERVICE_WAIT_TIME;
  155. _theServiceStatus.dwWin32ExitCode = NO_ERROR;
  156. _theServiceStatus.dwServiceSpecificExitCode = 0; // ignored
  157. // Update SCM with the service's current status
  158. if (!SetServiceStatus(_theServiceStatusHandle, &_theServiceStatus)) {
  159. // TBD, report error?
  160. ret_val = FALSE;
  161. }
  162. // Initialize the UPS policy manager
  163. result = PolicyManagerInit();
  164. if (result != ERROR_SUCCESS) {
  165. // An error occured, set the service error code and update the SCM
  166. _theServiceStatus.dwWin32ExitCode = result;
  167. SetServiceStatus(_theServiceStatusHandle, &_theServiceStatus);
  168. ret_val = FALSE;
  169. }
  170. }
  171. else {
  172. ret_val = FALSE;
  173. }
  174. return ret_val;
  175. }
  176. /**
  177. * SetServiceState
  178. *
  179. * Description:
  180. * This function is responsible the updating the SCM with the current service state.
  181. *
  182. * Parameters:
  183. * aNewState - the state to update the SCM with
  184. *
  185. * Returns:
  186. * TRUE - if the update was successfull
  187. * FALSE - if the service set was not able to be updated
  188. */
  189. static BOOL SetServiceState(DWORD aNewState) {
  190. BOOL ret_val = TRUE;
  191. if (_theServiceStatusHandle) {
  192. _theServiceStatus.dwCurrentState = aNewState;
  193. // Update SCM with the service's current status
  194. if (!SetServiceStatus(_theServiceStatusHandle, &_theServiceStatus)) {
  195. // TBD, report error?
  196. ret_val = FALSE;
  197. }
  198. }
  199. else {
  200. ret_val = FALSE;
  201. }
  202. return ret_val;
  203. }
  204. #ifdef __cplusplus
  205. }
  206. #endif