]> git.pond.sub.org Git - empserver/blob - src/lib/gen/service.c
(main,service_main) [_WIN32]: Fix config_file for 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 #ifdef _WIN32
35 #include <windows.h>
36
37 #include "prototypes.h"
38 #include "service.h"
39 #include "../gen/getopt.h"
40 #include "optlist.h"
41
42 int
43 install_service(char *program_name, char *service_name, int datadir_set, char *config_file)
44 {
45     char strDir[1024];
46     HANDLE schSCManager,schService;
47     LPCTSTR lpszBinaryPathName;
48     SERVICE_DESCRIPTION sdBuf;
49
50     if (strrchr(program_name,'\\') == NULL) {
51         GetCurrentDirectory(sizeof(strDir), strDir);
52         strcat(strDir, "\\");
53         strcat(strDir, program_name);
54     } else
55         strcpy(strDir, program_name);
56
57     if (datadir_set) {
58         strcat(strDir, " -D ");
59         strcat(strDir, datadir);
60     }
61     if (config_file != NULL) {
62         strcat(strDir, " -e ");
63         strcat(strDir, config_file);
64     }
65
66     if (service_name == NULL)
67         service_name = DEFAULT_SERVICE_NAME;
68     else if (service_name[0] == '\0')
69         service_name = DEFAULT_SERVICE_NAME;
70
71     schSCManager = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);
72
73     if (schSCManager == NULL) {
74         logerror("install_service failed to open Service Control Manager"); 
75         printf("Install service: failed to open Service Control Manager.\n"); 
76         return EXIT_FAILURE;
77     }
78
79     lpszBinaryPathName = strDir;
80
81     schService = CreateService(schSCManager,
82         service_name,
83         service_name,                   /* service name to display */
84         SERVICE_ALL_ACCESS,             /* desired access */
85         SERVICE_WIN32_OWN_PROCESS,      /* service type */
86         SERVICE_AUTO_START,             /* start type */
87         SERVICE_ERROR_NORMAL,           /* error control type */
88         lpszBinaryPathName,             /* service's binary */
89         NULL,                           /* no load ordering group */
90         NULL,                           /* no tag identifier */
91         NULL,                           /* database service dependency */
92         NULL,                           /* LocalSystem account */
93         NULL);                          /* no password */
94  
95     if (schService == NULL) {
96         logerror("install_service failed to create service %s", service_name);
97         printf("Install service: failed to create service %s.\n", service_name);
98         return EXIT_FAILURE;
99     }
100     sdBuf.lpDescription = "Server for Empire game";
101
102     if(!ChangeServiceConfig2(
103           schService,                 /* handle to service */
104           SERVICE_CONFIG_DESCRIPTION, /* change: description */
105           &sdBuf)) {                  /* value: new description */
106         logerror("install_service failed to set the description");
107         printf("Install service: failed to set the description.\n");
108     }
109
110     logerror("install_service successfully created the service %s", service_name);
111     printf("Service %s installed.\n", service_name);
112     CloseServiceHandle(schService);
113     return EXIT_SUCCESS;
114 }
115
116 int
117 remove_service(char *service_name)
118 {
119     HANDLE schSCManager;
120     SC_HANDLE hService;
121
122     if (service_name == NULL)
123         service_name = DEFAULT_SERVICE_NAME;
124     else if (service_name[0] == '\0')
125         service_name = DEFAULT_SERVICE_NAME;
126
127     schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
128
129     if (schSCManager == NULL) {
130         logerror("remove_service failed to open Service Control Manager"); 
131         printf("remove service: failed to open Service Control Manager.\n"); 
132         return EXIT_FAILURE;
133     }
134
135     hService = OpenService(schSCManager, service_name, SERVICE_ALL_ACCESS);
136
137     if (hService == NULL) {
138         logerror("remove_service failed to open service %s", service_name);
139         printf("Remove service: failed to open service %s.\n", service_name);
140         return EXIT_FAILURE;
141     }
142
143     if (DeleteService(hService) == 0) {
144         logerror("remove_service failed to remove service %s", service_name);
145         printf("Remove service: failed to remove service %s.\n", service_name); 
146         return EXIT_FAILURE;
147     }
148
149     if (CloseServiceHandle(hService) == 0) {
150         logerror("remove_service failed to close service %s", service_name); 
151         printf("Remove service: failed to close service %s.\n", service_name); 
152         return EXIT_FAILURE;
153     } else {
154         logerror("remove_service successfully removed service %s", service_name);
155         printf("Service %s removed.\n", service_name); 
156         return EXIT_SUCCESS;
157     }
158 }
159
160 static SERVICE_STATUS          service_status; 
161 static SERVICE_STATUS_HANDLE   service_status_handle; 
162
163 void WINAPI
164 service_ctrl_handler(DWORD Opcode) 
165
166     DWORD status; 
167  
168     switch(Opcode) 
169     { 
170         case SERVICE_CONTROL_PAUSE: 
171             service_status.dwCurrentState = SERVICE_PAUSED;
172             logerror("Pausing the service not supported");
173             break; 
174  
175         case SERVICE_CONTROL_CONTINUE: 
176             logerror("Continuing the service not supported");
177             service_status.dwCurrentState = SERVICE_RUNNING; 
178             break; 
179  
180         case SERVICE_CONTROL_STOP: 
181             service_status.dwWin32ExitCode = 0; 
182             service_status.dwCurrentState  = SERVICE_STOPPED; 
183             service_status.dwCheckPoint    = 0; 
184             service_status.dwWaitHint      = 0; 
185  
186             if (!SetServiceStatus (service_status_handle, 
187                 &service_status)) { 
188                 status = GetLastError(); 
189                 logerror("Error while stopping service SetServiceStatus"
190                     " error %ld", status); 
191             } 
192  
193             logerror("Service stopped"); 
194             return; 
195  
196         case SERVICE_CONTROL_INTERROGATE: 
197         /* Fall through to send current status.  */
198             break; 
199  
200         default: 
201             logerror("Unrecognized opcode %ld in ServiceCtrlHandler", 
202                 Opcode); 
203     } 
204  
205     /* Send current status. */
206     if (!SetServiceStatus (service_status_handle,  &service_status)) { 
207         status = GetLastError(); 
208         logerror("SetServiceStatus error %ld",status); 
209     } 
210     return; 
211
212
213 void WINAPI
214 service_main(DWORD argc, LPTSTR *argv)
215
216     int op;
217     s_char tbuf[256];
218     DWORD status;
219     char *config_file = NULL;
220
221     optind = 1;
222     opterr = 1;
223     while ((op = getopt(argc, argv, "D:e:")) != EOF) {
224         switch (op) {
225         case 'D':
226                 datadir = optarg;
227                 break;
228         case 'e':
229                 config_file = optarg;
230                 break;
231         }
232     }  
233
234     if (config_file == NULL) {
235         sprintf(tbuf, "%s/econfig", datadir);
236         config_file = tbuf;
237     }
238     emp_config(config_file);
239
240     service_status.dwServiceType        = SERVICE_WIN32; 
241     service_status.dwCurrentState       = SERVICE_START_PENDING; 
242     service_status.dwControlsAccepted   = SERVICE_ACCEPT_STOP; 
243     service_status.dwWin32ExitCode      = 0; 
244     service_status.dwServiceSpecificExitCode = 0; 
245     service_status.dwCheckPoint         = 0; 
246     service_status.dwWaitHint           = 0; 
247  
248     service_status_handle = RegisterServiceCtrlHandler(
249         DEFAULT_SERVICE_NAME, service_ctrl_handler);
250  
251     if (service_status_handle == (SERVICE_STATUS_HANDLE)0) { 
252         logerror("RegisterServiceCtrlHandler failed %d\n", GetLastError()); 
253         return; 
254     }
255  
256     /* Initialization code goes here. */
257     init_server(0);
258     start_server(0);
259  
260     /* Initialization complete - report running status. */
261     service_status.dwCurrentState       = SERVICE_RUNNING; 
262     service_status.dwCheckPoint         = 0; 
263     service_status.dwWaitHint           = 0; 
264  
265     if (!SetServiceStatus (service_status_handle, &service_status)) { 
266         status = GetLastError();
267         logerror("SetServiceStatus error %ld\n",status);
268     }
269
270     empth_exit();
271
272 /* We should never get here.  But, just in case... */
273     close_files();
274
275     loc_NTTerm();
276
277     // This is where the service does its work.
278     logerror("Returning the Main Thread \n",0);
279     return;
280 }
281
282 int
283 service_stopped(void)
284 {
285     if (service_status.dwCurrentState == SERVICE_STOPPED)
286         return 1;
287     else
288         return 0;
289 }
290
291 #endif /* _WIN32 */