src/lib/w32/service.c

Go to the documentation of this file.
00001 /*
00002  *  Empire - A multi-player, client/server Internet based war game.
00003  *  Copyright (C) 1986-2007, Dave Pare, Jeff Bailey, Thomas Ruschak,
00004  *                           Ken Stevens, Steve McClure
00005  *
00006  *  This program is free software; you can redistribute it and/or modify
00007  *  it under the terms of the GNU General Public License as published by
00008  *  the Free Software Foundation; either version 2 of the License, or
00009  *  (at your option) any later version.
00010  *
00011  *  This program is distributed in the hope that it will be useful,
00012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  *  GNU General Public License for more details.
00015  *
00016  *  You should have received a copy of the GNU General Public License
00017  *  along with this program; if not, write to the Free Software
00018  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019  *
00020  *  ---
00021  *
00022  *  See files README, COPYING and CREDITS in the root of the source
00023  *  tree for related information and legal notices.  It is expected
00024  *  that future projects/authors will amend these files as needed.
00025  *
00026  *  ---
00027  *
00028  *  service.c: Windows services support
00029  * 
00030  *  Known contributors to this file:
00031  *     Ron Koenderink, 2004
00032  */
00033 
00034 #include <config.h>
00035 
00036 #include <windows.h>
00037 
00038 #include "service.h"
00039 #include "empthread.h"
00040 #include "prototypes.h"
00041 
00042 int
00043 install_service(char *program_name, char *service_name, char *config_file)
00044 {
00045     HANDLE schSCManager,schService;
00046     SERVICE_DESCRIPTION sdBuf;
00047 
00048     if (config_file != NULL)
00049         snprintf(&program_name[strlen(program_name)], _MAX_PATH-strlen(program_name), " -e %s",
00050             config_file);
00051 
00052     if (service_name == NULL)
00053         service_name = DEFAULT_SERVICE_NAME;
00054     else if (service_name[0] == '\0')
00055         service_name = DEFAULT_SERVICE_NAME;
00056 
00057     schSCManager = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);
00058 
00059     if (schSCManager == NULL) {
00060         fprintf(stderr, "install_service failed to open Service Control Manager\n"); 
00061         return EXIT_FAILURE;
00062     }
00063 
00064     schService = CreateService(schSCManager,
00065         service_name,
00066         service_name,                   /* service name to display */
00067         SERVICE_ALL_ACCESS,             /* desired access */
00068         SERVICE_WIN32_OWN_PROCESS,      /* service type */
00069         SERVICE_AUTO_START,             /* start type */
00070         SERVICE_ERROR_NORMAL,           /* error control type */
00071         program_name,                   /* service's binary */
00072         NULL,                           /* no load ordering group */
00073         NULL,                           /* no tag identifier */
00074         NULL,                           /* database service dependency */
00075         NULL,                           /* LocalSystem account */
00076         NULL);                          /* no password */
00077  
00078     if (schService == NULL) {
00079         fprintf(stderr, "install_service failed to create service %s\n", service_name);
00080         return EXIT_FAILURE;
00081     }
00082     sdBuf.lpDescription = "Server for Empire game";
00083 
00084     if(!ChangeServiceConfig2(
00085           schService,                 /* handle to service */
00086           SERVICE_CONFIG_DESCRIPTION, /* change: description */
00087           &sdBuf)) {                  /* value: new description */
00088         fprintf(stderr, "install_service failed to set the description\n");
00089     }
00090 
00091     printf("Service %s installed.\n", service_name);
00092     CloseServiceHandle(schService);
00093     return EXIT_SUCCESS;
00094 }
00095 
00096 int
00097 remove_service(char *service_name)
00098 {
00099     HANDLE schSCManager;
00100     SC_HANDLE hService;
00101 
00102     if (service_name == NULL)
00103         service_name = DEFAULT_SERVICE_NAME;
00104     else if (service_name[0] == '\0')
00105         service_name = DEFAULT_SERVICE_NAME;
00106 
00107     schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
00108 
00109     if (schSCManager == NULL) {
00110         fprintf(stderr, "remove_service failed to open Service Control Manager\n"); 
00111         return EXIT_FAILURE;
00112     }
00113 
00114     hService = OpenService(schSCManager, service_name, SERVICE_ALL_ACCESS);
00115 
00116     if (hService == NULL) {
00117         fprintf(stderr, "remove_service failed to open service %s\n", service_name);
00118         return EXIT_FAILURE;
00119     }
00120 
00121     if (DeleteService(hService) == 0) {
00122         fprintf(stderr, "remove_service failed to remove service %s\n", service_name);
00123         return EXIT_FAILURE;
00124     }
00125 
00126     if (CloseServiceHandle(hService) == 0) {
00127         fprintf(stderr, "remove_service failed to close service %s\n", service_name); 
00128         return EXIT_FAILURE;
00129     } else {
00130         printf("Service %s removed.\n", service_name); 
00131         return EXIT_SUCCESS;
00132     }
00133 }
00134 
00135 static SERVICE_STATUS           service_status; 
00136 static SERVICE_STATUS_HANDLE    service_status_handle;
00137 
00138 static void WINAPI
00139 service_ctrl_handler(DWORD Opcode) 
00140 { 
00141     switch(Opcode) { 
00142         case SERVICE_CONTROL_PAUSE: 
00143             service_status.dwCurrentState = SERVICE_PAUSED;
00144             logerror("Pausing the service not supported");
00145             break; 
00146  
00147         case SERVICE_CONTROL_CONTINUE: 
00148             logerror("Continuing the service not supported");
00149             service_status.dwCurrentState = SERVICE_RUNNING; 
00150             break; 
00151  
00152         case SERVICE_CONTROL_STOP:
00153             logerror("Service stopping");
00154             empth_request_shutdown();
00155             return; 
00156  
00157         case SERVICE_CONTROL_INTERROGATE: 
00158         /* Fall through to send current status.  */
00159             break; 
00160  
00161         default: 
00162             logerror("Unrecognized opcode %ld in ServiceCtrlHandler", 
00163                 Opcode); 
00164     } 
00165  
00166     /* Send current status. */
00167     if (!SetServiceStatus (service_status_handle,  &service_status))
00168         logerror("SetServiceStatus error %ld",GetLastError()); 
00169     return; 
00170 } 
00171 
00172 void WINAPI
00173 service_main(DWORD argc, LPTSTR *argv)
00174 {
00175     int sig;
00176     
00177     service_status.dwServiceType        = SERVICE_WIN32; 
00178     service_status.dwCurrentState       = SERVICE_START_PENDING; 
00179     service_status.dwControlsAccepted   = SERVICE_ACCEPT_STOP; 
00180     service_status.dwWin32ExitCode      = 0; 
00181     service_status.dwServiceSpecificExitCode = 0; 
00182     service_status.dwCheckPoint         = 0; 
00183     service_status.dwWaitHint           = 0; 
00184  
00185     service_status_handle = RegisterServiceCtrlHandler(
00186         DEFAULT_SERVICE_NAME, service_ctrl_handler);
00187  
00188     if (service_status_handle == (SERVICE_STATUS_HANDLE)0) { 
00189         logerror("RegisterServiceCtrlHandler failed %lu\n", GetLastError());
00190         finish_server();
00191         return;
00192     }
00193  
00194     start_server(0);
00195  
00196     /* Initialization complete - report running status. */
00197     service_status.dwCurrentState       = SERVICE_RUNNING; 
00198     service_status.dwCheckPoint         = 0; 
00199     service_status.dwWaitHint           = 0; 
00200  
00201     if (!SetServiceStatus (service_status_handle, &service_status)) { 
00202         logerror("SetServiceStatus error %ld\n", GetLastError());
00203     }
00204 
00205     sig = empth_wait_for_signal();
00206 
00207     shutdwn(sig);
00208 
00209     CANT_REACH();
00210     finish_server();
00211 }
00212 
00213 void
00214 stop_service(void)
00215 {
00216     logerror("Service stopped");
00217     service_status.dwWin32ExitCode = 0; 
00218     service_status.dwCurrentState  = SERVICE_STOPPED; 
00219     service_status.dwCheckPoint    = 0; 
00220     service_status.dwWaitHint      = 0; 
00221 
00222     if (!SetServiceStatus (service_status_handle, &service_status)) 
00223         logerror("Error while stopping service SetServiceStatus"
00224             " error %ld", GetLastError()); 
00225 }

Generated on Fri Mar 28 11:01:16 2008 for empserver by  doxygen 1.5.2