1 //%/////////////////////////////////////////////////////////////////////////////
\r
3 // Copyright (c) 2000, 2001 The Open group, BMC Software, Tivoli Systems, IBM
\r
5 // Permission is hereby granted, free of charge, to any person obtaining a copy
\r
6 // of this software and associated documentation files (the "Software"), to
\r
7 // deal in the Software without restriction, including without limitation the
\r
8 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
\r
9 // sell copies of the Software, and to permit persons to whom the Software is
\r
10 // furnished to do so, subject to the following conditions:
\r
12 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
\r
13 // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
\r
14 // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
\r
15 // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
\r
16 // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
\r
17 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
\r
18 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
\r
19 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\r
21 //==============================================================================
\r
23 // Author: Mike Brasher (mbrasher@bmc.com)
\r
27 //%/////////////////////////////////////////////////////////////////////////////
\r
29 #include <windows.h>
\r
34 #include "Service.h"
\r
36 PEGASUS_NAMESPACE_BEGIN
\r
38 using namespace std;
\r
46 static const char* _serviceName = "";
\r
47 static HANDLE _terminateEvent = NULL;
\r
48 static SERVICE_STATUS_HANDLE _serviceStatusHandle = NULL;
\r
49 static HANDLE _threadHandle = 0;
\r
50 static BOOL _serviceRunning = FALSE;
\r
51 static BOOL _servicePaused = FALSE;
\r
52 static SERVICE_TABLE_ENTRY _serviceTable[2];
\r
53 static ServiceHandler* _serviceHandler = 0;
\r
54 static ClientData _clientData;
\r
56 static void _stopService()
\r
58 _serviceRunning = FALSE;
\r
59 SetEvent(_terminateEvent);
\r
62 static BOOL _sendStatusToSCM(
\r
63 DWORD dwCurrentState,
\r
64 DWORD dwWin32ExitCode,
\r
65 DWORD dwServiceSpecificExitCode,
\r
69 SERVICE_STATUS serviceStatus;
\r
71 serviceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
\r
72 serviceStatus.dwCurrentState = dwCurrentState;
\r
74 if (dwCurrentState == SERVICE_START_PENDING)
\r
75 serviceStatus.dwControlsAccepted = 0;
\r
78 serviceStatus.dwControlsAccepted =
\r
79 SERVICE_ACCEPT_STOP |
\r
80 SERVICE_ACCEPT_PAUSE_CONTINUE |
\r
81 SERVICE_ACCEPT_SHUTDOWN;
\r
84 if (dwServiceSpecificExitCode == 0)
\r
85 serviceStatus.dwWin32ExitCode = dwWin32ExitCode;
\r
87 serviceStatus.dwWin32ExitCode = ERROR_SERVICE_SPECIFIC_ERROR;
\r
89 serviceStatus.dwServiceSpecificExitCode = dwServiceSpecificExitCode;
\r
90 serviceStatus.dwCheckPoint = dwCheckPoint;
\r
91 serviceStatus.dwWaitHint = dwWaitHint;
\r
93 BOOL success = SetServiceStatus(_serviceStatusHandle, &serviceStatus);
\r
101 static void _resumeService()
\r
103 _servicePaused = FALSE;
\r
104 ResumeThread(_threadHandle);
\r
107 static void _pauseService()
\r
109 _servicePaused = TRUE;
\r
110 SuspendThread(_threadHandle);
\r
113 static void _terminate(DWORD error)
\r
115 if (_terminateEvent)
\r
116 CloseHandle(_terminateEvent);
\r
118 if (_serviceStatusHandle)
\r
119 _sendStatusToSCM(SERVICE_STOPPED, error, 0, 0, 0);
\r
122 CloseHandle(_threadHandle);
\r
125 static DWORD _serviceThread(LPDWORD param)
\r
127 ClientData* clientData = (ClientData*)param;
\r
128 int status = _serviceHandler->main(clientData->argc, clientData->argv);
\r
132 static void _serviceCtrlHandler(DWORD controlCode)
\r
134 DWORD currentState = 0;
\r
136 switch(controlCode)
\r
138 case SERVICE_CONTROL_STOP:
\r
140 SERVICE_STOP_PENDING;
\r
141 _sendStatusToSCM( SERVICE_STOP_PENDING, NO_ERROR, 0, 1, 5000);
\r
143 _serviceHandler->stop();
\r
147 case SERVICE_CONTROL_PAUSE:
\r
149 if (_serviceRunning && !_servicePaused)
\r
151 _sendStatusToSCM(SERVICE_PAUSE_PENDING, NO_ERROR, 0, 1, 1000);
\r
153 currentState = SERVICE_PAUSED;
\r
154 _serviceHandler->pause();
\r
159 case SERVICE_CONTROL_CONTINUE:
\r
161 if (_serviceRunning && _servicePaused)
\r
164 SERVICE_CONTINUE_PENDING, NO_ERROR, 0, 1, 1000);
\r
166 currentState = SERVICE_RUNNING;
\r
167 _serviceHandler->resume();
\r
172 case SERVICE_CONTROL_INTERROGATE:
\r
173 case SERVICE_CONTROL_SHUTDOWN:
\r
178 _sendStatusToSCM(currentState, NO_ERROR, 0, 0, 0);
\r
181 static void _serviceMain(DWORD argc, LPTSTR *argv)
\r
183 // Register the service control handler:
\r
185 _serviceStatusHandle = RegisterServiceCtrlHandler(
\r
186 _serviceName, (LPHANDLER_FUNCTION)_serviceCtrlHandler);
\r
188 if (!_serviceStatusHandle)
\r
190 _terminate(GetLastError());
\r
194 if (!_sendStatusToSCM(SERVICE_START_PENDING, NO_ERROR, 0, 1, 5000))
\r
196 _terminate(GetLastError());
\r
200 if (!(_terminateEvent = CreateEvent (0, TRUE, FALSE, 0)))
\r
202 _terminate(GetLastError());
\r
206 if (!_sendStatusToSCM(SERVICE_START_PENDING, NO_ERROR, 0, 2, 1000))
\r
208 _terminate(GetLastError());
\r
212 if (!_sendStatusToSCM(SERVICE_START_PENDING, NO_ERROR, 0, 3, 5000))
\r
214 _terminate(GetLastError());
\r
218 // Create the service thread:
\r
220 _clientData.argc = argc;
\r
221 _clientData.argv = argv;
\r
224 _threadHandle = CreateThread(
\r
225 0, 0, (LPTHREAD_START_ROUTINE)_serviceThread, &_clientData, 0, &id);
\r
228 _serviceRunning = TRUE;
\r
231 _terminate(GetLastError());
\r
235 // Send status to SCM:
\r
237 if (!_sendStatusToSCM( SERVICE_RUNNING, NO_ERROR, 0, 0, 0))
\r
239 _terminate(GetLastError());
\r
243 // Wait for termination!
\r
245 WaitForSingleObject(_terminateEvent, INFINITE);
\r
252 const char* serviceName,
\r
253 ServiceHandler* serviceHandler,
\r
258 serviceHandler->main(argc, argv);
\r
262 _serviceHandler = serviceHandler;
\r
264 _serviceName = serviceName;
\r
265 _serviceTable[0].lpServiceName = (char*)serviceName;
\r
266 _serviceTable[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTION)_serviceMain;
\r
267 _serviceTable[1].lpServiceName = NULL;
\r
268 _serviceTable[1].lpServiceProc = NULL;
\r
270 return StartServiceCtrlDispatcher(_serviceTable) ? true : false;
\r
273 PEGASUS_NAMESPACE_END
\r