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