Crossfire Server, Trunk  R20513
win32.c
Go to the documentation of this file.
1 /*
2  * Crossfire -- cooperative multi-player graphical RPG and adventure game
3  *
4  * Copyright (c) 1999-2014 Mark Wedel and the Crossfire Development Team
5  * Copyright (c) 1992 Frank Tore Johansen
6  *
7  * Crossfire is free software and comes with ABSOLUTELY NO WARRANTY. You are
8  * welcome to redistribute it under certain conditions. For details, please
9  * see COPYING and LICENSE.
10  *
11  * The authors can be reached via e-mail at <crossfire@metalforge.org>.
12  */
13 
21 #include <global.h>
22 
23 #include <stdarg.h>
24 #include <malloc.h>
25 #include <string.h>
26 #include <errno.h>
27 #include <mmsystem.h>
28 
37 DIR *opendir(const char *dir) {
38  DIR *dp;
39  char *filespec;
40  long handle;
41  int index;
42 
43  filespec = malloc(strlen(dir)+2+1);
44  strcpy(filespec, dir);
45  index = strlen(filespec)-1;
46  if (index >= 0 && (filespec[index] == '/' || filespec[index] == '\\'))
47  filespec[index] = '\0';
48  strcat(filespec, "/*");
49 
50  dp = (DIR *)malloc(sizeof(DIR));
51  dp->offset = 0;
52  dp->finished = 0;
53  dp->dir = strdup(dir);
54 
55  if ((handle = _findfirst(filespec, &(dp->fileinfo))) < 0) {
56  free(filespec);
57  free(dp);
58  return NULL;
59  }
60  dp->handle = handle;
61  free(filespec);
62 
63  return dp;
64 }
65 
75 struct dirent *readdir(DIR *dp) {
76  if (!dp || dp->finished)
77  return NULL;
78 
79  if (dp->offset != 0) {
80  if (_findnext(dp->handle, &(dp->fileinfo)) < 0) {
81  dp->finished = 1;
82  if (ENOENT == errno)
83  /* Clear error set to mean no more files else that breaks things */
84  errno = 0;
85  return NULL;
86  }
87  }
88  dp->offset++;
89 
90  strncpy(dp->dent.d_name, dp->fileinfo.name, _MAX_FNAME);
91  dp->dent.d_name[_MAX_FNAME] = '\0';
92  dp->dent.d_ino = 1;
93  /* reclen is used as meaning the length of the whole record */
94  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);
95  dp->dent.d_off = dp->offset;
96 
97  return &(dp->dent);
98 }
99 
108 int closedir(DIR *dp) {
109  if (!dp)
110  return 0;
111  _findclose(dp->handle);
112  free(dp->dir);
113  free(dp);
114 
115  return 0;
116 }
117 
124 void rewinddir(DIR *dir_Info) {
125  /* Re-set to the beginning */
126  char *filespec;
127  long handle;
128  int index;
129 
130  dir_Info->handle = 0;
131  dir_Info->offset = 0;
132  dir_Info->finished = 0;
133 
134  filespec = malloc(strlen(dir_Info->dir)+2+1);
135  strcpy(filespec, dir_Info->dir);
136  index = strlen(filespec)-1;
137  if (index >= 0 && (filespec[index] == '/' || filespec[index] == '\\'))
138  filespec[index] = '\0';
139  strcat(filespec, "/*");
140 
141  if ((handle = _findfirst(filespec, &(dir_Info->fileinfo))) < 0) {
142  if (errno == ENOENT) {
143  dir_Info->finished = 1;
144  }
145  }
146  dir_Info->handle = handle;
147  free(filespec);
148 }
149 
150 /* Service-related stuff
151 
152  Those functions are called while init is still being done, so no logging available.
153 
154  Not useful for plugins, though.
155 
156  */
157 
160 
161 #ifndef PYTHON_PLUGIN_EXPORTS
162 
164 SERVICE_STATUS m_ServiceStatus;
166 SERVICE_STATUS_HANDLE m_ServiceStatusHandle;
168 #define SERVICE_NAME "Crossfire"
169 
170 #define SERVICE_DISPLAY "Crossfire server"
171 
172 #define SERVICE_DESCRIPTION "Crossfire is a multiplayer online RPG game."
173 
174 #include <winsvc.h>
175 
180 void service_register(void) {
181  char strDir[1024];
182  HANDLE schSCManager, schService;
183  char *strDescription = SERVICE_DESCRIPTION;
184 
185  GetModuleFileName(NULL, strDir, 1024);
186  strcat(strDir, " -srv");
187 
188  schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
189 
190  if (schSCManager == NULL) {
191  printf("openscmanager failed");
192  exit(1);
193  }
194 
195  schService = CreateService(schSCManager,
196  SERVICE_NAME,
197  SERVICE_DISPLAY, /* service name to display */
198  SERVICE_ALL_ACCESS, /* desired access */
199  SERVICE_WIN32_OWN_PROCESS, /* service type */
200  SERVICE_DEMAND_START, /* start type */
201  SERVICE_ERROR_NORMAL, /* error control type */
202  strDir, /* service's binary */
203  NULL, /* no load ordering group */
204  NULL, /* no tag identifier */
205  NULL, /* no dependencies */
206  NULL, /* LocalSystem account */
207  NULL); /* no password */
208 
209  if (schService == NULL) {
210  printf("createservice failed");
211  exit(1);
212  }
213 
214  ChangeServiceConfig2(schService, SERVICE_CONFIG_DESCRIPTION, &strDescription);
215 
216  CloseServiceHandle(schService);
217  CloseServiceHandle(schSCManager);
218  exit(0);
219 }
220 
225 void service_unregister(void) {
226  HANDLE schSCManager;
227  SC_HANDLE hService;
228 
229  schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
230 
231  if (schSCManager == NULL) {
232  printf("open failed");
233  exit(1);
234  }
235 
236  hService = OpenService(schSCManager, SERVICE_NAME, SERVICE_ALL_ACCESS);
237 
238  if (hService == NULL) {
239  printf("openservice failed");
240  exit(1);
241  }
242 
243  if (DeleteService(hService) == 0) {
244  printf("Delete failed");
245  exit(1);
246  }
247 
248  if (CloseServiceHandle(hService) == 0) {
249  printf("close failed");
250  exit(1);
251  }
252 
253  if (!CloseServiceHandle(schSCManager)) {
254  printf("close schSCManager failed");
255  exit(1);
256  }
257 
258  exit(0);
259 }
260 
267 void WINAPI ServiceCtrlHandler(DWORD Opcode) {
268  switch (Opcode) {
269  case SERVICE_CONTROL_PAUSE:
270  m_ServiceStatus.dwCurrentState = SERVICE_PAUSED;
271  break;
272 
273  case SERVICE_CONTROL_CONTINUE:
274  m_ServiceStatus.dwCurrentState = SERVICE_RUNNING;
275  break;
276 
277  case SERVICE_CONTROL_STOP:
278  m_ServiceStatus.dwWin32ExitCode = 0;
279  m_ServiceStatus.dwCurrentState = SERVICE_STOPPED;
280  m_ServiceStatus.dwCheckPoint = 0;
281  m_ServiceStatus.dwWaitHint = 0;
282 
283  SetServiceStatus(m_ServiceStatusHandle, &m_ServiceStatus);
284 
285  bRunning = 0;
286 
287  LOG(llevInfo, "Service stopped.\n");
288 
289  break;
290 
291  case SERVICE_CONTROL_INTERROGATE:
292  break;
293  }
294  return;
295 }
296 
297 extern int main(int argc, char **argv);
298 
306 void WINAPI ServiceMain(DWORD argc, LPTSTR *argv) {
307  char strDir[1024];
308  char *strSlash;
309 
310  GetModuleFileName(NULL, strDir, 1024);
311  strSlash = strrchr(strDir, '\\');
312  if (strSlash)
313  *strSlash = '\0';
314  chdir(strDir);
315 
316  m_ServiceStatus.dwServiceType = SERVICE_WIN32;
317  m_ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
318  m_ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
319  m_ServiceStatus.dwWin32ExitCode = 0;
320  m_ServiceStatus.dwServiceSpecificExitCode = 0;
321  m_ServiceStatus.dwCheckPoint = 0;
322  m_ServiceStatus.dwWaitHint = 0;
323 
324  m_ServiceStatusHandle = RegisterServiceCtrlHandler(SERVICE_NAME, ServiceCtrlHandler);
325  if (m_ServiceStatusHandle == (SERVICE_STATUS_HANDLE)0) {
326  return;
327  }
328 
329  m_ServiceStatus.dwCurrentState = SERVICE_RUNNING;
330  m_ServiceStatus.dwCheckPoint = 0;
331  m_ServiceStatus.dwWaitHint = 0;
332  SetServiceStatus(m_ServiceStatusHandle, &m_ServiceStatus);
333 
334  bRunning = 1;
335  main(0, NULL);
336 
337  return;
338 }
339 
343 void service_handle(void) {
344  SERVICE_TABLE_ENTRY DispatchTable[] = {
346  { NULL, NULL }
347  };
348  StartServiceCtrlDispatcher(DispatchTable);
349  exit(0);
350 }
351 #endif /* PYTHON_PLUGIN_EXPORTS */
Information.
Definition: logger.h:12
struct dirent dent
Definition: win32.h:126
#define SERVICE_DESCRIPTION
Description of the service.
Definition: win32.c:172
unsigned short d_reclen
Definition: win32.h:113
int closedir(DIR *dp)
Dispose of a directory handle.
Definition: win32.c:108
short finished
Definition: win32.h:123
int bRunning
Will be set to FALSE when the server should stop running because the service is turned off...
Definition: win32.c:159
char * dir
Definition: win32.h:125
DIR * opendir(const char *dir)
Opens a directory for reading.
Definition: win32.c:37
long handle
Definition: win32.h:121
Definition: win32.h:110
Global type definitions and header inclusions.
void service_register(void)
Registers the server to the service manager.
Definition: win32.c:180
short offset
Definition: win32.h:122
Definition: win32.h:120
#define SERVICE_NAME
Internal name of the service.
Definition: win32.c:168
long d_ino
Definition: win32.h:111
void WINAPI ServiceCtrlHandler(DWORD Opcode)
Main service dispatch routine.
Definition: win32.c:267
int main(int argc, char **argv)
Definition: cre.cpp:16
char d_name[_MAX_FNAME+1]
Definition: win32.h:114
void service_unregister(void)
Removes the Crossfire service from the service manager.
Definition: win32.c:225
SERVICE_STATUS m_ServiceStatus
Status when the server is started as a service.
Definition: win32.c:164
struct dirent * readdir(DIR *dp)
Returns the next file/directory for specified directory handle, obtained through a call to opendir()...
Definition: win32.c:75
char * strdup(const char *str)
Portable implementation of strdup(3).
Definition: porting.c:200
void LOG(LogLevel logLevel, const char *format,...)
Logs a message to stderr, or to file.
Definition: logger.c:51
off_t d_off
Definition: win32.h:112
struct _finddata_t fileinfo
Definition: win32.h:124
SERVICE_STATUS_HANDLE m_ServiceStatusHandle
Handle to the service the server is started as.
Definition: win32.c:166
void service_handle(void)
Service entry point.
Definition: win32.c:343
void rewinddir(DIR *dir_Info)
Restart a directory listing from the beginning.
Definition: win32.c:124
void WINAPI ServiceMain(DWORD argc, LPTSTR *argv)
Main service entrypoint.
Definition: win32.c:306
#define SERVICE_DISPLAY
Name that will appear in the service list.
Definition: win32.c:170