2005-07-20 17:55:40 +02:00
|
|
|
#include <windows.h>
|
|
|
|
#include <assert.h>
|
|
|
|
#include ".\windowsservice.h"
|
|
|
|
|
|
|
|
static WindowsService *gService;
|
|
|
|
|
2005-08-05 15:02:06 +02:00
|
|
|
WindowsService::WindowsService(void) :
|
|
|
|
statusCheckpoint(0),
|
|
|
|
serviceName(NULL),
|
2006-05-18 16:57:50 +02:00
|
|
|
inited(FALSE),
|
2005-09-13 21:53:19 +02:00
|
|
|
dwAcceptedControls(SERVICE_ACCEPT_STOP),
|
2006-05-18 16:57:50 +02:00
|
|
|
debugging(FALSE)
|
2005-07-20 17:55:40 +02:00
|
|
|
{
|
2005-08-03 23:20:27 +02:00
|
|
|
gService= this;
|
|
|
|
status.dwServiceType= SERVICE_WIN32_OWN_PROCESS;
|
|
|
|
status.dwServiceSpecificExitCode= 0;
|
2005-07-20 17:55:40 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
WindowsService::~WindowsService(void)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL WindowsService::Install()
|
|
|
|
{
|
2006-05-18 16:57:50 +02:00
|
|
|
bool ret_val= FALSE;
|
2005-08-03 23:20:27 +02:00
|
|
|
SC_HANDLE newService;
|
|
|
|
SC_HANDLE scm;
|
2005-07-20 17:55:40 +02:00
|
|
|
|
2006-05-18 16:57:50 +02:00
|
|
|
if (IsInstalled())
|
|
|
|
return TRUE;
|
2005-07-20 17:55:40 +02:00
|
|
|
|
2005-08-03 23:20:27 +02:00
|
|
|
// determine the name of the currently executing file
|
|
|
|
char szFilePath[_MAX_PATH];
|
|
|
|
GetModuleFileName(NULL, szFilePath, sizeof(szFilePath));
|
2005-07-20 17:55:40 +02:00
|
|
|
|
2005-08-03 23:20:27 +02:00
|
|
|
// open a connection to the SCM
|
2005-08-05 15:02:06 +02:00
|
|
|
if (!(scm= OpenSCManager(0, 0,SC_MANAGER_CREATE_SERVICE)))
|
2006-05-18 16:57:50 +02:00
|
|
|
return FALSE;
|
2005-07-20 17:55:40 +02:00
|
|
|
|
2005-08-03 23:20:27 +02:00
|
|
|
newService= CreateService(scm, serviceName, displayName,
|
2005-08-05 15:02:06 +02:00
|
|
|
SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
|
|
|
|
SERVICE_AUTO_START, SERVICE_ERROR_NORMAL,
|
|
|
|
szFilePath, NULL, NULL, NULL, username,
|
|
|
|
password);
|
2005-07-20 17:55:40 +02:00
|
|
|
|
2005-08-03 23:20:27 +02:00
|
|
|
if (newService)
|
|
|
|
{
|
|
|
|
CloseServiceHandle(newService);
|
2006-05-18 16:57:50 +02:00
|
|
|
ret_val= TRUE;
|
2005-08-03 23:20:27 +02:00
|
|
|
}
|
2005-07-20 17:55:40 +02:00
|
|
|
|
2005-08-03 23:20:27 +02:00
|
|
|
CloseServiceHandle(scm);
|
|
|
|
return ret_val;
|
2005-07-20 17:55:40 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
BOOL WindowsService::Init()
|
|
|
|
{
|
|
|
|
assert(serviceName != NULL);
|
|
|
|
|
2006-05-18 16:57:50 +02:00
|
|
|
if (inited)
|
|
|
|
return TRUE;
|
2005-07-20 17:55:40 +02:00
|
|
|
|
2005-08-03 23:20:27 +02:00
|
|
|
SERVICE_TABLE_ENTRY stb[] =
|
|
|
|
{
|
|
|
|
{ (LPSTR)serviceName, (LPSERVICE_MAIN_FUNCTION) ServiceMain},
|
|
|
|
{ NULL, NULL }
|
|
|
|
};
|
2006-05-18 16:57:50 +02:00
|
|
|
inited= TRUE;
|
2005-08-03 23:20:27 +02:00
|
|
|
return StartServiceCtrlDispatcher(stb); //register with the Service Manager
|
2005-07-20 17:55:40 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
BOOL WindowsService::Remove()
|
|
|
|
{
|
2006-05-18 16:57:50 +02:00
|
|
|
bool ret_val= FALSE;
|
2005-08-03 23:20:27 +02:00
|
|
|
|
2006-05-18 16:57:50 +02:00
|
|
|
if (!IsInstalled())
|
|
|
|
return TRUE;
|
2005-08-03 23:20:27 +02:00
|
|
|
|
|
|
|
// open a connection to the SCM
|
|
|
|
SC_HANDLE scm= OpenSCManager(0, 0,SC_MANAGER_CREATE_SERVICE);
|
2006-05-18 16:57:50 +02:00
|
|
|
if (!scm)
|
|
|
|
return FALSE;
|
2005-08-03 23:20:27 +02:00
|
|
|
|
|
|
|
SC_HANDLE service= OpenService(scm, serviceName, DELETE);
|
|
|
|
if (service)
|
|
|
|
{
|
2005-08-05 15:02:06 +02:00
|
|
|
if (DeleteService(service))
|
2006-05-18 16:57:50 +02:00
|
|
|
ret_val= TRUE;
|
2005-08-03 23:20:27 +02:00
|
|
|
DWORD dw= ::GetLastError();
|
|
|
|
CloseServiceHandle(service);
|
|
|
|
}
|
|
|
|
|
|
|
|
CloseServiceHandle(scm);
|
|
|
|
return ret_val;
|
2005-07-20 17:55:40 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
BOOL WindowsService::IsInstalled()
|
|
|
|
{
|
2005-08-03 23:20:27 +02:00
|
|
|
BOOL ret_val= FALSE;
|
2005-07-20 17:55:40 +02:00
|
|
|
|
2005-08-03 23:20:27 +02:00
|
|
|
SC_HANDLE scm= ::OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
|
|
|
|
SC_HANDLE serv_handle= ::OpenService(scm, serviceName, SERVICE_QUERY_STATUS);
|
2005-07-20 17:55:40 +02:00
|
|
|
|
2005-08-03 23:20:27 +02:00
|
|
|
ret_val= serv_handle != NULL;
|
2005-07-20 17:55:40 +02:00
|
|
|
|
|
|
|
::CloseServiceHandle(serv_handle);
|
|
|
|
::CloseServiceHandle(scm);
|
|
|
|
|
|
|
|
return ret_val;
|
|
|
|
}
|
|
|
|
|
|
|
|
void WindowsService::SetAcceptedControls(DWORD acceptedControls)
|
|
|
|
{
|
2005-08-03 23:20:27 +02:00
|
|
|
dwAcceptedControls= acceptedControls;
|
2005-07-20 17:55:40 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-08-05 15:02:06 +02:00
|
|
|
BOOL WindowsService::ReportStatus(DWORD currentState, DWORD waitHint,
|
2005-08-03 23:20:27 +02:00
|
|
|
DWORD dwError)
|
2005-07-20 17:55:40 +02:00
|
|
|
{
|
2006-05-18 16:57:50 +02:00
|
|
|
if (debugging)
|
|
|
|
return TRUE;
|
2005-07-20 17:55:40 +02:00
|
|
|
|
|
|
|
if(currentState == SERVICE_START_PENDING)
|
2005-08-05 15:02:06 +02:00
|
|
|
status.dwControlsAccepted= 0;
|
2005-07-20 17:55:40 +02:00
|
|
|
else
|
2005-08-05 15:02:06 +02:00
|
|
|
status.dwControlsAccepted= dwAcceptedControls;
|
2005-07-20 17:55:40 +02:00
|
|
|
|
2005-08-03 23:20:27 +02:00
|
|
|
status.dwCurrentState= currentState;
|
2005-08-05 15:02:06 +02:00
|
|
|
status.dwWin32ExitCode= dwError != 0 ?
|
2005-08-03 23:20:27 +02:00
|
|
|
ERROR_SERVICE_SPECIFIC_ERROR : NO_ERROR;
|
|
|
|
status.dwWaitHint= waitHint;
|
|
|
|
status.dwServiceSpecificExitCode= dwError;
|
2005-07-20 17:55:40 +02:00
|
|
|
|
2005-08-03 23:20:27 +02:00
|
|
|
if(currentState == SERVICE_RUNNING || currentState == SERVICE_STOPPED)
|
|
|
|
{
|
|
|
|
status.dwCheckPoint= 0;
|
|
|
|
statusCheckpoint= 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
status.dwCheckPoint= ++statusCheckpoint;
|
2005-07-20 17:55:40 +02:00
|
|
|
|
|
|
|
// Report the status of the service to the service control manager.
|
2005-08-03 23:20:27 +02:00
|
|
|
BOOL result= SetServiceStatus(statusHandle, &status);
|
2005-07-20 17:55:40 +02:00
|
|
|
if (!result)
|
|
|
|
Log("ReportStatus failed");
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
void WindowsService::RegisterAndRun(DWORD argc, LPTSTR *argv)
|
|
|
|
{
|
2005-08-03 23:20:27 +02:00
|
|
|
statusHandle= ::RegisterServiceCtrlHandler(serviceName, ControlHandler);
|
2005-07-20 17:55:40 +02:00
|
|
|
if (statusHandle && ReportStatus(SERVICE_START_PENDING))
|
2005-09-13 21:53:19 +02:00
|
|
|
Run(argc, argv);
|
2005-07-20 17:55:40 +02:00
|
|
|
ReportStatus(SERVICE_STOPPED);
|
|
|
|
}
|
|
|
|
|
|
|
|
void WindowsService::HandleControlCode(DWORD opcode)
|
|
|
|
{
|
|
|
|
// Handle the requested control code.
|
2005-08-05 15:02:06 +02:00
|
|
|
switch(opcode) {
|
|
|
|
case SERVICE_CONTROL_STOP:
|
|
|
|
// Stop the service.
|
|
|
|
status.dwCurrentState= SERVICE_STOP_PENDING;
|
|
|
|
Stop();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SERVICE_CONTROL_PAUSE:
|
|
|
|
status.dwCurrentState= SERVICE_PAUSE_PENDING;
|
|
|
|
Pause();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SERVICE_CONTROL_CONTINUE:
|
|
|
|
status.dwCurrentState= SERVICE_CONTINUE_PENDING;
|
|
|
|
Continue();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SERVICE_CONTROL_SHUTDOWN:
|
|
|
|
Shutdown();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SERVICE_CONTROL_INTERROGATE:
|
|
|
|
ReportStatus(status.dwCurrentState);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
// invalid control code
|
|
|
|
break;
|
2005-08-03 23:20:27 +02:00
|
|
|
}
|
2005-07-20 17:55:40 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void WINAPI WindowsService::ServiceMain(DWORD argc, LPTSTR *argv)
|
|
|
|
{
|
2005-08-03 23:20:27 +02:00
|
|
|
assert(gService != NULL);
|
2005-07-20 17:55:40 +02:00
|
|
|
|
2005-08-03 23:20:27 +02:00
|
|
|
// register our service control handler:
|
2005-07-20 17:55:40 +02:00
|
|
|
gService->RegisterAndRun(argc, argv);
|
|
|
|
}
|
|
|
|
|
|
|
|
void WINAPI WindowsService::ControlHandler(DWORD opcode)
|
|
|
|
{
|
|
|
|
assert(gService != NULL);
|
|
|
|
|
|
|
|
return gService->HandleControlCode(opcode);
|
|
|
|
}
|