mariadb/server-tools/instance-manager/WindowsService.cpp

207 lines
4.5 KiB
C++
Raw Normal View History

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),
inited(FALSE),
2005-09-13 21:53:19 +02:00
dwAcceptedControls(SERVICE_ACCEPT_STOP),
debugging(FALSE)
2005-07-20 17:55:40 +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()
{
bool ret_val= FALSE;
SC_HANDLE newService;
SC_HANDLE scm;
2005-07-20 17:55:40 +02:00
if (IsInstalled())
return TRUE;
2005-07-20 17:55:40 +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
// open a connection to the SCM
2005-08-05 15:02:06 +02:00
if (!(scm= OpenSCManager(0, 0,SC_MANAGER_CREATE_SERVICE)))
return FALSE;
2005-07-20 17:55:40 +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
if (newService)
{
CloseServiceHandle(newService);
ret_val= TRUE;
}
2005-07-20 17:55:40 +02:00
CloseServiceHandle(scm);
return ret_val;
2005-07-20 17:55:40 +02:00
}
BOOL WindowsService::Init()
{
assert(serviceName != NULL);
if (inited)
return TRUE;
2005-07-20 17:55:40 +02:00
SERVICE_TABLE_ENTRY stb[] =
{
{ (LPSTR)serviceName, (LPSERVICE_MAIN_FUNCTION) ServiceMain},
{ NULL, NULL }
};
inited= TRUE;
return StartServiceCtrlDispatcher(stb); //register with the Service Manager
2005-07-20 17:55:40 +02:00
}
BOOL WindowsService::Remove()
{
bool ret_val= FALSE;
if (!IsInstalled())
return TRUE;
// open a connection to the SCM
SC_HANDLE scm= OpenSCManager(0, 0,SC_MANAGER_CREATE_SERVICE);
if (!scm)
return FALSE;
SC_HANDLE service= OpenService(scm, serviceName, DELETE);
if (service)
{
2005-08-05 15:02:06 +02:00
if (DeleteService(service))
ret_val= TRUE;
DWORD dw= ::GetLastError();
CloseServiceHandle(service);
}
CloseServiceHandle(scm);
return ret_val;
2005-07-20 17:55:40 +02:00
}
BOOL WindowsService::IsInstalled()
{
BOOL ret_val= FALSE;
2005-07-20 17:55:40 +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
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)
{
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,
DWORD dwError)
2005-07-20 17:55:40 +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
status.dwCurrentState= currentState;
2005-08-05 15:02:06 +02:00
status.dwWin32ExitCode= dwError != 0 ?
ERROR_SERVICE_SPECIFIC_ERROR : NO_ERROR;
status.dwWaitHint= waitHint;
status.dwServiceSpecificExitCode= dwError;
2005-07-20 17:55:40 +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.
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)
{
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-07-20 17:55:40 +02:00
}
void WINAPI WindowsService::ServiceMain(DWORD argc, LPTSTR *argv)
{
assert(gService != NULL);
2005-07-20 17:55:40 +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);
}