diff options
Diffstat (limited to 'bin/bbackupd/Win32ServiceFunctions.cpp')
-rw-r--r-- | bin/bbackupd/Win32ServiceFunctions.cpp | 236 |
1 files changed, 236 insertions, 0 deletions
diff --git a/bin/bbackupd/Win32ServiceFunctions.cpp b/bin/bbackupd/Win32ServiceFunctions.cpp new file mode 100644 index 00000000..89f02f62 --- /dev/null +++ b/bin/bbackupd/Win32ServiceFunctions.cpp @@ -0,0 +1,236 @@ +//*************************************************************** +// From the book "Win32 System Services: The Heart of Windows 98 +// and Windows 2000" +// by Marshall Brain +// Published by Prentice Hall +// Copyright 1995 Prentice Hall. +// +// This code implements the Windows API Service interface +// for the Box Backup for Windows native port. +// Adapted for Box Backup by Nick Knight. +//*************************************************************** + +#ifdef WIN32 + +#include "Box.h" + +//#include <stdio.h> +//#include <stdlib.h> +#include <unistd.h> +//#include <windows.h> + +extern void TerminateService(void); +extern unsigned int WINAPI RunService(LPVOID lpParameter); + +// Global variables + +TCHAR* gServiceName = TEXT("Box Backup Service"); +SERVICE_STATUS gServiceStatus; +SERVICE_STATUS_HANDLE gServiceStatusHandle = 0; +HANDLE gStopServiceEvent = 0; + +#define SERVICE_NAME "boxbackup" + +void ErrorHandler(char *s, DWORD err) +{ + char buf[256]; + memset(buf, 0, sizeof(buf)); + snprintf(buf, sizeof(buf)-1, "%s (%d)", s, err); + ::syslog(LOG_ERR, "%s", buf); + MessageBox(0, buf, "Error", + MB_OK | MB_SETFOREGROUND | MB_DEFAULT_DESKTOP_ONLY); + ExitProcess(err); +} + + +void WINAPI ServiceControlHandler( DWORD controlCode ) +{ + switch ( controlCode ) + { + case SERVICE_CONTROL_INTERROGATE: + break; + + case SERVICE_CONTROL_SHUTDOWN: + case SERVICE_CONTROL_STOP: + Beep(1000,100); + TerminateService(); + gServiceStatus.dwCurrentState = SERVICE_STOP_PENDING; + SetServiceStatus(gServiceStatusHandle, &gServiceStatus); + + SetEvent(gStopServiceEvent); + return; + + case SERVICE_CONTROL_PAUSE: + break; + + case SERVICE_CONTROL_CONTINUE: + break; + + default: + if ( controlCode >= 128 && controlCode <= 255 ) + // user defined control code + break; + else + // unrecognised control code + break; + } + + SetServiceStatus( gServiceStatusHandle, &gServiceStatus ); +} + +// ServiceMain is called when the SCM wants to +// start the service. When it returns, the service +// has stopped. It therefore waits on an event +// just before the end of the function, and +// that event gets set when it is time to stop. +// It also returns on any error because the +// service cannot start if there is an eror. + +VOID ServiceMain(DWORD argc, LPTSTR *argv) +{ + // initialise service status + gServiceStatus.dwServiceType = SERVICE_WIN32; + gServiceStatus.dwCurrentState = SERVICE_STOPPED; + gServiceStatus.dwControlsAccepted = 0; + gServiceStatus.dwWin32ExitCode = NO_ERROR; + gServiceStatus.dwServiceSpecificExitCode = NO_ERROR; + gServiceStatus.dwCheckPoint = 0; + gServiceStatus.dwWaitHint = 0; + + gServiceStatusHandle = RegisterServiceCtrlHandler(gServiceName, + ServiceControlHandler); + + if (gServiceStatusHandle) + { + // service is starting + gServiceStatus.dwCurrentState = SERVICE_START_PENDING; + SetServiceStatus(gServiceStatusHandle, &gServiceStatus); + + // do initialisation here + gStopServiceEvent = CreateEvent( 0, TRUE, FALSE, 0 ); + if (!gStopServiceEvent) + { + gServiceStatus.dwControlsAccepted &= + ~(SERVICE_ACCEPT_STOP | + SERVICE_ACCEPT_SHUTDOWN); + gServiceStatus.dwCurrentState = SERVICE_STOPPED; + SetServiceStatus(gServiceStatusHandle, &gServiceStatus); + return; + } + + HANDLE ourThread = (HANDLE)_beginthreadex( + NULL, + 0, + RunService, + 0, + CREATE_SUSPENDED, + NULL); + + SetThreadPriority(ourThread, THREAD_PRIORITY_LOWEST); + ResumeThread(ourThread); + + // we are now running so tell the SCM + gServiceStatus.dwControlsAccepted |= + (SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN); + gServiceStatus.dwCurrentState = SERVICE_RUNNING; + SetServiceStatus(gServiceStatusHandle, &gServiceStatus); + + // do cleanup here + WaitForSingleObject(gStopServiceEvent, INFINITE); + CloseHandle(gStopServiceEvent); + gStopServiceEvent = 0; + + // service was stopped + gServiceStatus.dwCurrentState = SERVICE_STOP_PENDING; + SetServiceStatus(gServiceStatusHandle, &gServiceStatus); + + // service is now stopped + gServiceStatus.dwControlsAccepted &= + ~(SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN); + gServiceStatus.dwCurrentState = SERVICE_STOPPED; + SetServiceStatus(gServiceStatusHandle, &gServiceStatus); + } +} + +void OurService(void) +{ + SERVICE_TABLE_ENTRY serviceTable[] = + { + { SERVICE_NAME, (LPSERVICE_MAIN_FUNCTION) ServiceMain }, + { NULL, NULL } + }; + BOOL success; + + // Register with the SCM + success = StartServiceCtrlDispatcher(serviceTable); + + if (!success) + { + ErrorHandler("Failed to start service. Did you start " + "Box Backup from the Service Control Manager? " + "(StartServiceCtrlDispatcher)", GetLastError()); + } +} + +void InstallService(void) +{ + SC_HANDLE newService, scm; + + scm = OpenSCManager(0,0,SC_MANAGER_CREATE_SERVICE); + + if (!scm) return; + + char cmd[MAX_PATH]; + GetModuleFileName(NULL, cmd, sizeof(cmd)-1); + cmd[sizeof(cmd)-1] = 0; + + char cmd_args[MAX_PATH]; + snprintf(cmd_args, sizeof(cmd_args)-1, "%s --service", cmd); + cmd_args[sizeof(cmd_args)-1] = 0; + + newService = CreateService( + scm, + SERVICE_NAME, + "Box Backup", + SERVICE_ALL_ACCESS, + SERVICE_WIN32_OWN_PROCESS, + SERVICE_DEMAND_START, + SERVICE_ERROR_NORMAL, + cmd_args, + 0,0,0,0,0); + + if (newService) CloseServiceHandle(newService); + CloseServiceHandle(scm); +} + +void RemoveService(void) +{ + SC_HANDLE service, scm; + SERVICE_STATUS status; + + scm = OpenSCManager(0,0,SC_MANAGER_CREATE_SERVICE); + + if (!scm) return; + + service = OpenService(scm, SERVICE_NAME, SERVICE_ALL_ACCESS|DELETE); + ControlService(service, SERVICE_CONTROL_STOP, &status); + + if (!service) + { + printf("Failed to open service manager"); + return; + } + if (DeleteService(service)) + { + printf("Service removed"); + } + else + { + printf("Failed to remove service"); + } + + CloseServiceHandle(service); + CloseServiceHandle(scm); +} + +#endif // WIN32 |