1 /* +------------------------------------+
2 * | Inspire Internet Relay Chat Daemon |
3 * +------------------------------------+
5 * InspIRCd: (C) 2002-2008 InspIRCd Development Team
6 * See: http://www.inspircd.org/wiki/index.php/Credits
8 * This program is free but copyrighted software; see
9 * the file COPYING for details.
11 * ---------------------------------------------------
14 #include <windows.h>
\r
18 extern int smain(int argc, char** argv);
\r
20 static SERVICE_STATUS_HANDLE serviceStatusHandle;
\r
21 static HANDLE hThreadEvent;
\r
22 static HANDLE killServiceEvent;
\r
23 static int serviceCurrentStatus;
\r
25 // This is used to define ChangeServiceConf2() as we can't link
\r
26 // directly against this symbol (see below where it is used)
\r
27 typedef BOOL (CALLBACK* SETSERVDESC)(SC_HANDLE,DWORD,LPVOID);
\r
29 SETSERVDESC ChangeServiceConf; // A function pointer for dynamic linking tricks
\r
34 /* FIXME: This should set a flag in the mainloop for shutting down */
\r
35 SetEvent(hThreadEvent);
\r
37 SetEvent(killServiceEvent);
\r
40 DWORD WINAPI WorkerThread(LPDWORD param)
\r
42 // *** REAL MAIN HERE ***
\r
43 char modname[MAX_PATH];
\r
44 GetModuleFileName(NULL, modname, sizeof(modname));
\r
45 char* argv[] = { modname, "--nofork", "--debug" };
\r
51 void StartServiceThread()
\r
54 CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)WorkerThread,NULL,0,&dwd);
\r
58 BOOL UpdateSCMStatus (DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwServiceSpecificExitCode, DWORD dwCheckPoint, DWORD dwWaitHint)
\r
61 SERVICE_STATUS serviceStatus;
\r
62 serviceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
\r
63 serviceStatus.dwCurrentState = dwCurrentState;
\r
65 if (dwCurrentState == SERVICE_START_PENDING)
\r
67 serviceStatus.dwControlsAccepted = 0;
\r
71 serviceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
\r
74 if (dwServiceSpecificExitCode == 0)
\r
76 serviceStatus.dwWin32ExitCode = dwWin32ExitCode;
\r
80 serviceStatus.dwWin32ExitCode = ERROR_SERVICE_SPECIFIC_ERROR;
\r
82 serviceStatus.dwServiceSpecificExitCode = dwServiceSpecificExitCode;
\r
83 serviceStatus.dwCheckPoint = dwCheckPoint;
\r
84 serviceStatus.dwWaitHint = dwWaitHint;
\r
86 success = SetServiceStatus (serviceStatusHandle, &serviceStatus);
\r
95 void terminateService (int code, int wincode)
\r
97 UpdateSCMStatus(SERVICE_STOPPED,wincode?wincode:ERROR_SERVICE_SPECIFIC_ERROR,(wincode)?0:code,0,0);
\r
102 VOID ServiceCtrlHandler (DWORD controlCode)
\r
104 switch(controlCode)
\r
106 case SERVICE_CONTROL_INTERROGATE:
\r
108 case SERVICE_CONTROL_SHUTDOWN:
\r
109 case SERVICE_CONTROL_STOP:
\r
110 serviceCurrentStatus = SERVICE_STOP_PENDING;
\r
111 UpdateSCMStatus(SERVICE_STOP_PENDING, NO_ERROR, 0, 1, 5000);
\r
113 UpdateSCMStatus(SERVICE_STOPPED, NO_ERROR, 0, 0, 0);
\r
118 UpdateSCMStatus(serviceCurrentStatus, NO_ERROR, 0, 0, 0);
\r
122 VOID ServiceMain(DWORD argc, LPTSTR *argv)
\r
125 DWORD type=0, size=0;
\r
127 serviceStatusHandle = RegisterServiceCtrlHandler("InspIRCd", (LPHANDLER_FUNCTION)ServiceCtrlHandler);
\r
128 if (!serviceStatusHandle)
\r
130 terminateService(1,GetLastError());
\r
134 success = UpdateSCMStatus(SERVICE_START_PENDING, NO_ERROR, 0, 1, 1000);
\r
137 terminateService(2,GetLastError());
\r
141 killServiceEvent = CreateEvent(NULL,true,false,NULL);
\r
142 hThreadEvent = CreateEvent(NULL,true,false,NULL);
\r
144 if (!killServiceEvent || !hThreadEvent)
\r
146 terminateService(99,GetLastError());
\r
150 success = UpdateSCMStatus(SERVICE_START_PENDING, NO_ERROR, 0, 2, 1000);
\r
153 terminateService(2,GetLastError());
\r
157 StartServiceThread();
\r
158 serviceCurrentStatus = SERVICE_RUNNING;
\r
159 success = UpdateSCMStatus(SERVICE_RUNNING, NO_ERROR, 0, 0, 0);
\r
162 terminateService(6,GetLastError());
\r
165 WaitForSingleObject (killServiceEvent, INFINITE);
\r
168 void InstallService(void)
\r
170 SC_HANDLE myService, scm;
\r
171 SERVICE_DESCRIPTION svDesc;
\r
172 HINSTANCE advapi32;
\r
174 char modname[MAX_PATH];
\r
175 GetModuleFileName(NULL, modname, sizeof(modname));
\r
177 scm = OpenSCManager(0,0,SC_MANAGER_CREATE_SERVICE);
\r
181 myService = CreateService(scm,"InspIRCd","Inspire IRC Daemon", SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS, SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL, modname, 0, 0, 0, 0, 0);
\r
185 CloseServiceHandle(scm);
\r
189 // *** Set service description ***
\r
190 // this is supported from 5.0 (win2k) onwards only, so we can't link to the definition of
\r
191 // this function in advapi32.lib, otherwise the program will not run on windows NT 4. We
\r
192 // must use LoadLibrary and GetProcAddress to export the function name from advapi32.dll
\r
193 advapi32 = LoadLibrary("advapi32.dll");
\r
196 ChangeServiceConf = (SETSERVDESC)GetProcAddress(advapi32,"ChangeServiceConfig2A");
\r
197 if (ChangeServiceConf)
\r
199 char desc[] = "The Inspire Internet Relay Chat Daemon hosts IRC channels and conversations. \
\r
200 If this service is stopped, the IRC server will not run.";
\r
201 svDesc.lpDescription = desc;
\r
202 BOOL success = ChangeServiceConf(myService,SERVICE_CONFIG_DESCRIPTION, &svDesc);
\r
205 CloseServiceHandle(myService);
\r
206 CloseServiceHandle(scm);
\r
210 FreeLibrary(advapi32);
\r
213 CloseServiceHandle(myService);
\r
214 CloseServiceHandle(scm);
\r
217 void RemoveService(void)
\r
219 SC_HANDLE myService, scm;
\r
221 scm = OpenSCManager(0,0,SC_MANAGER_CREATE_SERVICE);
\r
225 myService = OpenService(scm,"InspIRCd",SERVICE_ALL_ACCESS);
\r
228 CloseServiceHandle(scm);
\r
232 if (!DeleteService(myService))
\r
234 CloseServiceHandle(myService);
\r
235 CloseServiceHandle(scm);
\r
239 CloseServiceHandle(myService);
\r
240 CloseServiceHandle(scm);
\r
243 /* In windows, our main() flows through here, before calling the 'real' main, smain() in inspircd.cpp */
\r
244 int main(int argc, char** argv)
\r
246 /* Check for parameters */
\r
249 if (!_stricmp(argv[1], "--installservice"))
\r
254 else if (!_stricmp(argv[1], "--removeservice"))
\r
261 /* First, check if the service is installed.
\r
262 * if it is not, just call smain().
\r
264 SC_HANDLE myService, scm;
\r
265 scm = OpenSCManager(0,0,SC_MANAGER_CREATE_SERVICE);
\r
268 myService = OpenService(scm,"InspIRCd",SERVICE_ALL_ACCESS);
\r
271 /* Service not installed or no permission to modify it */
\r
272 CloseServiceHandle(scm);
\r
278 /* Not enough privileges to open the SCM */
\r
282 CloseServiceHandle(myService);
\r
283 CloseServiceHandle(scm);
\r
285 /* If we get here, we know the service is installed so we can start it */
\r
287 SERVICE_TABLE_ENTRY serviceTable[] =
\r
289 {"InspIRCd", (LPSERVICE_MAIN_FUNCTION) ServiceMain },
\r
293 StartServiceCtrlDispatcher(serviceTable);
\r