]> git.netwichtig.de Git - user/henk/code/inspircd.git/commitdiff
EWWW windows line endings!
authorbrain <brain@e03df62e-2008-0410-955e-edbf42e46eb7>
Fri, 22 Aug 2008 20:01:13 +0000 (20:01 +0000)
committerbrain <brain@e03df62e-2008-0410-955e-edbf42e46eb7>
Fri, 22 Aug 2008 20:01:13 +0000 (20:01 +0000)
git-svn-id: http://svn.inspircd.org/repository/trunk/inspircd@10223 e03df62e-2008-0410-955e-edbf42e46eb7

win/win32service.cpp

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