tWin32 installer updates - 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 40ec03f43f7910bd549c4324e545089c2c24cee4
(DIR) parent a5f688bfb27f69264afa2f75ea6975f7ad2ab24b
(HTM) Author: Ben Webb <ben@salilab.org>
Date: Mon, 24 Sep 2001 22:37:10 +0000
Win32 installer updates
Diffstat:
M win32/Makefile | 27 +++++++++++++++++++--------
M win32/contid.h | 7 +++++++
A win32/dialogs.c | 169 +++++++++++++++++++++++++++++++
M win32/dialogs.rc | 21 ++++++++++++++++++---
M win32/filelist | 44 +++++++++++++++++++++++++++----
A win32/guifunc.c | 70 +++++++++++++++++++++++++++++++
A win32/guifunc.h | 4 ++++
A win32/install.c | 37 +++++++++++++++++++++++++++++++
A win32/install.rc | 21 +++++++++++++++++++++
A win32/makeinstall.c | 228 +++++++++++++++++++++++++++++++
A win32/setup.c | 656 +++++++++++++++++++++++++++++++
A win32/uninstall.c | 290 +++++++++++++++++++++++++++++++
M win32/uninstall.rc | 13 +++++++++++++
A win32/util.c | 358 +++++++++++++++++++++++++++++++
A win32/util.h | 65 +++++++++++++++++++++++++++++++
15 files changed, 1994 insertions(+), 16 deletions(-)
---
(DIR) diff --git a/win32/Makefile b/win32/Makefile
t@@ -1,22 +1,33 @@
all: setup makeinstall uninstall
-setup: setup.o setup.res
- gcc -Wall -mno-cygwin -mwindows -o setup setup.o setup.res zlib/libz.a -lcomctl32 -lole32 -luuid
+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
+ strip setup.exe
-uninstall: uninstall.o uninstall.res
- gcc -Wall -mno-cygwin -o uninstall uninstall.o uninstall.res
+uninstall: uninstall.o util.o guifunc.o uninstall.res
+ gcc -Wall -mno-cygwin -mwindows -o uninstall uninstall.o util.o guifunc.o uninstall.res
+ strip uninstall.exe
-uninstall.o: uninstall.c
+uninstall.o: uninstall.c util.h guifunc.h
gcc -Wall -mno-cygwin -c uninstall.c
uninstall.res: uninstall.rc
windres -O coff -o uninstall.res uninstall.rc
-setup.o: setup.c contid.h
+setup.o: setup.c contid.h util.h guifunc.h
gcc -Wall -mno-cygwin -c setup.c
+util.o: util.c util.h
+ gcc -Wall -mno-cygwin -c util.c
+
+guifunc.o: guifunc.c guifunc.h
+ gcc -Wall -mno-cygwin -c guifunc.c
+
setup.res: setup.rc dialogs.rc contid.h manifest installfiles.gz
windres -O coff -o setup.res setup.rc
-makeinstall: makeinstall.c
- gcc -Wall -mno-cygwin -o makeinstall makeinstall.c zlib/libz.a
+makeinstall: makeinstall.o util.o
+ gcc -Wall -mno-cygwin -o makeinstall makeinstall.o util.o zlib/libz.a
+
+makeinstall.o: makeinstall.c util.h
+ gcc -Wall -mno-cygwin -c makeinstall.c
(DIR) diff --git a/win32/contid.h b/win32/contid.h
t@@ -7,3 +7,10 @@
#define ST_FILELIST 207
#define ST_COMPLETE 208
#define ST_EXIT 209
+#define ED_FOLDER 210
+#define LB_FOLDLIST 211
+#define CB_DESKTOP 212
+#define ST_INSTDIR 213
+#define ST_DELSTAT 214
+#define ST_DELDONE 215
+#define BT_DELOK 216
(DIR) diff --git a/win32/dialogs.c b/win32/dialogs.c
t@@ -0,0 +1,169 @@
+#include <windows.h>
+#include <commctrl.h>
+#include "contid.h"
+
+#define NUMDIALOGS 4
+
+HWND mainDlg[NUMDIALOGS];
+
+int CurrentDialog;
+
+HINSTANCE hInst=NULL;
+
+BOOL CALLBACK enumFunc(HWND hWnd,LPARAM lParam) {
+ HFONT GuiFont;
+ GuiFont=(HFONT)lParam;
+ SendMessage(hWnd,WM_SETFONT,(WPARAM)GuiFont,MAKELPARAM(FALSE,0));
+ return TRUE;
+}
+
+void ShowNewDialog(int NewDialog) {
+ RECT DeskRect,OurRect;
+ int newX,newY;
+ HWND hWnd;
+ if (NewDialog<0 || NewDialog>=NUMDIALOGS) return;
+
+ hWnd=mainDlg[NewDialog];
+ if (GetWindowRect(hWnd,&OurRect) &&
+ GetWindowRect(GetDesktopWindow(),&DeskRect)) {
+ newX = (DeskRect.left+DeskRect.right+OurRect.left-OurRect.right)/2;
+ newY = (DeskRect.top+DeskRect.bottom+OurRect.top-OurRect.bottom)/2;
+ SetWindowPos(hWnd,HWND_TOP,newX,newY,0,0,SWP_NOSIZE);
+ }
+ ShowWindow(hWnd,SW_SHOW);
+
+ if (CurrentDialog!=-1) ShowWindow(mainDlg[CurrentDialog],SW_HIDE);
+ CurrentDialog=NewDialog;
+}
+
+LRESULT CALLBACK GtkSepProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam) {
+ PAINTSTRUCT ps;
+ HPEN oldpen,dkpen,ltpen;
+ RECT rect;
+ HDC hDC;
+ if (msg==WM_PAINT) {
+ if (GetUpdateRect(hwnd,NULL,TRUE)) {
+ BeginPaint(hwnd,&ps);
+ GetClientRect(hwnd,&rect);
+ hDC=ps.hdc;
+ ltpen=CreatePen(PS_SOLID,0,(COLORREF)GetSysColor(COLOR_3DHILIGHT));
+ dkpen=CreatePen(PS_SOLID,0,(COLORREF)GetSysColor(COLOR_3DSHADOW));
+
+ if (rect.right > rect.bottom) {
+ oldpen=SelectObject(hDC,dkpen);
+ MoveToEx(hDC,rect.left,rect.top,NULL);
+ LineTo(hDC,rect.right,rect.top);
+
+ SelectObject(hDC,ltpen);
+ MoveToEx(hDC,rect.left,rect.top+1,NULL);
+ LineTo(hDC,rect.right,rect.top+1);
+ } else {
+ oldpen=SelectObject(hDC,dkpen);
+ MoveToEx(hDC,rect.left,rect.top,NULL);
+ LineTo(hDC,rect.left,rect.bottom);
+
+ SelectObject(hDC,ltpen);
+ MoveToEx(hDC,rect.left+1,rect.top,NULL);
+ LineTo(hDC,rect.left+1,rect.bottom);
+ }
+
+ SelectObject(hDC,oldpen);
+ DeleteObject(ltpen); DeleteObject(dkpen);
+ EndPaint(hwnd,&ps);
+ }
+ return TRUE;
+ } else return DefWindowProc(hwnd,msg,wParam,lParam);
+}
+
+void ConditionalExit(HWND hWnd) {
+ if (MessageBox(hWnd,"This will exit without installing any new software on "
+ "your machine.\nAre you sure you want to quit?\n\n(You can "
+ "continue the installation at a\nlater date simply by "
+ "running this program again.)","Exit Install",
+ MB_YESNO|MB_ICONQUESTION)==IDYES) {
+ PostQuitMessage(0);
+ }
+}
+
+BOOL CALLBACK MainDlgProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam) {
+ switch(msg) {
+ case WM_INITDIALOG:
+ return TRUE;
+ case WM_COMMAND:
+ if (HIWORD(wParam)==BN_CLICKED && lParam) {
+ switch(LOWORD(wParam)) {
+ case BT_CANCEL: ConditionalExit(hWnd); break;
+ case BT_NEXT: ShowNewDialog(CurrentDialog+1); break;
+ case BT_BACK: ShowNewDialog(CurrentDialog-1); break;
+ case BT_FINISH: PostQuitMessage(0); break;
+// case BT_BROWSE: SelectInstDir(); break;
+ }
+ }
+ break;
+ case WM_CLOSE:
+ ConditionalExit(hWnd);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,
+ LPSTR lpszCmdParam,int nCmdShow) {
+ MSG msg;
+ HWND mainWin;
+ DWORD err;
+ LPVOID lpMsgBuf;
+ WNDCLASS wc;
+ int i;
+ BOOL Handled;
+ HFONT GuiFont;
+//InitCommonControls();
+
+ hInst = hInstance;
+
+ if (!hPrevInstance) {
+ wc.style = CS_HREDRAW|CS_VREDRAW;
+ wc.lpfnWndProc = GtkSepProc;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = 0;
+ wc.hInstance = hInstance;
+ wc.hIcon = NULL;
+ wc.hCursor = LoadCursor(NULL,IDC_ARROW);
+ wc.hbrBackground = (HBRUSH)(1+COLOR_BTNFACE);
+ wc.lpszMenuName = NULL;
+ wc.lpszClassName = "WC_GTKSEP";
+ RegisterClass(&wc);
+ }
+
+ for (i=0;i<NUMDIALOGS;i++) {
+ mainDlg[i] = CreateDialog(hInst,MAKEINTRESOURCE(i+1),NULL,MainDlgProc);
+ }
+
+ GuiFont=(HFONT)GetStockObject(DEFAULT_GUI_FONT);
+ if (GuiFont) for (i=0;i<NUMDIALOGS;i++) {
+ EnumChildWindows(mainDlg[i],enumFunc,(LPARAM)GuiFont);
+ }
+ CurrentDialog=-1;
+ ShowNewDialog(0);
+
+/*if (!mainWin) {
+ err=GetLastError();
+ FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL,GetLastError(),MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT),
+ (LPTSTR)&lpMsgBuf,0,NULL);
+ MessageBox(NULL,lpMsgBuf,"Error",MB_OK | MB_ICONSTOP);
+ LocalFree(lpMsgBuf);
+ return 0;
+ }*/
+
+ while (GetMessage(&msg,NULL,0,0)) {
+ Handled=FALSE;
+ for (i=0;i<NUMDIALOGS && !Handled;i++) {
+ Handled=IsDialogMessage(mainDlg[i],&msg);
+ }
+ if (!Handled) {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+ }
+}
(DIR) diff --git a/win32/dialogs.rc b/win32/dialogs.rc
t@@ -23,7 +23,7 @@ BEGIN
CONTROL "", ED_LICENCE, "EDIT", ES_LEFT | ES_MULTILINE | ES_AUTOVSCROLL | ES_READONLY | WS_CHILD | WS_VISIBLE | WS_BORDER | WS_TABSTOP | WS_VSCROLL, 22, 45, 195, 75
END
-3 DIALOG 17, 40, 239, 162
+4 DIALOG 17, 40, 239, 162
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Installation directory"
BEGIN
t@@ -35,12 +35,12 @@ BEGIN
LTEXT "To install in this directory, select ""Next"".", -1, 22, 33, 195, 9, WS_CHILD | WS_VISIBLE | WS_GROUP
LTEXT "To install in a different directory, select ""Browse"" and select the desired location.", -1, 22, 51, 195, 18, WS_CHILD | WS_VISIBLE | WS_GROUP
GROUPBOX "Destination directory", 105, 22, 84, 195, 35, WS_CHILD | WS_VISIBLE | WS_TABSTOP
- LTEXT "C:\\Windows\\Program Files\\dopewars-1.5.2\\", -1, 28, 100, 142, 8, WS_CHILD | WS_VISIBLE | WS_GROUP
+ LTEXT "", ST_INSTDIR, 28, 100, 142, 8, WS_CHILD | WS_VISIBLE | WS_GROUP
PUSHBUTTON "B&rowse...", BT_BROWSE, 171, 98, 39, 13, WS_CHILD | WS_VISIBLE | WS_TABSTOP
END
-4 DIALOG 17, 40, 239, 162
+5 DIALOG 17, 40, 239, 162
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Installing..."
BEGIN
t@@ -56,3 +56,18 @@ END
mainicon ICON "setup.ico"
+3 DIALOG 17, 40, 239, 162
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Shortcuts"
+BEGIN
+ LTEXT "Program icons will be added to the Program Folder on the Start Menu shown below. You can enter a new folder name, or select one from the Existing Folders list.", -1, 22, 7, 195, 25, WS_CHILD | WS_VISIBLE | WS_GROUP
+ LTEXT "&Program Folder:", -1, 22, 35, 68, 8, WS_CHILD | WS_VISIBLE | WS_GROUP
+ CONTROL "", ED_FOLDER, "EDIT", ES_LEFT | ES_AUTOHSCROLL | WS_CHILD | WS_VISIBLE | WS_BORDER | WS_TABSTOP, 22, 45, 195, 10
+ LTEXT "E&xisting Folders:", -1, 22, 61, 92, 8, WS_CHILD | WS_VISIBLE | WS_GROUP
+ CONTROL "", LB_FOLDLIST, "LISTBOX", LBS_NOTIFY | WS_CHILD | WS_VISIBLE | WS_BORDER | WS_VSCROLL | WS_TABSTOP, 22, 71, 195, 46
+ CONTROL "Create desktop icons as well", CB_DESKTOP, "BUTTON", BS_AUTOCHECKBOX | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 22, 121, 110, 10
+ CONTROL "", 101, "WC_GTKSEP", 2 | WS_CHILD | WS_VISIBLE, 7, 135, 225, 2
+ PUSHBUTTON "< &Back", BT_BACK, 105, 143, 39, 13, WS_CHILD | WS_VISIBLE | WS_TABSTOP
+ 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
+END
(DIR) diff --git a/win32/filelist b/win32/filelist
t@@ -1,3 +1,10 @@
+[product]
+dopewars-1.5.2
+
+[instdir]
+C:\Program Files\dopewars-1.5.2
+
+[install]
licence.txt
aiplayer.html
clientplay.html
t@@ -5,16 +12,43 @@ commandline.html
configfile.html
credits.html
developer.html
-dopewars-config.txt
-dopewars.exe
-example-cfg.txt
-glib-1.3.dll
i18n.html
index.html
installation.html
metaserver.html
-readme.txt
server.html
servercommands.html
windows.html
+dopewars-config.txt
+dopewars.exe
+example-cfg.txt
+glib-1.3.dll
+readme.txt
uninstall.exe
+
+[extrafiles]
+dopewars-log.txt
+dopewars.sco
+
+[startmenudir]
+dopewars-1.5.2
+
+[startmenu]
+dopewars.lnk
+dopewars.exe
+
+dopewars server.lnk
+dopewars.exe
+-s
+
+dopewars help.lnk
+index.html
+
+
+[desktop]
+dopewars.lnk
+dopewars.exe
+
+dopewars server.lnk
+dopewars.exe
+-s
(DIR) diff --git a/win32/guifunc.c b/win32/guifunc.c
t@@ -0,0 +1,70 @@
+#include <windows.h>
+#include "guifunc.h"
+
+static LRESULT CALLBACK GtkSepProc(HWND hwnd,UINT msg,WPARAM wParam,
+ LPARAM lParam) {
+ PAINTSTRUCT ps;
+ HPEN oldpen,dkpen,ltpen;
+ RECT rect;
+ HDC hDC;
+ if (msg==WM_PAINT) {
+ if (GetUpdateRect(hwnd,NULL,TRUE)) {
+ BeginPaint(hwnd,&ps);
+ GetClientRect(hwnd,&rect);
+ hDC=ps.hdc;
+ ltpen=CreatePen(PS_SOLID,0,(COLORREF)GetSysColor(COLOR_3DHILIGHT));
+ dkpen=CreatePen(PS_SOLID,0,(COLORREF)GetSysColor(COLOR_3DSHADOW));
+
+ if (rect.right > rect.bottom) {
+ oldpen=SelectObject(hDC,dkpen);
+ MoveToEx(hDC,rect.left,rect.top,NULL);
+ LineTo(hDC,rect.right,rect.top);
+
+ SelectObject(hDC,ltpen);
+ MoveToEx(hDC,rect.left,rect.top+1,NULL);
+ LineTo(hDC,rect.right,rect.top+1);
+ } else {
+ oldpen=SelectObject(hDC,dkpen);
+ MoveToEx(hDC,rect.left,rect.top,NULL);
+ LineTo(hDC,rect.left,rect.bottom);
+
+ SelectObject(hDC,ltpen);
+ MoveToEx(hDC,rect.left+1,rect.top,NULL);
+ LineTo(hDC,rect.left+1,rect.bottom);
+ }
+
+ SelectObject(hDC,oldpen);
+ DeleteObject(ltpen); DeleteObject(dkpen);
+ EndPaint(hwnd,&ps);
+ }
+ return TRUE;
+ } else return DefWindowProc(hwnd,msg,wParam,lParam);
+}
+
+void RegisterSepClass(HINSTANCE hInstance) {
+ WNDCLASS wc;
+ wc.style = CS_HREDRAW|CS_VREDRAW;
+ wc.lpfnWndProc = GtkSepProc;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = 0;
+ wc.hInstance = hInstance;
+ wc.hIcon = NULL;
+ wc.hCursor = LoadCursor(NULL,IDC_ARROW);
+ wc.hbrBackground = (HBRUSH)(1+COLOR_BTNFACE);
+ wc.lpszMenuName = NULL;
+ wc.lpszClassName = "WC_GTKSEP";
+ RegisterClass(&wc);
+}
+
+static BOOL CALLBACK enumFunc(HWND hWnd,LPARAM lParam) {
+ HFONT GuiFont;
+ GuiFont=(HFONT)lParam;
+ SendMessage(hWnd,WM_SETFONT,(WPARAM)GuiFont,MAKELPARAM(FALSE,0));
+ return TRUE;
+}
+
+void SetGuiFont(HWND hWnd) {
+ HFONT GuiFont;
+ GuiFont=(HFONT)GetStockObject(DEFAULT_GUI_FONT);
+ if (GuiFont) EnumChildWindows(hWnd,enumFunc,(LPARAM)GuiFont);
+}
(DIR) diff --git a/win32/guifunc.h b/win32/guifunc.h
t@@ -0,0 +1,4 @@
+#include <windows.h>
+
+void RegisterSepClass(HINSTANCE hInstance);
+void SetGuiFont(HWND hWnd);
(DIR) diff --git a/win32/install.c b/win32/install.c
t@@ -0,0 +1,37 @@
+#include <stdio.h>
+#include <windows.h>
+
+int main() {
+ HRSRC hrsrc;
+ HGLOBAL hglobal;
+ DWORD ressize,i;
+ LPVOID respt;
+ HANDLE fout;
+ DWORD byteswritten;
+
+ printf("Looking for resource...\n");
+
+ hrsrc = FindResource(NULL,MAKEINTRESOURCE(10),"INSTFILE");
+ if (!hrsrc) { printf("Could not find resource!\n"); return 1; }
+
+ ressize=SizeofResource(NULL,hrsrc);
+ printf("Resource found; size returned = %ld bytes\n",ressize);
+
+ hglobal = LoadResource(NULL,hrsrc);
+ if (!hglobal) { printf("Could not load resource!\n"); return 1; }
+
+ respt = LockResource(hglobal);
+ if (!respt) { printf("Could not lock resource!\n"); return 1; }
+
+ fout = CreateFile("windowsout.html",GENERIC_WRITE,0,NULL,CREATE_ALWAYS,
+ 0,NULL);
+ if (!fout) { printf("Could not open file\n"); return 1; }
+
+ if (!WriteFile(fout,respt,ressize,&byteswritten,NULL)) {
+ printf("Write to file failed - %ld of %ld bytes written\n",
+ byteswritten,ressize);
+ }
+ CloseHandle(fout);
+
+ return 0;
+}
(DIR) diff --git a/win32/install.rc b/win32/install.rc
t@@ -0,0 +1,21 @@
+0 INSTLIST "install-list"
+
+1 INSTFILE "aiplayer.html"
+2 INSTFILE "clientplay.html"
+3 INSTFILE "commandline.html"
+4 INSTFILE "configfile.html"
+5 INSTFILE "credits.html"
+6 INSTFILE "developer.html"
+7 INSTFILE "i18n.html"
+8 INSTFILE "index.html"
+9 INSTFILE "dopewars-config.txt"
+10 INSTFILE "dopewars.exe"
+11 INSTFILE "example-cfg.txt"
+12 INSTFILE "glib-1.3.dll"
+13 INSTFILE "installation.html"
+14 INSTFILE "metaserver.html"
+15 INSTFILE "server.html"
+16 INSTFILE "servercommands.html"
+17 INSTFILE "windows.html"
+18 INSTFILE "licence.txt"
+19 INSTFILE "readme.txt"
(DIR) diff --git a/win32/makeinstall.c b/win32/makeinstall.c
t@@ -0,0 +1,228 @@
+#include <windows.h>
+#include <stdio.h>
+#include <zlib.h>
+#include "util.h"
+
+char *read_line(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]=='\r') continue;
+ else if (buf[strind]=='\n') { 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;
+}
+
+InstData *ReadInstallData() {
+ HANDLE fin;
+ char *line,*line2,*line3;
+ InstFiles *lastinst=NULL,*lastextra=NULL;
+ InstLink *lastmenu=NULL,*lastdesktop=NULL;
+ InstData *idata;
+ int i;
+ enum {
+ S_PRODUCT=0,S_INSTDIR,S_INSTALL,S_EXTRA,S_STARTMENUDIR,
+ S_STARTMENU,S_DESKTOP,
+ S_NONE
+ } section=S_NONE;
+ char *titles[S_NONE] = {
+ "[product]","[instdir]", "[install]","[extrafiles]","[startmenudir]",
+ "[startmenu]","[desktop]"
+ };
+
+ idata = bmalloc(sizeof(InstData));
+ idata->installdir = idata->startmenudir = NULL;
+ idata->instfiles = idata->extrafiles = NULL;
+ idata->startmenu = idata->desktop = NULL;
+
+ fin = CreateFile("filelist",GENERIC_READ,0,NULL,OPEN_EXISTING,0,NULL);
+
+ if (fin) {
+ while (1) {
+ line=read_line(fin);
+ if (!line) break;
+ if (line[0]=='\0') { bfree(line); continue; }
+
+ for (i=S_PRODUCT;i<S_NONE;i++) {
+ if (strcmp(line,titles[i])==0) {
+ section=i; break;
+ }
+ }
+ if (i<S_NONE) { bfree(line); continue; }
+
+ switch(section) {
+ case S_NONE:
+ printf("Bad line %s\n",line); exit(1);
+ case S_PRODUCT:
+printf("product ID = %s\n",line);
+ idata->product = line; break;
+ case S_INSTDIR:
+printf("install dir = %s\n",line);
+ idata->installdir = line; break;
+ case S_STARTMENUDIR:
+printf("start menu dir = %s\n",line);
+ idata->startmenudir = line; break;
+ case S_INSTALL:
+ AddInstFiles(line,0,&lastinst,&idata->instfiles);
+ break;
+ case S_EXTRA:
+ AddInstFiles(line,0,&lastextra,&idata->extrafiles);
+ break;
+ case S_STARTMENU:
+ line2=read_line(fin); line3=read_line(fin);
+printf("start menu entry = %s/%s/%s\n",line,line2,line3);
+ AddInstLink(line,line2,line3,&lastmenu,&idata->startmenu);
+ break;
+ case S_DESKTOP:
+ line2=read_line(fin); line3=read_line(fin);
+printf("desktop entry = %s/%s/%s\n",line,line2,line3);
+ AddInstLink(line,line2,line3,&lastdesktop,&idata->desktop);
+ break;
+ }
+ }
+ CloseHandle(fin);
+ }
+
+ if (idata->installdir && idata->startmenudir && idata->product) {
+ return idata;
+ } else {
+ printf("No directories specified\n");
+ exit(1);
+ }
+}
+
+#define BUFFER_SIZE (32*1024)
+#define COMPRESSION Z_BEST_COMPRESSION
+
+void OpenNextFile(InstFiles *filelist,InstFiles **listpt,HANDLE *fin) {
+ 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);
+}
+
+int main() {
+ HANDLE fout,fin;
+ DWORD bytes_read,bytes_written;
+ InstData *idata;
+ InstFiles *filept;
+ char *inbuf,*outbuf;
+ int status,count;
+ bstr *str;
+ z_stream z;
+
+ idata=ReadInstallData();
+
+ fout = CreateFile("installfiles.gz",GENERIC_WRITE,0,NULL,
+ CREATE_ALWAYS,0,NULL);
+
+ outbuf = bmalloc(BUFFER_SIZE);
+ inbuf = bmalloc(BUFFER_SIZE);
+
+ z.zalloc = Z_NULL;
+ z.zfree = Z_NULL;
+ z.opaque = Z_NULL;
+ deflateInit(&z,COMPRESSION);
+ z.avail_in=0;
+ z.next_out = outbuf;
+ z.avail_out = BUFFER_SIZE;
+
+ filept=NULL;
+ fin=NULL;
+ OpenNextFile(idata->instfiles,&filept,&fin);
+ if (!fin) { printf("Cannot open file\n"); return 1; }
+
+ while (fin) {
+ if (z.avail_in==0) {
+ z.next_in = inbuf;
+ bytes_read=0;
+ while (!bytes_read && fin) {
+ if (!ReadFile(fin,inbuf,BUFFER_SIZE,&bytes_read,NULL)) {
+ printf("Read error\n"); break;
+ }
+ filept->filesize+=bytes_read;
+ if (!bytes_read) OpenNextFile(idata->instfiles,&filept,&fin);
+ }
+ z.avail_in = bytes_read;
+ }
+ if (z.avail_in==0) {
+ status = deflate(&z,Z_FINISH);
+ count = BUFFER_SIZE - z.avail_out;
+ if (!WriteFile(fout,outbuf,count,&bytes_written,NULL)) {
+ printf("Write error\n");
+ }
+ break;
+ }
+ status = deflate(&z,Z_NO_FLUSH);
+ count = BUFFER_SIZE - z.avail_out;
+ if (!WriteFile(fout,outbuf,count,&bytes_written,NULL)) {
+ printf("Write error\n");
+ }
+ z.next_out = outbuf;
+ z.avail_out = BUFFER_SIZE;
+ }
+
+ printf("Written compressed data: raw %lu, compressed %lu\n",
+ z.total_in,z.total_out);
+ bytes_written = z.total_out;
+ deflateEnd(&z);
+
+ CloseHandle(fout);
+
+ fout = CreateFile("manifest",GENERIC_WRITE,0,NULL,
+ CREATE_ALWAYS,0,NULL);
+ if (!fout) printf("Cannot create file list\n");
+
+ str=bstr_new();
+ bstr_setlength(str,0);
+ bstr_append_long(str,bytes_written);
+ if (!WriteFile(fout,str->text,str->length+1,&bytes_written,NULL)) {
+ printf("Write error\n");
+ }
+
+ if (!WriteFile(fout,idata->product,strlen(idata->product)+1,
+ &bytes_written,NULL)) {
+ printf("Write error\n");
+ }
+ if (!WriteFile(fout,idata->installdir,strlen(idata->installdir)+1,
+ &bytes_written,NULL)) {
+ printf("Write error\n");
+ }
+ if (!WriteFile(fout,idata->startmenudir,strlen(idata->startmenudir)+1,
+ &bytes_written,NULL)) {
+ printf("Write error\n");
+ }
+
+ WriteFileList(fout,idata->instfiles);
+ WriteFileList(fout,idata->extrafiles);
+
+ WriteLinkList(fout,idata->startmenu);
+ WriteLinkList(fout,idata->desktop);
+
+ CloseHandle(fout);
+ bfree(inbuf);
+ bfree(outbuf);
+
+ FreeInstData(idata,TRUE);
+
+ return 0;
+}
(DIR) diff --git a/win32/setup.c b/win32/setup.c
t@@ -0,0 +1,656 @@
+#include <windows.h>
+#include <commctrl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <zlib.h>
+#include <shlobj.h>
+#include "contid.h"
+#include "guifunc.h"
+#include "util.h"
+
+typedef enum {
+ DL_INTRO=0, DL_LICENCE,DL_SHORTCUTS,DL_INSTALLDIR,DL_DOINSTALL,
+ DL_NUM
+} DialogType;
+
+InstData *idata;
+HWND mainDlg[DL_NUM];
+DialogType CurrentDialog;
+HINSTANCE hInst=NULL;
+
+DWORD WINAPI DoInstall(LPVOID lpParam);
+
+void ShowNewDialog(DialogType NewDialog) {
+ RECT DeskRect,OurRect;
+ int newX,newY;
+ HWND hWnd;
+ HANDLE hThread;
+ DWORD threadID;
+ if (NewDialog<0 || NewDialog>=DL_NUM) return;
+
+ hWnd=mainDlg[NewDialog];
+ if (GetWindowRect(hWnd,&OurRect) &&
+ GetWindowRect(GetDesktopWindow(),&DeskRect)) {
+ newX = (DeskRect.left+DeskRect.right+OurRect.left-OurRect.right)/2;
+ newY = (DeskRect.top+DeskRect.bottom+OurRect.top-OurRect.bottom)/2;
+ SetWindowPos(hWnd,HWND_TOP,newX,newY,0,0,SWP_NOSIZE);
+ }
+ ShowWindow(hWnd,SW_SHOW);
+
+ if (CurrentDialog!=DL_NUM) ShowWindow(mainDlg[CurrentDialog],SW_HIDE);
+ CurrentDialog=NewDialog;
+
+ if (NewDialog==DL_DOINSTALL) {
+ hThread = CreateThread(NULL,0,DoInstall,NULL,0,&threadID);
+ }
+}
+
+void SelectInstDir(HWND parent) {
+ BROWSEINFO bi = { 0 };
+ TCHAR path[MAX_PATH];
+ LPITEMIDLIST pidl;
+ IMalloc *imalloc=0;
+
+ bi.lpszTitle = "Pick a directory";
+ bi.pszDisplayName = path;
+ bi.ulFlags = BIF_STATUSTEXT|BIF_RETURNONLYFSDIRS|BIF_DONTGOBELOWDOMAIN;
+ pidl = SHBrowseForFolder(&bi);
+ if (pidl) {
+ if (SUCCEEDED(SHGetMalloc(&imalloc))) {
+// imalloc->free(pidl); imalloc->release();
+ }
+ }
+/*OPENFILENAME ofn;
+ char lpstrFile[200]="";
+
+ ofn.lStructSize = sizeof(OPENFILENAME);
+ ofn.hwndOwner = parent;
+ ofn.hInstance = hInst;
+ ofn.lpstrFilter = NULL;
+ ofn.lpstrCustomFilter = NULL;
+ ofn.nMaxCustFilter = 0;
+ ofn.nFilterIndex = 0;
+ ofn.lpstrFile = lpstrFile;
+ ofn.nMaxFile = 200;
+ ofn.lpstrFileTitle = NULL;
+ ofn.nMaxFileTitle = 0;
+ ofn.lpstrInitialDir = NULL;
+ ofn.lpstrTitle = NULL;
+ ofn.Flags = OFN_HIDEREADONLY;
+ ofn.lpstrDefExt = NULL;
+ ofn.lCustData = 0;
+ ofn.lpfnHook = NULL;
+ ofn.lpTemplateName = NULL;
+
+ GetOpenFileName(&ofn);*/
+}
+
+void ConditionalExit(HWND hWnd) {
+ if (MessageBox(hWnd,"This will exit without installing any new software on "
+ "your machine.\nAre you sure you want to quit?\n\n(You can "
+ "continue the installation at a\nlater date simply by "
+ "running this program again.)","Exit Install",
+ MB_YESNO|MB_ICONQUESTION)==IDYES) {
+ PostQuitMessage(0);
+ }
+}
+
+void UpdateStartMenuFolder(void) {
+ char *buf;
+ HWND folderlist;
+ LRESULT lres;
+ int selind;
+
+ folderlist = GetDlgItem(mainDlg[DL_SHORTCUTS],LB_FOLDLIST);
+ if (!folderlist) return;
+
+ lres=SendMessage(folderlist,LB_GETCURSEL,0,0);
+ if (lres==LB_ERR) return;
+
+ selind=(int)lres;
+ lres=SendMessage(folderlist,LB_GETTEXTLEN,(WPARAM)selind,0);
+ if (lres==LB_ERR) return;
+
+ buf = bmalloc(lres+1);
+ lres=SendMessage(folderlist,LB_GETTEXT,(WPARAM)selind,(LPARAM)buf);
+ if (lres!=LB_ERR) {
+ SendDlgItemMessage(mainDlg[DL_SHORTCUTS],ED_FOLDER,WM_SETTEXT,
+ 0,(LPARAM)buf);
+ }
+ bfree(buf);
+}
+
+BOOL CALLBACK MainDlgProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam) {
+ switch(msg) {
+ case WM_INITDIALOG:
+ return TRUE;
+ case WM_COMMAND:
+ if (HIWORD(wParam)==BN_CLICKED && lParam) {
+ switch(LOWORD(wParam)) {
+ case BT_CANCEL: ConditionalExit(hWnd); break;
+ case BT_NEXT: ShowNewDialog(CurrentDialog+1); break;
+ case BT_BACK: ShowNewDialog(CurrentDialog-1); break;
+ case BT_FINISH: PostQuitMessage(0); break;
+ case BT_BROWSE: SelectInstDir(hWnd); break;
+ }
+ } else if (HIWORD(wParam)==LBN_SELCHANGE && lParam &&
+ LOWORD(wParam)==LB_FOLDLIST) {
+ UpdateStartMenuFolder();
+ }
+ break;
+ case WM_CLOSE:
+ ConditionalExit(hWnd);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+LPVOID GetResource(LPCTSTR resname,LPCTSTR restype) {
+ HRSRC hrsrc;
+ HGLOBAL hglobal;
+ LPVOID respt;
+
+ hrsrc = FindResource(NULL,resname,restype);
+ if (!hrsrc) DisplayError("Could not find resource: ",TRUE,TRUE);
+
+ hglobal = LoadResource(NULL,hrsrc);
+ if (!hglobal) DisplayError("Could not load resource: ",TRUE,TRUE);
+
+ respt = LockResource(hglobal);
+ if (!respt) DisplayError("Could not lock resource: ",TRUE,TRUE);
+
+ return respt;
+}
+
+InstData *ReadInstData() {
+ InstFiles *lastinst=NULL,*lastextra=NULL;
+ InstLink *lastmenu=NULL,*lastdesktop=NULL;
+ char *instdata,*pt,*filename,*line2,*line3;
+ DWORD filesize;
+ InstData *idata;
+
+ instdata = GetResource(MAKEINTRESOURCE(0),"INSTLIST");
+ if (!instdata) return NULL;
+
+ pt=instdata;
+
+ idata = bmalloc(sizeof(InstData));
+ idata->totalsize = atol(pt);
+ pt += strlen(pt)+1;
+
+ idata->product = bstrdup(pt);
+ pt += strlen(pt)+1;
+
+ idata->installdir = bstrdup(pt);
+ pt += strlen(pt)+1;
+
+ idata->startmenudir = bstrdup(pt);
+ pt += strlen(pt)+1;
+
+ while (1) {
+ filename=pt;
+ pt += strlen(pt)+1;
+ if (filename[0]) {
+ filesize=atol(pt);
+ pt += strlen(pt)+1;
+ AddInstFiles(filename,filesize,&lastinst,&idata->instfiles);
+ } else break;
+ }
+ while (1) {
+ filename=pt;
+ pt += strlen(pt)+1;
+ if (filename[0]) {
+ filesize=atol(pt);
+ pt += strlen(pt)+1;
+ AddInstFiles(filename,filesize,&lastextra,&idata->extrafiles);
+ } else break;
+ }
+ while (1) {
+ filename=pt;
+ pt += strlen(pt)+1;
+ if (filename[0]) {
+ line2=pt; pt += strlen(pt)+1;
+ line3=pt; pt += strlen(pt)+1;
+ AddInstLink(filename,line2,line3,&lastmenu,&idata->startmenu);
+ } else break;
+ }
+ while (1) {
+ filename=pt;
+ pt += strlen(pt)+1;
+ if (filename[0]) {
+ line2=pt; pt += strlen(pt)+1;
+ line3=pt; pt += strlen(pt)+1;
+ AddInstLink(filename,line2,line3,&lastdesktop,&idata->desktop);
+ } else break;
+ }
+
+ return idata;
+}
+
+#define BUFFER_SIZE (32*1024)
+
+char *GetFirstFile(InstFiles *filelist,DWORD totalsize) {
+ DWORD bufsiz;
+ char *inbuf,*outbuf;
+ int status;
+ z_stream z;
+
+ if (!filelist) return NULL;
+
+ inbuf = GetResource(MAKEINTRESOURCE(1),"INSTFILE");
+ if (!inbuf) return NULL;
+
+ bufsiz = filelist->filesize;
+ outbuf = bmalloc(bufsiz+1);
+
+ z.zalloc = Z_NULL;
+ z.zfree = Z_NULL;
+ z.opaque = Z_NULL;
+ z.next_in = inbuf;
+ z.avail_in = totalsize;
+
+ inflateInit(&z);
+ z.next_out = outbuf;
+ z.avail_out = bufsiz;
+
+ while (1) {
+ status = inflate(&z,Z_SYNC_FLUSH);
+ if ((status!=Z_OK && status!=Z_STREAM_END) || z.avail_out==0) break;
+ }
+ inflateEnd(&z);
+
+ outbuf[bufsiz]='\0';
+ return outbuf;
+}
+
+BOOL OpenNextOutput(HANDLE *fout,InstFiles *filelist,InstFiles **listpt,
+ DWORD *fileleft,HANDLE logf) {
+ bstr *str;
+ DWORD bytes_written;
+
+ if (*fout) CloseHandle(*fout);
+ *fout = NULL;
+
+ str=bstr_new();
+
+ if (*listpt) {
+ if (!WriteFile(logf,(*listpt)->filename,strlen((*listpt)->filename)+1,
+ &bytes_written,NULL)) {
+ printf("Write error\n");
+ }
+
+ bstr_setlength(str,0);
+ bstr_append_long(str,(*listpt)->filesize);
+ if (!WriteFile(logf,str->text,str->length+1,&bytes_written,NULL)) {
+ printf("Write error\n");
+ }
+ *listpt=(*listpt)->next;
+ } else *listpt = filelist;
+
+ if (*listpt) {
+ *fout = CreateFile((*listpt)->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," (size ");
+ bstr_append_long(str,(*listpt)->filesize);
+ bstr_append(str,")");
+ SendDlgItemMessage(mainDlg[DL_DOINSTALL],ST_FILELIST,
+ WM_SETTEXT,0,(LPARAM)str->text);
+ }
+
+ bstr_free(str,TRUE);
+
+ return (*fout!=NULL);
+}
+
+HRESULT CreateLink(LPCSTR origPath,LPSTR linkArgs,LPSTR workDir,
+ LPSTR linkPath,LPSTR linkDesc) {
+ HRESULT hres;
+ IShellLink *psl;
+ IPersistFile *ppf;
+ WORD wsz[MAX_PATH];
+
+ hres = CoCreateInstance(&CLSID_ShellLink,NULL,CLSCTX_INPROC_SERVER,
+ &IID_IShellLink,(void **)&psl);
+ if (SUCCEEDED(hres)) {
+ psl->lpVtbl->SetPath(psl,origPath);
+ if (workDir) psl->lpVtbl->SetWorkingDirectory(psl,workDir);
+ if (linkDesc) psl->lpVtbl->SetDescription(psl,linkDesc);
+ if (linkArgs) psl->lpVtbl->SetArguments(psl,linkArgs);
+ hres = psl->lpVtbl->QueryInterface(psl,&IID_IPersistFile,(void **)&ppf);
+ if (SUCCEEDED(hres)) {
+ MultiByteToWideChar(CP_ACP,0,linkPath,-1,wsz,MAX_PATH);
+ hres = ppf->lpVtbl->Save(ppf,wsz,TRUE);
+ ppf->lpVtbl->Release(ppf);
+ } else {
+ DisplayError("Cannot write shortcut",FALSE,FALSE);
+ }
+ psl->lpVtbl->Release(psl);
+ } else {
+ DisplayError("Cannot create shortcut",FALSE,FALSE);
+ }
+ return hres;
+}
+
+void GetWinText(char **text,HWND hWnd) {
+ int textlen;
+ bfree(*text);
+ *text=NULL;
+ if (!hWnd) return;
+
+ textlen=GetWindowTextLength(hWnd)+1;
+ if (!textlen) return;
+
+ *text=bmalloc(textlen);
+ if (!GetWindowText(hWnd,*text,textlen)) {
+ bfree(*text); *text=NULL;
+ }
+}
+
+void CreateLinks(char *linkdir,InstLink *linkpt) {
+ bstr *linkpath,*origfile;
+
+ linkpath=bstr_new();
+ origfile=bstr_new();
+
+ for (;linkpt;linkpt=linkpt->next) {
+ bstr_assign(linkpath,linkdir);
+ bstr_appendpath(linkpath,linkpt->linkfile);
+
+ bstr_assign(origfile,idata->installdir);
+ bstr_appendpath(origfile,linkpt->origfile);
+
+ 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);*/
+ }
+}
+
+void SetupShortcuts(HANDLE fout) {
+ char *startmenu,*desktop;
+ BOOL dodesktop;
+
+ startmenu = GetStartMenuDir(idata);
+ desktop = GetDesktopDir();
+
+ dodesktop=(IsDlgButtonChecked(mainDlg[DL_SHORTCUTS],CB_DESKTOP)==BST_CHECKED);
+
+ if (startmenu) {
+ CreateDirectory(startmenu,NULL);
+
+ CreateLinks(startmenu,idata->startmenu);
+ WriteLinkList(fout,idata->startmenu);
+ } else {
+ WriteLinkList(fout,NULL);
+ }
+
+ if (dodesktop && desktop) {
+ CreateLinks(desktop,idata->desktop);
+ WriteLinkList(fout,idata->desktop);
+ } else {
+ WriteLinkList(fout,NULL);
+ }
+
+ bfree(startmenu); bfree(desktop);
+}
+
+void SetupUninstall() {
+ HKEY key;
+ DWORD disp;
+ bstr *str,*uninstexe,*link;
+ BOOL haveuninstall=FALSE;
+ char *startmenu;
+ InstFiles *listpt;
+
+ for (listpt=idata->instfiles;listpt;listpt=listpt->next) {
+ if (strcmp(listpt->filename,"uninstall.exe")==0) {
+ haveuninstall=TRUE;
+ break;
+ }
+ }
+
+ if (!haveuninstall) return;
+
+ str=bstr_new();
+ uninstexe=bstr_new();
+ link=bstr_new();
+
+ bstr_assign(str,UninstallKey);
+ bstr_appendpath(str,idata->product);
+
+ if (RegCreateKeyEx(HKEY_LOCAL_MACHINE,str->text,0,NULL,0,
+ KEY_ALL_ACCESS,NULL,&key,&disp)==ERROR_SUCCESS) {
+ RegSetValueEx(key,"DisplayName",0,REG_SZ,idata->product,
+ strlen(idata->product));
+ bstr_assign_windir(str);
+ bstr_appendpath(str,UninstallEXE);
+ bstr_append_c(str,' ');
+ bstr_append(str,idata->product);
+ RegSetValueEx(key,"UninstallString",0,REG_SZ,str->text,str->length);
+ bstr_assign(str,idata->installdir);
+ RegSetValueEx(key,"InstallDirectory",0,REG_SZ,str->text,str->length);
+ RegCloseKey(key);
+ } else {
+ DisplayError("Cannot create registry key: ",TRUE,FALSE);
+ }
+
+ bstr_assign_windir(str);
+ bstr_appendpath(str,"bw-uninstall.exe");
+ DeleteFile(str->text);
+
+ bstr_assign(uninstexe,idata->installdir);
+ bstr_appendpath(uninstexe,"uninstall.exe");
+
+ if (!MoveFile(uninstexe->text,str->text)) {
+ DisplayError("Unable to create uninstall program: ",TRUE,FALSE);
+ }
+ DeleteFile(uninstexe->text);
+
+ startmenu = GetStartMenuDir(idata);
+ bstr_assign(link,startmenu);
+ bstr_appendpath(link,"Uninstall ");
+ bstr_append(link,idata->product);
+ bstr_append(link,".LNK");
+
+ CreateLink(str->text,idata->product,NULL,link->text,NULL);
+/*bstr_append_c(str,',');
+bstr_append(str,idata->product);
+bstr_append(str,",NULL,");
+bstr_append(str,link->text);
+bstr_append(str,",NULL");
+MessageBox(NULL,str->text,NULL,MB_OK);*/
+
+ bstr_free(link,TRUE);
+ bstr_free(uninstexe,TRUE);
+ bstr_free(str,TRUE);
+ bfree(startmenu);
+}
+
+DWORD WINAPI DoInstall(LPVOID lpParam) {
+ HANDLE fout,logf;
+ DWORD bytes_written,fileleft;
+ char *inbuf,*outbuf;
+ int status,count;
+ z_stream z;
+ InstFiles *listpt;
+
+ inbuf = GetResource(MAKEINTRESOURCE(1),"INSTFILE");
+ if (!inbuf) return 0;
+
+ GetWinText(&idata->startmenudir,GetDlgItem(mainDlg[DL_SHORTCUTS],ED_FOLDER));
+
+ CreateDirectory(idata->installdir,NULL);
+ SetCurrentDirectory(idata->installdir);
+ logf = CreateFile("install.log",GENERIC_WRITE,0,NULL,
+ CREATE_ALWAYS,0,NULL);
+
+ if (!WriteFile(logf,idata->startmenudir,strlen(idata->startmenudir)+1,
+ &bytes_written,NULL)) {
+ printf("Write error\n");
+ }
+
+ fout = NULL;
+ listpt=NULL;
+ OpenNextOutput(&fout,idata->instfiles,&listpt,&fileleft,logf);
+
+ outbuf = bmalloc(BUFFER_SIZE);
+
+ z.zalloc = Z_NULL;
+ z.zfree = Z_NULL;
+ z.opaque = Z_NULL;
+ z.next_in = inbuf;
+ z.avail_in = idata->totalsize;
+
+ inflateInit(&z);
+ z.next_out = outbuf;
+ z.avail_out = BUFFER_SIZE;
+
+ while (1) {
+ status = inflate(&z,Z_SYNC_FLUSH);
+ if (status==Z_OK || status==Z_STREAM_END) {
+ count = BUFFER_SIZE - z.avail_out;
+ z.next_out = outbuf;
+ while (count >= fileleft) {
+ if (fileleft &&
+ !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 (!fout) break;
+ if (count && !WriteFile(fout,z.next_out,count,&bytes_written,NULL)) {
+ printf("Write error\n");
+ }
+ fileleft-=count;
+ z.next_out = outbuf;
+ z.avail_out = BUFFER_SIZE;
+ }
+ if (status!=Z_OK) break;
+ }
+
+ inflateEnd(&z);
+ CloseHandle(fout);
+
+ outbuf[0]='\0';
+ if (!WriteFile(logf,outbuf,1,&bytes_written,NULL)) {
+ printf("Write error\n");
+ }
+ bfree(outbuf);
+
+ WriteFileList(logf,idata->extrafiles);
+
+ CoInitialize(NULL);
+ SetupShortcuts(logf);
+ SetupUninstall();
+ CoUninitialize();
+
+ CloseHandle(logf);
+
+ SetFileAttributes("install.log",FILE_ATTRIBUTE_HIDDEN);
+
+ ShowWindow(GetDlgItem(mainDlg[DL_DOINSTALL],ST_COMPLETE),SW_SHOW);
+ ShowWindow(GetDlgItem(mainDlg[DL_DOINSTALL],ST_EXIT),SW_SHOW);
+ return 0;
+}
+
+void FillFolderList(void) {
+ HANDLE findfile;
+ WIN32_FIND_DATA finddata;
+ bstr *str;
+ HWND folderlist;
+
+ folderlist = GetDlgItem(mainDlg[DL_SHORTCUTS],LB_FOLDLIST);
+ if (!folderlist) return;
+
+ str=bstr_new();
+
+ bstr_assign_windir(str);
+ bstr_appendpath(str,"Start Menu\\Programs\\*");
+
+ findfile = FindFirstFile(str->text,&finddata);
+ if (findfile) {
+ while(1) {
+ if (finddata.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY &&
+ strcmp(finddata.cFileName,".")!=0 &&
+ strcmp(finddata.cFileName,"..")!=0) {
+ SendMessage(folderlist,LB_ADDSTRING,0,(LPARAM)finddata.cFileName);
+ }
+ if (!FindNextFile(findfile,&finddata)) break;
+ }
+ FindClose(findfile);
+ }
+ bstr_free(str,TRUE);
+}
+
+int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,
+ LPSTR lpszCmdParam,int nCmdShow) {
+ MSG msg;
+ int i;
+ BOOL Handled;
+ char *licence;
+
+ InitCommonControls();
+
+ hInst = hInstance;
+
+ if (!hPrevInstance) RegisterSepClass(hInstance);
+
+ for (i=0;i<DL_NUM;i++) {
+ mainDlg[i] = CreateDialog(hInst,MAKEINTRESOURCE(i+1),NULL,MainDlgProc);
+ }
+
+ CheckDlgButton(mainDlg[DL_SHORTCUTS],CB_DESKTOP,BST_CHECKED);
+
+ FillFolderList();
+
+ ShowWindow(GetDlgItem(mainDlg[DL_DOINSTALL],ST_COMPLETE),SW_HIDE);
+ ShowWindow(GetDlgItem(mainDlg[DL_DOINSTALL],ST_EXIT),SW_HIDE);
+
+ idata=ReadInstData();
+
+ SendDlgItemMessage(mainDlg[DL_SHORTCUTS],ED_FOLDER,WM_SETTEXT,
+ 0,(LPARAM)idata->startmenudir);
+ SendDlgItemMessage(mainDlg[DL_INSTALLDIR],ST_INSTDIR,WM_SETTEXT,
+ 0,(LPARAM)idata->installdir);
+
+ licence=GetFirstFile(idata->instfiles,idata->totalsize);
+
+ if (licence) {
+ SendDlgItemMessage(mainDlg[DL_LICENCE],ED_LICENCE,WM_SETTEXT,
+ 0,(LPARAM)licence);
+ bfree(licence);
+ }
+
+ for (i=0;i<DL_NUM;i++) SetGuiFont(mainDlg[i]);
+
+ CurrentDialog=DL_NUM;
+ ShowNewDialog(DL_INTRO);
+
+ while (GetMessage(&msg,NULL,0,0)) {
+ Handled=FALSE;
+ for (i=0;i<DL_NUM && !Handled;i++) {
+ Handled=IsDialogMessage(mainDlg[i],&msg);
+ }
+ if (!Handled) {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+ }
+ FreeInstData(idata,FALSE);
+
+ return 0;
+}
(DIR) diff --git a/win32/uninstall.c b/win32/uninstall.c
t@@ -0,0 +1,290 @@
+#include <windows.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "contid.h"
+#include "guifunc.h"
+#include "util.h"
+
+HINSTANCE hInst;
+HWND mainDlg;
+char *product;
+
+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;
+}
+
+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(),' ');
+ if (product) return bstrdup(++product);
+ else {
+ DisplayError("This program should be called with a product ID",FALSE,TRUE);
+ ExitProcess(1);
+ }
+}
+
+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);
+ return idata;
+}
+
+void DeleteFileList(InstFiles *listpt) {
+ bstr *str;
+ 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);
+ }
+ bstr_free(str,TRUE);
+}
+
+void DeleteLinkList(char *dir,InstLink *listpt) {
+ bstr *str;
+ str=bstr_new();
+ SetCurrentDirectory(dir);
+ for (;listpt;listpt=listpt->next) {
+ bstr_assign(str,"Deleting link: ");
+ bstr_append(str,listpt->linkfile);
+ SendDlgItemMessage(mainDlg,ST_DELSTAT,WM_SETTEXT,0,(LPARAM)str->text);
+ DeleteFile(listpt->linkfile);
+ }
+ 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;
+ bstr *str;
+ char *startmenu,*desktop,*installdir;
+
+ installdir=GetInstallDir(product);
+
+ SetCurrentDirectory(installdir);
+ fin = CreateFile("install.log",GENERIC_READ,0,NULL,OPEN_EXISTING,0,NULL);
+
+ if (fin) {
+ idata = ReadInstData(fin,product,installdir);
+ CloseHandle(fin);
+ DeleteFile("install.log");
+ DeleteFileList(idata->instfiles);
+ DeleteFileList(idata->extrafiles);
+
+ startmenu = GetStartMenuDir(idata);
+ desktop = GetDesktopDir();
+ DeleteLinkList(startmenu,idata->startmenu);
+ DeleteLinkList(desktop,idata->desktop);
+
+ RemoveUninstall(startmenu,product);
+
+ SetCurrentDirectory(desktop); /* Just make sure we're not in the install
+ directory any more */
+ RemoveDirectory(installdir);
+ RemoveDirectory(startmenu);
+
+ str=bstr_new();
+ bstr_assign(str,UninstallKey);
+ bstr_appendpath(str,product);
+ RegDeleteKey(HKEY_LOCAL_MACHINE,str->text);
+ bstr_free(str,TRUE);
+
+ bfree(startmenu); bfree(desktop);
+ FreeInstData(idata,TRUE);
+ } else {
+ bfree(product); bfree(installdir); /* Normally FreeInstData frees these */
+ }
+ ShowWindow(GetDlgItem(mainDlg,ST_DELDONE),SW_SHOW);
+ EnableWindow(GetDlgItem(mainDlg,BT_DELOK),TRUE);
+ return 0;
+}
+
+BOOL CALLBACK MainDlgProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam) {
+ HANDLE hThread;
+ DWORD threadID;
+ switch(msg) {
+ case WM_INITDIALOG:
+ hThread = CreateThread(NULL,0,DoUninstall,NULL,0,&threadID);
+ return TRUE;
+ case WM_COMMAND:
+ if (HIWORD(wParam)==BN_CLICKED && LOWORD(wParam)==BT_DELOK && lParam) {
+ PostQuitMessage(0);
+ return TRUE;
+ }
+ break;
+ case WM_CLOSE:
+ PostQuitMessage(0);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,
+ LPSTR lpszCmdParam,int nCmdShow) {
+ MSG msg;
+ bstr *str;
+
+ product=GetProduct();
+
+ str=bstr_new();
+ bstr_assign(str,"Are you sure you want to uninstall ");
+ bstr_append(str,product);
+ bstr_append(str," ?");
+ if (MessageBox(NULL,str->text,"Uninstall",MB_YESNO)==IDNO) return(1);
+ bstr_free(str,TRUE);
+
+ hInst = hInstance;
+ if (!hPrevInstance) RegisterSepClass(hInstance);
+
+ mainDlg = CreateDialog(hInstance,MAKEINTRESOURCE(1),NULL,MainDlgProc);
+ SetGuiFont(mainDlg);
+
+ EnableWindow(GetDlgItem(mainDlg,BT_DELOK),FALSE);
+ ShowWindow(mainDlg,SW_SHOW);
+ ShowWindow(GetDlgItem(mainDlg,ST_DELDONE),SW_HIDE);
+
+ while (GetMessage(&msg,NULL,0,0)) {
+ if (!IsDialogMessage(mainDlg,&msg)) {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+ }
+
+ return 0;
+}
(DIR) diff --git a/win32/uninstall.rc b/win32/uninstall.rc
t@@ -1 +1,14 @@
+#include <windows.h>
+#include "contid.h"
+
mainicon ICON "setup.ico"
+
+1 DIALOG 17, 40, 190, 115
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Uninstall"
+BEGIN
+ CONTROL "", 101, "WC_GTKSEP", 2 | WS_CHILD | WS_VISIBLE, 8, 88, 174, 2
+ DEFPUSHBUTTON "OK", BT_DELOK, 75, 96, 39, 13, WS_CHILD | WS_VISIBLE | WS_TABSTOP
+ LTEXT "Deleting file: dopewars.exe", ST_DELSTAT, 15, 14, 159, 17, WS_CHILD | WS_VISIBLE | WS_GROUP
+ LTEXT "All files successfully uninstalled.", ST_DELDONE, 15, 51, 159, 25, WS_CHILD | WS_VISIBLE | WS_GROUP
+END
(DIR) diff --git a/win32/util.c b/win32/util.c
t@@ -0,0 +1,358 @@
+#include <windows.h>
+#include <stdio.h>
+#include <string.h>
+#include "util.h"
+
+const char *UninstallKey=
+ "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall";
+const char *UninstallEXE="bw-uninstall.exe";
+
+static void bstr_append_dir(bstr *str,BOOL windir);
+
+void *bmalloc(UINT numbytes) {
+ HLOCAL localpt;
+
+ if (numbytes<=0) numbytes=1;
+
+ localpt = LocalAlloc(LMEM_FIXED,numbytes);
+ if (localpt) return (void *)localpt;
+ else {
+ DisplayError("Could not allocate memory: ",TRUE,TRUE);
+ ExitProcess(1);
+ }
+}
+
+void bfree(void *pt) {
+ if (!pt) return;
+ if (LocalFree((HLOCAL)pt)) {
+ DisplayError("Could not free memory: ",TRUE,TRUE);
+ }
+}
+
+void *brealloc(void *pt,UINT numbytes) {
+ HLOCAL localpt;
+ UINT numcp;
+ void *newpt;
+ if (!pt && numbytes) return bmalloc(numbytes);
+ else if (pt && !numbytes) bfree(pt);
+ else if (pt && numbytes) {
+ localpt = LocalReAlloc((HLOCAL)pt,numbytes,0);
+ if (localpt) return (void *)localpt;
+ else if (GetLastError()==ERROR_LOCKED) { /* OK, we'll do it the hard way */
+ newpt=bmalloc(numbytes);
+ memset(newpt,0,numbytes);
+ numcp = LocalSize((HLOCAL)pt);
+ if (numbytes < numcp) numcp = numbytes;
+ memcpy((char *)newpt,(char *)pt,numcp);
+ bfree(pt);
+ return newpt;
+ } else {
+ DisplayError("Could not reallocate memory: ",TRUE,TRUE);
+ ExitProcess(1);
+ }
+ }
+ return NULL;
+}
+
+char *bstrdup(char *str) {
+ char *newstr;
+ if (str) {
+ newstr = bmalloc(strlen(str)+1);
+ strcpy(newstr,str);
+ } else {
+ newstr = bmalloc(1);
+ newstr[0]='\0';
+ }
+ return newstr;
+}
+
+bstr *bstr_new(void) {
+ bstr *str;
+ str = bmalloc(sizeof(bstr));
+ str->bufsiz=64;
+ str->length=0;
+ str->text= bmalloc(str->bufsiz);
+ str->text[0]='\0';
+ return str;
+}
+
+void bstr_free(bstr *str,BOOL free_text) {
+ if (free_text) bfree(str->text);
+ bfree(str);
+}
+
+void bstr_expandby(bstr *str,unsigned extralength) {
+ if (str->bufsiz >= str->length+1+extralength) return;
+
+ while (str->bufsiz < str->length+1+extralength) str->bufsiz*=2;
+ str->text = brealloc(str->text,str->bufsiz);
+}
+
+void bstr_setlength(bstr *str,unsigned length) {
+ if (length+1 <= str->bufsiz) {
+ if (length < str->length) {
+ str->length = length;
+ str->text[length]='\0';
+ }
+ } else {
+ bstr_expandby(str,length+1-str->bufsiz);
+ }
+}
+
+void bstr_assign(bstr *str,const char *text) {
+ if (text) {
+ bstr_setlength(str,strlen(text));
+ strcpy(str->text,text);
+ str->length=strlen(text);
+ } else {
+ bstr_setlength(str,0);
+ }
+}
+
+void bstr_append(bstr *str,const char *text) {
+ if (!text) return;
+ bstr_expandby(str,strlen(text));
+ strcat(str->text,text);
+ str->length+=strlen(text);
+}
+
+void bstr_appendpath(bstr *str,const char *text) {
+ if (str->length && str->text[str->length-1]!='\\') {
+ bstr_append_c(str,'\\');
+ }
+ bstr_append(str,text);
+}
+
+void bstr_append_c(bstr *str,char ch) {
+ bstr_expandby(str,1);
+ str->text[str->length]=ch;
+ str->length++;
+ str->text[str->length]='\0';
+}
+
+/* We can be pretty confident that this is enough space for an integer */
+#define MAX_LENGTH_INT 80
+
+void bstr_append_long(bstr *str,long val) {
+ char tmpbuf[MAX_LENGTH_INT];
+ sprintf(tmpbuf,"%ld",val);
+ bstr_append(str,tmpbuf);
+}
+
+void bstr_append_windir(bstr *str) {
+ bstr_append_dir(str,TRUE);
+}
+
+void bstr_append_curdir(bstr *str) {
+ bstr_append_dir(str,FALSE);
+}
+
+void bstr_assign_windir(bstr *str) {
+ bstr_setlength(str,0);
+ bstr_append_windir(str);
+}
+
+void bstr_assign_curdir(bstr *str) {
+ bstr_setlength(str,0);
+ bstr_append_curdir(str);
+}
+
+void bstr_append_dir(bstr *str,BOOL windir) {
+ unsigned spaceleft;
+ UINT retval;
+ int tries;
+
+ spaceleft = str->bufsiz-str->length; /* spaceleft includes the null */
+
+ for (tries=0;tries<5;tries++) {
+ if (windir) {
+ retval = GetWindowsDirectory(str->text+str->length,spaceleft);
+ } else {
+ retval = GetCurrentDirectory(spaceleft,str->text+str->length);
+ }
+ if (retval==0) DisplayError("Cannot get directory: ",TRUE,TRUE);
+ if (retval <= spaceleft-1) {
+ str->length += retval;
+ break;
+ }
+ bstr_expandby(str,retval); /* Let's err on the side of caution */
+ spaceleft = str->bufsiz-str->length;
+ }
+ if (tries>=5) DisplayError("Cannot get directory: ",TRUE,TRUE);
+}
+
+void DisplayError(const char *errtext,BOOL addsyserr,BOOL fatal) {
+ DWORD syserr;
+ bstr *str;
+ LPTSTR lpMsgBuf;
+
+ syserr=GetLastError();
+
+ str=bstr_new();
+ bstr_assign(str,errtext);
+
+ if (addsyserr) {
+ bstr_append_long(str,syserr);
+ bstr_append_c(str,' ');
+ FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL,syserr,MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT),
+ (LPTSTR)&lpMsgBuf,0,NULL);
+ bstr_append(str,lpMsgBuf);
+ LocalFree(lpMsgBuf);
+ }
+
+ MessageBox(NULL,str->text,fatal ? "Fatal Error" : "Error",
+ MB_OK | MB_ICONSTOP);
+ if (fatal) ExitProcess(1);
+}
+
+void AddInstFiles(char *filename,DWORD filesize,InstFiles **lastpt,
+ InstFiles **firstpt) {
+ InstFiles *newpt;
+
+ newpt = bmalloc(sizeof(InstFiles));
+ if (*lastpt) {
+ (*lastpt)->next = newpt;
+ } else {
+ *firstpt = newpt;
+ }
+ *lastpt = newpt;
+ newpt->next=NULL;
+ newpt->filename=filename;
+ newpt->filesize=filesize;
+}
+
+void AddInstLink(char *linkfile,char *origfile,char *args,InstLink **lastpt,
+ InstLink **firstpt) {
+ InstLink *newpt;
+
+ newpt = bmalloc(sizeof(InstLink));
+ if (*lastpt) {
+ (*lastpt)->next = newpt;
+ } else {
+ *firstpt = newpt;
+ }
+ *lastpt = newpt;
+ newpt->next=NULL;
+ newpt->linkfile=linkfile;
+ newpt->origfile=origfile;
+ newpt->args=args;
+}
+
+void FreeLinkList(InstLink *linklist,BOOL freepts) {
+ InstLink *thispt,*nextpt;
+
+ thispt=linklist;
+ while (thispt) {
+ nextpt=thispt->next;
+
+ if (freepts) {
+ bfree(thispt->linkfile);
+ bfree(thispt->origfile);
+ bfree(thispt->args);
+ }
+ bfree(thispt);
+
+ thispt=nextpt;
+ }
+}
+
+void FreeFileList(InstFiles *filelist,BOOL freepts) {
+ InstFiles *thispt,*nextpt;
+
+ thispt=filelist;
+ while (thispt) {
+ nextpt=thispt->next;
+
+ if (freepts) bfree(thispt->filename);
+ bfree(thispt);
+
+ thispt=nextpt;
+ }
+}
+
+void FreeInstData(InstData *idata,BOOL freepts) {
+ FreeFileList(idata->instfiles,freepts);
+ FreeFileList(idata->extrafiles,freepts);
+
+ FreeLinkList(idata->startmenu,freepts);
+ FreeLinkList(idata->desktop,freepts);
+
+ bfree(idata->product);
+ bfree(idata->installdir);
+ bfree(idata->startmenudir);
+
+ bfree(idata);
+}
+
+void WriteLinkList(HANDLE fout,InstLink *listpt) {
+ char str[]="";
+ DWORD bytes_written;
+ for (;listpt;listpt=listpt->next) {
+ if (!WriteFile(fout,listpt->linkfile,strlen(listpt->linkfile)+1,
+ &bytes_written,NULL)) {
+ printf("Write error\n");
+ }
+ if (!WriteFile(fout,listpt->origfile,strlen(listpt->origfile)+1,
+ &bytes_written,NULL)) {
+ printf("Write error\n");
+ }
+ if (!WriteFile(fout,listpt->args,strlen(listpt->args)+1,
+ &bytes_written,NULL)) {
+ printf("Write error\n");
+ }
+ }
+ if (!WriteFile(fout,str,strlen(str)+1,&bytes_written,NULL)) {
+ printf("Write error\n");
+ }
+}
+
+void WriteFileList(HANDLE fout,InstFiles *listpt) {
+ bstr *str;
+ DWORD bytes_written;
+ str=bstr_new();
+
+ for (;listpt;listpt=listpt->next) {
+ if (!WriteFile(fout,listpt->filename,strlen(listpt->filename)+1,
+ &bytes_written,NULL)) {
+ printf("Write error\n");
+ }
+ bstr_setlength(str,0);
+ bstr_append_long(str,listpt->filesize);
+ if (!WriteFile(fout,str->text,str->length+1,&bytes_written,NULL)) {
+ printf("Write error\n");
+ }
+ }
+ bstr_assign(str,"");
+ if (!WriteFile(fout,str->text,str->length+1,&bytes_written,NULL)) {
+ printf("Write error\n");
+ }
+ bstr_free(str,TRUE);
+}
+
+char *GetStartMenuDir(InstData *idata) {
+ bstr *str;
+ char *retval;
+
+ str = bstr_new();
+ bstr_assign_windir(str);
+ bstr_appendpath(str,"Start Menu\\Programs");
+ bstr_appendpath(str,idata->startmenudir);
+
+ retval = str->text;
+ bstr_free(str,FALSE);
+ return retval;
+}
+
+char *GetDesktopDir(void) {
+ bstr *str;
+ char *retval;
+
+ str = bstr_new();
+ bstr_assign_windir(str);
+ bstr_appendpath(str,"Desktop");
+
+ retval = str->text;
+ bstr_free(str,FALSE);
+ return retval;
+}
(DIR) diff --git a/win32/util.h b/win32/util.h
t@@ -0,0 +1,65 @@
+#include <windows.h>
+
+typedef struct _bstr {
+ char *text;
+ unsigned length; /* Length of current text, NOT including terminating null */
+ unsigned bufsiz; /* Size of the allocated memory buffer */
+} bstr;
+
+typedef struct _InstFiles {
+ char *filename;
+ DWORD filesize;
+ struct _InstFiles *next;
+} InstFiles;
+
+typedef struct _InstLink {
+ char *linkfile;
+ char *origfile;
+ char *args;
+ struct _InstLink *next;
+} InstLink;
+
+typedef struct _InstData {
+ char *product;
+ char *installdir,*startmenudir;
+ DWORD totalsize;
+ InstFiles *instfiles;
+ InstFiles *extrafiles;
+ InstLink *startmenu;
+ InstLink *desktop;
+} InstData;
+
+extern const char *UninstallKey;
+extern const char *UninstallEXE;
+
+void *bmalloc(UINT numbytes);
+void bfree(void *pt);
+void *brealloc(void *pt,UINT numbytes);
+char *bstrdup(char *str);
+
+bstr *bstr_new(void);
+void bstr_free(bstr *str,BOOL free_text);
+void bstr_expandby(bstr *str,unsigned extralength);
+void bstr_setlength(bstr *str,unsigned length);
+void bstr_assign(bstr *str,const char *text);
+void bstr_append(bstr *str,const char *text);
+void bstr_appendpath(bstr *str,const char *text);
+void bstr_append_c(bstr *str,const char ch);
+void bstr_append_long(bstr *str,const long val);
+void bstr_append_windir(bstr *str);
+void bstr_append_curdir(bstr *str);
+void bstr_assign_windir(bstr *str);
+void bstr_assign_curdir(bstr *str);
+
+void DisplayError(const char *errtext,BOOL addsyserr,BOOL fatal);
+void AddInstFiles(char *filename,DWORD filesize,InstFiles **lastpt,
+ InstFiles **firstpt);
+void AddInstLink(char *linkfile,char *origfile,char *args,InstLink **lastpt,
+ InstLink **firstpt);
+void FreeLinkList(InstLink *linklist,BOOL freepts);
+void FreeFileList(InstFiles *filelist,BOOL freepts);
+void FreeInstData(InstData *idata,BOOL freepts);
+void WriteLinkList(HANDLE fout,InstLink *listpt);
+void WriteFileList(HANDLE fout,InstFiles *listpt);
+char *GetStartMenuDir(InstData *idata);
+char *GetDesktopDir(void);