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