Updated init script.
[dtbartle/bnbt.git] / util_ntservice.cpp
1 /***\r
2 *\r
3 * BNBT Beta 8.0 - A C++ BitTorrent Tracker\r
4 * Copyright (C) 2003 Trevor Hogan\r
5 *\r
6 * CBTT variations (C) 2003-2005 Harold Feit\r
7 *\r
8 * This library is free software; you can redistribute it and/or\r
9 * modify it under the terms of the GNU Lesser General Public\r
10 * License as published by the Free Software Foundation; either\r
11 * version 2.1 of the License, or (at your option) any later version.\r
12 *\r
13 * This library is distributed in the hope that it will be useful,\r
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\r
16 * Lesser General Public License for more details.\r
17 *\r
18 * You should have received a copy of the GNU Lesser General Public\r
19 * License along with this library; if not, write to the Free Software\r
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\r
21 *\r
22 ***/\r
23 \r
24 /***********************************************************************\r
25 * NT Service code written by ConfusedFish and modified by Trevor Hogan *\r
26 ***********************************************************************/\r
27 \r
28 #include "bnbt.h"\r
29 #include "server.h"\r
30 #include "util_ntservice.h"\r
31 #include "util.h"\r
32 #include "config.h"\r
33 \r
34 \r
35 BOOL UTIL_NTServiceTest( )\r
36 {\r
37                 CFG_Open( CFG_FILE );\r
38 //#undef BNBT_SERVICE_NAME\r
39 #define BNBT_SERVICE_NAME const_cast<LPSTR> (CFG_GetString( "cbtt_service_name", "CBTT Service" ).c_str())\r
40                 CFG_Close( CFG_FILE );\r
41 \r
42                 // test if the service is installed or not\r
43 \r
44         BOOL bResult = FALSE;\r
45 \r
46         // open the Service Control Manager\r
47 \r
48         SC_HANDLE hSCM = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS );\r
49 \r
50         if( hSCM )\r
51         {\r
52                 // try to open the service\r
53 \r
54                 SC_HANDLE hService = OpenService( hSCM, BNBT_SERVICE_NAME, SERVICE_QUERY_CONFIG );\r
55 \r
56                 if( hService )\r
57                 {\r
58                         bResult = TRUE;\r
59 \r
60                         CloseServiceHandle( hService );\r
61                 }\r
62 \r
63                 CloseServiceHandle( hSCM );\r
64         }\r
65 \r
66         return bResult;\r
67 }\r
68 \r
69 BOOL UTIL_NTServiceInstall( )\r
70 {\r
71                 CFG_Open( CFG_FILE );\r
72 //#undef BNBT_SERVICE_NAME\r
73 #define BNBT_SERVICE_NAME const_cast<LPSTR> (CFG_GetString( "cbtt_service_name", "CBTT Service" ).c_str())\r
74                 CFG_Close( CFG_FILE );\r
75         // open the Service Control Manager\r
76 \r
77         SC_HANDLE hSCM = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS );\r
78 \r
79         if( !hSCM )\r
80                 return FALSE;\r
81 \r
82         // get the executable file path\r
83 \r
84         char szFilePath[_MAX_PATH];\r
85 \r
86         GetModuleFileName( NULL, szFilePath, sizeof( szFilePath ) );\r
87 \r
88         // add the run as service parameter\r
89 \r
90         strcat( szFilePath, " -s" );\r
91 \r
92         // create the service\r
93 \r
94         SC_HANDLE hService = CreateService(     hSCM,\r
95                                                                                 BNBT_SERVICE_NAME,\r
96                                                                                 BNBT_SERVICE_NAME,\r
97                                                                                 SERVICE_ALL_ACCESS,\r
98                                                                                 SERVICE_WIN32_OWN_PROCESS,\r
99                                                                                 SERVICE_AUTO_START,\r
100                                                                                 SERVICE_ERROR_NORMAL,\r
101                                                                                 szFilePath,\r
102                                                                                 NULL,\r
103                                                                                 NULL,\r
104                                                                                 NULL,\r
105                                                                                 NULL,\r
106                                                                                 NULL );\r
107 \r
108         if( !hService )\r
109         {\r
110                 CloseServiceHandle( hSCM );\r
111 \r
112                 return FALSE;\r
113         }\r
114 \r
115         // make registry entries to support logging messages to the EventLog\r
116 \r
117         char szKey[256];\r
118 \r
119         HKEY hKey = NULL;\r
120 \r
121         strcpy( szKey, "SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\" );\r
122 \r
123         strcat( szKey, BNBT_SERVICE_NAME );\r
124 \r
125         if( RegCreateKey( HKEY_LOCAL_MACHINE, szKey, &hKey ) != ERROR_SUCCESS )\r
126         {\r
127                 CloseServiceHandle( hService );\r
128                 CloseServiceHandle( hSCM );\r
129 \r
130                 return FALSE;\r
131         }\r
132 \r
133         RegSetValueEx( hKey, "EventMessageFile", 0, REG_EXPAND_SZ, (CONST BYTE *)szFilePath, strlen( szFilePath ) + 1 );\r
134 \r
135         // set the supported types flags\r
136 \r
137         DWORD dwData = EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE | EVENTLOG_INFORMATION_TYPE;\r
138 \r
139         RegSetValueEx( hKey, "TypesSupported", 0, REG_DWORD, (CONST BYTE *)&dwData, sizeof( DWORD ) );\r
140 \r
141         RegCloseKey( hKey );\r
142 \r
143         UTIL_NTLogEvent( EVENTLOG_INFORMATION_TYPE, EVMSG_INSTALLED, BNBT_SERVICE_NAME );\r
144 \r
145         // tidy up\r
146 \r
147         CloseServiceHandle( hService );\r
148         CloseServiceHandle( hSCM );\r
149 \r
150         return TRUE;\r
151 }\r
152 \r
153 BOOL UTIL_NTServiceUninstall( )\r
154 {\r
155                 CFG_Open( CFG_FILE );\r
156 //#undef BNBT_SERVICE_NAME\r
157 #define BNBT_SERVICE_NAME const_cast<LPSTR> (CFG_GetString( "cbtt_service_name", "CBTT Service" ).c_str())\r
158                 CFG_Close( CFG_FILE );\r
159         // open the Service Control Manager\r
160 \r
161         SC_HANDLE hSCM = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS );\r
162 \r
163         if( !hSCM )\r
164                 return FALSE;\r
165 \r
166         BOOL bResult = FALSE;\r
167 \r
168         SC_HANDLE hService = OpenService( hSCM, BNBT_SERVICE_NAME, DELETE );\r
169 \r
170         if( hService )\r
171         {\r
172                 if( DeleteService( hService ) )\r
173                 {\r
174                         UTIL_NTLogEvent( EVENTLOG_INFORMATION_TYPE, EVMSG_REMOVED, BNBT_SERVICE_NAME );\r
175 \r
176                         bResult = TRUE;\r
177                 }\r
178                 else\r
179                         UTIL_NTLogEvent( EVENTLOG_ERROR_TYPE, EVMSG_NOTREMOVED, BNBT_SERVICE_NAME );\r
180 \r
181                 CloseServiceHandle( hService );\r
182         }\r
183 \r
184         CloseServiceHandle( hSCM );\r
185 \r
186         return bResult;\r
187 }\r
188 \r
189 BOOL UTIL_NTServiceStart( )\r
190 {\r
191                 CFG_Open( CFG_FILE );\r
192 //#undef BNBT_SERVICE_NAME\r
193 #define BNBT_SERVICE_NAME const_cast<LPSTR> (CFG_GetString( "cbtt_service_name", "CBTT Service" ).c_str())\r
194                 CFG_Close( CFG_FILE );\r
195         BOOL bResult = FALSE;\r
196 \r
197         // open the Service Control Manager\r
198 \r
199         SC_HANDLE hSCM = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS );\r
200 \r
201         if( hSCM )\r
202         {\r
203                 // try to open the service\r
204 \r
205                 SC_HANDLE hService = OpenService( hSCM, BNBT_SERVICE_NAME, SERVICE_START );\r
206 \r
207                 if( hService )\r
208                 {\r
209                         StartService( hService, 0, NULL );\r
210 \r
211                         bResult = TRUE;\r
212 \r
213                         CloseServiceHandle( hService );\r
214                 }\r
215 \r
216                 // tidy up\r
217 \r
218                 CloseServiceHandle( hSCM );\r
219         }\r
220 \r
221         return bResult;\r
222 }\r
223 \r
224 BOOL UTIL_NTServiceStop( )\r
225 {\r
226                 CFG_Open( CFG_FILE );\r
227 //#undef BNBT_SERVICE_NAME\r
228 #define BNBT_SERVICE_NAME const_cast<LPSTR> (CFG_GetString( "cbtt_service_name", "CBTT Service" ).c_str())\r
229                 CFG_Close( CFG_FILE );\r
230         BOOL bResult = FALSE;\r
231 \r
232         // open the Service Control Manager\r
233 \r
234         SC_HANDLE hSCM = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS );\r
235 \r
236         if( hSCM )\r
237         {\r
238                 // try to open the service\r
239 \r
240                 SC_HANDLE hService = OpenService( hSCM, BNBT_SERVICE_NAME, SERVICE_STOP );\r
241 \r
242                 if( hService )\r
243                 {\r
244                         SERVICE_STATUS ssStatus;\r
245 \r
246                         if( ControlService( hService, SERVICE_CONTROL_STOP, &ssStatus ) )\r
247                                 bResult = TRUE;\r
248 \r
249                         CloseServiceHandle( hService );\r
250                 }\r
251 \r
252                 CloseServiceHandle( hSCM );\r
253         }\r
254 \r
255         return bResult;\r
256 }\r
257 \r
258 void UTIL_NTLogEvent( WORD wType, DWORD dwID, const char *pszS1, const char *pszS2, const char *pszS3 )\r
259 {\r
260                 CFG_Open( CFG_FILE );\r
261 //#undef BNBT_SERVICE_NAME\r
262 #define BNBT_SERVICE_NAME const_cast<LPSTR> (CFG_GetString( "cbtt_service_name", "CBTT Service" ).c_str())\r
263                 CFG_Close( CFG_FILE );\r
264         // make an entry into the application event log\r
265 \r
266         const char *ps[3];\r
267         ps[0] = pszS1;\r
268         ps[1] = pszS2;\r
269         ps[2] = pszS3;\r
270 \r
271         int iStr = 0;\r
272 \r
273         for( int i = 0; i < 3; i++ )\r
274         {\r
275                 if( ps[i] != NULL )\r
276                         iStr++;\r
277         }\r
278 \r
279         // check if the event source has been registered, and if not then register it now\r
280 \r
281         HANDLE hNTEventSource = RegisterEventSource( NULL, BNBT_SERVICE_NAME );\r
282 \r
283         if( hNTEventSource )\r
284         {\r
285                 ReportEvent( hNTEventSource, wType, 0, dwID, NULL, iStr, 0, ps, NULL );\r
286 \r
287                 DeregisterEventSource( hNTEventSource );\r
288         }\r
289 }\r
290 \r
291 void WINAPI NTServiceHandler( DWORD dwOpcode )\r
292 {\r
293                 CFG_Open( CFG_FILE );\r
294 //#undef BNBT_SERVICE_NAME\r
295 #define BNBT_SERVICE_NAME const_cast<LPSTR> (CFG_GetString( "cbtt_service_name", "CBTT Service" ).c_str())\r
296                 CFG_Close( CFG_FILE );\r
297         // handle commands from the Service Control Manager\r
298 \r
299         if( dwOpcode == SERVICE_CONTROL_STOP )\r
300         {\r
301                 gssStatus.dwCurrentState = SERVICE_STOP_PENDING;\r
302 \r
303                 SetServiceStatus( ghServiceStatus, &gssStatus );\r
304 \r
305                 gpServer->Kill( );\r
306         }\r
307 \r
308         SetServiceStatus( ghServiceStatus, &gssStatus );\r
309 }\r
310 \r
311 void WINAPI NTServiceMain( DWORD dwArgc, LPTSTR *lpszArgv )\r
312 {\r
313         gssStatus.dwCheckPoint = 0;\r
314         gssStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;\r
315         gssStatus.dwCurrentState = SERVICE_START_PENDING;\r
316         gssStatus.dwServiceSpecificExitCode = 0;\r
317         gssStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;\r
318         gssStatus.dwWaitHint = 0;\r
319         gssStatus.dwWin32ExitCode = 0;\r
320 \r
321         // register the control request handler\r
322 \r
323         if( !( ghServiceStatus = RegisterServiceCtrlHandler( BNBT_SERVICE_NAME, NTServiceHandler ) ) )\r
324                 return;\r
325 \r
326         SetServiceStatus( ghServiceStatus, &gssStatus );\r
327 \r
328         gssStatus.dwWin32ExitCode = 0;\r
329         gssStatus.dwCheckPoint = 0;\r
330         gssStatus.dwWaitHint = 0;\r
331 \r
332         UTIL_NTLogEvent( EVENTLOG_INFORMATION_TYPE, EVMSG_STARTED );\r
333 \r
334         // tell the Service Control Manager we started\r
335 \r
336         gssStatus.dwCurrentState = SERVICE_RUNNING;\r
337 \r
338         SetServiceStatus( ghServiceStatus, &gssStatus );\r
339 \r
340         gssStatus.dwWin32ExitCode = 0;\r
341         gssStatus.dwCheckPoint = 0;\r
342         gssStatus.dwWaitHint = 0;\r
343 \r
344         // run the tracker\r
345 \r
346         bnbtmain( );\r
347 \r
348         // tell the Service Control Manager we stopped\r
349 \r
350         UTIL_NTLogEvent( EVENTLOG_INFORMATION_TYPE, EVMSG_STOPPED );\r
351 \r
352         gssStatus.dwCurrentState = SERVICE_STOPPED;\r
353 \r
354         SetServiceStatus( ghServiceStatus, &gssStatus );\r
355 }\r
356 \r
357 SERVICE_STATUS_HANDLE ghServiceStatus;\r
358 SERVICE_STATUS gssStatus;\r