*/
#include "inspircd_config.h"
#include "inspircd.h"
+#include "exitcodes.h"
#include <windows.h>
#include <stdlib.h>
#include <string.h>
*/
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);
/* 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()
{
{
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()
{
/** 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;
}
/** 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)
{
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;
}
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);
}
/* 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 */