tWin32 installer now installs locale files and 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 b07a0994d9818454a7d2184a9fa9b06932e348e9
 (DIR) parent f352a9079a7907f5d1aed2befaa77dc2eeb4b5a5
 (HTM) Author: Ben Webb <ben@salilab.org>
       Date:   Wed,  7 Nov 2001 18:43:54 +0000
       
       Win32 installer now installs locale files and NT Service
       
       
       Diffstat:
         M TODO                                |       1 +
         M src/winmain.c                       |       8 ++++++--
         M win32/Makefile                      |       4 +++-
         M win32/dialogs.rc                    |       4 ++--
         M win32/filelist                      |      49 ++++++++++++++++---------------
         M win32/makeinstall.c                 |      25 ++++++++++++++++---------
         M win32/setup.c                       |      83 ++++++++++++++++++++++++-------
         M win32/uninstall.c                   |      40 +++++++++++++++++++++++++++++++
         M win32/util.c                        |       9 ++++++---
       
       9 files changed, 165 insertions(+), 58 deletions(-)
       ---
 (DIR) diff --git a/TODO b/TODO
       t@@ -1,3 +1,4 @@
       +- Make Windows installer deal with old installed versions properly
        - Make server run as an NT Service
        - Configuration file editor thingy in the client?
        - Make minimize-to-systray code a) more robust and b) configurable
 (DIR) diff --git a/src/winmain.c b/src/winmain.c
       t@@ -167,10 +167,14 @@ int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,
           LogFileStart();
           g_set_print_handler(LogFilePrintFunc);
        
       -   g_log_set_handler(NULL,LogMask()|G_LOG_LEVEL_MESSAGE|G_LOG_LEVEL_WARNING|
       -                     G_LOG_LEVEL_CRITICAL,
       +   g_log_set_handler(NULL,LogMask()|G_LOG_LEVEL_MESSAGE,
                             ServerLogMessage,NULL);
        
       +   if (!is_service) {
       +     g_log_set_handler(NULL,G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL,
       +                       LogMessage,NULL);
       +   }
       +
        #ifdef ENABLE_NLS
           winlocale=GetWindowsLocale();
           if (winlocale) putenv(winlocale);
 (DIR) diff --git a/win32/Makefile b/win32/Makefile
       t@@ -3,7 +3,6 @@ all: setup makeinstall uninstall
        clean:
                /bin/rm -f *.o *.res uninstall.exe setup.exe makeinstall.exe core *~
                /bin/rm -f installfiles.gz manifest
       -        touch installfiles.gz manifest
        
        setup: setup.o util.o guifunc.o setup.res
                gcc -Wall -mno-cygwin -mwindows -o setup setup.o util.o guifunc.o setup.res zlib/libz.a -lcomctl32 -lole32 -luuid
       t@@ -28,6 +27,9 @@ util.o: util.c util.h
        guifunc.o: guifunc.c guifunc.h
                gcc -Wall -mno-cygwin -c guifunc.c
        
       +manifest installfiles.gz: filelist makeinstall uninstall
       +        ./makeinstall
       +
        setup.res: setup.rc dialogs.rc contid.h manifest installfiles.gz
                windres -O coff -o setup.res setup.rc
        
 (DIR) diff --git a/win32/dialogs.rc b/win32/dialogs.rc
       t@@ -1,13 +1,13 @@
        #include "contid.h"
        1 DIALOG 17, 40, 239, 162
        STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
       -CAPTION "dopewars-1.5.2 installation"
       +CAPTION "dopewars-1.5.3 installation"
        BEGIN
                CONTROL "", 101, "WC_GTKSEP", 2 | WS_CHILD | WS_VISIBLE, 7, 135, 225, 2
                CONTROL "< &Back", BT_BACK, "BUTTON", BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_DISABLED | WS_TABSTOP, 105, 143, 39, 13
                PUSHBUTTON "&Next >", BT_NEXT, 144, 143, 39, 13, WS_CHILD | WS_VISIBLE | WS_TABSTOP
                PUSHBUTTON "Cancel", BT_CANCEL, 191, 143, 39, 13, WS_CHILD | WS_VISIBLE | WS_TABSTOP
       -        LTEXT "Welcome to the dopewars-1.5.2 installation program.\nThis program will install dopewars-1.5.2 on your computer.", -1, 22, 14, 195, 17, WS_CHILD | WS_VISIBLE | WS_GROUP
       +        LTEXT "Welcome to the dopewars-1.5.3 installation program.\nThis program will install dopewars-1.5.3 on your computer.", -1, 22, 14, 195, 17, WS_CHILD | WS_VISIBLE | WS_GROUP
                LTEXT "Use the ""Back"" and ""Next"" buttons at the bottom of the dialog to control the installation. You can quit at any time using the ""Cancel"" button.", -1, 22, 51, 195, 25, WS_CHILD | WS_VISIBLE | WS_GROUP
                LTEXT "Newer versions of this program, when available, can be obtained from the dopewars website, http://dopewars.sf.net/", -1, 22, 94, 195, 18, WS_CHILD | WS_VISIBLE | WS_GROUP
        END
 (DIR) diff --git a/win32/filelist b/win32/filelist
       t@@ -11,37 +11,38 @@ Server for the drug-dealing game "dopewars"
        dopewars.exe -N
        
        [install]
       -licence.txt
       -aiplayer.html
       -clientplay.html
       -commandline.html
       -configfile.html
       -credits.html
       -developer.html
       -i18n.html
       -index.html
       -installation.html
       -metaserver.html
       -server.html
       -servercommands.html
       -windows.html
       -dopewars-config.txt
       -dopewars.exe
       -example-cfg.txt
       -glib-1.3.dll
       -readme.txt
       +../../auxdope/licence.txt -> licence.txt
        uninstall.exe
       -locale/de/LC_MESSAGES/dopewars.mo
       -locale/pl/LC_MESSAGES/dopewars.mo
       -locale/pt_BR/LC_MESSAGES/dopewars.mo
       -locale/fr/LC_MESSAGES/dopewars.mo
       +../doc/aiplayer.html -> aiplayer.html
       +../doc/clientplay.html -> clientplay.html
       +../doc/commandline.html -> commandline.html
       +../doc/configfile.html -> configfile.html
       +../doc/credits.html -> credits.html
       +../doc/developer.html -> developer.html
       +../doc/i18n.html -> i18n.html
       +../doc/index.html -> index.html
       +../doc/installation.html -> installation.html
       +../doc/metaserver.html -> metaserver.html
       +../doc/protocol.html -> protocol.html
       +../doc/server.html -> server.html
       +../doc/servercommands.html -> servercommands.html
       +../doc/windows.html -> windows.html
       +../../auxdope/dopewars-config.txt -> dopewars-config.txt
       +../src/dopewars.exe -> dopewars.exe
       +../../auxdope/example-cfg.txt -> example-cfg.txt
       +../../auxdope/glib-1.3.dll -> glib-1.3.dll
       +../../auxdope/readme.txt -> readme.txt
       +../po/fr.gmo -> locale\fr\LC_MESSAGES\dopewars.mo
       +../po/de.gmo -> locale\de\LC_MESSAGES\dopewars.mo
       +../po/pl.gmo -> locale\pl\LC_MESSAGES\dopewars.mo
       +../po/pt_BR.gmo -> locale\pt_BR\LC_MESSAGES\dopewars.mo
        
        [extrafiles]
        dopewars-log.txt
        dopewars.sco
        
        [startmenudir]
       -dopewars-1.5.2
       +dopewars-1.5.3
        
        [startmenu]
        dopewars.lnk
 (DIR) diff --git a/win32/makeinstall.c b/win32/makeinstall.c
       t@@ -20,7 +20,7 @@
        
        #include <windows.h>
        #include <stdio.h>
       -#include <zlib.h>
       +#include "zlib/zlib.h"
        #include "util.h"
        
        char *read_line(HANDLE hin) {
       t@@ -57,12 +57,12 @@ InstData *ReadInstallData() {
          int i;
          enum {
            S_PRODUCT=0,S_INSTDIR,S_INSTALL,S_EXTRA,S_STARTMENUDIR,
       -    S_STARTMENU,S_DESKTOP,
       +    S_STARTMENU,S_DESKTOP,S_NTSERVICE,
            S_NONE
          } section=S_NONE;
          char *titles[S_NONE] = {
            "[product]","[instdir]", "[install]","[extrafiles]","[startmenudir]",
       -    "[startmenu]","[desktop]"
       +    "[startmenu]","[desktop]","[NT Service]"
          };
        
          idata = bmalloc(sizeof(InstData));
       t@@ -72,7 +72,7 @@ InstData *ReadInstallData() {
        
          fin = CreateFile("filelist",GENERIC_READ,0,NULL,OPEN_EXISTING,0,NULL);
        
       -  if (fin) {
       +  if (fin!=INVALID_HANDLE_VALUE) {
            while (1) {
              line=read_line(fin);
              if (!line) break;
       t@@ -130,14 +130,21 @@ printf("desktop entry = %s/%s/%s\n",line,line2,line3);
        #define COMPRESSION Z_BEST_COMPRESSION
        
        void OpenNextFile(InstFiles *filelist,InstFiles **listpt,HANDLE *fin) {
       +  char *filename,*sep;
          if (*fin) CloseHandle(*fin);
          *fin=NULL;
        
          if (!*listpt) *listpt = filelist;
          else *listpt = (*listpt)->next;
        
       -  if (*listpt) *fin = CreateFile((*listpt)->filename,GENERIC_READ,0,NULL,
       -                                 OPEN_EXISTING,0,NULL);
       +  if (*listpt) {
       +    filename = (*listpt)->filename;
       +    sep = strstr(filename," -> ");
       +    if (sep) *sep='\0';
       +    *fin = CreateFile(filename,GENERIC_READ,0,NULL,OPEN_EXISTING,0,NULL);
       +    if (sep) strcpy(filename,sep+4);
       +    if (*fin==INVALID_HANDLE_VALUE) printf("Cannot open file: %s\n",filename);
       +  }
        }
        
        int main() {
       t@@ -169,9 +176,9 @@ int main() {
          filept=NULL;
          fin=NULL;
          OpenNextFile(idata->instfiles,&filept,&fin);
       -  if (!fin) { printf("Cannot open file\n"); return 1; }
       +  if (fin==INVALID_HANDLE_VALUE) { return 1; }
        
       -  while (fin) {
       +  while (fin!=INVALID_HANDLE_VALUE) {
            if (z.avail_in==0) {
              z.next_in = inbuf;
              bytes_read=0;
       t@@ -210,7 +217,7 @@ int main() {
        
          fout = CreateFile("manifest",GENERIC_WRITE,0,NULL,
                            CREATE_ALWAYS,0,NULL);
       -  if (!fout) printf("Cannot create file list\n");
       +  if (fout==INVALID_HANDLE_VALUE) printf("Cannot create file list\n");
        
          str=bstr_new();
          bstr_setlength(str,0);
 (DIR) diff --git a/win32/setup.c b/win32/setup.c
       t@@ -23,7 +23,7 @@
        #include <stdio.h>
        #include <stdlib.h>
        #include <string.h>
       -#include <zlib.h>
       +#include "zlib/zlib.h"
        #include <shlobj.h>
        
        #include "contid.h"
       t@@ -43,6 +43,50 @@ HINSTANCE hInst=NULL;
        DWORD WINAPI DoInstall(LPVOID lpParam);
        static void GetWinText(char **text,HWND hWnd);
        
       +void InstallService(void) {
       +  SC_HANDLE scManager,scService;
       +  HKEY key;
       +  bstr *str;
       +  static char keyprefix[] = "SYSTEM\\ControlSet001\\Services\\";
       +
       +  static char servicename[] = "dopewars-server";
       +  static char servicedisp[] = "dopewars server";
       +  static char serviceexe[] = "dopewars.exe -N";
       +  static char servicedesc[] = "Server for the drug-dealing game \"dopewars\"";
       +
       +  scManager = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);
       +
       +  if (!scManager) {
       +    DisplayError("Cannot connect to service manager",TRUE,FALSE);
       +    return;
       +  }
       +
       +  str = bstr_new();
       +  bstr_assign(str,idata->installdir);
       +  bstr_appendpath(str,serviceexe);
       +
       +  scService = CreateService(scManager,servicename,servicedisp,
       +                            SERVICE_ALL_ACCESS,SERVICE_WIN32_OWN_PROCESS,
       +                            SERVICE_DEMAND_START,SERVICE_ERROR_NORMAL,
       +                            str->text,NULL,NULL,NULL,NULL,NULL);
       +  if (!scService) {
       +    DisplayError("Cannot create service",TRUE,FALSE);
       +    bstr_free(str,TRUE);
       +    return;
       +  }
       +
       +  bstr_assign(str,keyprefix);
       +  bstr_append(str,servicename);
       +  if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,str->text,0,KEY_WRITE,&key)
       +      ==ERROR_SUCCESS) {
       +    RegSetValueEx(key,"Description",0,REG_SZ,servicedesc,strlen(servicedesc));
       +    RegCloseKey(key);
       +  }
       +
       +  CloseServiceHandle(scService);
       +  CloseServiceHandle(scManager);
       +}
       +
        BOOL CheckCreateDir(void) {
        /* Checks that the install directory exists, and creates it if it does not.
           Returns TRUE if the directory is OK. */
       t@@ -309,11 +353,12 @@ char *GetFirstFile(InstFiles *filelist,DWORD totalsize) {
        
        BOOL OpenNextOutput(HANDLE *fout,InstFiles *filelist,InstFiles **listpt,
                            DWORD *fileleft,HANDLE logf) {
       +  char *filename,*sep;
          bstr *str;
          DWORD bytes_written;
        
          if (*fout) CloseHandle(*fout);
       -  *fout = NULL;
       +  *fout = INVALID_HANDLE_VALUE;
        
          str=bstr_new();
        
       t@@ -332,21 +377,32 @@ BOOL OpenNextOutput(HANDLE *fout,InstFiles *filelist,InstFiles **listpt,
          } else *listpt = filelist;
        
          if (*listpt) {
       -    *fout = CreateFile((*listpt)->filename,GENERIC_WRITE,0,NULL,
       -                       CREATE_ALWAYS,0,NULL);
       +    filename = (*listpt)->filename;
       +    sep = strrchr(filename,'\\');
       +    if (sep) {
       +      *sep = '\0';
       +      CreateWholeDirectory(filename);
       +      *sep = '\\';
       +    }
       +    *fout = CreateFile(filename,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,0,NULL);
            *fileleft = (*listpt)->filesize;
            bstr_assign(str,"Installing file: ");
       -    bstr_append(str,(*listpt)->filename);
       +    bstr_append(str,filename);
            bstr_append(str," (size ");
            bstr_append_long(str,(*listpt)->filesize);
            bstr_append(str,")");
            SendDlgItemMessage(mainDlg[DL_DOINSTALL],ST_FILELIST,
                               WM_SETTEXT,0,(LPARAM)str->text);
       +    if (*fout==INVALID_HANDLE_VALUE) {
       +      bstr_assign(str,"Cannot create file ");
       +      bstr_append(str,filename);
       +      DisplayError(str->text,TRUE,FALSE);
       +    }
          }
        
          bstr_free(str,TRUE);
        
       -  return (*fout!=NULL);
       +  return (*fout!=INVALID_HANDLE_VALUE);
        }
        
        HRESULT CreateLink(LPCSTR origPath,LPSTR linkArgs,LPSTR workDir,
       t@@ -408,15 +464,6 @@ void CreateLinks(char *linkdir,InstLink *linkpt) {
        
            CreateLink(origfile->text,linkpt->args,idata->installdir,
                       linkpath->text,NULL);
       -
       -/*bstr_append_c(origfile,',');
       -bstr_append(origfile,linkpt->args);
       -bstr_append_c(origfile,',');
       -bstr_append(origfile,idata->installdir);
       -bstr_append_c(origfile,',');
       -bstr_append(origfile,linkpath->text);
       -bstr_append(origfile,", NULL");
       -MessageBox(NULL,origfile->text,NULL,MB_OK);*/
          }
        }
        
       t@@ -539,7 +586,7 @@ DWORD WINAPI DoInstall(LPVOID lpParam) {
            printf("Write error\n");
          }
        
       -  fout = NULL;
       +  fout = INVALID_HANDLE_VALUE;
          listpt=NULL;
          OpenNextOutput(&fout,idata->instfiles,&listpt,&fileleft,logf);
        
       t@@ -570,7 +617,7 @@ DWORD WINAPI DoInstall(LPVOID lpParam) {
                if (!OpenNextOutput(&fout,idata->instfiles,&listpt,
                                    &fileleft,logf)) break;
              }
       -      if (!fout) break;
       +      if (fout==INVALID_HANDLE_VALUE) break;
              if (count && !WriteFile(fout,z.next_out,count,&bytes_written,NULL)) {
                printf("Write error\n");
              }
       t@@ -592,6 +639,8 @@ DWORD WINAPI DoInstall(LPVOID lpParam) {
        
          WriteFileList(logf,idata->extrafiles);
        
       +  InstallService();
       +
          CoInitialize(NULL);
          SetupShortcuts(logf);
          SetupUninstall();
 (DIR) diff --git a/win32/uninstall.c b/win32/uninstall.c
       t@@ -30,6 +30,35 @@ HINSTANCE hInst;
        HWND mainDlg;
        char *product;
        
       +void RemoveService(void) {
       +  SC_HANDLE scManager,scService;
       +  SERVICE_STATUS status;
       +  static char servicename[] = "dopewars-server";
       +
       +  scManager = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);
       +
       +  if (!scManager) {
       +    DisplayError("Cannot connect to service manager",TRUE,FALSE);
       +    return;
       +  }
       +
       +  scService = OpenService(scManager,servicename,DELETE|SERVICE_STOP);
       +  if (!scService) {
       +    DisplayError("Cannot open service",TRUE,FALSE);
       +  } else {
       +    if (!ControlService(scService,SERVICE_CONTROL_STOP,&status) &&
       +        GetLastError()!=ERROR_SERVICE_NOT_ACTIVE) {
       +      DisplayError("Cannot stop service",TRUE,FALSE);
       +    }
       +    if (!DeleteService(scService)) {
       +      DisplayError("Cannot delete service",TRUE,FALSE);
       +    }
       +    CloseServiceHandle(scService);
       +  }
       +
       +  CloseServiceHandle(scManager);
       +}
       +
        char *read_line0(HANDLE hin) {
          char *buf;
          int bufsize=32,strind=0;
       t@@ -157,12 +186,20 @@ InstData *ReadInstData(HANDLE fin,char *product,char *installdir) {
        
        void DeleteFileList(InstFiles *listpt) {
          bstr *str;
       +  char *sep;
       +
          str=bstr_new();
          for (;listpt;listpt=listpt->next) {
            bstr_assign(str,"Deleting file: ");
            bstr_append(str,listpt->filename);
            SendDlgItemMessage(mainDlg,ST_DELSTAT,WM_SETTEXT,0,(LPARAM)str->text);
            DeleteFile(listpt->filename);
       +    sep = strrchr(listpt->filename,'\\');
       +    if (sep) {
       +      *sep = '\0';
       +      RemoveWholeDirectory(listpt->filename);
       +      *sep = '\\';
       +    }
          }
          bstr_free(str,TRUE);
        }
       t@@ -235,6 +272,9 @@ DWORD WINAPI DoUninstall(LPVOID lpParam) {
          if (fin) {
            idata = ReadInstData(fin,product,installdir);
            CloseHandle(fin);
       +
       +    RemoveService();
       +
            DeleteFile("install.log");
            DeleteFileList(idata->instfiles);
            DeleteFileList(idata->extrafiles);
 (DIR) diff --git a/win32/util.c b/win32/util.c
       t@@ -396,23 +396,26 @@ BOOL CreateWholeDirectory(char *path) {
          /* \\machine\share notation */
          if (strlen(path)>2 && path[0]=='\\' && path[1]=='\\') {
            pt=&path[2]; /* Skip initial "\\" */
       +    while (*pt && *pt!='\\') pt++;  /* Skip the machine name */
       +  /* X: notation */
       +  } else if (strlen(path)>2 && path[1]==':') {
       +    pt=&path[2]; /* Skip the X: part */
          } else {
            pt=path;
          }
        
       -  while (*pt && *pt!='\\') pt++;  /* Skip the first (root) '\' */
        
          while (*pt) {
            pt++;
            if (*pt=='\\') {
              *pt='\0';
       -      if (!CreateDirectory(path,NULL)) {
       +      if (!CreateDirectory(path,NULL) && GetLastError()!=ERROR_ALREADY_EXISTS) {
                *pt='\\'; return FALSE;
              }
              *pt='\\';
            }
          }
       -  return CreateDirectory(path,NULL);
       +  return (CreateDirectory(path,NULL) || GetLastError()==ERROR_ALREADY_EXISTS);
        }
        
        BOOL RemoveWholeDirectory(char *path) {