mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
initial import of Windows port of IM.
server-tools/instance-manager/commands.cc: type cleanups for compiling on Windows now using Options::config_file for the location of the single my.cnf file we are using server-tools/instance-manager/guardian.cc: pthread_mutex_lock and unlock do not return a value on Windows so we return 0 in all cases server-tools/instance-manager/instance.cc: big changes here. Had to implement Windows versions of launch_and_wait and kill() server-tools/instance-manager/instance.h: added some function defs server-tools/instance-manager/instance_map.cc: pthread_mutex_lock and unlock do not return a value on Windows Also, now using only the file named as Options::config_file server-tools/instance-manager/instance_options.h: added reference to port.h server-tools/instance-manager/listener.cc: reworked and simplified the socket handling code. Added windows versions of the code that sets the sockets to be non-blocking and non-inheritable server-tools/instance-manager/listener.h: change Options to always be a struct. Really surprised GCC was letting this go. Options was declared to be struct in some places and class in other places. server-tools/instance-manager/log.cc: added reference to port.h server-tools/instance-manager/manager.cc: moved all the signal code inside some #ifndef __WIN__ blocks server-tools/instance-manager/manager.h: change Options to always be a struct. Really surprised GCC was letting this go. Options was declared to be struct in some places and class in other places. server-tools/instance-manager/mysqlmanager.cc: added in the Windows service code. server-tools/instance-manager/options.cc: Added in the windows options for running as a service and the code for loading settings only from a single file server-tools/instance-manager/options.h: added definitions for the new Windows service vars and routines server-tools/instance-manager/parse_output.cc: added reference to port.h server-tools/instance-manager/priv.cc: added reference to port.h server-tools/instance-manager/priv.h: linuxthreads should not be visible on Windows server-tools/instance-manager/thread_registry.cc: more __WIN__ blocking server-tools/instance-manager/user_map.cc: fixed passwd file code to handle files with \r\n line endings server-tools/instance-manager/IMService.cpp: New BitKeeper file ``server-tools/instance-manager/IMService.cpp'' server-tools/instance-manager/IMService.h: New BitKeeper file ``server-tools/instance-manager/IMService.h'' server-tools/instance-manager/WindowsService.cpp: New BitKeeper file ``server-tools/instance-manager/WindowsService.cpp'' server-tools/instance-manager/WindowsService.h: New BitKeeper file ``server-tools/instance-manager/WindowsService.h'' server-tools/instance-manager/mysqlmanager.vcproj: New BitKeeper file ``server-tools/instance-manager/mysqlmanager.vcproj'' server-tools/instance-manager/port.h: New BitKeeper file ``server-tools/instance-manager/port.h''
This commit is contained in:
200
server-tools/instance-manager/WindowsService.cpp
Executable file
200
server-tools/instance-manager/WindowsService.cpp
Executable file
@ -0,0 +1,200 @@
|
||||
#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)
|
||||
{
|
||||
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();
|
||||
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);
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user