tIntroduction of -N flag to support functioning as an NT Service - vaccinewars - be a doctor and try to vaccinate the world
 (HTM) git clone git://src.adamsgaard.dk/vaccinewars
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit f62a9d1e6315c24677fea70fd7727e348c861ddc
 (DIR) parent 38f976f2b148003c9a5ee01061093b831d42d1bf
 (HTM) Author: Ben Webb <ben@salilab.org>
       Date:   Mon,  5 Nov 2001 19:06:27 +0000
       
       Introduction of -N flag to support functioning as an NT Service
       
       
       Diffstat:
         M src/dopewars.c                      |       4 ++--
         M src/serverside.c                    |      79 +++++++++++++++++++++++++++++--
         M src/serverside.h                    |       2 +-
         M src/winmain.c                       |      58 ++++++++++++++++++++++---------
       
       4 files changed, 118 insertions(+), 25 deletions(-)
       ---
 (DIR) diff --git a/src/dopewars.c b/src/dopewars.c
       t@@ -1948,7 +1948,7 @@ Report bugs to the author at ben@bellatrix.pcl.ox.ac.uk\n"),DATADIR);
        
        void HandleCmdLine(int argc,char *argv[]) {
           int c;
       -   static const gchar *options = "anbchvf:o:sSp:g:r:wtC:l:";
       +   static const gchar *options = "anbchvf:o:sSp:g:r:wtC:l:N";
        #ifdef HAVE_GETOPT_LONG
           static const struct option long_options[] = {
              { "no-color", no_argument, NULL, 'b' },
       t@@ -2074,7 +2074,7 @@ int main(int argc,char *argv[]) {
        #ifdef GUI_SERVER
                    gtk_set_locale();
                    gtk_init(&argc,&argv);
       -            GuiServerLoop();
       +            GuiServerLoop(FALSE);
        #else
        /* Deal with dopelog() stuff nicely */
                    logfp = fopen(Log.File,"a");
 (DIR) diff --git a/src/serverside.c b/src/serverside.c
       t@@ -1257,10 +1257,73 @@ static gint GuiRequestDelete(GtkWidget *widget,GdkEvent *event,gpointer data) {
        
        #ifdef CYGWIN
        static HWND mainhwnd=NULL;
       +static SERVICE_STATUS_HANDLE scHandle;
       +
       +static BOOL RegisterStatus(DWORD state) {
       +  SERVICE_STATUS status;
       +  status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
       +  status.dwCurrentState = state;
       +  status.dwControlsAccepted = SERVICE_ACCEPT_STOP;
       +  status.dwWin32ExitCode = NO_ERROR;
       +  status.dwCheckPoint = 0;
       +  status.dwWaitHint = 5000;
       +  return SetServiceStatus(scHandle,&status);
       +}
       +
       +static VOID WINAPI ServiceHandler(DWORD control) {
       +  DWORD state=SERVICE_RUNNING;
       +  switch(control) {
       +    case SERVICE_CONTROL_STOP:
       +      state=SERVICE_STOP_PENDING;
       +      break;
       +  }
       +  if (!RegisterStatus(state)) {
       +    dopelog(0,_("Failed to set NT Service status"));
       +    return;
       +  }
       +
       +  if (mainhwnd && !PostMessage(mainhwnd,MYWM_SERVICE,0,(LPARAM)control)) {
       +    dopelog(0,_("Failed to post service notification message"));
       +    return;
       +  }
       +}
       +
       +static VOID WINAPI ServiceInit(DWORD argc,LPTSTR *argv) {
       +  scHandle = RegisterServiceCtrlHandler("dopewars-server",ServiceHandler);
       +  if (!scHandle) {
       +    dopelog(0,_("Failed to register service handler")); return;
       +  }
       +  if (!RegisterStatus(SERVICE_START_PENDING)) {
       +    dopelog(0,_("Failed to set NT Service status"));
       +    return;
       +  }
       +
       +  GuiServerLoop(TRUE);
       +
       +  if (!RegisterStatus(SERVICE_STOPPED)) {
       +    dopelog(0,_("Failed to set NT Service status"));
       +    return;
       +  }
       +}
       +
       +void ServiceMain(void) {
       +  SERVICE_TABLE_ENTRY services[] = {
       +    { "dopewars-server",ServiceInit },
       +    { NULL,NULL }
       +  };
       +  if (!StartServiceCtrlDispatcher(services)) {
       +    dopelog(0,_("Failed to start NT Service"));
       +  }
       +}
        
        static LRESULT CALLBACK GuiServerWndProc(HWND hwnd,UINT msg,WPARAM wparam,
                                                 LPARAM lparam) {
          if (hwnd==mainhwnd) switch(msg) {
       +    case MYWM_SERVICE:
       +      if (lparam==SERVICE_CONTROL_STOP) {
       +        GuiQuitServer();
       +      }
       +      break;
            case MYWM_TASKBAR:
              if ((UINT)lparam==WM_LBUTTONDOWN) ShowWindow(mainhwnd,SW_SHOW);
              break;
       t@@ -1281,7 +1344,6 @@ static void SetupTaskBarIcon(GtkWidget *widget) {
          if (widget && !widget->hWnd) return;
          if (!widget && !mainhwnd) return;
        
       -  if (widget) mainhwnd = widget->hWnd;
          nid.hWnd = mainhwnd;
          if (widget) {
            nid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
       t@@ -1296,7 +1358,7 @@ static void SetupTaskBarIcon(GtkWidget *widget) {
        }
        #endif /* CYGWIN */
        
       -void GuiServerLoop() {
       +void GuiServerLoop(gboolean is_service) {
           GtkWidget *window,*text,*hbox,*vbox,*entry,*label;
           GtkAdjustment *adj;
        
       t@@ -1329,14 +1391,21 @@ void GuiServerLoop() {
           gtk_container_add(GTK_CONTAINER(window),vbox);
           gtk_widget_show_all(window);
        
       -   g_set_print_handler(GuiServerPrintFunc);
       -   g_log_set_handler(NULL,LogMask()|G_LOG_LEVEL_MESSAGE|G_LOG_LEVEL_WARNING,
       -                     GuiServerLogMessage,NULL);
       +   if (!is_service) {
       +     g_set_print_handler(GuiServerPrintFunc);
       +     g_log_set_handler(NULL,LogMask()|G_LOG_LEVEL_MESSAGE|G_LOG_LEVEL_WARNING,
       +                       GuiServerLogMessage,NULL);
       +   }
           StartServer();
        
           ListenTag=gdk_input_add(ListenSock,GDK_INPUT_READ,GuiNewConnect,NULL);
        #ifdef CYGWIN
       +   mainhwnd=window->hWnd;
           SetupTaskBarIcon(window);
       +   if (is_service && !RegisterStatus(SERVICE_RUNNING)) {
       +     dopelog(0,_("Failed to set NT Service status"));
       +     return;
       +   }
        #endif
           gtk_main();
        #ifdef CYGWIN
 (DIR) diff --git a/src/serverside.h b/src/serverside.h
       t@@ -71,7 +71,7 @@ gboolean CanPlayerFire(Player *Play);
        gboolean CanRunHere(Player *Play);
        Player *GetNextShooter(Player *Play);
        #ifdef GUI_SERVER
       -void GuiServerLoop(void);
       +void GuiServerLoop(gboolean is_service);
        #endif
        
        #endif
 (DIR) diff --git a/src/winmain.c b/src/winmain.c
       t@@ -47,8 +47,9 @@ static void ServerLogMessage(const gchar *log_domain,GLogLevelFlags log_level,
           text=GetLogString(log_level,message);
           if (text) {
              g_string_append(text,"\n");
       -      WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE),text->str,strlen(text->str),
       -                   &NumChar,NULL);
       +  g_print(text->str);
       +/*    WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE),text->str,strlen(text->str),
       +                   &NumChar,NULL);*/
              g_string_free(text,TRUE);
           }
        }
       t@@ -146,15 +147,30 @@ int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,
                             LPSTR lpszCmdParam,int nCmdShow) {
           gchar **split;
           int argc;
       +   gboolean is_service;
       +   gchar modpath[300],*lastslash;
        #ifdef ENABLE_NLS
           gchar *winlocale;
        #endif
        
       -   g_log_set_handler(NULL,LogMask()|G_LOG_LEVEL_MESSAGE|G_LOG_LEVEL_WARNING|
       -                     G_LOG_LEVEL_CRITICAL,LogMessage,NULL);
       +/* Are we running as an NT service? */
       +   is_service = (lpszCmdParam && strncmp(lpszCmdParam,"-N",2)==0);
       +
       +   if (is_service) {
       +     modpath[0]='\0';
       +     GetModuleFileName(NULL,modpath,300);
       +     lastslash=strrchr(modpath,'\\');
       +     if (lastslash) *lastslash='\0';
       +     SetCurrentDirectory(modpath);
       +   }
       +
           LogFileStart();
           g_set_print_handler(LogFilePrintFunc);
        
       +   g_log_set_handler(NULL,LogMask()|G_LOG_LEVEL_MESSAGE|G_LOG_LEVEL_WARNING|
       +                     G_LOG_LEVEL_CRITICAL,
       +                     ServerLogMessage,NULL);
       +
        #ifdef ENABLE_NLS
           winlocale=GetWindowsLocale();
           if (winlocale) putenv(winlocale);
       t@@ -176,25 +192,33 @@ int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,
           while (split[argc] && split[argc][0]) argc++;
        
           if (GeneralStartup(argc,split)==0) {
       -      if (WantVersion || WantHelp) {
       -         WindowPrintStart();
       -         g_set_print_handler(WindowPrintFunc);
       -         HandleHelpTexts();
       -         WindowPrintEnd();
       -      } else if (WantConvert) {
       -         WindowPrintStart();
       -         g_set_print_handler(WindowPrintFunc);
       -         ConvertHighScoreFile();
       -         WindowPrintEnd();
       -      } else {
       +    if (WantVersion || WantHelp) {
       +      WindowPrintStart();
       +      g_set_print_handler(WindowPrintFunc);
       +      HandleHelpTexts();
       +      WindowPrintEnd();
       +#ifdef NETWORKING
       +    } else if (is_service) {
       +      StartNetworking();
       +Network=Server=TRUE;
       +      win32_init(hInstance,hPrevInstance,"mainicon");
       +      ServiceMain();
       +      StopNetworking();
       +#endif
       +    } else if (WantConvert) {
       +      WindowPrintStart();
       +      g_set_print_handler(WindowPrintFunc);
       +      ConvertHighScoreFile();
       +      WindowPrintEnd();
       +    } else {
        #ifdef NETWORKING
       -         StartNetworking();
       +      StartNetworking();
        #endif
                 if (Server) {
        #ifdef NETWORKING
        #ifdef GUI_SERVER
                    win32_init(hInstance,hPrevInstance,"mainicon");
       -            GuiServerLoop();
       +            GuiServerLoop(FALSE);
        #else
                    AllocConsole();
                    SetConsoleTitle(_("dopewars server"));