summaryrefslogtreecommitdiff
path: root/win/win32service.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'win/win32service.cpp')
-rw-r--r--win/win32service.cpp666
1 files changed, 333 insertions, 333 deletions
diff --git a/win/win32service.cpp b/win/win32service.cpp
index c3dd9871f..0fb94f3e4 100644
--- a/win/win32service.cpp
+++ b/win/win32service.cpp
@@ -9,336 +9,336 @@
* the file COPYING for details.
*
* ---------------------------------------------------
- */
-#include "inspircd_config.h"
-#include "inspircd.h"
-#include <windows.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-
-static SERVICE_STATUS_HANDLE serviceStatusHandle;
-static HANDLE hThreadEvent;
-static HANDLE killServiceEvent;
-static int serviceCurrentStatus;
-
-/** This is used to define ChangeServiceConf2() as we can't link
- * directly against this symbol (see below where it is used)
- */
-typedef BOOL (CALLBACK* SETSERVDESC)(SC_HANDLE,DWORD,LPVOID);
-
-/* A commandline parameter handler for service specific commandline parameters */
-typedef void (*CommandlineParameterHandler)(void);
-
-/* Represents a commandline and its handler */
-struct Commandline
-{
- const char* Switch;
- CommandlineParameterHandler Handler;
-};
-
-/* A function pointer for dynamic linking tricks */
-SETSERVDESC ChangeServiceConf;
-
-/* Kills the service by setting an event which the other thread picks up and exits */
-void KillService()
-{
- SetEvent(hThreadEvent);
- Sleep(2000);
- SetEvent(killServiceEvent);
-}
-
-/** The main part of inspircd runs within this thread function. This allows the service part to run
- * seperately on its own and to be able to kill the worker thread when its time to quit.
- */
-DWORD WINAPI WorkerThread(LPDWORD param)
-{
- char modname[MAX_PATH];
- GetModuleFileName(NULL, modname, sizeof(modname));
- char* argv[] = { modname, "--nofork", "--debug" };
- smain(3, argv);
- KillService();
- return 0;
-}
-
-/** Starts the worker thread above */
-void StartServiceThread()
-{
- DWORD dwd;
- CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)WorkerThread,NULL,0,&dwd);
-}
-
-/** This function updates the status of the service in the SCM
- * (service control manager, the services.msc applet)
- */
-BOOL UpdateSCMStatus (DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwServiceSpecificExitCode, DWORD dwCheckPoint, DWORD dwWaitHint)
-{
- BOOL success;
- SERVICE_STATUS serviceStatus;
- serviceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
- serviceStatus.dwCurrentState = dwCurrentState;
-
- if (dwCurrentState == SERVICE_START_PENDING)
- {
- serviceStatus.dwControlsAccepted = 0;
- }
- else
- {
- serviceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
- }
-
- if (dwServiceSpecificExitCode == 0)
- {
- serviceStatus.dwWin32ExitCode = dwWin32ExitCode;
- }
- else
- {
- serviceStatus.dwWin32ExitCode = ERROR_SERVICE_SPECIFIC_ERROR;
- }
- serviceStatus.dwServiceSpecificExitCode = dwServiceSpecificExitCode;
- serviceStatus.dwCheckPoint = dwCheckPoint;
- serviceStatus.dwWaitHint = dwWaitHint;
-
- success = SetServiceStatus (serviceStatusHandle, &serviceStatus);
- if (!success)
- {
- KillService();
- }
- return success;
-}
-
-/** This function is called by us when the service is being shut down or when it can't be started */
-void terminateService (int code, int wincode)
-{
- UpdateSCMStatus(SERVICE_STOPPED,wincode?wincode:ERROR_SERVICE_SPECIFIC_ERROR,(wincode)?0:code,0,0);
- return;
-}
-
-/** This callback is called by windows when the state of the service has been changed */
-VOID ServiceCtrlHandler (DWORD controlCode)
-{
- switch(controlCode)
- {
- case SERVICE_CONTROL_INTERROGATE:
- break;
- case SERVICE_CONTROL_SHUTDOWN:
- case SERVICE_CONTROL_STOP:
- serviceCurrentStatus = SERVICE_STOP_PENDING;
- UpdateSCMStatus(SERVICE_STOP_PENDING, NO_ERROR, 0, 1, 5000);
- KillService();
- UpdateSCMStatus(SERVICE_STOPPED, NO_ERROR, 0, 0, 0);
- return;
- default:
- break;
- }
- UpdateSCMStatus(serviceCurrentStatus, NO_ERROR, 0, 0, 0);
-}
-
-/** This callback is called by windows when the service is started */
-VOID ServiceMain(DWORD argc, LPTSTR *argv)
-{
- BOOL success;
- DWORD type=0, size=0;
-
- serviceStatusHandle = RegisterServiceCtrlHandler("InspIRCd", (LPHANDLER_FUNCTION)ServiceCtrlHandler);
- if (!serviceStatusHandle)
- {
- terminateService(1, GetLastError());
- return;
- }
-
- success = UpdateSCMStatus(SERVICE_START_PENDING, NO_ERROR, 0, 1, 1000);
- if (!success)
- {
- terminateService(2, GetLastError());
- return;
- }
-
- killServiceEvent = CreateEvent(NULL, true, false, NULL);
- hThreadEvent = CreateEvent(NULL, true, false, NULL);
-
- if (!killServiceEvent || !hThreadEvent)
- {
- terminateService(99, GetLastError());
- return;
- }
-
- success = UpdateSCMStatus(SERVICE_START_PENDING, NO_ERROR, 0, 2, 1000);
- if (!success)
- {
- terminateService(2, GetLastError());
- return;
- }
-
- StartServiceThread();
- serviceCurrentStatus = SERVICE_RUNNING;
- success = UpdateSCMStatus(SERVICE_RUNNING, NO_ERROR, 0, 0, 0);
- if (!success)
- {
- terminateService(6, GetLastError());
- return;
- }
- WaitForSingleObject (killServiceEvent, INFINITE);
-}
-
-/** Install the windows service. This requires administrator privileges. */
-void InstallService()
-{
- SC_HANDLE myService, scm;
- SERVICE_DESCRIPTION svDesc;
- HINSTANCE advapi32;
-
- char modname[MAX_PATH];
- GetModuleFileName(NULL, modname, sizeof(modname));
-
- scm = OpenSCManager(0,0,SC_MANAGER_CREATE_SERVICE);
- if (!scm)
- {
- printf("Unable to open service control manager: %s\n", dlerror());
- return;
- }
-
- myService = CreateService(scm,"InspIRCd","Inspire IRC Daemon", SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
- SERVICE_AUTO_START, SERVICE_ERROR_NORMAL, modname, 0, 0, 0, NULL, NULL);
-
- if (!myService)
- {
- printf("Unable to create service: %s\n", dlerror());
- CloseServiceHandle(scm);
- return;
- }
-
- // *** Set service description ***
- // this is supported from 5.0 (win2k) onwards only, so we can't link to the definition of
- // this function in advapi32.lib, otherwise the program will not run on windows NT 4. We
- // must use LoadLibrary and GetProcAddress to export the function name from advapi32.dll
- advapi32 = LoadLibrary("advapi32.dll");
- if (advapi32)
- {
- ChangeServiceConf = (SETSERVDESC)GetProcAddress(advapi32,"ChangeServiceConfig2A");
- if (ChangeServiceConf)
- {
- char desc[] = "The Inspire Internet Relay Chat Daemon hosts IRC channels and conversations.\
- If this service is stopped, the IRC server will not run.";
- svDesc.lpDescription = desc;
- BOOL success = ChangeServiceConf(myService,SERVICE_CONFIG_DESCRIPTION, &svDesc);
- if (!success)
- {
- printf("Unable to set service description: %s\n", dlerror());
- CloseServiceHandle(myService);
- CloseServiceHandle(scm);
- return;
- }
- }
- FreeLibrary(advapi32);
- }
-
- printf("Service installed.\n");
- CloseServiceHandle(myService);
- CloseServiceHandle(scm);
-}
-
-/** Remove the windows service. This requires administrator privileges. */
-void RemoveService()
-{
- SC_HANDLE myService, scm;
-
- scm = OpenSCManager(0,0,SC_MANAGER_CREATE_SERVICE);
- if (!scm)
- {
- printf("Unable to open service control manager: %s\n", dlerror());
- return;
- }
-
- myService = OpenService(scm,"InspIRCd",SERVICE_ALL_ACCESS);
- if (!myService)
- {
- printf("Unable to open service: %s\n", dlerror());
- CloseServiceHandle(scm);
- return;
- }
-
- if (!DeleteService(myService))
- {
- printf("Unable to delete service: %s\n", dlerror());
- CloseServiceHandle(myService);
- CloseServiceHandle(scm);
- return;
- }
-
- printf("Service removed.\n");
- CloseServiceHandle(myService);
- CloseServiceHandle(scm);
-}
-
-/* In windows, our main() flows through here, before calling the 'real' main, smain() in inspircd.cpp */
-int main(int argc, char** argv)
-{
- /* List of parameters and handlers */
- Commandline params[] = {
- { "--installservice", InstallService },
- { "--removeservice", RemoveService },
- { NULL }
- };
-
- /* Check for parameters */
- if (argc > 1)
- {
- for (int z = 0; params[z].Switch; ++z)
- {
- if (!_stricmp(argv[1], params[z].Switch))
- {
- params[z].Handler();
- return 0;
- }
- }
- }
-
- /* First, check if the service is installed.
- * if it is not, or we're starting as non-administrator,
- * just call smain() and start as normal non-service
- * process.
- */
- SC_HANDLE myService, scm;
- scm = OpenSCManager(0,0,SC_MANAGER_CREATE_SERVICE);
- if (scm)
- {
- myService = OpenService(scm,"InspIRCd",SERVICE_ALL_ACCESS);
- if (!myService)
- {
- /* Service not installed or no permission to modify it */
- CloseServiceHandle(scm);
- return smain(argc, argv);
- }
- }
- else
- {
- /* Not enough privileges to open the SCM */
- return smain(argc, argv);
- }
-
- CloseServiceHandle(myService);
- CloseServiceHandle(scm);
-
- /* Check if the process is running interactively. InspIRCd does not run interactively
- * as a service so if this is true, we just run the non-service inspircd.
- */
- USEROBJECTFLAGS uoflags;
- HWINSTA winstation = GetProcessWindowStation();
- if (GetUserObjectInformation(winstation, UOI_FLAGS, &uoflags, sizeof(uoflags), NULL))
- {
- if (uoflags.dwFlags == WSF_VISIBLE)
- return smain(argc, argv);
- }
-
- /* If we get here, we know the service is installed so we can start it */
-
- SERVICE_TABLE_ENTRY serviceTable[] =
- {
- {"InspIRCd", (LPSERVICE_MAIN_FUNCTION) ServiceMain },
- {NULL, NULL}
- };
-
- StartServiceCtrlDispatcher(serviceTable);
- return 0;
-}
+ */
+#include "inspircd_config.h"
+#include "inspircd.h"
+#include <windows.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+static SERVICE_STATUS_HANDLE serviceStatusHandle;
+static HANDLE hThreadEvent;
+static HANDLE killServiceEvent;
+static int serviceCurrentStatus;
+
+/** This is used to define ChangeServiceConf2() as we can't link
+ * directly against this symbol (see below where it is used)
+ */
+typedef BOOL (CALLBACK* SETSERVDESC)(SC_HANDLE,DWORD,LPVOID);
+
+/* A commandline parameter handler for service specific commandline parameters */
+typedef void (*CommandlineParameterHandler)(void);
+
+/* Represents a commandline and its handler */
+struct Commandline
+{
+ const char* Switch;
+ CommandlineParameterHandler Handler;
+};
+
+/* A function pointer for dynamic linking tricks */
+SETSERVDESC ChangeServiceConf;
+
+/* Kills the service by setting an event which the other thread picks up and exits */
+void KillService()
+{
+ SetEvent(hThreadEvent);
+ Sleep(2000);
+ SetEvent(killServiceEvent);
+}
+
+/** The main part of inspircd runs within this thread function. This allows the service part to run
+ * seperately on its own and to be able to kill the worker thread when its time to quit.
+ */
+DWORD WINAPI WorkerThread(LPDWORD param)
+{
+ char modname[MAX_PATH];
+ GetModuleFileName(NULL, modname, sizeof(modname));
+ char* argv[] = { modname, "--nofork", "--debug" };
+ smain(3, argv);
+ KillService();
+ return 0;
+}
+
+/** Starts the worker thread above */
+void StartServiceThread()
+{
+ DWORD dwd;
+ CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)WorkerThread,NULL,0,&dwd);
+}
+
+/** This function updates the status of the service in the SCM
+ * (service control manager, the services.msc applet)
+ */
+BOOL UpdateSCMStatus (DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwServiceSpecificExitCode, DWORD dwCheckPoint, DWORD dwWaitHint)
+{
+ BOOL success;
+ SERVICE_STATUS serviceStatus;
+ serviceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
+ serviceStatus.dwCurrentState = dwCurrentState;
+
+ if (dwCurrentState == SERVICE_START_PENDING)
+ {
+ serviceStatus.dwControlsAccepted = 0;
+ }
+ else
+ {
+ serviceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
+ }
+
+ if (dwServiceSpecificExitCode == 0)
+ {
+ serviceStatus.dwWin32ExitCode = dwWin32ExitCode;
+ }
+ else
+ {
+ serviceStatus.dwWin32ExitCode = ERROR_SERVICE_SPECIFIC_ERROR;
+ }
+ serviceStatus.dwServiceSpecificExitCode = dwServiceSpecificExitCode;
+ serviceStatus.dwCheckPoint = dwCheckPoint;
+ serviceStatus.dwWaitHint = dwWaitHint;
+
+ success = SetServiceStatus (serviceStatusHandle, &serviceStatus);
+ if (!success)
+ {
+ KillService();
+ }
+ return success;
+}
+
+/** This function is called by us when the service is being shut down or when it can't be started */
+void terminateService (int code, int wincode)
+{
+ UpdateSCMStatus(SERVICE_STOPPED,wincode?wincode:ERROR_SERVICE_SPECIFIC_ERROR,(wincode)?0:code,0,0);
+ return;
+}
+
+/** This callback is called by windows when the state of the service has been changed */
+VOID ServiceCtrlHandler (DWORD controlCode)
+{
+ switch(controlCode)
+ {
+ case SERVICE_CONTROL_INTERROGATE:
+ break;
+ case SERVICE_CONTROL_SHUTDOWN:
+ case SERVICE_CONTROL_STOP:
+ serviceCurrentStatus = SERVICE_STOP_PENDING;
+ UpdateSCMStatus(SERVICE_STOP_PENDING, NO_ERROR, 0, 1, 5000);
+ KillService();
+ UpdateSCMStatus(SERVICE_STOPPED, NO_ERROR, 0, 0, 0);
+ return;
+ default:
+ break;
+ }
+ UpdateSCMStatus(serviceCurrentStatus, NO_ERROR, 0, 0, 0);
+}
+
+/** This callback is called by windows when the service is started */
+VOID ServiceMain(DWORD argc, LPTSTR *argv)
+{
+ BOOL success;
+ DWORD type=0, size=0;
+
+ serviceStatusHandle = RegisterServiceCtrlHandler("InspIRCd", (LPHANDLER_FUNCTION)ServiceCtrlHandler);
+ if (!serviceStatusHandle)
+ {
+ terminateService(1, GetLastError());
+ return;
+ }
+
+ success = UpdateSCMStatus(SERVICE_START_PENDING, NO_ERROR, 0, 1, 1000);
+ if (!success)
+ {
+ terminateService(2, GetLastError());
+ return;
+ }
+
+ killServiceEvent = CreateEvent(NULL, true, false, NULL);
+ hThreadEvent = CreateEvent(NULL, true, false, NULL);
+
+ if (!killServiceEvent || !hThreadEvent)
+ {
+ terminateService(99, GetLastError());
+ return;
+ }
+
+ success = UpdateSCMStatus(SERVICE_START_PENDING, NO_ERROR, 0, 2, 1000);
+ if (!success)
+ {
+ terminateService(2, GetLastError());
+ return;
+ }
+
+ StartServiceThread();
+ serviceCurrentStatus = SERVICE_RUNNING;
+ success = UpdateSCMStatus(SERVICE_RUNNING, NO_ERROR, 0, 0, 0);
+ if (!success)
+ {
+ terminateService(6, GetLastError());
+ return;
+ }
+ WaitForSingleObject (killServiceEvent, INFINITE);
+}
+
+/** Install the windows service. This requires administrator privileges. */
+void InstallService()
+{
+ SC_HANDLE myService, scm;
+ SERVICE_DESCRIPTION svDesc;
+ HINSTANCE advapi32;
+
+ char modname[MAX_PATH];
+ GetModuleFileName(NULL, modname, sizeof(modname));
+
+ scm = OpenSCManager(0,0,SC_MANAGER_CREATE_SERVICE);
+ if (!scm)
+ {
+ printf("Unable to open service control manager: %s\n", dlerror());
+ return;
+ }
+
+ myService = CreateService(scm,"InspIRCd","Inspire IRC Daemon", SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
+ SERVICE_AUTO_START, SERVICE_ERROR_NORMAL, modname, 0, 0, 0, NULL, NULL);
+
+ if (!myService)
+ {
+ printf("Unable to create service: %s\n", dlerror());
+ CloseServiceHandle(scm);
+ return;
+ }
+
+ // *** Set service description ***
+ // this is supported from 5.0 (win2k) onwards only, so we can't link to the definition of
+ // this function in advapi32.lib, otherwise the program will not run on windows NT 4. We
+ // must use LoadLibrary and GetProcAddress to export the function name from advapi32.dll
+ advapi32 = LoadLibrary("advapi32.dll");
+ if (advapi32)
+ {
+ ChangeServiceConf = (SETSERVDESC)GetProcAddress(advapi32,"ChangeServiceConfig2A");
+ if (ChangeServiceConf)
+ {
+ char desc[] = "The Inspire Internet Relay Chat Daemon hosts IRC channels and conversations.\
+ If this service is stopped, the IRC server will not run.";
+ svDesc.lpDescription = desc;
+ BOOL success = ChangeServiceConf(myService,SERVICE_CONFIG_DESCRIPTION, &svDesc);
+ if (!success)
+ {
+ printf("Unable to set service description: %s\n", dlerror());
+ CloseServiceHandle(myService);
+ CloseServiceHandle(scm);
+ return;
+ }
+ }
+ FreeLibrary(advapi32);
+ }
+
+ printf("Service installed.\n");
+ CloseServiceHandle(myService);
+ CloseServiceHandle(scm);
+}
+
+/** Remove the windows service. This requires administrator privileges. */
+void RemoveService()
+{
+ SC_HANDLE myService, scm;
+
+ scm = OpenSCManager(0,0,SC_MANAGER_CREATE_SERVICE);
+ if (!scm)
+ {
+ printf("Unable to open service control manager: %s\n", dlerror());
+ return;
+ }
+
+ myService = OpenService(scm,"InspIRCd",SERVICE_ALL_ACCESS);
+ if (!myService)
+ {
+ printf("Unable to open service: %s\n", dlerror());
+ CloseServiceHandle(scm);
+ return;
+ }
+
+ if (!DeleteService(myService))
+ {
+ printf("Unable to delete service: %s\n", dlerror());
+ CloseServiceHandle(myService);
+ CloseServiceHandle(scm);
+ return;
+ }
+
+ printf("Service removed.\n");
+ CloseServiceHandle(myService);
+ CloseServiceHandle(scm);
+}
+
+/* In windows, our main() flows through here, before calling the 'real' main, smain() in inspircd.cpp */
+int main(int argc, char** argv)
+{
+ /* List of parameters and handlers */
+ Commandline params[] = {
+ { "--installservice", InstallService },
+ { "--removeservice", RemoveService },
+ { NULL }
+ };
+
+ /* Check for parameters */
+ if (argc > 1)
+ {
+ for (int z = 0; params[z].Switch; ++z)
+ {
+ if (!_stricmp(argv[1], params[z].Switch))
+ {
+ params[z].Handler();
+ return 0;
+ }
+ }
+ }
+
+ /* First, check if the service is installed.
+ * if it is not, or we're starting as non-administrator,
+ * just call smain() and start as normal non-service
+ * process.
+ */
+ SC_HANDLE myService, scm;
+ scm = OpenSCManager(0,0,SC_MANAGER_CREATE_SERVICE);
+ if (scm)
+ {
+ myService = OpenService(scm,"InspIRCd",SERVICE_ALL_ACCESS);
+ if (!myService)
+ {
+ /* Service not installed or no permission to modify it */
+ CloseServiceHandle(scm);
+ return smain(argc, argv);
+ }
+ }
+ else
+ {
+ /* Not enough privileges to open the SCM */
+ return smain(argc, argv);
+ }
+
+ CloseServiceHandle(myService);
+ CloseServiceHandle(scm);
+
+ /* Check if the process is running interactively. InspIRCd does not run interactively
+ * as a service so if this is true, we just run the non-service inspircd.
+ */
+ USEROBJECTFLAGS uoflags;
+ HWINSTA winstation = GetProcessWindowStation();
+ if (GetUserObjectInformation(winstation, UOI_FLAGS, &uoflags, sizeof(uoflags), NULL))
+ {
+ if (uoflags.dwFlags == WSF_VISIBLE)
+ return smain(argc, argv);
+ }
+
+ /* If we get here, we know the service is installed so we can start it */
+
+ SERVICE_TABLE_ENTRY serviceTable[] =
+ {
+ {"InspIRCd", (LPSERVICE_MAIN_FUNCTION) ServiceMain },
+ {NULL, NULL}
+ };
+
+ StartServiceCtrlDispatcher(serviceTable);
+ return 0;
+}