mariadb/server-tools/instance-manager/WindowsService.cpp
unknown c6dfe79beb fixed the service bits of the IM
server-tools/instance-manager/IMService.cpp:
  * setting username and password to NULL so that the 
  IM runs at LocalSystem (this should be changed soon)
  * implemented stop service by raising a sigterm
  * implemented start service by loading options and calling manager()
server-tools/instance-manager/IMService.h:
  changed the sig for Run()
server-tools/instance-manager/WindowsService.cpp:
  default debugging to false
  changed the sig of RuN()
server-tools/instance-manager/WindowsService.h:
  change the sig of run()
server-tools/instance-manager/instance.cc:
  * remove the inclusion of process.h
  * concat all args into a single buffer to pass to CreateProcess
server-tools/instance-manager/instance_options.cc:
  quoting the binary to handle paths with quotes
server-tools/instance-manager/listener.cc:
  use a timeval for select so that our select will only run
  for 100 msec before we check to see if we are shutting down
server-tools/instance-manager/mysqlmanager.cc:
  if we are given the stand alone option, then run the manager as 
  standalone
server-tools/instance-manager/options.cc:
  Added stand alone command line arg
server-tools/instance-manager/options.h:
  Added stand alone command line arg
2005-09-13 14:53:19 -05:00

203 lines
4.5 KiB
C++

#include <windows.h>
#include <assert.h>
#include ".\windowsservice.h"
static WindowsService *gService;
WindowsService::WindowsService(void) :
statusCheckpoint(0),
serviceName(NULL),
inited(false),
dwAcceptedControls(SERVICE_ACCEPT_STOP),
debugging(false)
{
gService= this;
status.dwServiceType= SERVICE_WIN32_OWN_PROCESS;
status.dwServiceSpecificExitCode= 0;
}
WindowsService::~WindowsService(void)
{
}
BOOL WindowsService::Install()
{
bool ret_val= false;
SC_HANDLE newService;
SC_HANDLE scm;
if (IsInstalled()) return true;
// determine the name of the currently executing file
char szFilePath[_MAX_PATH];
GetModuleFileName(NULL, szFilePath, sizeof(szFilePath));
// open a connection to the SCM
if (!(scm= OpenSCManager(0, 0,SC_MANAGER_CREATE_SERVICE)))
return false;
newService= CreateService(scm, serviceName, displayName,
SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
SERVICE_AUTO_START, SERVICE_ERROR_NORMAL,
szFilePath, NULL, NULL, NULL, username,
password);
if (newService)
{
CloseServiceHandle(newService);
ret_val= true;
}
CloseServiceHandle(scm);
return ret_val;
}
BOOL WindowsService::Init()
{
assert(serviceName != NULL);
if (inited) return true;
SERVICE_TABLE_ENTRY stb[] =
{
{ (LPSTR)serviceName, (LPSERVICE_MAIN_FUNCTION) ServiceMain},
{ NULL, NULL }
};
inited= true;
return StartServiceCtrlDispatcher(stb); //register with the Service Manager
}
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)
{
if (DeleteService(service))
ret_val= true;
DWORD dw= ::GetLastError();
CloseServiceHandle(service);
}
CloseServiceHandle(scm);
return ret_val;
}
BOOL WindowsService::IsInstalled()
{
BOOL ret_val= FALSE;
SC_HANDLE scm= ::OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
SC_HANDLE serv_handle= ::OpenService(scm, serviceName, SERVICE_QUERY_STATUS);
ret_val= serv_handle != NULL;
::CloseServiceHandle(serv_handle);
::CloseServiceHandle(scm);
return ret_val;
}
void WindowsService::SetAcceptedControls(DWORD acceptedControls)
{
dwAcceptedControls= acceptedControls;
}
BOOL WindowsService::ReportStatus(DWORD currentState, DWORD waitHint,
DWORD dwError)
{
if(debugging) return TRUE;
if(currentState == SERVICE_START_PENDING)
status.dwControlsAccepted= 0;
else
status.dwControlsAccepted= dwAcceptedControls;
status.dwCurrentState= currentState;
status.dwWin32ExitCode= dwError != 0 ?
ERROR_SERVICE_SPECIFIC_ERROR : NO_ERROR;
status.dwWaitHint= waitHint;
status.dwServiceSpecificExitCode= dwError;
if(currentState == SERVICE_RUNNING || currentState == SERVICE_STOPPED)
{
status.dwCheckPoint= 0;
statusCheckpoint= 0;
}
else
status.dwCheckPoint= ++statusCheckpoint;
// Report the status of the service to the service control manager.
BOOL result= SetServiceStatus(statusHandle, &status);
if (!result)
Log("ReportStatus failed");
return result;
}
void WindowsService::RegisterAndRun(DWORD argc, LPTSTR *argv)
{
statusHandle= ::RegisterServiceCtrlHandler(serviceName, ControlHandler);
if (statusHandle && ReportStatus(SERVICE_START_PENDING))
Run(argc, argv);
ReportStatus(SERVICE_STOPPED);
}
void WindowsService::HandleControlCode(DWORD opcode)
{
// Handle the requested control code.
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;
}
}
void WINAPI WindowsService::ServiceMain(DWORD argc, LPTSTR *argv)
{
assert(gService != NULL);
// register our service control handler:
gService->RegisterAndRun(argc, argv);
}
void WINAPI WindowsService::ControlHandler(DWORD opcode)
{
assert(gService != NULL);
return gService->HandleControlCode(opcode);
}