tWin32 installer updates - vaccinewars - be a doctor and try to vaccinate the w… | |
git clone git://src.adamsgaard.dk/vaccinewars | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
commit 40ec03f43f7910bd549c4324e545089c2c24cee4 | |
parent a5f688bfb27f69264afa2f75ea6975f7ad2ab24b | |
Author: Ben Webb <[email protected]> | |
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(-) | |
--- | |
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… | |
+setup: setup.o util.o guifunc.o setup.res | |
+ gcc -Wall -mno-cygwin -mwindows -o setup setup.o util.o guifunc.o setu… | |
+ 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 guifun… | |
+ 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 | |
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 | |
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); | |
+ } | |
+ } | |
+} | |
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_AUTOVSCROL… | |
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, 19… | |
LTEXT "To install in a different directory, select ""Browse"" and sele… | |
GROUPBOX "Destination directory", 105, 22, 84, 195, 35, WS_CHILD | WS_… | |
- LTEXT "C:\\Windows\\Program Files\\dopewars-1.5.2\\", -1, 28, 100, 142… | |
+ 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_VIS… | |
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 … | |
+ LTEXT "&Program Folder:", -1, 22, 35, 68, 8, WS_CHILD | WS_VISIBLE | W… | |
+ CONTROL "", ED_FOLDER, "EDIT", ES_LEFT | ES_AUTOHSCROLL | WS_CHILD | W… | |
+ LTEXT "E&xisting Folders:", -1, 22, 61, 92, 8, WS_CHILD | WS_VISIBLE |… | |
+ CONTROL "", LB_FOLDLIST, "LISTBOX", LBS_NOTIFY | WS_CHILD | WS_VISIBLE… | |
+ CONTROL "Create desktop icons as well", CB_DESKTOP, "BUTTON", BS_AUTOC… | |
+ 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… | |
+ PUSHBUTTON "&Next >", BT_NEXT, 144, 143, 39, 13, WS_CHILD | WS_VISIBLE… | |
+ PUSHBUTTON "Cancel", BT_CANCEL, 191, 143, 39, 13, WS_CHILD | WS_VISIBL… | |
+END | |
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 | |
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); | |
+} | |
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); | |
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; | |
+} | |
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" | |
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; | |
+} | |
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; | |
+} | |
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; | |
+} | |
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 | … | |
+ LTEXT "Deleting file: dopewars.exe", ST_DELSTAT, 15, 14, 159, 17, WS_C… | |
+ LTEXT "All files successfully uninstalled.", ST_DELDONE, 15, 51, 159, … | |
+END | |
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; | |
+} | |
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); |