Crossfire Server, Branch 1.12  R12190
win32.c
Go to the documentation of this file.
00001 /*
00002     CrossFire, A Multiplayer game for X-windows
00003 
00004     Copyright (C) 1992 Frank Tore Johansen
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., 675 Mass Ave, Cambridge, MA 02139, USA.
00019 
00020     The author can be reached via e-mail to frankj@ifi.uio.no.
00021 */
00022 
00030 #include <global.h>
00031 
00032 #include <stdarg.h>
00033 #include <malloc.h>
00034 #include <string.h>
00035 #include <errno.h>
00036 #include <mmsystem.h>
00037 
00039 struct timezone {
00040     int tz_minuteswest;
00041     int tz_dsttime;
00042 };
00043 
00054 int gettimeofday(struct timeval *time_Info, struct timezone *timezone_Info) {
00055     /* Get the time, if they want it */
00056     if (time_Info != NULL) {
00057         time_Info->tv_sec = time(NULL);
00058         time_Info->tv_usec = timeGetTime()*1000;
00059     }
00060     /* Get the timezone, if they want it */
00061     if (timezone_Info != NULL) {
00062         _tzset();
00063         timezone_Info->tz_minuteswest = _timezone;
00064         timezone_Info->tz_dsttime = _daylight;
00065     }
00066     /* And return */
00067     return 0;
00068 }
00069 
00078 DIR *opendir(const char *dir) {
00079     DIR *dp;
00080     char *filespec;
00081     long handle;
00082     int index;
00083 
00084     filespec = malloc(strlen(dir)+2+1);
00085     strcpy(filespec, dir);
00086     index = strlen(filespec)-1;
00087     if (index >= 0 && (filespec[index] == '/' || filespec[index] == '\\'))
00088         filespec[index] = '\0';
00089     strcat(filespec, "/*");
00090 
00091     dp = (DIR *)malloc(sizeof(DIR));
00092     dp->offset = 0;
00093     dp->finished = 0;
00094     dp->dir = strdup(dir);
00095 
00096     if ((handle = _findfirst(filespec, &(dp->fileinfo))) < 0) {
00097         free(filespec);
00098         free(dp);
00099         return NULL;
00100     }
00101     dp->handle = handle;
00102     free(filespec);
00103 
00104     return dp;
00105 }
00106 
00116 struct dirent *readdir(DIR *dp) {
00117     if (!dp || dp->finished)
00118         return NULL;
00119 
00120     if (dp->offset != 0) {
00121         if (_findnext(dp->handle, &(dp->fileinfo)) < 0) {
00122             dp->finished = 1;
00123             if (ENOENT == errno)
00124                 /* Clear error set to mean no more files else that breaks things */
00125                 errno = 0;
00126             return NULL;
00127         }
00128     }
00129     dp->offset++;
00130 
00131     strncpy(dp->dent.d_name, dp->fileinfo.name, _MAX_FNAME);
00132     dp->dent.d_name[_MAX_FNAME] = '\0';
00133     dp->dent.d_ino = 1;
00134     /* reclen is used as meaning the length of the whole record */
00135     dp->dent.d_reclen = strlen(dp->dent.d_name)+sizeof(char)+sizeof(dp->dent.d_ino)+sizeof(dp->dent.d_reclen)+sizeof(dp->dent.d_off);
00136     dp->dent.d_off = dp->offset;
00137 
00138     return &(dp->dent);
00139 }
00140 
00149 int closedir(DIR *dp) {
00150     if (!dp)
00151         return 0;
00152     _findclose(dp->handle);
00153     if (dp->dir)
00154         free(dp->dir);
00155     if (dp)
00156         free(dp);
00157 
00158     return 0;
00159 }
00160 
00167 void rewinddir(DIR *dir_Info) {
00168     /* Re-set to the beginning */
00169     char *filespec;
00170     long handle;
00171     int index;
00172 
00173     dir_Info->handle = 0;
00174     dir_Info->offset = 0;
00175     dir_Info->finished = 0;
00176 
00177     filespec = malloc(strlen(dir_Info->dir)+2+1);
00178     strcpy(filespec, dir_Info->dir);
00179     index = strlen(filespec)-1;
00180     if (index >= 0 && (filespec[index] == '/' || filespec[index] == '\\'))
00181         filespec[index] = '\0';
00182     strcat(filespec, "/*");
00183 
00184     if ((handle = _findfirst(filespec, &(dir_Info->fileinfo))) < 0) {
00185         if (errno == ENOENT) {
00186             dir_Info->finished = 1;
00187         }
00188     }
00189     dir_Info->handle = handle;
00190     free(filespec);
00191 }
00192 
00193 /* Service-related stuff
00194 
00195   Those functions are called while init is still being done, so no logging available.
00196 
00197   Not useful for plugins, though.
00198 
00199  */
00200 
00202 int bRunning;
00203 
00204 #ifndef PYTHON_PLUGIN_EXPORTS
00205 
00206 SERVICE_STATUS m_ServiceStatus;
00207 SERVICE_STATUS_HANDLE m_ServiceStatusHandle;
00209 #define SERVICE_NAME        "Crossfire"
00210 
00211 #define SERVICE_DISPLAY     "Crossfire server"
00212 
00213 #define SERVICE_DESCRIPTION "Crossfire is a multiplayer online RPG game."
00214 
00215 #include <winsvc.h>
00216 
00221 void service_register() {
00222     char strDir[1024];
00223     HANDLE schSCManager, schService;
00224     char *strDescription = SERVICE_DESCRIPTION;
00225 
00226     GetModuleFileName(NULL, strDir, 1024);
00227     strcat(strDir, " -srv");
00228 
00229     schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
00230 
00231     if (schSCManager == NULL) {
00232         printf("openscmanager failed");
00233         exit(1);
00234     }
00235 
00236     schService = CreateService(schSCManager,
00237         SERVICE_NAME,
00238         SERVICE_DISPLAY,           /* service name to display */
00239         SERVICE_ALL_ACCESS,        /* desired access */
00240         SERVICE_WIN32_OWN_PROCESS, /* service type */
00241         SERVICE_DEMAND_START,      /* start type */
00242         SERVICE_ERROR_NORMAL,      /* error control type */
00243         strDir,                    /* service's binary */
00244         NULL,                      /* no load ordering group */
00245         NULL,                      /* no tag identifier */
00246         NULL,                      /* no dependencies */
00247         NULL,                      /* LocalSystem account */
00248         NULL);                     /* no password */
00249 
00250     if (schService == NULL) {
00251         printf("createservice failed");
00252         exit(1);
00253     }
00254 
00255     ChangeServiceConfig2(schService, SERVICE_CONFIG_DESCRIPTION, &strDescription);
00256 
00257     CloseServiceHandle(schService);
00258     CloseServiceHandle(schSCManager);
00259     exit(0);
00260 }
00261 
00266 void service_unregister() {
00267     HANDLE schSCManager;
00268     SC_HANDLE hService;
00269 
00270     schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
00271 
00272     if (schSCManager == NULL) {
00273         printf("open failed");
00274         exit(1);
00275     }
00276 
00277     hService = OpenService(schSCManager, SERVICE_NAME, SERVICE_ALL_ACCESS);
00278 
00279     if (hService == NULL) {
00280         printf("openservice failed");
00281         exit(1);
00282     }
00283 
00284     if (DeleteService(hService) == 0) {
00285         printf("Delete failed");
00286         exit(1);
00287     }
00288 
00289     if (CloseServiceHandle(hService) == 0) {
00290         printf("close failed");
00291         exit(1);
00292     }
00293 
00294     if (!CloseServiceHandle(schSCManager)) {
00295         printf("close schSCManager failed");
00296         exit(1);
00297     }
00298 
00299     exit(0);
00300 }
00301 
00308 void WINAPI ServiceCtrlHandler(DWORD Opcode) {
00309     switch (Opcode) {
00310     case SERVICE_CONTROL_PAUSE:
00311         m_ServiceStatus.dwCurrentState = SERVICE_PAUSED;
00312         break;
00313 
00314     case SERVICE_CONTROL_CONTINUE:
00315         m_ServiceStatus.dwCurrentState = SERVICE_RUNNING;
00316         break;
00317 
00318     case SERVICE_CONTROL_STOP:
00319         m_ServiceStatus.dwWin32ExitCode = 0;
00320         m_ServiceStatus.dwCurrentState = SERVICE_STOPPED;
00321         m_ServiceStatus.dwCheckPoint = 0;
00322         m_ServiceStatus.dwWaitHint = 0;
00323 
00324         SetServiceStatus(m_ServiceStatusHandle, &m_ServiceStatus);
00325 
00326         bRunning = 0;
00327 
00328         LOG(llevInfo, "Service stopped.\n");
00329 
00330         break;
00331 
00332     case SERVICE_CONTROL_INTERROGATE:
00333         break;
00334     }
00335     return;
00336 }
00337 
00338 extern int main(int argc, char **argv);
00339 
00347 void WINAPI ServiceMain(DWORD argc, LPTSTR *argv) {
00348     char strDir[1024];
00349     char *strSlash;
00350 
00351     GetModuleFileName(NULL, strDir, 1024);
00352     strSlash = strrchr(strDir, '\\');
00353     if (strSlash)
00354         *strSlash = '\0';
00355     chdir(strDir);
00356 
00357     m_ServiceStatus.dwServiceType        = SERVICE_WIN32;
00358     m_ServiceStatus.dwCurrentState       = SERVICE_START_PENDING;
00359     m_ServiceStatus.dwControlsAccepted   = SERVICE_ACCEPT_STOP;
00360     m_ServiceStatus.dwWin32ExitCode      = 0;
00361     m_ServiceStatus.dwServiceSpecificExitCode = 0;
00362     m_ServiceStatus.dwCheckPoint         = 0;
00363     m_ServiceStatus.dwWaitHint           = 0;
00364 
00365     m_ServiceStatusHandle = RegisterServiceCtrlHandler(SERVICE_NAME, ServiceCtrlHandler);
00366     if (m_ServiceStatusHandle == (SERVICE_STATUS_HANDLE)0) {
00367         return;
00368     }
00369 
00370     m_ServiceStatus.dwCurrentState       = SERVICE_RUNNING;
00371     m_ServiceStatus.dwCheckPoint         = 0;
00372     m_ServiceStatus.dwWaitHint           = 0;
00373     SetServiceStatus(m_ServiceStatusHandle, &m_ServiceStatus);
00374 
00375     bRunning = 1;
00376     main(0, NULL);
00377 
00378     return;
00379 }
00380 
00384 void service_handle() {
00385     SERVICE_TABLE_ENTRY DispatchTable[] = {
00386         { SERVICE_NAME, ServiceMain },
00387         { NULL, NULL }
00388     };
00389     StartServiceCtrlDispatcher(DispatchTable);
00390     exit(0);
00391 }
00392 #endif /* PYTHON_PLUGIN_EXPORTS */