mirror of https://github.com/tongzx/nt5src
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
220 lines
4.5 KiB
/*
|
|
* Service.c
|
|
*
|
|
*
|
|
* Service control interface to sumserve
|
|
*
|
|
* Geraint Davies, July 93
|
|
*/
|
|
|
|
#include <windows.h>
|
|
#include <sumserve.h> // public header for sumserve
|
|
#include "errlog.h"
|
|
#include <server.h> // private header for sumserve
|
|
|
|
|
|
/*
|
|
* this is the function (in some other module) that actually
|
|
* does all the work (probably used to be main or WinMain until
|
|
* we added all the service-control stuff in this file).
|
|
*/
|
|
extern VOID MainLoop(DWORD dwArgc, LPTSTR *lpszArgv);
|
|
|
|
|
|
|
|
|
|
|
|
// service status handle - used in SetServiceStatus calls.
|
|
SERVICE_STATUS_HANDLE sshSumserve;
|
|
|
|
//signaled when service completed
|
|
HANDLE hServiceDoneEvent;
|
|
|
|
SERVICE_STATUS gssStatus;
|
|
|
|
|
|
/* structure to pass more than one parameter to the worker thread. */
|
|
typedef struct _threadinitparams {
|
|
DWORD dwArgc;
|
|
LPTSTR *lpszArgv;
|
|
} threadinitparams, * pthreadinitparams;
|
|
|
|
|
|
/*
|
|
* MainLoopCaller
|
|
*
|
|
* This function is called on the worker thread created to do all the
|
|
* real work. It calls the main loop function for the service, and
|
|
* when that exits, signals the completion event to tell the
|
|
* SS_Main thread that it is time to exit the process.
|
|
*/
|
|
DWORD
|
|
MainLoopCaller(LPVOID lpgeneric)
|
|
{
|
|
pthreadinitparams pta;
|
|
|
|
pta = (pthreadinitparams) lpgeneric;
|
|
|
|
dprintf1(("calling main loop"));
|
|
|
|
MainLoop(pta->dwArgc, pta->lpszArgv);
|
|
|
|
SetEvent(hServiceDoneEvent);
|
|
|
|
return(0);
|
|
}
|
|
|
|
/*
|
|
* handler function called to perform start/stop
|
|
* requests.
|
|
*/
|
|
VOID
|
|
SS_ServiceHandler(DWORD dwCtrlCode)
|
|
{
|
|
|
|
switch(dwCtrlCode) {
|
|
|
|
case SERVICE_CONTROL_STOP:
|
|
|
|
gssStatus.dwCurrentState = SERVICE_STOP_PENDING;
|
|
gssStatus.dwControlsAccepted = 0;
|
|
gssStatus.dwCheckPoint = 1;
|
|
gssStatus.dwWaitHint = 3000;
|
|
|
|
SetServiceStatus(sshSumserve, &gssStatus);
|
|
SetEvent(hServiceDoneEvent);
|
|
break;
|
|
|
|
default:
|
|
/*
|
|
* we must always update the service status every time we are
|
|
* called.
|
|
*/
|
|
SetServiceStatus(sshSumserve, &gssStatus);
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* service main function - called by service controller
|
|
* during StartServiceCtlDispatcher processing.
|
|
*
|
|
* Register our handler function, and initialise the service.
|
|
* create a thread to do the work, and then wait for someone to
|
|
* signal time to end. When this function exits, the call to
|
|
* StartServiceCtlDispatcher will return, and the process will exit
|
|
*
|
|
* The args are passed from the program that called start service, and
|
|
* are parameters that are passed to the main loop of the program.
|
|
*/
|
|
VOID
|
|
SS_Main(DWORD dwArgc, LPTSTR *lpszArgv)
|
|
{
|
|
threadinitparams ta;
|
|
HANDLE thread;
|
|
DWORD threadid;
|
|
|
|
dprintf1(("in ss_main"));
|
|
|
|
|
|
sshSumserve = RegisterServiceCtrlHandler(
|
|
TEXT("SumServe"),
|
|
(LPHANDLER_FUNCTION) SS_ServiceHandler);
|
|
|
|
gssStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
|
|
gssStatus.dwServiceSpecificExitCode = 0;
|
|
|
|
gssStatus.dwCurrentState = SERVICE_START_PENDING;
|
|
gssStatus.dwControlsAccepted = 0;
|
|
gssStatus.dwWin32ExitCode = NO_ERROR;
|
|
gssStatus.dwCheckPoint = 1;
|
|
gssStatus.dwWaitHint = 3000;
|
|
SetServiceStatus(sshSumserve, &gssStatus);
|
|
|
|
|
|
hServiceDoneEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
|
|
|
gssStatus.dwCheckPoint = 2;
|
|
SetServiceStatus(sshSumserve, &gssStatus);
|
|
|
|
|
|
|
|
// create a thread to do all the real work
|
|
|
|
// init args
|
|
ta.dwArgc = dwArgc;
|
|
ta.lpszArgv = lpszArgv;
|
|
|
|
thread = CreateThread(
|
|
NULL,
|
|
0,
|
|
(LPTHREAD_START_ROUTINE) MainLoopCaller,
|
|
(LPVOID)&ta,
|
|
0,
|
|
&threadid);
|
|
|
|
if (thread != NULL) {
|
|
|
|
CloseHandle(thread);
|
|
|
|
|
|
gssStatus.dwCurrentState = SERVICE_RUNNING;
|
|
gssStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
|
|
|
|
gssStatus.dwCheckPoint = 0;
|
|
gssStatus.dwWaitHint = 0;
|
|
SetServiceStatus(sshSumserve, &gssStatus);
|
|
|
|
|
|
WaitForSingleObject(hServiceDoneEvent, INFINITE);
|
|
}
|
|
|
|
CloseHandle(hServiceDoneEvent);
|
|
|
|
gssStatus.dwCurrentState = SERVICE_STOPPED;
|
|
gssStatus.dwControlsAccepted = 0;
|
|
SetServiceStatus(sshSumserve, &gssStatus);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* main entry point.
|
|
*
|
|
* for a service, we need to call the service manager telling it our
|
|
* main init function. It will then do everything. When the service
|
|
* manager returns, it's time to exit.
|
|
*/
|
|
int WINAPI
|
|
WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdParam,
|
|
int nCmdShow)
|
|
{
|
|
SERVICE_TABLE_ENTRY steDispatch[] = {
|
|
|
|
{ TEXT("SumServe"), (LPSERVICE_MAIN_FUNCTION) SS_Main },
|
|
|
|
//end of table marker
|
|
{ NULL, NULL }
|
|
};
|
|
|
|
|
|
dprintf1(("in winmain"));
|
|
|
|
StartServiceCtrlDispatcher(steDispatch);
|
|
|
|
|
|
return(0);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|