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