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
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.
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, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
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.
28 * service.c: Windows services support
30 * Known contributors to this file:
31 * Ron Koenderink, 2004
37 #include "prototypes.h"
42 install_service(char *program_name, char *service_name, int datadir_set, char *config_file)
45 HANDLE schSCManager,schService;
46 LPCTSTR lpszBinaryPathName;
47 SERVICE_DESCRIPTION sdBuf;
49 if (strrchr(program_name,'\\') == NULL) {
50 GetCurrentDirectory(sizeof(strDir), strDir);
52 strcat(strDir, program_name);
54 strcpy(strDir, program_name);
57 strcat(strDir, " -D ");
58 strcat(strDir, datadir);
60 if (config_file != NULL) {
61 strcat(strDir, " -e ");
62 strcat(strDir, config_file);
65 if (service_name == NULL)
66 service_name = DEFAULT_SERVICE_NAME;
67 else if (service_name[0] == '\0')
68 service_name = DEFAULT_SERVICE_NAME;
70 schSCManager = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);
72 if (schSCManager == NULL) {
73 fprintf(stderr, "install_service failed to open Service Control Manager\n");
77 lpszBinaryPathName = strDir;
79 schService = CreateService(schSCManager,
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 */
93 if (schService == NULL) {
94 fprintf(stderr, "install_service failed to create service %s\n", service_name);
97 sdBuf.lpDescription = "Server for Empire game";
99 if(!ChangeServiceConfig2(
100 schService, /* handle to service */
101 SERVICE_CONFIG_DESCRIPTION, /* change: description */
102 &sdBuf)) { /* value: new description */
103 fprintf(stderr, "install_service failed to set the description\n");
106 printf("Service %s installed.\n", service_name);
107 CloseServiceHandle(schService);
112 remove_service(char *service_name)
117 if (service_name == NULL)
118 service_name = DEFAULT_SERVICE_NAME;
119 else if (service_name[0] == '\0')
120 service_name = DEFAULT_SERVICE_NAME;
122 schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
124 if (schSCManager == NULL) {
125 fprintf(stderr, "remove_service failed to open Service Control Manager\n");
129 hService = OpenService(schSCManager, service_name, SERVICE_ALL_ACCESS);
131 if (hService == NULL) {
132 fprintf(stderr, "remove_service failed to open service %s\n", service_name);
136 if (DeleteService(hService) == 0) {
137 fprintf(stderr, "remove_service failed to remove service %s\n", service_name);
141 if (CloseServiceHandle(hService) == 0) {
142 fprintf(stderr, "remove_service failed to close service %s\n", service_name);
145 printf("Service %s removed.\n", service_name);
150 static SERVICE_STATUS service_status;
151 static SERVICE_STATUS_HANDLE service_status_handle;
152 static HANDLE hShutdownEvent = NULL;
155 service_ctrl_handler(DWORD Opcode)
159 case SERVICE_CONTROL_PAUSE:
160 service_status.dwCurrentState = SERVICE_PAUSED;
161 logerror("Pausing the service not supported");
164 case SERVICE_CONTROL_CONTINUE:
165 logerror("Continuing the service not supported");
166 service_status.dwCurrentState = SERVICE_RUNNING;
169 case SERVICE_CONTROL_STOP:
170 logerror("Service stopping");
171 SetEvent(hShutdownEvent);
174 case SERVICE_CONTROL_INTERROGATE:
175 /* Fall through to send current status. */
179 logerror("Unrecognized opcode %ld in ServiceCtrlHandler",
183 /* Send current status. */
184 if (!SetServiceStatus (service_status_handle, &service_status))
185 logerror("SetServiceStatus error %ld",GetLastError());
190 service_main(DWORD argc, LPTSTR *argv)
192 service_status.dwServiceType = SERVICE_WIN32;
193 service_status.dwCurrentState = SERVICE_START_PENDING;
194 service_status.dwControlsAccepted = SERVICE_ACCEPT_STOP;
195 service_status.dwWin32ExitCode = 0;
196 service_status.dwServiceSpecificExitCode = 0;
197 service_status.dwCheckPoint = 0;
198 service_status.dwWaitHint = 0;
200 service_status_handle = RegisterServiceCtrlHandler(
201 DEFAULT_SERVICE_NAME, service_ctrl_handler);
203 if (service_status_handle == (SERVICE_STATUS_HANDLE)0) {
204 logerror("RegisterServiceCtrlHandler failed %d\n", GetLastError());
209 if ((hShutdownEvent = CreateEvent(NULL, TRUE, FALSE, NULL)) == NULL) {
210 logerror("CreateEvent for Shutdown failed %d\n", GetLastError());
217 /* Initialization complete - report running status. */
218 service_status.dwCurrentState = SERVICE_RUNNING;
219 service_status.dwCheckPoint = 0;
220 service_status.dwWaitHint = 0;
222 if (!SetServiceStatus (service_status_handle, &service_status)) {
223 logerror("SetServiceStatus error %ld\n", GetLastError());
228 CANT_HAPPEN("main thread terminated");
233 service_stopped(void)
235 if (hShutdownEvent != NULL) {
236 WaitForSingleObject(hShutdownEvent,INFINITE);
243 logerror("Service stopped");
244 service_status.dwWin32ExitCode = 0;
245 service_status.dwCurrentState = SERVICE_STOPPED;
246 service_status.dwCheckPoint = 0;
247 service_status.dwWaitHint = 0;
249 if (!SetServiceStatus (service_status_handle, &service_status))
250 logerror("Error while stopping service SetServiceStatus"
251 " error %ld", GetLastError());