tWindows installer now upgrades properly; Windows system tray icon can be contr… | |
git clone git://src.adamsgaard.dk/vaccinewars | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
commit c77672f5f19dc6838e0f010339fa43dbab051ff3 | |
parent 8f75f1bd80b636b71b665bf2b93d10c5adcdd511 | |
Author: Ben Webb <[email protected]> | |
Date: Sun, 11 Nov 2001 19:20:30 +0000 | |
Windows installer now upgrades properly; Windows system tray icon can be | |
controlled via. MinToSysTray config variable; Unix server can now be | |
configured while running via. "dopewars -A" | |
Diffstat: | |
M ChangeLog | 5 ++++- | |
M TODO | 7 ++++--- | |
M doc/configfile.html | 9 ++++++++- | |
M po/POTFILES.in | 1 + | |
M src/Makefile.am | 2 +- | |
M src/Makefile.in | 21 ++++++++++++--------- | |
A src/admin.c | 104 +++++++++++++++++++++++++++++… | |
A src/admin.h | 35 +++++++++++++++++++++++++++++… | |
M src/dopewars.c | 48 +++++++++++++++++++++--------… | |
M src/dopewars.h | 6 +++++- | |
M src/serverside.c | 113 +++++++++++++++++++----------… | |
M src/serverside.h | 1 - | |
M win32/filelist | 5 +++++ | |
M win32/makeinstall.c | 14 +++++++++----- | |
M win32/setup.c | 240 +++++++++++++++++++++++++++--… | |
M win32/uninstall.c | 249 ++---------------------------… | |
M win32/util.c | 247 +++++++++++++++++++++++++++++… | |
M win32/util.h | 7 +++++++ | |
18 files changed, 765 insertions(+), 349 deletions(-) | |
--- | |
diff --git a/ChangeLog b/ChangeLog | |
t@@ -1,4 +1,7 @@ | |
cvs | |
+ - Fatal bug when visiting the bank (under Win2000/XP) fixed | |
+ - Windows installer should now upgrade old versions properly | |
+ - Windows server can now be run as an NT Service | |
- Currency can now be configured with Currency.Symbol and Currency.Prefix | |
- Windows client windows cannot now be made unreadably small | |
- Bank/loan shark dialog now warns on entering negative prices | |
t@@ -7,7 +10,7 @@ cvs | |
- Documentation on the client-server protocol added | |
- Windows graphical server can be minimized to the System Tray | |
- Keyboard shortcuts for menu items in Windows client | |
- - Default buttons for Windows client, bank bug (hopefully) fixed | |
+ - Default buttons (ENTER -> "OK") for Windows client | |
- RPM build/make install can now be run as non-superuser | |
- Code cleanups | |
diff --git a/TODO b/TODO | |
t@@ -1,7 +1,8 @@ | |
-- Make Windows installer deal with old installed versions properly | |
-- Make server run as an NT Service | |
+- Admin of running servers | |
+ DONE (- feedback when setting/querying variables) | |
+ - mechanism for interacting with NT Service servers | |
+DONE for Unix - test Windows (- Fix error reporting for config. file reading) | |
- Configuration file editor thingy in the client? | |
-- Make minimize-to-systray code a) more robust and b) configurable | |
- GSS_API SOCKS support? | |
- Fix problem with dialogs popping up while menus are open | |
- Increase difficulty of escaping from another player - impose penalty on | |
diff --git a/doc/configfile.html b/doc/configfile.html | |
t@@ -141,6 +141,13 @@ mode, not connected to a server) to use the file <i>/var/… | |
to store high scores. This can be overridden with the -f | |
<a href="commandline.html#hiscore">command line option</a>.</dd> | |
+<dt><b>MinToSysTray=<i>TRUE</i></b></dt> | |
+<dd>Rather than behaving as a normal window, the dopewars server window adds | |
+an icon to the Windows System Tray, and, when the window is minimized, it | |
+vanishes completely. Clicking on the System Tray icon will restore the | |
+window to its normal state. If FALSE, the System Tray is not used. Only | |
+supported on Windows systems.</dd> | |
+ | |
<dt><b>Pager=<i>"more"</i></b></dt> | |
<dd>Sets the pager used to display multi-page output in an interactive server | |
to <i>more</i>. ("less" is a popular alternative)</dd> | |
t@@ -597,6 +604,6 @@ any drugs, and clients will display this information if av… | |
<ul> | |
<li><a href="index.html">Main index</a></li> | |
</ul> | |
-<p>Last update: <b>28-10-2001</b></p> | |
+<p>Last update: <b>20-11-2001</b></p> | |
</body> | |
</html> | |
diff --git a/po/POTFILES.in b/po/POTFILES.in | |
t@@ -10,4 +10,5 @@ src/serverside.c | |
src/error.c | |
src/message.c | |
src/network.c | |
+src/admin.c | |
src/AIPlayer.c | |
diff --git a/src/Makefile.am b/src/Makefile.am | |
t@@ -1,5 +1,5 @@ | |
bin_PROGRAMS = dopewars | |
-dopewars_SOURCES = AIPlayer.c curses_client.c dopeos.c dopewars.c \ | |
+dopewars_SOURCES = admin.c AIPlayer.c curses_client.c dopeos.c dopewars.c \ | |
error.c gtk_client.c message.c network.c serverside.c \ | |
tstring.c winmain.c @GTKPORT_C@ | |
dopewars_DEPENDENCIES = @INTLLIBS@ @GTKPORT_O@ @WNDRES@ | |
diff --git a/src/Makefile.in b/src/Makefile.in | |
t@@ -1,6 +1,6 @@ | |
-# Makefile.in generated automatically by automake 1.4 from Makefile.am | |
+# Makefile.in generated automatically by automake 1.4-p5 from Makefile.am | |
-# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc. | |
+# Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc. | |
# This Makefile.in is free software; the Free Software Foundation | |
# gives unlimited permission to copy and/or distribute it, | |
# with or without modifications, as long as this notice is preserved. | |
t@@ -96,7 +96,9 @@ WNDRES = @WNDRES@ | |
localedir = @localedir@ | |
bin_PROGRAMS = dopewars | |
-dopewars_SOURCES = AIPlayer.c curses_client.c dopeos.c dopewars.c … | |
+dopewars_SOURCES = admin.c AIPlayer.c curses_client.c dopeos.c dopewars.c \ | |
+ error.c gtk_client.c message.c network.c serverside.c \ | |
+ tstring.c winmain.c @GTKPORT_C@ | |
dopewars_DEPENDENCIES = @INTLLIBS@ @GTKPORT_O@ @WNDRES@ | |
INCLUDES = @GTK_CFLAGS@ -I.. -I. | |
t@@ -114,9 +116,9 @@ PROGRAMS = $(bin_PROGRAMS) | |
CPPFLAGS = @CPPFLAGS@ | |
LDFLAGS = @LDFLAGS@ | |
LIBS = @LIBS@ | |
-dopewars_OBJECTS = AIPlayer.o curses_client.o dopeos.o dopewars.o \ | |
-error.o gtk_client.o message.o network.o serverside.o tstring.o \ | |
-winmain.o | |
+dopewars_OBJECTS = admin.o AIPlayer.o curses_client.o dopeos.o \ | |
+dopewars.o error.o gtk_client.o message.o network.o serverside.o \ | |
+tstring.o winmain.o | |
dopewars_LDADD = $(LDADD) | |
dopewars_LDFLAGS = | |
CFLAGS = @CFLAGS@ | |
t@@ -130,9 +132,10 @@ DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINF… | |
TAR = gtar | |
GZIP_ENV = --best | |
-DEP_FILES = .deps/AIPlayer.P .deps/curses_client.P .deps/dopeos.P \ | |
-.deps/dopewars.P .deps/error.P .deps/gtk_client.P .deps/message.P \ | |
-.deps/network.P .deps/serverside.P .deps/tstring.P .deps/winmain.P | |
+DEP_FILES = .deps/AIPlayer.P .deps/admin.P .deps/curses_client.P \ | |
+.deps/dopeos.P .deps/dopewars.P .deps/error.P .deps/gtk_client.P \ | |
+.deps/message.P .deps/network.P .deps/serverside.P .deps/tstring.P \ | |
+.deps/winmain.P | |
SOURCES = $(dopewars_SOURCES) | |
OBJECTS = $(dopewars_OBJECTS) | |
diff --git a/src/admin.c b/src/admin.c | |
t@@ -0,0 +1,104 @@ | |
+/* admin.c Dopewars server administration */ | |
+/* Copyright (C) 1998-2001 Ben Webb */ | |
+/* Email: [email protected] */ | |
+/* WWW: http://dopewars.sourceforge.net/ */ | |
+ | |
+/* This program is free software; you can redistribute it and/or */ | |
+/* modify it under the terms of the GNU General Public License */ | |
+/* as published by the Free Software Foundation; either version 2 */ | |
+/* of the License, or (at your option) any later version. */ | |
+ | |
+/* This program is distributed in the hope that it will be useful, */ | |
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ | |
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ | |
+/* GNU General Public License for more details. */ | |
+ | |
+/* You should have received a copy of the GNU General Public License */ | |
+/* along with this program; if not, write to the Free Software */ | |
+/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, */ | |
+/* MA 02111-1307, USA. */ | |
+ | |
+#ifdef HAVE_CONFIG_H | |
+#include <config.h> | |
+#endif | |
+ | |
+#ifndef CYGWIN | |
+#include <sys/types.h> | |
+#include <sys/socket.h> | |
+#include <sys/un.h> | |
+#include <errno.h> | |
+#include <stdio.h> | |
+#include <glib.h> | |
+ | |
+#include "network.h" | |
+ | |
+static int OpenSocket(void) { | |
+ struct sockaddr_un addr; | |
+ int sock; | |
+ | |
+ g_print("Attempting to connect to local dopewars server via. Unix domain\n" | |
+ "socket /tmp/.dopewars/socket...\n"); | |
+ sock = socket(PF_UNIX,SOCK_STREAM,0); | |
+ if (sock==-1) { perror("socket"); exit(1); } | |
+ | |
+ addr.sun_family = AF_UNIX; | |
+ strncpy(addr.sun_path,"/tmp/.dopewars/socket",sizeof(addr.sun_path)); | |
+ addr.sun_path[sizeof(addr.sun_path)-1]='\0'; | |
+ | |
+ if (connect(sock,(struct sockaddr *)&addr,sizeof(struct sockaddr_un))==-1) { | |
+ perror("connect"); exit(1); | |
+ } | |
+ | |
+ g_print("Connection established.\n\n"); | |
+ | |
+ return sock; | |
+} | |
+ | |
+void AdminServer(void) { | |
+ int sock,topsock; | |
+ NetworkBuffer *netbuf; | |
+ fd_set readfds,writefds,errorfds; | |
+ gchar *msg,inbuf[200]; | |
+ gboolean doneOK; | |
+ | |
+ sock=OpenSocket(); | |
+ netbuf = g_new(NetworkBuffer,1); | |
+ InitNetworkBuffer(netbuf,'\n','\r',NULL); | |
+ BindNetworkBufferToSocket(netbuf,sock); | |
+ | |
+ while(1) { | |
+ FD_ZERO(&readfds); | |
+ FD_ZERO(&writefds); | |
+ FD_ZERO(&errorfds); | |
+ | |
+ FD_SET(0,&readfds); | |
+ topsock=1; | |
+ SetSelectForNetworkBuffer(netbuf,&readfds,&writefds,&errorfds,&topsock); | |
+ | |
+ if (select(topsock,&readfds,&writefds,&errorfds,NULL)==-1) { | |
+ if (errno==EINTR) continue; | |
+ else perror("select"); break; | |
+ } | |
+ | |
+ if (FD_ISSET(0,&readfds)) { | |
+ if (fgets(inbuf,sizeof(inbuf),stdin)) { | |
+ inbuf[sizeof(inbuf)-1]='\0'; | |
+ if (strlen(inbuf)>0) { | |
+ if (inbuf[strlen(inbuf)-1]=='\n') inbuf[strlen(inbuf)-1]='\0'; | |
+ QueueMessageForSend(netbuf,inbuf); | |
+ } | |
+ } else break; | |
+ } | |
+ | |
+ if (RespondToSelect(netbuf,&readfds,&writefds,&errorfds,&doneOK)) { | |
+ while((msg=GetWaitingMessage(netbuf))!=NULL) { | |
+ g_print("%s\n",msg); g_free(msg); | |
+ } | |
+ } | |
+ if (!doneOK) break; | |
+ } | |
+ ShutdownNetworkBuffer(netbuf); | |
+ g_free(netbuf); | |
+ g_print("Connection closed\n"); | |
+} | |
+#endif | |
diff --git a/src/admin.h b/src/admin.h | |
t@@ -0,0 +1,35 @@ | |
+/* admin.h Header file for dopewars server administration */ | |
+/* Copyright (C) 1998-2001 Ben Webb */ | |
+/* Email: [email protected] */ | |
+/* WWW: http://dopewars.sourceforge.net/ */ | |
+ | |
+/* This program is free software; you can redistribute it and/or */ | |
+/* modify it under the terms of the GNU General Public License */ | |
+/* as published by the Free Software Foundation; either version 2 */ | |
+/* of the License, or (at your option) any later version. */ | |
+ | |
+/* This program is distributed in the hope that it will be useful, */ | |
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ | |
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ | |
+/* GNU General Public License for more details. */ | |
+ | |
+/* You should have received a copy of the GNU General Public License */ | |
+/* along with this program; if not, write to the Free Software */ | |
+/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, */ | |
+/* MA 02111-1307, USA. */ | |
+ | |
+ | |
+#ifndef __ADMIN_H__ | |
+#define __ADMIN_H__ | |
+ | |
+#ifdef HAVE_CONFIG_H | |
+#include <config.h> | |
+#endif | |
+ | |
+#ifndef CYGWIN | |
+ | |
+void AdminServer(void); | |
+ | |
+#endif /* CYGWIN */ | |
+ | |
+#endif | |
diff --git a/src/dopewars.c b/src/dopewars.c | |
t@@ -41,6 +41,7 @@ | |
#include <signal.h> | |
#include <glib.h> | |
#include <stdarg.h> | |
+#include "admin.h" | |
#include "curses_client.h" | |
#include "dopeos.h" | |
#include "gtk_client.h" | |
t@@ -69,7 +70,13 @@ FILE *logfp; | |
unsigned Port=7902; | |
gboolean Sanitized,ConfigVerbose,DrugValue; | |
gchar *HiScoreFile=NULL,*ServerName=NULL,*Pager=NULL,*ConvertFile=NULL; | |
-gboolean WantHelp,WantVersion,WantAntique,WantColour,WantNetwork,WantConvert; | |
+gboolean WantHelp,WantVersion,WantAntique,WantColour,WantNetwork, | |
+ WantConvert,WantAdmin; | |
+ | |
+#ifdef CYGWIN | |
+gboolean MinToSysTray=TRUE; | |
+#endif | |
+ | |
ClientType WantedClient; | |
int NumLocation=0,NumGun=0,NumCop=0,NumDrug=0,NumSubway=0, | |
NumPlaying=0,NumStoppedTo=0; | |
t@@ -259,6 +266,11 @@ struct GLOBALS Globals[] = { | |
"MetaServer.Proxy.Password", | |
N_("Password for HTTP Basic proxy authentication"), | |
NULL,NULL,0,"",NULL,NULL }, | |
+#endif /* NETWORKING */ | |
+#ifdef CYGWIN | |
+ { NULL,&MinToSysTray,NULL,NULL,NULL,"MinToSysTray", | |
+ N_("If TRUE, the server minimizes to the System Tray"), | |
+ NULL,NULL,0,"",NULL,NULL }, | |
#endif | |
{ NULL,NULL,NULL,&Pager,NULL,"Pager", | |
N_("Program used to display multi-page output"),NULL,NULL,0,"",NULL,NULL … | |
t@@ -1433,7 +1445,8 @@ void ReadConfigFile(char *FileName) { | |
while (!g_scanner_eof(scanner)) if (!ParseNextConfig(scanner,FALSE)) { | |
errors++; | |
g_scanner_error(scanner, | |
- _("Unable to process configuration file line")); | |
+ _("Unable to process configuration file line %d"), | |
+ g_scanner_cur_line(scanner)); | |
} | |
g_scanner_destroy(scanner); | |
fclose(fp); | |
t@@ -1448,8 +1461,8 @@ _("Errors were encountered during the reading of the con… | |
"file \"dopewars-log.txt\" for further details.")); | |
#else | |
g_warning( | |
-_("Errors were encountered during the reading of the configuration file.\n" | |
-"As a result, some settings may not work as expected. Please see the\n" | |
+_("Errors were encountered during the reading of the configuration\n" | |
+"file. As a result, some settings may not work as expected. Please see the\n" | |
"messages on standard output for further details.")); | |
#endif | |
} | |
t@@ -1796,7 +1809,7 @@ void SetupParameters() { | |
FirstClient=FirstServer=NULL; | |
Noone.Name=g_strdup("Noone"); | |
WantColour=WantNetwork=TRUE; | |
- WantHelp=WantConvert=WantVersion=WantAntique=FALSE; | |
+ WantHelp=WantConvert=WantVersion=WantAntique=WantAdmin=FALSE; | |
WantedClient=CLIENT_AUTO; | |
Server=AIPlayer=Client=Network=FALSE; | |
t@@ -1891,16 +1904,16 @@ Drug dealing game based on \"Drug Wars\" by John E. De… | |
default %s/dopewars.sco is used)\n\ | |
-o, --hostname=ADDR specify a hostname where the server for multiplayer\… | |
dopewars can be found\n\ | |
- -s, --public-server run in server mode (note: for a \"non-interactive\"\… | |
- server, simply run as\n\ | |
- dopewars -s < /dev/null >> logfile & )\n\ | |
+ -s, --public-server run in server mode (note: see the -A option for\n\ | |
+ configuring a server once it\'s running)\n\ | |
-S, --private-server run a \"private\" server (do not notify the metaserv… | |
-p, --port=PORT specify the network port to use (default: 7902)\n\ | |
- -g, --config-file=FILE specify the pathname of a dopewars configuration fil… | |
- This file is read immediately when the -g option\n\ | |
+ -g, --config-file=FILE specify the pathname of a dopewars configuration fil… | |
+ this file is read immediately when the -g option\n\ | |
is encountered\n\ | |
-r, --pidfile=FILE maintain pid file \"FILE\" while running the server\… | |
-l, --logfile=FILE write log information to \"FILE\"\n\ | |
+ -A, --admin connect to a locally-running server for administrati… | |
-c, --ai-player create and run a computer player\n\ | |
-w, --windowed-client force the use of a graphical (windowed)\n\ | |
client (GTK+ or Win32)\n\ | |
t@@ -1926,11 +1939,11 @@ Drug dealing game based on \"Drug Wars\" by John E. De… | |
(by default %s/dopewars.sco is used)\n\ | |
-o addr specify a hostname where the server for multiplayer dopewars\n\ | |
can be found\n\ | |
- -s run in server mode (note: for a \"non-interactive\" server, simply\… | |
- run as dopewars -s < /dev/null >> logfile & )\n\ | |
+ -s run in server mode (note: see the -A option for configuring a\n\ | |
+ server once it\'s running)\n\ | |
-S run a \"private\" server (i.e. do not notify the metaserver)\n\ | |
-p port specify the network port to use (default: 7902)\n\ | |
- -g file specify the pathname of a dopewars configuration file. This file\n\ | |
+ -g file specify the pathname of a dopewars configuration file; this file\n\ | |
is read immediately when the -g option is encountered\n\ | |
-r file maintain pid file \"file\" while running the server\n\ | |
-l file write log information to \"file\"\n\ | |
t@@ -1939,6 +1952,7 @@ Drug dealing game based on \"Drug Wars\" by John E. Dell… | |
-t force the use of a text-mode client (curses)\n\ | |
(by default, a windowed client is used when possible)\n\ | |
-C file convert an \"old format\" score file to the new format\n\ | |
+ -A connect to a locally-running server for administration\n\ | |
-h display this help information\n\ | |
-v output version information and exit\n\n\ | |
dopewars is Copyright (C) Ben Webb 1998-2001, and released under the GNU GPL\n\ | |
t@@ -1948,7 +1962,7 @@ Report bugs to the author at [email protected]\… | |
void HandleCmdLine(int argc,char *argv[]) { | |
int c; | |
- static const gchar *options = "anbchvf:o:sSp:g:r:wtC:l:N"; | |
+ static const gchar *options = "anbchvf:o:sSp:g:r:wtC:l:NA"; | |
#ifdef HAVE_GETOPT_LONG | |
static const struct option long_options[] = { | |
{ "no-color", no_argument, NULL, 'b' }, | |
t@@ -1967,6 +1981,7 @@ void HandleCmdLine(int argc,char *argv[]) { | |
{ "text-client", no_argument, NULL, 't' }, | |
{ "convert", required_argument, NULL, 'C' }, | |
{ "logfile", required_argument, NULL, 'l' }, | |
+ { "admin", no_argument, NULL, 'A' }, | |
{ "help", no_argument, NULL, 'h' }, | |
{ "version", no_argument, NULL, 'v' }, | |
{ 0, 0, 0, 0 } | |
t@@ -1999,6 +2014,7 @@ void HandleCmdLine(int argc,char *argv[]) { | |
case 'w': WantedClient=CLIENT_WINDOW; break; | |
case 't': WantedClient=CLIENT_CURSES; break; | |
case 'C': AssignName(&ConvertFile,optarg); WantConvert=TRUE; break; | |
+ case 'A': WantAdmin=TRUE; break; | |
} | |
} while (c!=-1); | |
} | |
t@@ -2008,7 +2024,7 @@ int GeneralStartup(int argc,char *argv[]) { | |
/* score init.) - Returns 0 if OK, -1 if something failed. */ | |
SetupParameters(); | |
HandleCmdLine(argc,argv); | |
- if (!WantVersion && !WantHelp && !AIPlayer && !WantConvert) { | |
+ if (!WantVersion && !WantHelp && !AIPlayer && !WantConvert && !WantAdmin) { | |
return InitHighScoreFile(); | |
} | |
return 0; | |
t@@ -2063,6 +2079,8 @@ int main(int argc,char *argv[]) { | |
if (GeneralStartup(argc,argv)==0) { | |
if (WantVersion || WantHelp) { | |
HandleHelpTexts(); | |
+ } else if (WantAdmin) { | |
+ AdminServer(); | |
} else if (WantConvert) { | |
ConvertHighScoreFile(); | |
} else { | |
diff --git a/src/dopewars.h b/src/dopewars.h | |
t@@ -155,7 +155,10 @@ extern gboolean Sanitized,ConfigVerbose,DrugValue; | |
extern int NumLocation,NumGun,NumCop,NumDrug,NumSubway,NumPlaying,NumStoppedTo; | |
extern gchar *HiScoreFile,*ServerName,*Pager,*ConvertFile; | |
extern gboolean WantHelp,WantVersion,WantAntique,WantColour, | |
- WantNetwork,WantConvert; | |
+ WantNetwork,WantConvert,WantAdmin; | |
+#ifdef CYGWIN | |
+extern gboolean MinToSysTray; | |
+#endif | |
extern ClientType WantedClient; | |
extern int LoanSharkLoc,BankLoc,GunShopLoc,RoughPubLoc; | |
extern int DrugSortMethod,FightTimeout,IdleTimeout,ConnectTimeout; | |
t@@ -393,4 +396,5 @@ void dopelog(int loglevel,const gchar *format,...); | |
GLogLevelFlags LogMask(void); | |
GString *GetLogString(GLogLevelFlags log_level,const gchar *message); | |
void RestoreConfig(void); | |
+void ScannerErrorHandler(GScanner *scanner,gchar *msg,gint error); | |
#endif | |
diff --git a/src/serverside.c b/src/serverside.c | |
t@@ -598,10 +598,26 @@ void PrintHelpTo(FILE *fp) { | |
g_string_free(VarName,TRUE); | |
} | |
+static NetworkBuffer *reply_netbuf; | |
+static void ServerReply(const gchar *msg) { | |
+ int msglen; | |
+ gchar *msgcp; | |
+ | |
+ if (reply_netbuf) { | |
+ msglen=strlen(msg); | |
+ while (msglen>0 && msg[msglen-1]=='\n') msglen--; | |
+ if (msglen>0) { | |
+ msgcp = g_strndup(msg,msglen); | |
+ QueueMessageForSend(reply_netbuf,msgcp); | |
+ g_free(msgcp); | |
+ } | |
+ } else g_print(msg); | |
+} | |
+ | |
void ServerHelp(void) { | |
/* Displays a simple help screen listing the server commands and options */ | |
int i; | |
-#if CYGWIN || GUI_SERVER | |
+//#if CYGWIN || GUI_SERVER | |
int Lines; | |
GString *VarName; | |
VarName=g_string_new(""); | |
t@@ -616,14 +632,14 @@ void ServerHelp(void) { | |
} | |
g_print("%-26s\t%s\n",VarName->str,_(Globals[i].Help)); | |
Lines++; | |
-#ifndef GUI_SERVER | |
+/*#ifndef GUI_SERVER | |
if (Lines%24==0) { | |
g_print(_("--More--")); bgetch(); g_print("\n"); | |
} | |
-#endif | |
+endif*/ | |
} | |
g_string_free(VarName,TRUE); | |
-#else | |
+/*#else | |
FILE *fp; | |
fp=popen(Pager,"w"); | |
if (fp) { | |
t@@ -634,7 +650,7 @@ void ServerHelp(void) { | |
PrintHelpTo(stdout); | |
} | |
} | |
-#endif | |
+endif*/ | |
} | |
#if NETWORKING | |
t@@ -706,6 +722,7 @@ static void StartServer(void) { | |
#endif | |
Scanner=g_scanner_new(&ScannerConfig); | |
+ Scanner->msg_handler=ScannerErrorHandler; | |
Scanner->input_name="(stdin)"; | |
CreatePidFile(); | |
t@@ -810,9 +827,23 @@ gboolean IsServerShutdown(void) { | |
return (WantQuit && !FirstServer && !MetaConn); | |
} | |
-void HandleServerCommand(char *string) { | |
+static GPrintFunc StartServerReply(NetworkBuffer *netbuf) { | |
+ reply_netbuf = netbuf; | |
+ if (netbuf) return g_set_print_handler(ServerReply); | |
+ else return NULL; | |
+} | |
+ | |
+static void FinishServerReply(GPrintFunc oldprint) { | |
+ if (oldprint) g_set_print_handler(oldprint); | |
+} | |
+ | |
+static void HandleServerCommand(char *string,NetworkBuffer *netbuf) { | |
GSList *list; | |
Player *tmp; | |
+ GPrintFunc oldprint; | |
+ | |
+ oldprint = StartServerReply(netbuf); | |
+ | |
g_scanner_input_text(Scanner,string,strlen(string)); | |
if (!ParseNextConfig(Scanner,TRUE)) { | |
if (g_strcasecmp(string,"help")==0 || g_strcasecmp(string,"h")==0 || | |
t@@ -827,27 +858,30 @@ void HandleServerCommand(char *string) { | |
g_print(_("Users currently logged on:-\n")); | |
for (list=FirstServer;list;list=g_slist_next(list)) { | |
tmp=(Player *)list->data; | |
- if (!IsCop(tmp)) g_print("%s\n",GetPlayerName(tmp)); | |
+ if (!IsCop(tmp)) { | |
+ g_print("%s\n",GetPlayerName(tmp)); | |
+ } | |
} | |
} else g_print(_("No users currently logged on!\n")); | |
} else if (g_strncasecmp(string,"push ",5)==0) { | |
tmp=GetPlayerByName(string+5,FirstServer); | |
if (tmp) { | |
- dopelog(0,_("Pushing %s"),GetPlayerName(tmp)); | |
+ g_print(_("Pushing %s\n"),GetPlayerName(tmp)); | |
SendServerMessage(NULL,C_NONE,C_PUSH,tmp,NULL); | |
- } else g_warning(_("No such user!")); | |
+ } else g_print(_("No such user!\n")); | |
} else if (g_strncasecmp(string,"kill ",5)==0) { | |
tmp=GetPlayerByName(string+5,FirstServer); | |
if (tmp) { | |
- dopelog(0,_("%s killed"),GetPlayerName(tmp)); | |
+ g_print(_("%s killed\n"),GetPlayerName(tmp)); | |
BroadcastToClients(C_NONE,C_KILL,GetPlayerName(tmp),tmp, | |
(Player *)FirstServer->data); | |
FirstServer=RemovePlayer(tmp,FirstServer); | |
- } else g_warning(_("No such user!")); | |
+ } else g_print(_("No such user!\n")); | |
} else { | |
- g_warning(_("Unknown command - try \"help\" for help...")); | |
+ g_print(_("Unknown command - try \"help\" for help...\n")); | |
} | |
} | |
+ FinishServerReply(oldprint); | |
} | |
Player *HandleNewConnection(void) { | |
t@@ -890,27 +924,15 @@ void RemovePlayerFromServer(Player *Play) { | |
} | |
#ifndef CYGWIN | |
-static gchar sockdir[] = "/tmp/.dopewars/"; | |
- | |
-static gchar *GetLocalSocket(void) { | |
- return g_strdup_printf("%ssocket-%u",sockdir,Port); | |
-} | |
- | |
static void CloseLocalSocket(int localsock) { | |
- gchar *sockname; | |
- | |
if (localsock>=0) close(localsock); | |
- | |
- sockname=GetLocalSocket(); | |
- unlink(sockname); | |
- rmdir(sockdir); | |
- g_free(sockname); | |
+ unlink("/tmp/.dopewars/socket"); | |
+ rmdir("/tmp/.dopewars"); | |
} | |
static int SetupLocalSocket(void) { | |
int sock; | |
struct sockaddr_un addr; | |
- gchar *sockname; | |
CloseLocalSocket(-1); | |
t@@ -919,20 +941,17 @@ static int SetupLocalSocket(void) { | |
SetBlocking(sock,FALSE); | |
- sockname=GetLocalSocket(); | |
- mkdir(sockdir,S_IRUSR|S_IWUSR|S_IXUSR); | |
+ mkdir("/tmp/.dopewars",S_IRUSR|S_IWUSR|S_IXUSR); | |
addr.sun_family = AF_UNIX; | |
- strncpy(addr.sun_path,sockname,sizeof(addr.sun_path)); | |
+ strncpy(addr.sun_path,"/tmp/.dopewars/socket",sizeof(addr.sun_path)); | |
addr.sun_path[sizeof(addr.sun_path)-1]='\0'; | |
bind(sock,(struct sockaddr *)&addr,sizeof(struct sockaddr_un)); | |
- chmod(sockname,S_IRUSR|S_IWUSR); | |
+ chmod("/tmp/.dopewars/socket",S_IRUSR|S_IWUSR); | |
listen(sock,10); | |
- | |
- g_free(sockname); | |
return sock; | |
} | |
t@@ -945,11 +964,12 @@ void ServerLoop() { | |
GSList *list,*nextlist,*localconn=NULL; | |
fd_set readfs,writefs,errorfs; | |
int topsock; | |
+ GPrintFunc oldprint; | |
// gboolean InputClosed=FALSE; | |
struct timeval timeout; | |
int MinTimeout; | |
GString *LineBuf; | |
- gboolean EndOfLine,DoneOK; | |
+ gboolean /*EndOfLine,*/DoneOK; | |
gchar *buf; | |
#ifndef CYGWIN | |
int localsock; | |
t@@ -1039,9 +1059,12 @@ void ServerLoop() { | |
netbuf=g_new(NetworkBuffer,1); | |
InitNetworkBuffer(netbuf,'\n','\r',NULL); | |
BindNetworkBufferToSocket(netbuf,newlocal); | |
- SetBlocking(newlocal,FALSE); | |
localconn = g_slist_append(localconn,netbuf); | |
-g_print("New connection on Unix socket\n"); | |
+ oldprint = StartServerReply(netbuf); | |
+ g_print(_("dopewars server version %s ready for admin commands; " | |
+ "try \"help\" for help"),VERSION); | |
+ FinishServerReply(oldprint); | |
+ dopelog(1,_("New admin connection")); | |
} | |
list=localconn; | |
while (list) { | |
t@@ -1051,13 +1074,13 @@ g_print("New connection on Unix socket\n"); | |
if (netbuf) { | |
if (RespondToSelect(netbuf,&readfs,&writefs,&errorfs,&DoneOK)) { | |
while((buf=GetWaitingMessage(netbuf))!=NULL) { | |
- g_print("Unix message received: %s\n",buf); | |
- HandleServerCommand(buf); | |
+ dopelog(2,_("Admin command: %s"),buf); | |
+ HandleServerCommand(buf,netbuf); | |
g_free(buf); | |
} | |
} | |
if (!DoneOK) { | |
-g_print("Unix socket closed\n"); | |
+ dopelog(1,_("Admin connection closed")); | |
localconn = g_slist_remove(localconn,netbuf); | |
ShutdownNetworkBuffer(netbuf); | |
g_free(netbuf); | |
t@@ -1198,7 +1221,7 @@ static void GuiDoCommand(GtkWidget *widget,gpointer data… | |
gchar *text; | |
text=gtk_editable_get_chars(GTK_EDITABLE(widget),0,-1); | |
gtk_editable_delete_text(GTK_EDITABLE(widget),0,-1); | |
- HandleServerCommand(text); | |
+ HandleServerCommand(text,NULL); | |
g_free(text); | |
if (IsServerShutdown()) GuiQuitServer(); | |
} | |
t@@ -1289,7 +1312,7 @@ static gint GuiRequestDelete(GtkWidget *widget,GdkEvent … | |
GuiQuitServer(); | |
} else { | |
TriedPoliteShutdown=TRUE; | |
- HandleServerCommand("quit"); | |
+ HandleServerCommand("quit",NULL); | |
if (IsServerShutdown()) GuiQuitServer(); | |
} | |
return TRUE; /* Never allow automatic deletion - we handle it manually */ | |
t@@ -1297,6 +1320,7 @@ static gint GuiRequestDelete(GtkWidget *widget,GdkEvent … | |
#ifdef CYGWIN | |
static HWND mainhwnd=NULL; | |
+static BOOL systray=FALSE; | |
static BOOL RegisterStatus(DWORD state) { | |
SERVICE_STATUS status; | |
t@@ -1367,7 +1391,7 @@ static LRESULT CALLBACK GuiServerWndProc(HWND hwnd,UINT … | |
if ((UINT)lparam==WM_LBUTTONDOWN) ShowWindow(mainhwnd,SW_SHOW); | |
break; | |
case WM_SYSCOMMAND: | |
- if (wparam==SC_MINIMIZE) { | |
+ if (wparam==SC_MINIMIZE && systray) { | |
ShowWindow(mainhwnd,SW_HIDE); return TRUE; | |
} | |
break; | |
t@@ -1384,14 +1408,14 @@ static void SetupTaskBarIcon(GtkWidget *widget) { | |
if (!widget && !mainhwnd) return; | |
nid.hWnd = mainhwnd; | |
- if (widget) { | |
+ if (widget && MinToSysTray) { | |
nid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP; | |
nid.uCallbackMessage = MYWM_TASKBAR; | |
nid.hIcon = mainIcon; | |
strcpy(nid.szTip,"dopewars server - running"); | |
- Shell_NotifyIcon(NIM_ADD,&nid); | |
- SetCustomWndProc(GuiServerWndProc); | |
+ systray=Shell_NotifyIcon(NIM_ADD,&nid); | |
} else { | |
+ systray=FALSE; | |
Shell_NotifyIcon(NIM_DELETE,&nid); | |
} | |
} | |
t@@ -1445,6 +1469,7 @@ void GuiServerLoop(gboolean is_service) { | |
#ifdef CYGWIN | |
mainhwnd=window->hWnd; | |
SetupTaskBarIcon(window); | |
+ SetCustomWndProc(GuiServerWndProc); | |
if (is_service && !RegisterStatus(SERVICE_RUNNING)) { | |
dopelog(0,_("Failed to set NT Service status")); | |
return; | |
diff --git a/src/serverside.h b/src/serverside.h | |
t@@ -35,7 +35,6 @@ void CleanUpServer(void); | |
void BreakHandle(int sig); | |
void ClientLeftServer(Player *Play); | |
void StopServer(void); | |
-void HandleServerCommand(char *string); | |
Player *HandleNewConnection(void); | |
void ServerLoop(void); | |
void HandleServerPlayer(Player *Play); | |
diff --git a/win32/filelist b/win32/filelist | |
t@@ -41,6 +41,11 @@ uninstall.exe | |
dopewars-log.txt | |
dopewars.sco | |
+[keepfiles] | |
+dopewars-config.txt | |
+dopewars-log.txt | |
+dopewars.sco | |
+ | |
[startmenudir] | |
dopewars-1.5.3 | |
diff --git a/win32/makeinstall.c b/win32/makeinstall.c | |
t@@ -51,23 +51,23 @@ char *read_line(HANDLE hin) { | |
InstData *ReadInstallData() { | |
HANDLE fin; | |
char *line,*line2,*line3,*line4; | |
- InstFiles *lastinst=NULL,*lastextra=NULL; | |
+ InstFiles *lastinst=NULL,*lastextra=NULL,*lastkeep=NULL; | |
InstLink *lastmenu=NULL,*lastdesktop=NULL; | |
InstData *idata; | |
int i; | |
enum { | |
- S_PRODUCT=0,S_INSTDIR,S_INSTALL,S_EXTRA,S_STARTMENUDIR, | |
+ S_PRODUCT=0,S_INSTDIR,S_INSTALL,S_EXTRA,S_KEEP,S_STARTMENUDIR, | |
S_STARTMENU,S_DESKTOP,S_NTSERVICE, | |
S_NONE | |
} section=S_NONE; | |
char *titles[S_NONE] = { | |
- "[product]","[instdir]", "[install]","[extrafiles]","[startmenudir]", | |
- "[startmenu]","[desktop]","[NT Service]" | |
+ "[product]","[instdir]", "[install]","[extrafiles]","[keepfiles]", | |
+ "[startmenudir]","[startmenu]","[desktop]","[NT Service]" | |
}; | |
idata = bmalloc(sizeof(InstData)); | |
idata->installdir = idata->startmenudir = NULL; | |
- idata->instfiles = idata->extrafiles = NULL; | |
+ idata->instfiles = idata->extrafiles = idata->keepfiles = NULL; | |
idata->startmenu = idata->desktop = NULL; | |
idata->service = NULL; | |
t@@ -104,6 +104,9 @@ printf("start menu dir = %s\n",line); | |
case S_EXTRA: | |
AddInstFiles(line,0,&lastextra,&idata->extrafiles); | |
break; | |
+ case S_KEEP: | |
+ AddInstFiles(line,0,&lastkeep,&idata->keepfiles); | |
+ break; | |
case S_STARTMENU: | |
line2=read_line(fin); line3=read_line(fin); | |
printf("start menu entry = %s/%s/%s\n",line,line2,line3); | |
t@@ -252,6 +255,7 @@ int main() { | |
WriteLinkList(fout,idata->desktop); | |
WriteServiceDetails(fout,idata->service); | |
+ WriteFileList(fout,idata->keepfiles); | |
CloseHandle(fout); | |
bfree(inbuf); | |
diff --git a/win32/setup.c b/win32/setup.c | |
t@@ -39,6 +39,7 @@ InstData *idata; | |
HWND mainDlg[DL_NUM]; | |
DialogType CurrentDialog; | |
HINSTANCE hInst=NULL; | |
+char *oldversion=NULL; | |
DWORD WINAPI DoInstall(LPVOID lpParam); | |
static void GetWinText(char **text,HWND hWnd); | |
t@@ -251,7 +252,7 @@ LPVOID GetResource(LPCTSTR resname,LPCTSTR restype) { | |
} | |
InstData *ReadInstData() { | |
- InstFiles *lastinst=NULL,*lastextra=NULL; | |
+ InstFiles *lastinst=NULL,*lastextra=NULL,*lastkeep=NULL; | |
InstLink *lastmenu=NULL,*lastdesktop=NULL; | |
char *instdata,*pt,*filename,*line2,*line3,*line4; | |
DWORD filesize; | |
t@@ -319,6 +320,15 @@ InstData *ReadInstData() { | |
line4=pt; pt += strlen(pt)+1; | |
AddServiceDetails(filename,line2,line3,line4,&idata->service); | |
} | |
+ while (1) { | |
+ filename=pt; | |
+ pt += strlen(pt)+1; | |
+ if (filename[0]) { | |
+ filesize=atol(pt); | |
+ pt += strlen(pt)+1; | |
+ AddInstFiles(filename,filesize,&lastkeep,&idata->keepfiles); | |
+ } else break; | |
+ } | |
return idata; | |
} | |
t@@ -359,12 +369,16 @@ char *GetFirstFile(InstFiles *filelist,DWORD totalsize) { | |
return outbuf; | |
} | |
-BOOL OpenNextOutput(HANDLE *fout,InstFiles *filelist,InstFiles **listpt, | |
- DWORD *fileleft,HANDLE logf) { | |
+BOOL OpenNextOutput(HANDLE *fout,InstFiles *filelist,InstFiles *keepfiles, | |
+ InstFiles **listpt,DWORD *fileleft,HANDLE logf, | |
+ BOOL *skipfile) { | |
char *filename,*sep; | |
bstr *str; | |
+ InstFiles *keeppt; | |
DWORD bytes_written; | |
+ *skipfile=FALSE; | |
+ | |
if (*fout) CloseHandle(*fout); | |
*fout = INVALID_HANDLE_VALUE; | |
t@@ -392,20 +406,29 @@ BOOL OpenNextOutput(HANDLE *fout,InstFiles *filelist,Ins… | |
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,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 "); | |
+ keeppt = keepfiles; | |
+ while (keeppt && strcmp(keeppt->filename,filename)!=0) keeppt=keeppt->next; | |
+ | |
+/* If the file is already installed (filesize!=0), then skip it */ | |
+ if (keeppt && keeppt->filesize!=0) { | |
+ *fout = INVALID_HANDLE_VALUE+1; /* Make sure the handle is valid */ | |
+ *skipfile = TRUE; | |
+ } else { | |
+ *fout = CreateFile(filename,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,0,NULL); | |
+ bstr_assign(str,"Installing file: "); | |
bstr_append(str,filename); | |
- DisplayError(str->text,TRUE,FALSE); | |
+ 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); | |
+ } | |
} | |
+ *fileleft = (*listpt)->filesize; | |
} | |
bstr_free(str,TRUE); | |
t@@ -569,13 +592,123 @@ void SetupUninstall() { | |
bfree(startmenu); | |
} | |
+void StartRemoveOldVersion(char *oldversion,InstData *idata, | |
+ InstData **oldidata,HWND hwnd) { | |
+ InstData *old; | |
+ bstr *str; | |
+ char *oldidir,*startmenu,*desktop; | |
+ HANDLE fin; | |
+ | |
+ *oldidata=NULL; | |
+ | |
+ if (!oldversion) return; | |
+ | |
+ oldidir = GetInstallDir(oldversion); | |
+ | |
+ if (!SetCurrentDirectory(oldidir)) { | |
+ str=bstr_new(); | |
+ bstr_assign(str,"Could not access old version's install directory "); | |
+ bstr_append(str,oldidir); | |
+ DisplayError(str->text,TRUE,TRUE); | |
+ } | |
+ | |
+ fin = CreateFile("install.log",GENERIC_READ,0,NULL,OPEN_EXISTING,0,NULL); | |
+ | |
+ if (fin) { | |
+ old = ReadOldInstData(fin,oldversion,oldidir); | |
+ CloseHandle(fin); | |
+ DeleteFile("install.log"); | |
+ | |
+ RemoveService(old->service); | |
+ DeleteFileList(old->instfiles,hwnd,idata->keepfiles); | |
+ DeleteFileList(old->extrafiles,hwnd,idata->keepfiles); | |
+ | |
+ startmenu = GetStartMenuDir(old); | |
+ desktop = GetDesktopDir(); | |
+ DeleteLinkList(startmenu,old->startmenu,hwnd); | |
+ DeleteLinkList(desktop,old->desktop,hwnd); | |
+ | |
+ RemoveUninstall(startmenu,oldversion,FALSE); | |
+ | |
+ bfree(startmenu); bfree(desktop); | |
+ *oldidata = old; | |
+ } | |
+} | |
+ | |
+void FinishRemoveOldVersion(char *oldversion,InstData *idata, | |
+ InstData *oldidata) { | |
+ InstFiles *keeppt; | |
+ bstr *str; | |
+ char *desktop,*startmenu; | |
+ if (!oldidata) return; | |
+ | |
+ desktop = GetDesktopDir(); | |
+ | |
+ str = bstr_new(); | |
+/* If we're installing into a different directory, move config. files etc. | |
+ from the old directory to the new one */ | |
+ if (strcmp(oldidata->installdir,idata->installdir)!=0 && | |
+ SetCurrentDirectory(oldidata->installdir)) { | |
+ for (keeppt = idata->keepfiles;keeppt;keeppt=keeppt->next) { | |
+ if (keeppt->filesize!=0) { | |
+ bstr_assign(str,idata->installdir); | |
+ bstr_appendpath(str,keeppt->filename); | |
+ if (CopyFile(keeppt->filename,str->text,FALSE)) { | |
+ DeleteFile(keeppt->filename); | |
+ } | |
+ } | |
+ } | |
+ SetCurrentDirectory(desktop); /* Make sure we're not in the install dir */ | |
+ if (!RemoveWholeDirectory(oldidata->installdir)) { | |
+ bstr_assign(str,"Could not remove old install directory:\n"); | |
+ bstr_append(str,oldidata->installdir); | |
+ bstr_append(str,"\nYou may wish to manually remove it later."); | |
+ DisplayError(str->text,FALSE,FALSE); | |
+ } | |
+ } | |
+ | |
+ if (strcmp(idata->startmenudir,oldidata->startmenudir)!=0) { | |
+ SetCurrentDirectory(desktop); /* Make sure we're not in the menu dir */ | |
+ startmenu = GetStartMenuDir(oldidata); | |
+ if (!RemoveWholeDirectory(startmenu)) { | |
+ bstr_assign(str,"Could not remove old Start Menu directory:\n"); | |
+ bstr_append(str,startmenu); | |
+ bstr_append(str,"\nYou may wish to manually remove it later."); | |
+ DisplayError(str->text,FALSE,FALSE); | |
+ } | |
+ bfree(startmenu); | |
+ } | |
+ | |
+/* Remove the old registry key */ | |
+ bstr_assign(str,UninstallKey); | |
+ bstr_appendpath(str,oldversion); | |
+ RegDeleteKey(HKEY_LOCAL_MACHINE,str->text); | |
+ | |
+ bfree(desktop); | |
+ bstr_free(str,TRUE); | |
+ | |
+ FreeInstData(oldidata,TRUE); | |
+ oldversion=NULL; /* This is freed by FreeInstData */ | |
+} | |
+ | |
DWORD WINAPI DoInstall(LPVOID lpParam) { | |
- HANDLE fout,logf; | |
+ HANDLE fout,logf,fin; | |
DWORD bytes_written,fileleft; | |
+ BOOL skipfile; | |
char *inbuf,*outbuf; | |
int status,count; | |
z_stream z; | |
InstFiles *listpt; | |
+ InstData *oldidata; | |
+ | |
+/* Steal the filesize attribute to mark that these files are not | |
+ already installed */ | |
+ for (listpt=idata->keepfiles;listpt;listpt=listpt->next) { | |
+ listpt->filesize=0; | |
+ } | |
+ | |
+ StartRemoveOldVersion(oldversion,idata,&oldidata, | |
+ GetDlgItem(mainDlg[DL_DOINSTALL],ST_FILELIST)); | |
inbuf = GetResource(MAKEINTRESOURCE(1),"INSTFILE"); | |
if (!inbuf) return 0; | |
t@@ -586,6 +719,16 @@ DWORD WINAPI DoInstall(LPVOID lpParam) { | |
DisplayError("Cannot access install directory",TRUE,TRUE); | |
} | |
+/* Check for already-installed files */ | |
+ for (listpt=idata->keepfiles;listpt;listpt=listpt->next) { | |
+ fin = CreateFile(listpt->filename,GENERIC_READ,0,NULL,OPEN_EXISTING, | |
+ 0,NULL); | |
+ if (fin != INVALID_HANDLE_VALUE) { | |
+ CloseHandle(fin); | |
+ listpt->filesize=1; | |
+ } | |
+ } | |
+ | |
logf = CreateFile("install.log",GENERIC_WRITE,0,NULL, | |
CREATE_ALWAYS,0,NULL); | |
t@@ -596,7 +739,8 @@ DWORD WINAPI DoInstall(LPVOID lpParam) { | |
fout = INVALID_HANDLE_VALUE; | |
listpt=NULL; | |
- OpenNextOutput(&fout,idata->instfiles,&listpt,&fileleft,logf); | |
+ OpenNextOutput(&fout,idata->instfiles,idata->keepfiles, | |
+ &listpt,&fileleft,logf,&skipfile); | |
outbuf = bmalloc(BUFFER_SIZE); | |
t@@ -616,17 +760,18 @@ DWORD WINAPI DoInstall(LPVOID lpParam) { | |
count = BUFFER_SIZE - z.avail_out; | |
z.next_out = outbuf; | |
while (count >= fileleft) { | |
- if (fileleft && | |
+ if (fileleft && !skipfile && | |
!WriteFile(fout,z.next_out,fileleft,&bytes_written,NULL)) { | |
printf("Write error\n"); | |
} | |
count-=fileleft; | |
z.next_out+=fileleft; | |
- if (!OpenNextOutput(&fout,idata->instfiles,&listpt, | |
- &fileleft,logf)) break; | |
+ if (!OpenNextOutput(&fout,idata->instfiles,idata->keepfiles, | |
+ &listpt,&fileleft,logf,&skipfile)) break; | |
} | |
if (fout==INVALID_HANDLE_VALUE) break; | |
- if (count && !WriteFile(fout,z.next_out,count,&bytes_written,NULL)) { | |
+ if (count && !skipfile && | |
+ !WriteFile(fout,z.next_out,count,&bytes_written,NULL)) { | |
printf("Write error\n"); | |
} | |
fileleft-=count; | |
t@@ -637,7 +782,7 @@ DWORD WINAPI DoInstall(LPVOID lpParam) { | |
} | |
inflateEnd(&z); | |
- CloseHandle(fout); | |
+ if (!skipfile) CloseHandle(fout); | |
outbuf[0]='\0'; | |
if (!WriteFile(logf,outbuf,1,&bytes_written,NULL)) { | |
t@@ -647,6 +792,8 @@ DWORD WINAPI DoInstall(LPVOID lpParam) { | |
WriteFileList(logf,idata->extrafiles); | |
+ FinishRemoveOldVersion(oldversion,idata,oldidata); | |
+ | |
InstallService(idata); | |
CoInitialize(NULL); | |
t@@ -699,7 +846,11 @@ void FillFolderList(void) { | |
} | |
BOOL CheckExistingInstall(InstData *idata) { | |
- bstr *str,*subkey; | |
+ bstr *str; | |
+ char *sep,*prodname,*prodversion; | |
+ char *subkey; | |
+ int sublen; | |
+ DWORD sublencp; | |
HKEY key; | |
DWORD ind; | |
FILETIME ftime; | |
t@@ -708,6 +859,9 @@ BOOL CheckExistingInstall(InstData *idata) { | |
str=bstr_new(); | |
bstr_assign(str,UninstallKey); | |
bstr_appendpath(str,idata->product); | |
+ | |
+/* Split product into name and version */ | |
+ sep = strrchr(idata->product,'-'); | |
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,str->text,0,KEY_READ,&key) | |
==ERROR_SUCCESS) { | |
t@@ -715,15 +869,45 @@ BOOL CheckExistingInstall(InstData *idata) { | |
if (MessageBox(NULL,"This program appears to already be installed.\n" | |
"Are you sure you want to go ahead and install it anyway?", | |
idata->product,MB_YESNO)==IDNO) retval=FALSE; | |
- } else { | |
-// TODO: Check for old versions to upgrade | |
+ } else if (sep) { | |
+ *sep='\0'; | |
+ prodversion = sep+1; | |
+ prodname = bstrdup(idata->product); | |
+ *sep='-'; | |
+ sublencp=sublen=strlen(idata->product)+30; | |
+ subkey = bmalloc(sublen); | |
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,UninstallKey,0,KEY_READ,&key) | |
==ERROR_SUCCESS) { | |
-/* for (ind=0;RegEnumKeyEx(key,ind,subkey,subkey->len, | |
- NULL,NULL,NULL,&ftime)==ERROR_SUCCESS;ind++) { | |
- }*/ | |
+ ind=0; | |
+ while (RegEnumKeyEx(key,ind++,subkey,&sublencp, | |
+ NULL,NULL,NULL,&ftime)==ERROR_SUCCESS) { | |
+ sublencp=sublen; | |
+ sep=strrchr(subkey,'-'); | |
+ if (sep) { | |
+ *sep='\0'; | |
+ if (strcmp(subkey,prodname)==0) { | |
+ bstr_assign(str,"You are trying to install "); | |
+ bstr_append(str,idata->product); | |
+ bstr_append(str,".\nHowever, version "); | |
+ bstr_append(str,sep+1); | |
+ bstr_append(str," appears to already be installed.\n" | |
+ "Do you want to replace the existing version with " | |
+ "this one?\n(If you answer \"No\", and continue, " | |
+ "both versions will be installed.)"); | |
+ if (MessageBox(NULL,str->text,"Existing version",MB_YESNO)==IDYES)… | |
+ *sep='-'; | |
+ oldversion=bstrdup(subkey); | |
+ } | |
+ break; | |
+ } | |
+ } | |
+ } | |
+ RegCloseKey(key); | |
} | |
+ bfree(prodname); | |
+ bfree(subkey); | |
} | |
+ bstr_free(str,TRUE); | |
return retval; | |
} | |
diff --git a/win32/uninstall.c b/win32/uninstall.c | |
t@@ -30,123 +30,6 @@ HINSTANCE hInst; | |
HWND mainDlg; | |
char *product; | |
-void RemoveService(NTService *service) { | |
- SC_HANDLE scManager,scService; | |
- SERVICE_STATUS status; | |
- | |
- if (!service) return; | |
- | |
- scManager = OpenSCManager(NULL,NULL,GENERIC_READ); | |
- | |
- if (!scManager) { | |
- DisplayError("Cannot connect to service manager",TRUE,FALSE); | |
- return; | |
- } | |
- | |
- scService = OpenService(scManager,service->name,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; | |
- DWORD bytes_read; | |
- buf = bmalloc(bufsize); | |
- | |
- while (1) { | |
- if (!ReadFile(hin,&buf[strind],1,&bytes_read,NULL)) { | |
- printf("Read error\n"); break; | |
- } | |
- if (bytes_read==0) { buf[strind]='\0'; break; } | |
- else if (buf[strind]=='\0') break; | |
- else { | |
- strind++; | |
- if (strind>=bufsize) { | |
- bufsize*=2; | |
- buf = brealloc(buf,bufsize); | |
- } | |
- } | |
- } | |
- if (strind==0) { bfree(buf); return NULL; } | |
- else return buf; | |
-} | |
- | |
-InstLink *ReadLinkList(HANDLE fin) { | |
- InstLink *first=NULL,*listpt=NULL,*newpt; | |
- char *linkfile,*origfile,*args; | |
- | |
- while (1) { | |
- linkfile=read_line0(fin); | |
- if (!linkfile) break; | |
- origfile=read_line0(fin); | |
- args=read_line0(fin); | |
- if (!origfile) DisplayError("Corrupt install.log",FALSE,TRUE); | |
- newpt = bmalloc(sizeof(InstLink)); | |
- if (listpt) listpt->next = newpt; | |
- else first = newpt; | |
- listpt = newpt; | |
- newpt->next=NULL; | |
- newpt->linkfile=linkfile; | |
- newpt->origfile=origfile; | |
- newpt->args=args; | |
- } | |
- return first; | |
-} | |
- | |
-NTService *ReadServiceDetails(HANDLE fin) { | |
- NTService *service=NULL; | |
- char *name,*disp,*desc,*exe; | |
- | |
- name = read_line0(fin); | |
- if (name) { | |
- disp = read_line0(fin); | |
- desc = read_line0(fin); | |
- exe = read_line0(fin); | |
- if (!disp || !desc || !exe) { | |
- DisplayError("Corrupt install.log",FALSE,TRUE); | |
- } else { | |
- AddServiceDetails(name,disp,desc,exe,&service); | |
- } | |
- } | |
- | |
- return service; | |
-} | |
- | |
-InstFiles *ReadFileList(HANDLE fin) { | |
- InstFiles *first=NULL,*listpt=NULL,*newpt; | |
- char *filename,*filesize; | |
- | |
- while (1) { | |
- filename=read_line0(fin); | |
- if (!filename) break; | |
- filesize=read_line0(fin); | |
- if (!filesize) DisplayError("Corrupt install.log",FALSE,TRUE); | |
- newpt = bmalloc(sizeof(InstFiles)); | |
- if (listpt) listpt->next = newpt; | |
- else first = newpt; | |
- listpt = newpt; | |
- | |
- newpt->next=NULL; | |
- newpt->filename=filename; | |
- newpt->filesize=atol(filesize); | |
- bfree(filesize); | |
- } | |
- return first; | |
-} | |
- | |
char *GetProduct(void) { | |
char *product; | |
product = strrchr(GetCommandLine(),' '); | |
t@@ -157,125 +40,10 @@ char *GetProduct(void) { | |
} | |
} | |
-char *GetInstallDir(char *product) { | |
- HKEY key; | |
- bstr *str; | |
- DWORD keytype,keylen; | |
- char *installdir; | |
- | |
- str=bstr_new(); | |
- bstr_assign(str,UninstallKey); | |
- bstr_appendpath(str,product); | |
- if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,str->text,0, | |
- KEY_ALL_ACCESS,&key)!=ERROR_SUCCESS) { | |
- DisplayError("Could not open registry",FALSE,TRUE); | |
- } | |
- | |
- if (RegQueryValueEx(key,"InstallDirectory",NULL, | |
- &keytype,NULL,&keylen)!=ERROR_SUCCESS || | |
- keytype!=REG_SZ) { | |
- DisplayError("Could not query registry key",FALSE,TRUE); | |
- } | |
- | |
- installdir = bmalloc(keylen); | |
- if (RegQueryValueEx(key,"InstallDirectory",NULL, | |
- &keytype,installdir,&keylen)!=ERROR_SUCCESS) { | |
- DisplayError("Could not get registry key value",FALSE,TRUE); | |
- } | |
- | |
- bstr_free(str,TRUE); | |
- return installdir; | |
-} | |
- | |
-InstData *ReadInstData(HANDLE fin,char *product,char *installdir) { | |
- InstData *idata; | |
- | |
- idata=bmalloc(sizeof(InstData)); | |
- | |
- idata->product=product; | |
- idata->installdir=installdir; | |
- idata->startmenudir=read_line0(fin); | |
- | |
- idata->instfiles = ReadFileList(fin); | |
- idata->extrafiles = ReadFileList(fin); | |
- | |
- idata->startmenu = ReadLinkList(fin); | |
- idata->desktop = ReadLinkList(fin); | |
- | |
- idata->service = ReadServiceDetails(fin); | |
- return idata; | |
-} | |
- | |
-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); | |
-} | |
- | |
-void DeleteLinkList(char *dir,InstLink *listpt) { | |
- bstr *str; | |
- str=bstr_new(); | |
- if (SetCurrentDirectory(dir)) { | |
- for (;listpt;listpt=listpt->next) { | |
- bstr_assign(str,"Deleting shortcut: "); | |
- bstr_append(str,listpt->linkfile); | |
- SendDlgItemMessage(mainDlg,ST_DELSTAT,WM_SETTEXT,0,(LPARAM)str->text); | |
- DeleteFile(listpt->linkfile); | |
- } | |
- } else { | |
- bstr_assign(str,"Could not find shortcut directory "); | |
- bstr_append(str,dir); | |
- DisplayError(str->text,TRUE,FALSE); | |
- } | |
- bstr_free(str,TRUE); | |
-} | |
- | |
-void RemoveUninstall(char *startmenu,char *product) { | |
- bstr *inipath,*uninstpath,*uninstlink; | |
- | |
- inipath=bstr_new(); | |
- uninstpath=bstr_new(); | |
- uninstlink=bstr_new(); | |
- | |
- bstr_assign(uninstlink,startmenu); | |
- bstr_appendpath(uninstlink,"Uninstall "); | |
- bstr_append(uninstlink,product); | |
- bstr_append(uninstlink,".LNK"); | |
- DeleteFile(uninstlink->text); | |
- | |
- bstr_assign_windir(inipath); | |
- bstr_assign(uninstpath,inipath->text); | |
- | |
- bstr_appendpath(inipath,"wininit.ini"); | |
- bstr_appendpath(uninstpath,UninstallEXE); | |
- | |
- if (!WritePrivateProfileString("Renane","NUL",uninstpath->text, | |
- inipath->text)) { | |
- DisplayError("Cannot write to wininit.ini: ",TRUE,FALSE); | |
- } | |
- | |
- bstr_free(uninstlink,TRUE); | |
- bstr_free(uninstpath,TRUE); | |
- bstr_free(inipath,TRUE); | |
-} | |
- | |
DWORD WINAPI DoUninstall(LPVOID lpParam) { | |
InstData *idata; | |
HANDLE fin; | |
+ HWND delstat; | |
bstr *str; | |
char *startmenu,*desktop,*installdir; | |
t@@ -292,21 +60,22 @@ DWORD WINAPI DoUninstall(LPVOID lpParam) { | |
fin = CreateFile("install.log",GENERIC_READ,0,NULL,OPEN_EXISTING,0,NULL); | |
if (fin) { | |
- idata = ReadInstData(fin,product,installdir); | |
+ idata = ReadOldInstData(fin,product,installdir); | |
CloseHandle(fin); | |
+ DeleteFile("install.log"); | |
RemoveService(idata->service); | |
- DeleteFile("install.log"); | |
- DeleteFileList(idata->instfiles); | |
- DeleteFileList(idata->extrafiles); | |
+ delstat = GetDlgItem(mainDlg,ST_DELSTAT); | |
+ DeleteFileList(idata->instfiles,delstat,NULL); | |
+ DeleteFileList(idata->extrafiles,delstat,NULL); | |
startmenu = GetStartMenuDir(idata); | |
desktop = GetDesktopDir(); | |
- DeleteLinkList(startmenu,idata->startmenu); | |
- DeleteLinkList(desktop,idata->desktop); | |
+ DeleteLinkList(startmenu,idata->startmenu,delstat); | |
+ DeleteLinkList(desktop,idata->desktop,delstat); | |
- RemoveUninstall(startmenu,product); | |
+ RemoveUninstall(startmenu,product,TRUE); | |
SetCurrentDirectory(desktop); /* Just make sure we're not in the install | |
directory any more */ | |
diff --git a/win32/util.c b/win32/util.c | |
t@@ -309,6 +309,7 @@ void FreeServiceDetails(NTService *service,BOOL freepts) { | |
void FreeInstData(InstData *idata,BOOL freepts) { | |
FreeFileList(idata->instfiles,freepts); | |
FreeFileList(idata->extrafiles,freepts); | |
+ FreeFileList(idata->keepfiles,freepts); | |
FreeLinkList(idata->startmenu,freepts); | |
FreeLinkList(idata->desktop,freepts); | |
t@@ -485,3 +486,249 @@ BOOL RemoveWholeDirectory(char *path) { | |
} | |
return TRUE; | |
} | |
+ | |
+void RemoveService(NTService *service) { | |
+ SC_HANDLE scManager,scService; | |
+ SERVICE_STATUS status; | |
+ | |
+ if (!service) return; | |
+ | |
+ scManager = OpenSCManager(NULL,NULL,GENERIC_READ); | |
+ | |
+ if (!scManager) { | |
+ DisplayError("Cannot connect to service manager",TRUE,FALSE); | |
+ return; | |
+ } | |
+ | |
+ scService = OpenService(scManager,service->name,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; | |
+ DWORD bytes_read; | |
+ buf = bmalloc(bufsize); | |
+ | |
+ while (1) { | |
+ if (!ReadFile(hin,&buf[strind],1,&bytes_read,NULL)) { | |
+ printf("Read error\n"); break; | |
+ } | |
+ if (bytes_read==0) { buf[strind]='\0'; break; } | |
+ else if (buf[strind]=='\0') break; | |
+ else { | |
+ strind++; | |
+ if (strind>=bufsize) { | |
+ bufsize*=2; | |
+ buf = brealloc(buf,bufsize); | |
+ } | |
+ } | |
+ } | |
+ if (strind==0) { bfree(buf); return NULL; } | |
+ else return buf; | |
+} | |
+ | |
+InstLink *ReadLinkList(HANDLE fin) { | |
+ InstLink *first=NULL,*listpt=NULL,*newpt; | |
+ char *linkfile,*origfile,*args; | |
+ | |
+ while (1) { | |
+ linkfile=read_line0(fin); | |
+ if (!linkfile) break; | |
+ origfile=read_line0(fin); | |
+ args=read_line0(fin); | |
+ if (!origfile) DisplayError("Corrupt install.log",FALSE,TRUE); | |
+ newpt = bmalloc(sizeof(InstLink)); | |
+ if (listpt) listpt->next = newpt; | |
+ else first = newpt; | |
+ listpt = newpt; | |
+ newpt->next=NULL; | |
+ newpt->linkfile=linkfile; | |
+ newpt->origfile=origfile; | |
+ newpt->args=args; | |
+ } | |
+ return first; | |
+} | |
+ | |
+NTService *ReadServiceDetails(HANDLE fin) { | |
+ NTService *service=NULL; | |
+ char *name,*disp,*desc,*exe; | |
+ | |
+ name = read_line0(fin); | |
+ if (name) { | |
+ disp = read_line0(fin); | |
+ desc = read_line0(fin); | |
+ exe = read_line0(fin); | |
+ if (!disp || !desc || !exe) { | |
+ DisplayError("Corrupt install.log",FALSE,TRUE); | |
+ } else { | |
+ AddServiceDetails(name,disp,desc,exe,&service); | |
+ } | |
+ } | |
+ | |
+ return service; | |
+} | |
+ | |
+InstFiles *ReadFileList(HANDLE fin) { | |
+ InstFiles *first=NULL,*listpt=NULL,*newpt; | |
+ char *filename,*filesize; | |
+ | |
+ while (1) { | |
+ filename=read_line0(fin); | |
+ if (!filename) break; | |
+ filesize=read_line0(fin); | |
+ if (!filesize) DisplayError("Corrupt install.log",FALSE,TRUE); | |
+ newpt = bmalloc(sizeof(InstFiles)); | |
+ if (listpt) listpt->next = newpt; | |
+ else first = newpt; | |
+ listpt = newpt; | |
+ | |
+ newpt->next=NULL; | |
+ newpt->filename=filename; | |
+ newpt->filesize=atol(filesize); | |
+ bfree(filesize); | |
+ } | |
+ return first; | |
+} | |
+ | |
+char *GetInstallDir(char *product) { | |
+ HKEY key; | |
+ bstr *str; | |
+ DWORD keytype,keylen; | |
+ char *installdir; | |
+ | |
+ str=bstr_new(); | |
+ bstr_assign(str,UninstallKey); | |
+ bstr_appendpath(str,product); | |
+ if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,str->text,0, | |
+ KEY_ALL_ACCESS,&key)!=ERROR_SUCCESS) { | |
+ DisplayError("Could not open registry",FALSE,TRUE); | |
+ } | |
+ | |
+ if (RegQueryValueEx(key,"InstallDirectory",NULL, | |
+ &keytype,NULL,&keylen)!=ERROR_SUCCESS || | |
+ keytype!=REG_SZ) { | |
+ DisplayError("Could not query registry key",FALSE,TRUE); | |
+ } | |
+ | |
+ installdir = bmalloc(keylen); | |
+ if (RegQueryValueEx(key,"InstallDirectory",NULL, | |
+ &keytype,installdir,&keylen)!=ERROR_SUCCESS) { | |
+ DisplayError("Could not get registry key value",FALSE,TRUE); | |
+ } | |
+ | |
+ bstr_free(str,TRUE); | |
+ return installdir; | |
+} | |
+ | |
+InstData *ReadOldInstData(HANDLE fin,char *product,char *installdir) { | |
+ InstData *idata; | |
+ | |
+ idata=bmalloc(sizeof(InstData)); | |
+ | |
+ idata->product=product; | |
+ idata->installdir=installdir; | |
+ idata->startmenudir=read_line0(fin); | |
+ | |
+ idata->instfiles = ReadFileList(fin); | |
+ idata->extrafiles = ReadFileList(fin); | |
+ | |
+ idata->startmenu = ReadLinkList(fin); | |
+ idata->desktop = ReadLinkList(fin); | |
+ | |
+ idata->service = ReadServiceDetails(fin); | |
+ idata->keepfiles = ReadFileList(fin); | |
+ | |
+ return idata; | |
+} | |
+ | |
+void DeleteFileList(InstFiles *listpt,HWND hwnd,InstFiles *keepfiles) { | |
+ bstr *str; | |
+ char *sep; | |
+ InstFiles *keeppt; | |
+ | |
+ str=bstr_new(); | |
+ for (;listpt;listpt=listpt->next) { | |
+ keeppt = keepfiles; | |
+ while (keeppt && strcmp(keeppt->filename,listpt->filename)!=0) { | |
+ keeppt = keeppt->next; | |
+ } | |
+ if (keeppt) { | |
+ keeppt->filesize=1; /* Mark that this file is already installed */ | |
+ } else { | |
+ bstr_assign(str,"Deleting file: "); | |
+ bstr_append(str,listpt->filename); | |
+ SendMessage(hwnd,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); | |
+} | |
+ | |
+void DeleteLinkList(char *dir,InstLink *listpt,HWND hwnd) { | |
+ bstr *str; | |
+ str=bstr_new(); | |
+ if (SetCurrentDirectory(dir)) { | |
+ for (;listpt;listpt=listpt->next) { | |
+ bstr_assign(str,"Deleting shortcut: "); | |
+ bstr_append(str,listpt->linkfile); | |
+ SendMessage(hwnd,WM_SETTEXT,0,(LPARAM)str->text); | |
+ DeleteFile(listpt->linkfile); | |
+ } | |
+ } else { | |
+ bstr_assign(str,"Could not find shortcut directory "); | |
+ bstr_append(str,dir); | |
+ DisplayError(str->text,TRUE,FALSE); | |
+ } | |
+ bstr_free(str,TRUE); | |
+} | |
+ | |
+void RemoveUninstall(char *startmenu,char *product,BOOL delexe) { | |
+ bstr *inipath,*uninstpath,*uninstlink; | |
+ | |
+ inipath=bstr_new(); | |
+ uninstpath=bstr_new(); | |
+ uninstlink=bstr_new(); | |
+ | |
+ bstr_assign(uninstlink,startmenu); | |
+ bstr_appendpath(uninstlink,"Uninstall "); | |
+ bstr_append(uninstlink,product); | |
+ bstr_append(uninstlink,".LNK"); | |
+ DeleteFile(uninstlink->text); | |
+ | |
+ if (delexe) { | |
+ bstr_assign_windir(inipath); | |
+ bstr_assign(uninstpath,inipath->text); | |
+ | |
+ bstr_appendpath(inipath,"wininit.ini"); | |
+ bstr_appendpath(uninstpath,UninstallEXE); | |
+ | |
+ if (!WritePrivateProfileString("Renane","NUL",uninstpath->text, | |
+ inipath->text)) { | |
+ DisplayError("Cannot write to wininit.ini: ",TRUE,FALSE); | |
+ } | |
+ } | |
+ | |
+ bstr_free(uninstlink,TRUE); | |
+ bstr_free(uninstpath,TRUE); | |
+ bstr_free(inipath,TRUE); | |
+} | |
diff --git a/win32/util.h b/win32/util.h | |
t@@ -53,6 +53,7 @@ typedef struct _InstData { | |
NTService *service; | |
InstFiles *instfiles; | |
InstFiles *extrafiles; | |
+ InstFiles *keepfiles; | |
InstLink *startmenu; | |
InstLink *desktop; | |
} InstData; | |
t@@ -99,3 +100,9 @@ char *GetStartMenuDir(InstData *idata); | |
char *GetDesktopDir(void); | |
BOOL CreateWholeDirectory(char *path); | |
BOOL RemoveWholeDirectory(char *path); | |
+void DeleteLinkList(char *dir,InstLink *listpt,HWND hwnd); | |
+void DeleteFileList(InstFiles *listpt,HWND hwnd,InstFiles *keepfiles); | |
+InstData *ReadOldInstData(HANDLE fin,char *product,char *installdir); | |
+char *GetInstallDir(char *product); | |
+void RemoveService(NTService *service); | |
+void RemoveUninstall(char *startmenu,char *product,BOOL delexe); |