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