2 * Empire - A multi-player, client/server Internet based war game.
3 * Copyright (C) 1986-2017, Dave Pare, Jeff Bailey, Thomas Ruschak,
4 * Ken Stevens, Steve McClure, Markus Armbruster
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.
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.
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/>.
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.
27 * service.c: Windows services support
29 * Known contributors to this file:
30 * Ron Koenderink, 2004-2009
36 #include "empthread.h"
37 #include "prototypes.h"
40 install_service(char *program_name, char *service_name, char *config_file)
42 HANDLE schSCManager,schService;
43 SERVICE_DESCRIPTION sdBuf;
45 if (config_file != NULL)
46 snprintf(&program_name[strlen(program_name)],
47 _MAX_PATH - strlen(program_name),
48 " -e %s", config_file);
50 if (service_name == NULL)
51 service_name = DEFAULT_SERVICE_NAME;
52 else if (service_name[0] == '\0')
53 service_name = DEFAULT_SERVICE_NAME;
55 schSCManager = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);
57 if (schSCManager == NULL) {
58 fprintf(stderr, "install_service failed to open Service Control Manager\n");
62 schService = CreateService(schSCManager,
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 */
76 if (schService == NULL) {
77 fprintf(stderr, "install_service failed to create service %s\n", service_name);
80 sdBuf.lpDescription = "Server for Empire game";
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");
89 printf("Service %s installed.\n", service_name);
90 CloseServiceHandle(schService);
95 remove_service(char *service_name)
100 if (service_name == NULL)
101 service_name = DEFAULT_SERVICE_NAME;
102 else if (service_name[0] == '\0')
103 service_name = DEFAULT_SERVICE_NAME;
105 schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
107 if (schSCManager == NULL) {
108 fprintf(stderr, "remove_service failed to open Service Control Manager\n");
112 hService = OpenService(schSCManager, service_name, SERVICE_ALL_ACCESS);
114 if (hService == NULL) {
115 fprintf(stderr, "remove_service failed to open service %s\n", service_name);
119 if (DeleteService(hService) == 0) {
120 fprintf(stderr, "remove_service failed to remove service %s\n", service_name);
124 if (CloseServiceHandle(hService) == 0) {
125 fprintf(stderr, "remove_service failed to close service %s\n", service_name);
128 printf("Service %s removed.\n", service_name);
133 static SERVICE_STATUS service_status;
134 static SERVICE_STATUS_HANDLE service_status_handle;
137 service_ctrl_handler(DWORD Opcode)
140 case SERVICE_CONTROL_PAUSE:
141 service_status.dwCurrentState = SERVICE_PAUSED;
142 logerror("Pausing the service not supported");
145 case SERVICE_CONTROL_CONTINUE:
146 logerror("Continuing the service not supported");
147 service_status.dwCurrentState = SERVICE_RUNNING;
150 case SERVICE_CONTROL_STOP:
151 logerror("Service stopping");
152 empth_request_shutdown();
155 case SERVICE_CONTROL_INTERROGATE:
156 /* Fall through to send current status. */
160 logerror("Unrecognized opcode %ld in ServiceCtrlHandler",
164 /* Send current status. */
165 if (!SetServiceStatus (service_status_handle, &service_status))
166 logerror("SetServiceStatus error %ld",GetLastError());
171 service_main(DWORD argc, LPTSTR *argv)
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;
183 service_status_handle = RegisterServiceCtrlHandler(
184 DEFAULT_SERVICE_NAME, service_ctrl_handler);
186 if (service_status_handle == (SERVICE_STATUS_HANDLE)0) {
187 logerror("RegisterServiceCtrlHandler failed %lu\n", GetLastError());
194 /* Initialization complete - report running status. */
195 service_status.dwCurrentState = SERVICE_RUNNING;
196 service_status.dwCheckPoint = 0;
197 service_status.dwWaitHint = 0;
199 if (!SetServiceStatus (service_status_handle, &service_status)) {
200 logerror("SetServiceStatus error %ld\n", GetLastError());
203 sig = empth_wait_for_signal();
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;
220 if (!SetServiceStatus (service_status_handle, &service_status))
221 logerror("Error while stopping service SetServiceStatus"
222 " error %ld", GetLastError());