From a6cf47a2cd96c459bfc241c6dce8ca8454140484 Mon Sep 17 00:00:00 2001 From: brain Date: Sun, 24 Aug 2008 19:08:36 +0000 Subject: [PATCH] work in progress git-svn-id: http://svn.inspircd.org/repository/trunk/inspircd@10238 e03df62e-2008-0410-955e-edbf42e46eb7 --- include/win32service.h | 11 ++++++++ src/inspircd.cpp | 2 ++ win/configureVC80.vcproj | 45 ++++++++++++++--------------- win/inspircdVC80.vcproj | 4 +++ win/inspircd_win32wrapper.h | 2 ++ win/win32service.cpp | 56 +++++++++++++++++++++++++++---------- 6 files changed, 83 insertions(+), 37 deletions(-) create mode 100644 include/win32service.h diff --git a/include/win32service.h b/include/win32service.h new file mode 100644 index 000000000..93c9c8e09 --- /dev/null +++ b/include/win32service.h @@ -0,0 +1,11 @@ +#ifndef _WIN32SERVICE_H_ +#define _WIN32SERVICE_H_ + +/* Hook for win32service.cpp to exit properly with the service specific error code */ +#define exit(a) newexit(a) +void newexit(int status); + +/* Marks the service as running, not called until the config is parsed */ +void SetServiceRunning(); + +#endif \ No newline at end of file diff --git a/src/inspircd.cpp b/src/inspircd.cpp index 0efbd293a..dab49ddf0 100644 --- a/src/inspircd.cpp +++ b/src/inspircd.cpp @@ -719,6 +719,8 @@ InspIRCd::InspIRCd(int argc, char** argv) WindowsForkKillOwner(this); FreeConsole(); } + /* Set win32 service as running, if we are running as a service */ + SetServiceRunning(); #endif Logs->Log("STARTUP", DEFAULT, "Startup complete as '%s'[%s], %d max open sockets", Config->ServerName,Config->GetSID().c_str(), SE->GetMaxFds()); diff --git a/win/configureVC80.vcproj b/win/configureVC80.vcproj index 547091660..f9f23ed54 100644 --- a/win/configureVC80.vcproj +++ b/win/configureVC80.vcproj @@ -98,9 +98,9 @@ /> + + diff --git a/win/inspircd_win32wrapper.h b/win/inspircd_win32wrapper.h index 94f799c18..89309fbc9 100644 --- a/win/inspircd_win32wrapper.h +++ b/win/inspircd_win32wrapper.h @@ -18,6 +18,8 @@ #ifndef INSPIRCD_WIN32WRAPPER_H #define INSPIRCD_WIN32WRAPPER_H +#include "win32service.h" + /* Define the WINDOWS macro. This means we're building on windows to the rest of the server. I think this is more reasonable than using WIN32, especially if we're gonna be doing 64-bit compiles */ #define WINDOWS 1 diff --git a/win/win32service.cpp b/win/win32service.cpp index 0fb94f3e4..5923c1458 100644 --- a/win/win32service.cpp +++ b/win/win32service.cpp @@ -40,6 +40,16 @@ struct Commandline /* A function pointer for dynamic linking tricks */ SETSERVDESC ChangeServiceConf; +bool IsAService(); +{ + USEROBJECTFLAGS uoflags; + HWINSTA winstation = GetProcessWindowStation(); + if (GetUserObjectInformation(winstation, UOI_FLAGS, &uoflags, sizeof(uoflags), NULL)) + return ((uoflags.dwFlags & WSF_VISIBLE) == 0); + else + return false; +} + /* Kills the service by setting an event which the other thread picks up and exits */ void KillService() { @@ -61,6 +71,22 @@ DWORD WINAPI WorkerThread(LPDWORD param) return 0; } +/* This is called when all startup is done */ +void SetServiceRunning() +{ + if (!IsAService()) + return; + + serviceCurrentStatus = SERVICE_RUNNING; + success = UpdateSCMStatus(SERVICE_RUNNING, NO_ERROR, 0, 0, 0); + if (!success) + { + terminateService(6, GetLastError()); + return; + } +} + + /** Starts the worker thread above */ void StartServiceThread() { @@ -110,10 +136,22 @@ BOOL UpdateSCMStatus (DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwServi /** 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); + UpdateSCMStatus(SERVICE_STOPPED, wincode ? wincode : ERROR_SERVICE_SPECIFIC_ERROR, wincode ? 0 : code, 0, 0); return; } +/* In windows we hook this to exit() */ +void newexit(int status) +{ + if (!IsAService()) + exit(status); + + /* Are we running as a service? If so, trigger the service specific exit code */ + terminateService(status, 0); + KillService(); + exit(status); +} + /** This callback is called by windows when the state of the service has been changed */ VOID ServiceCtrlHandler (DWORD controlCode) { @@ -171,13 +209,6 @@ VOID ServiceMain(DWORD argc, LPTSTR *argv) } StartServiceThread(); - serviceCurrentStatus = SERVICE_RUNNING; - success = UpdateSCMStatus(SERVICE_RUNNING, NO_ERROR, 0, 0, 0); - if (!success) - { - terminateService(6, GetLastError()); - return; - } WaitForSingleObject (killServiceEvent, INFINITE); } @@ -323,13 +354,8 @@ int main(int argc, char** argv) /* 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 (!IsAService()) + return smain(argv, argc); /* If we get here, we know the service is installed so we can start it */ -- 2.39.2