]> git.pond.sub.org Git - empserver/blob - src/lib/gen/service.c
a5abe241f80c52e8240ceb759e5ad15bfea2ce40
[empserver] / src / lib / gen / service.c
1 /*
2  *  Empire - A multi-player, client/server Internet based war game.
3  *  Copyright (C) 1986-2006, 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 files README, COPYING and CREDITS in the root of the source
23  *  tree for related information and legal notices.  It is expected
24  *  that future 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 <config.h>
35
36 #ifdef _WIN32
37 #include <windows.h>
38
39 #include "service.h"
40 #include "empthread.h"
41 #include "prototypes.h"
42
43 int
44 install_service(char *program_name, char *service_name, char *config_file)
45 {
46     HANDLE schSCManager,schService;
47     SERVICE_DESCRIPTION sdBuf;
48
49     if (config_file != NULL)
50         snprintf(&program_name[strlen(program_name)], _MAX_PATH-strlen(program_name), " -e %s",
51             config_file);
52
53     if (service_name == NULL)
54         service_name = DEFAULT_SERVICE_NAME;
55     else if (service_name[0] == '\0')
56         service_name = DEFAULT_SERVICE_NAME;
57
58     schSCManager = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);
59
60     if (schSCManager == NULL) {
61         fprintf(stderr, "install_service failed to open Service Control Manager\n"); 
62         return EXIT_FAILURE;
63     }
64
65     schService = CreateService(schSCManager,
66         service_name,
67         service_name,                   /* service name to display */
68         SERVICE_ALL_ACCESS,             /* desired access */
69         SERVICE_WIN32_OWN_PROCESS,      /* service type */
70         SERVICE_AUTO_START,             /* start type */
71         SERVICE_ERROR_NORMAL,           /* error control type */
72         program_name,                   /* service's binary */
73         NULL,                           /* no load ordering group */
74         NULL,                           /* no tag identifier */
75         NULL,                           /* database service dependency */
76         NULL,                           /* LocalSystem account */
77         NULL);                          /* no password */
78  
79     if (schService == NULL) {
80         fprintf(stderr, "install_service failed to create service %s\n", service_name);
81         return EXIT_FAILURE;
82     }
83     sdBuf.lpDescription = "Server for Empire game";
84
85     if(!ChangeServiceConfig2(
86           schService,                 /* handle to service */
87           SERVICE_CONFIG_DESCRIPTION, /* change: description */
88           &sdBuf)) {                  /* value: new description */
89         fprintf(stderr, "install_service failed to set the description\n");
90     }
91
92     printf("Service %s installed.\n", service_name);
93     CloseServiceHandle(schService);
94     return EXIT_SUCCESS;
95 }
96
97 int
98 remove_service(char *service_name)
99 {
100     HANDLE schSCManager;
101     SC_HANDLE hService;
102
103     if (service_name == NULL)
104         service_name = DEFAULT_SERVICE_NAME;
105     else if (service_name[0] == '\0')
106         service_name = DEFAULT_SERVICE_NAME;
107
108     schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
109
110     if (schSCManager == NULL) {
111         fprintf(stderr, "remove_service failed to open Service Control Manager\n"); 
112         return EXIT_FAILURE;
113     }
114
115     hService = OpenService(schSCManager, service_name, SERVICE_ALL_ACCESS);
116
117     if (hService == NULL) {
118         fprintf(stderr, "remove_service failed to open service %s\n", service_name);
119         return EXIT_FAILURE;
120     }
121
122     if (DeleteService(hService) == 0) {
123         fprintf(stderr, "remove_service failed to remove service %s\n", service_name);
124         return EXIT_FAILURE;
125     }
126
127     if (CloseServiceHandle(hService) == 0) {
128         fprintf(stderr, "remove_service failed to close service %s\n", service_name); 
129         return EXIT_FAILURE;
130     } else {
131         printf("Service %s removed.\n", service_name); 
132         return EXIT_SUCCESS;
133     }
134 }
135
136 static SERVICE_STATUS           service_status; 
137 static SERVICE_STATUS_HANDLE    service_status_handle;
138
139 static void WINAPI
140 service_ctrl_handler(DWORD Opcode) 
141
142     switch(Opcode) { 
143         case SERVICE_CONTROL_PAUSE: 
144             service_status.dwCurrentState = SERVICE_PAUSED;
145             logerror("Pausing the service not supported");
146             break; 
147  
148         case SERVICE_CONTROL_CONTINUE: 
149             logerror("Continuing the service not supported");
150             service_status.dwCurrentState = SERVICE_RUNNING; 
151             break; 
152  
153         case SERVICE_CONTROL_STOP:
154             logerror("Service stopping");
155             empth_request_shutdown();
156             return; 
157  
158         case SERVICE_CONTROL_INTERROGATE: 
159         /* Fall through to send current status.  */
160             break; 
161  
162         default: 
163             logerror("Unrecognized opcode %ld in ServiceCtrlHandler", 
164                 Opcode); 
165     } 
166  
167     /* Send current status. */
168     if (!SetServiceStatus (service_status_handle,  &service_status))
169         logerror("SetServiceStatus error %ld",GetLastError()); 
170     return; 
171
172
173 void WINAPI
174 service_main(DWORD argc, LPTSTR *argv)
175 {
176     int sig;
177     
178     service_status.dwServiceType        = SERVICE_WIN32; 
179     service_status.dwCurrentState       = SERVICE_START_PENDING; 
180     service_status.dwControlsAccepted   = SERVICE_ACCEPT_STOP; 
181     service_status.dwWin32ExitCode      = 0; 
182     service_status.dwServiceSpecificExitCode = 0; 
183     service_status.dwCheckPoint         = 0; 
184     service_status.dwWaitHint           = 0; 
185  
186     service_status_handle = RegisterServiceCtrlHandler(
187         DEFAULT_SERVICE_NAME, service_ctrl_handler);
188  
189     if (service_status_handle == (SERVICE_STATUS_HANDLE)0) { 
190         logerror("RegisterServiceCtrlHandler failed %lu\n", GetLastError());
191         finish_server();
192         return;
193     }
194  
195     start_server(0);
196  
197     /* Initialization complete - report running status. */
198     service_status.dwCurrentState       = SERVICE_RUNNING; 
199     service_status.dwCheckPoint         = 0; 
200     service_status.dwWaitHint           = 0; 
201  
202     if (!SetServiceStatus (service_status_handle, &service_status)) { 
203         logerror("SetServiceStatus error %ld\n", GetLastError());
204     }
205
206     sig = empth_wait_for_signal();
207
208     shutdwn(sig);
209
210     CANT_REACH();
211     finish_server();
212 }
213
214 void
215 stop_service(void)
216 {
217     logerror("Service stopped");
218     service_status.dwWin32ExitCode = 0; 
219     service_status.dwCurrentState  = SERVICE_STOPPED; 
220     service_status.dwCheckPoint    = 0; 
221     service_status.dwWaitHint      = 0; 
222
223     if (!SetServiceStatus (service_status_handle, &service_status)) 
224         logerror("Error while stopping service SetServiceStatus"
225             " error %ld", GetLastError()); 
226 }
227
228 #endif /* _WIN32 */