]> git.netwichtig.de Git - user/henk/code/inspircd.git/blobdiff - win/win32service.cpp
Add contents of LDFLAGS in addition to CXXFLAGS
[user/henk/code/inspircd.git] / win / win32service.cpp
index 0fb94f3e43370a655f687aae420f16ae141120f3..59a06b7097dd6ebf2af7bd664137b42fafce1379 100644 (file)
@@ -2,8 +2,8 @@
  *       | Inspire Internet Relay Chat Daemon |
  *       +------------------------------------+
  *
- *  InspIRCd: (C) 2002-2008 InspIRCd Development Team
- * See: http://www.inspircd.org/wiki/index.php/Credits
+ *  InspIRCd: (C) 2002-2009 InspIRCd Development Team
+ * See: http://wiki.inspircd.org/Credits
  *
  * This program is free but copyrighted software; see
  *         the file COPYING for details.
@@ -12,6 +12,7 @@
  */
 #include "inspircd_config.h"
 #include "inspircd.h"
+#include "exitcodes.h"
 #include <windows.h>
 #include <stdlib.h>
 #include <string.h>
@@ -27,6 +28,9 @@ static int serviceCurrentStatus;
  */
 typedef BOOL (CALLBACK* SETSERVDESC)(SC_HANDLE,DWORD,LPVOID);
 
+BOOL UpdateSCMStatus(DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwServiceSpecificExitCode, DWORD dwCheckPoint, DWORD dwWaitHint);
+void terminateService(int code, int wincode);
+
 /* A commandline parameter handler for service specific commandline parameters */
 typedef void (*CommandlineParameterHandler)(void);
 
@@ -40,6 +44,17 @@ struct Commandline
 /* A function pointer for dynamic linking tricks */
 SETSERVDESC ChangeServiceConf;
 
+/* Returns true if this program is running as a service, false if it is running interactive */
+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()
 {
@@ -55,12 +70,28 @@ DWORD WINAPI WorkerThread(LPDWORD param)
 {
        char modname[MAX_PATH];
        GetModuleFileName(NULL, modname, sizeof(modname));
-       char* argv[] = { modname, "--nofork", "--debug" };
-       smain(3, argv);
+       char* argv[] = { modname, "--nofork" };
+       smain(2, argv);
        KillService();
        return 0;
 }
 
+/* This is called when all startup is done */
+void SetServiceRunning()
+{
+       if (!IsAService())
+               return;
+
+       serviceCurrentStatus = SERVICE_RUNNING;
+       BOOL success = UpdateSCMStatus(SERVICE_RUNNING, NO_ERROR, 0, 0, 0);
+       if (!success)
+       {
+               terminateService(EXIT_STATUS_UPDATESCM_FAILED, GetLastError());
+               return;
+       }
+}
+
+
 /** Starts the worker thread above */
 void StartServiceThread()
 {
@@ -71,7 +102,7 @@ void StartServiceThread()
 /** 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 UpdateSCMStatus(DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwServiceSpecificExitCode, DWORD dwCheckPoint, DWORD dwWaitHint)
 {
        BOOL success;
        SERVICE_STATUS serviceStatus;
@@ -108,14 +139,26 @@ 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)
+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 InspIRCd::Exit() */
+void SetServiceStopped(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)
+VOID ServiceCtrlHandler(DWORD controlCode)
 {
        switch(controlCode)
        {
@@ -138,19 +181,18 @@ VOID ServiceCtrlHandler (DWORD controlCode)
 VOID ServiceMain(DWORD argc, LPTSTR *argv)
 {
        BOOL success;
-       DWORD type=0, size=0;
 
        serviceStatusHandle = RegisterServiceCtrlHandler("InspIRCd", (LPHANDLER_FUNCTION)ServiceCtrlHandler);
        if (!serviceStatusHandle)
        {
-               terminateService(1, GetLastError());
+               terminateService(EXIT_STATUS_RSCH_FAILED, GetLastError());
                return;
        }
 
        success = UpdateSCMStatus(SERVICE_START_PENDING, NO_ERROR, 0, 1, 1000);
        if (!success)
        {
-               terminateService(2, GetLastError());
+               terminateService(EXIT_STATUS_UPDATESCM_FAILED, GetLastError());
                return;
        }
 
@@ -159,25 +201,18 @@ VOID ServiceMain(DWORD argc, LPTSTR *argv)
 
        if (!killServiceEvent || !hThreadEvent)
        {
-               terminateService(99, GetLastError());
+               terminateService(EXIT_STATUS_CREATE_EVENT_FAILED, GetLastError());
                return;
        }
 
        success = UpdateSCMStatus(SERVICE_START_PENDING, NO_ERROR, 0, 2, 1000);
        if (!success)
        {
-               terminateService(2, GetLastError());
+               terminateService(EXIT_STATUS_UPDATESCM_FAILED, GetLastError());
                return;
        }
 
        StartServiceThread();
-       serviceCurrentStatus = SERVICE_RUNNING;
-       success = UpdateSCMStatus(SERVICE_RUNNING, NO_ERROR, 0, 0, 0);
-       if (!success)
-       {
-               terminateService(6, GetLastError());
-               return;
-       }
        WaitForSingleObject (killServiceEvent, INFINITE);
 }
 
@@ -323,13 +358,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(argc, argv);
 
        /* If we get here, we know the service is installed so we can start it */