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