]> git.pond.sub.org Git - empserver/blob - src/lib/gen/service.c
(main,install_service,remove_service,service_main) [_WIN32]:
[empserver] / src / lib / gen / service.c
1 /*
2  *  Empire - A multi-player, client/server Internet based war game.
3  *  Copyright (C) 1986-2004, Dave Pare, Jeff Bailey, Thomas Ruschak,
4  *                           Ken Stevens, Steve McClure
5  *
6  *  This program is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation; either version 2 of the License, or
9  *  (at your option) any later version.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  *  ---
21  *
22  *  See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the
23  *  related information and legal notices. It is expected that any future
24  *  projects/authors will amend these files as needed.
25  *
26  *  ---
27  *
28  *  service.c: Windows services support
29  * 
30  *  Known contributors to this file:
31  *     Ron Koenderink, 2004
32  */
33
34 #include <windows.h>
35 #include <winsock.h>
36 #include <process.h>
37 #include <stdio.h>
38
39 #include "prototypes.h"
40 #include "service.h"
41 #include "../gen/getopt.h"
42 #include "optlist.h"
43
44
45 char *config_file = NULL;
46
47 int
48 install_service(char *program_name, char *service_name, int datadir_set)
49 {
50     char strDir[1024];
51     HANDLE schSCManager,schService;
52     LPCTSTR lpszBinaryPathName;
53     SERVICE_DESCRIPTION sdBuf;
54
55     if (strrchr(program_name,'\\') == NULL) {
56         GetCurrentDirectory(sizeof(strDir), strDir);
57         strcat(strDir, "\\");
58         strcat(strDir, program_name);
59     } else
60         strcpy(strDir, program_name);
61
62     if (datadir_set) {
63         strcat(strDir, " -D ");
64         strcat(strDir, datadir);
65     }
66     if (config_file != NULL) {
67         strcat(strDir, " -e ");
68         strcat(strDir, config_file);
69     }
70
71     if (service_name == NULL)
72         service_name = DEFAULT_SERVICE_NAME;
73     else if (service_name[0] == '\0')
74         service_name = DEFAULT_SERVICE_NAME;
75
76     schSCManager = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);
77
78     if (schSCManager == NULL) {
79         logerror("install_service failed to open Service Control Manager"); 
80         printf("Install service: failed to open Service Control Manager.\n"); 
81         return EXIT_FAILURE;
82     }
83
84     lpszBinaryPathName = strDir;
85
86     schService = CreateService(schSCManager,
87         service_name,
88         service_name,                   /* service name to display */
89         SERVICE_ALL_ACCESS,             /* desired access */
90         SERVICE_WIN32_OWN_PROCESS,      /* service type */
91         SERVICE_AUTO_START,             /* start type */
92         SERVICE_ERROR_NORMAL,           /* error control type */
93         lpszBinaryPathName,             /* service's binary */
94         NULL,                           /* no load ordering group */
95         NULL,                           /* no tag identifier */
96         NULL,                           /* database service dependency */
97         NULL,                           /* LocalSystem account */
98         NULL);                          /* no password */
99  
100     if (schService == NULL) {
101         logerror("install_service failed to create service %s", service_name);
102         printf("Install service: failed to create service %s.\n", service_name);
103         return EXIT_FAILURE;
104     }
105     sdBuf.lpDescription = "Server for Empire game";
106
107     if(!ChangeServiceConfig2(
108           schService,                 /* handle to service */
109           SERVICE_CONFIG_DESCRIPTION, /* change: description */
110           &sdBuf)) {                  /* value: new description */
111         logerror("install_service failed to set the description");
112         printf("Install service: failed to set the description.\n");
113     }
114
115     logerror("install_service successfully created the service %s", service_name);
116     printf("Service %s installed.\n", service_name);
117     CloseServiceHandle(schService);
118     return EXIT_SUCCESS;
119 }
120
121 int
122 remove_service(char *service_name)
123 {
124     HANDLE schSCManager;
125     SC_HANDLE hService;
126
127     if (service_name == NULL)
128         service_name = DEFAULT_SERVICE_NAME;
129     else if (service_name[0] == '\0')
130         service_name = DEFAULT_SERVICE_NAME;
131
132     schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
133
134     if (schSCManager == NULL) {
135         logerror("remove_service failed to open Service Control Manager"); 
136         printf("remove service: failed to open Service Control Manager.\n"); 
137         return EXIT_FAILURE;
138     }
139
140     hService = OpenService(schSCManager, service_name, SERVICE_ALL_ACCESS);
141
142     if (hService == NULL) {
143         logerror("remove_service failed to open service %s", service_name);
144         printf("Remove service: failed to open service %s.\n", service_name);
145         return EXIT_FAILURE;
146     }
147
148     if (DeleteService(hService) == 0) {
149         logerror("remove_service failed to remove service %s", service_name);
150         printf("Remove service: failed to remove service %s.\n", service_name); 
151         return EXIT_FAILURE;
152     }
153
154     if (CloseServiceHandle(hService) == 0) {
155         logerror("remove_service failed to close service %s", service_name); 
156         printf("Remove service: failed to close service %s.\n", service_name); 
157         return EXIT_FAILURE;
158     } else {
159         logerror("remove_service successfully removed service %s", service_name);
160         printf("Service %s removed.\n", service_name); 
161         return EXIT_SUCCESS;
162     }
163 }
164
165 static SERVICE_STATUS          service_status; 
166 static SERVICE_STATUS_HANDLE   service_status_handle; 
167
168 void WINAPI
169 service_ctrl_handler(DWORD Opcode) 
170
171     DWORD status; 
172  
173     switch(Opcode) 
174     { 
175         case SERVICE_CONTROL_PAUSE: 
176             service_status.dwCurrentState = SERVICE_PAUSED;
177             logerror("Pausing the service not supported");
178             break; 
179  
180         case SERVICE_CONTROL_CONTINUE: 
181             logerror("Continuing the service not supported");
182             service_status.dwCurrentState = SERVICE_RUNNING; 
183             break; 
184  
185         case SERVICE_CONTROL_STOP: 
186             service_status.dwWin32ExitCode = 0; 
187             service_status.dwCurrentState  = SERVICE_STOPPED; 
188             service_status.dwCheckPoint    = 0; 
189             service_status.dwWaitHint      = 0; 
190  
191             if (!SetServiceStatus (service_status_handle, 
192                 &service_status)) { 
193                 status = GetLastError(); 
194                 logerror("Error while stopping service SetServiceStatus"
195                     " error %ld", status); 
196             } 
197  
198             logerror("Service stopped"); 
199             return; 
200  
201         case SERVICE_CONTROL_INTERROGATE: 
202         /* Fall through to send current status.  */
203             break; 
204  
205         default: 
206             logerror("Unrecognized opcode %ld in ServiceCtrlHandler", 
207                 Opcode); 
208     } 
209  
210     /* Send current status. */
211     if (!SetServiceStatus (service_status_handle,  &service_status)) { 
212         status = GetLastError(); 
213         logerror("SetServiceStatus error %ld",status); 
214     } 
215     return; 
216
217
218 void WINAPI
219 service_main(DWORD argc, LPTSTR *argv)
220
221     int op;
222     s_char tbuf[256];
223     DWORD status;
224
225 //    DebugBreak();
226     optind = 1;
227     opterr = 1;
228     while ((op = getopt(argc, argv, "D:e:")) != EOF) {
229         switch (op) {
230         case 'D':
231                 datadir = optarg;
232                 break;
233         case 'e':
234                 config_file = optarg;
235                 break;
236         }
237     }  
238
239     if (config_file == NULL) {
240         sprintf(tbuf, "%s/econfig", datadir);
241         config_file = tbuf;
242     }
243
244     service_status.dwServiceType        = SERVICE_WIN32; 
245     service_status.dwCurrentState       = SERVICE_START_PENDING; 
246     service_status.dwControlsAccepted   = SERVICE_ACCEPT_STOP; 
247     service_status.dwWin32ExitCode      = 0; 
248     service_status.dwServiceSpecificExitCode = 0; 
249     service_status.dwCheckPoint         = 0; 
250     service_status.dwWaitHint           = 0; 
251  
252     service_status_handle = RegisterServiceCtrlHandler(
253         DEFAULT_SERVICE_NAME, service_ctrl_handler);
254  
255     if (service_status_handle == (SERVICE_STATUS_HANDLE)0) { 
256         logerror("RegisterServiceCtrlHandler failed %d\n", GetLastError()); 
257         return; 
258     }
259  
260     /* Initialization code goes here. */
261     start_server(0, config_file); 
262  
263     /* Initialization complete - report running status. */
264     service_status.dwCurrentState       = SERVICE_RUNNING; 
265     service_status.dwCheckPoint         = 0; 
266     service_status.dwWaitHint           = 0; 
267  
268     if (!SetServiceStatus (service_status_handle, &service_status)) { 
269         status = GetLastError();
270         logerror("SetServiceStatus error %ld\n",status);
271     }
272
273     empth_exit();
274
275 /* We should never get here.  But, just in case... */
276     close_files();
277
278     loc_NTTerm();
279
280     // This is where the service does its work.
281     logerror("Returning the Main Thread \n",0);
282     return;
283 }
284
285 int
286 service_stopped(void)
287 {
288     if (service_status.dwCurrentState == SERVICE_STOPPED)
289         return 1;
290     else
291         return 0;
292 }