tWin32 installer handling of directories and errors now much improved - 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 b303528750c77ad6dad59ead543ac18f856e52eb
(DIR) parent b3875bd825494c795438861554e458bd7976bb45
(HTM) Author: Ben Webb <ben@salilab.org>
Date: Mon, 1 Oct 2001 17:53:35 +0000
Win32 installer handling of directories and errors now much improved
Diffstat:
M win32/contid.h | 2 +-
M win32/dialogs.rc | 6 +++---
M win32/setup.c | 106 ++++++++++++++++++++-----------
M win32/uninstall.c | 48 +++++++++++++++++++++++++------
M win32/util.c | 89 ++++++++++++++++++++++++++-----
M win32/util.h | 3 +++
6 files changed, 192 insertions(+), 62 deletions(-)
---
(DIR) diff --git a/win32/contid.h b/win32/contid.h
t@@ -10,7 +10,7 @@
#define ED_FOLDER 210
#define LB_FOLDLIST 211
#define CB_DESKTOP 212
-#define ST_INSTDIR 213
+#define ED_INSTDIR 213
#define ST_DELSTAT 214
#define ST_DELDONE 215
#define BT_DELOK 216
(DIR) diff --git a/win32/dialogs.rc b/win32/dialogs.rc
t@@ -33,10 +33,10 @@ BEGIN
PUSHBUTTON "Cancel", BT_CANCEL, 191, 143, 39, 13, WS_CHILD | WS_VISIBLE | WS_TABSTOP
LTEXT "dopewars will be installed into the directory given below.", -1, 22, 14, 195, 9, WS_CHILD | WS_VISIBLE | WS_GROUP
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
+ LTEXT "To install in a different directory, enter the new directory into the box below, using the ""Browse"" button if necessary.", -1, 22, 51, 195, 35, WS_CHILD | WS_VISIBLE | WS_GROUP
GROUPBOX "Destination directory", 105, 22, 84, 195, 35, WS_CHILD | WS_VISIBLE | WS_TABSTOP
- 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
+ CONTROL "", ED_INSTDIR, "EDIT", ES_LEFT | ES_AUTOHSCROLL | WS_CHILD | WS_VISIBLE | WS_BORDER | WS_TABSTOP, 27, 99, 142, 10
+ PUSHBUTTON "B&rowse...", BT_BROWSE, 173, 98, 39, 13, WS_CHILD | WS_VISIBLE | WS_TABSTOP
END
(DIR) diff --git a/win32/setup.c b/win32/setup.c
t@@ -20,6 +20,27 @@ DialogType CurrentDialog;
HINSTANCE hInst=NULL;
DWORD WINAPI DoInstall(LPVOID lpParam);
+static void GetWinText(char **text,HWND hWnd);
+
+BOOL CheckCreateDir(void) {
+ char *instdir;
+ GetWinText(&idata->installdir,GetDlgItem(mainDlg[DL_INSTALLDIR],ED_INSTDIR));
+ instdir=idata->installdir;
+ if (SetCurrentDirectory(instdir)) {
+ return TRUE;
+ } else {
+ if (MessageBox(mainDlg[CurrentDialog],
+ "The install directory does not exist.\n"
+ "Create it?","Install Directory",MB_YESNO)==IDYES) {
+ if (CreateWholeDirectory(instdir)) {
+ return TRUE;
+ } else {
+ DisplayError("Could not create directory",FALSE,FALSE);
+ }
+ }
+ return FALSE;
+ }
+}
void ShowNewDialog(DialogType NewDialog) {
RECT DeskRect,OurRect;
t@@ -29,6 +50,10 @@ void ShowNewDialog(DialogType NewDialog) {
DWORD threadID;
if (NewDialog<0 || NewDialog>=DL_NUM) return;
+ if (NewDialog > CurrentDialog && CurrentDialog==DL_INSTALLDIR) {
+ if (!CheckCreateDir()) return;
+ }
+
hWnd=mainDlg[NewDialog];
if (GetWindowRect(hWnd,&OurRect) &&
GetWindowRect(GetDesktopWindow(),&DeskRect)) {
t@@ -46,44 +71,38 @@ void ShowNewDialog(DialogType NewDialog) {
}
}
+int CALLBACK BrowseCallback(HWND hwnd,UINT msg,LPARAM lParam,LPARAM lpData) {
+ switch(msg) {
+ case BFFM_INITIALIZED:
+ SendMessage(hwnd,BFFM_SETSELECTION,TRUE,(LPARAM)idata->installdir);
+ break;
+ }
+ return 0;
+}
+
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();
+ if (SUCCEEDED(SHGetMalloc(&imalloc))) {
+ bi.lpszTitle = "Pick a directory";
+ bi.pszDisplayName = path;
+ bi.ulFlags = BIF_STATUSTEXT|BIF_RETURNONLYFSDIRS;
+ bi.lpfn = BrowseCallback;
+ pidl = SHBrowseForFolder(&bi);
+ if (pidl) {
+ if (SHGetPathFromIDList(pidl,path)) {
+ bfree(idata->installdir);
+ idata->installdir = bstrdup(path);
+ SendDlgItemMessage(mainDlg[DL_INSTALLDIR],ED_INSTDIR,WM_SETTEXT,
+ 0,(LPARAM)idata->installdir);
+ }
+ imalloc->lpVtbl->Free(imalloc,pidl);
}
+ imalloc->lpVtbl->Release(imalloc);
}
-/*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) {
t@@ -490,8 +509,10 @@ DWORD WINAPI DoInstall(LPVOID lpParam) {
GetWinText(&idata->startmenudir,GetDlgItem(mainDlg[DL_SHORTCUTS],ED_FOLDER));
- CreateDirectory(idata->installdir,NULL);
- SetCurrentDirectory(idata->installdir);
+ if (!SetCurrentDirectory(idata->installdir)) {
+ DisplayError("Cannot access install directory",TRUE,TRUE);
+ }
+
logf = CreateFile("install.log",GENERIC_WRITE,0,NULL,
CREATE_ALWAYS,0,NULL);
t@@ -564,6 +585,7 @@ DWORD WINAPI DoInstall(LPVOID lpParam) {
ShowWindow(GetDlgItem(mainDlg[DL_DOINSTALL],ST_COMPLETE),SW_SHOW);
ShowWindow(GetDlgItem(mainDlg[DL_DOINSTALL],ST_EXIT),SW_SHOW);
+ EnableWindow(GetDlgItem(mainDlg[DL_DOINSTALL],BT_FINISH),TRUE);
return 0;
}
t@@ -571,6 +593,7 @@ void FillFolderList(void) {
HANDLE findfile;
WIN32_FIND_DATA finddata;
bstr *str;
+ char *startdir;
HWND folderlist;
folderlist = GetDlgItem(mainDlg[DL_SHORTCUTS],LB_FOLDLIST);
t@@ -578,22 +601,29 @@ void FillFolderList(void) {
str=bstr_new();
- bstr_assign_windir(str);
- bstr_appendpath(str,"Start Menu\\Programs\\*");
+ startdir=GetStartMenuTopDir();
+ bstr_assign(str,startdir);
+ bfree(startdir);
+ bstr_appendpath(str,"Programs\\*");
+//MessageBox(NULL,str->text,NULL,MB_OK);
+//MessageBox(NULL,"Finding first file",NULL,MB_OK);
findfile = FindFirstFile(str->text,&finddata);
- if (findfile) {
+ if (findfile!=INVALID_HANDLE_VALUE) {
while(1) {
+//MessageBox(NULL,finddata.cFileName,NULL,MB_OK);
if (finddata.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY &&
strcmp(finddata.cFileName,".")!=0 &&
strcmp(finddata.cFileName,"..")!=0) {
SendMessage(folderlist,LB_ADDSTRING,0,(LPARAM)finddata.cFileName);
}
+//MessageBox(NULL,"Finding next file",NULL,MB_OK);
if (!FindNextFile(findfile,&finddata)) break;
}
FindClose(findfile);
}
bstr_free(str,TRUE);
+//MessageBox(NULL,"Find done",NULL,MB_OK);
}
int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,
t@@ -607,14 +637,18 @@ int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,
hInst = hInstance;
+//MessageBox(NULL,"Registering class",NULL,MB_OK);
if (!hPrevInstance) RegisterSepClass(hInstance);
+//MessageBox(NULL,"Creating dialogs",NULL,MB_OK);
for (i=0;i<DL_NUM;i++) {
mainDlg[i] = CreateDialog(hInst,MAKEINTRESOURCE(i+1),NULL,MainDlgProc);
}
CheckDlgButton(mainDlg[DL_SHORTCUTS],CB_DESKTOP,BST_CHECKED);
+ EnableWindow(GetDlgItem(mainDlg[DL_DOINSTALL],BT_FINISH),FALSE);
+//MessageBox(NULL,"Filling folder list",NULL,MB_OK);
FillFolderList();
ShowWindow(GetDlgItem(mainDlg[DL_DOINSTALL],ST_COMPLETE),SW_HIDE);
t@@ -624,7 +658,7 @@ int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,
SendDlgItemMessage(mainDlg[DL_SHORTCUTS],ED_FOLDER,WM_SETTEXT,
0,(LPARAM)idata->startmenudir);
- SendDlgItemMessage(mainDlg[DL_INSTALLDIR],ST_INSTDIR,WM_SETTEXT,
+ SendDlgItemMessage(mainDlg[DL_INSTALLDIR],ED_INSTDIR,WM_SETTEXT,
0,(LPARAM)idata->installdir);
licence=GetFirstFile(idata->instfiles,idata->totalsize);
(DIR) diff --git a/win32/uninstall.c b/win32/uninstall.c
t@@ -150,12 +150,17 @@ void DeleteFileList(InstFiles *listpt) {
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);
+ if (SetCurrentDirectory(dir)) {
+ for (;listpt;listpt=listpt->next) {
+ bstr_assign(str,"Deleting shortcut: ");
+ bstr_append(str,listpt->linkfile);
+ SendDlgItemMessage(mainDlg,ST_DELSTAT,WM_SETTEXT,0,(LPARAM)str->text);
+ DeleteFile(listpt->linkfile);
+ }
+ } else {
+ bstr_assign(str,"Could not find shortcut directory ");
+ bstr_append(str,dir);
+ DisplayError(str->text,TRUE,FALSE);
}
bstr_free(str,TRUE);
}
t@@ -197,7 +202,14 @@ DWORD WINAPI DoUninstall(LPVOID lpParam) {
installdir=GetInstallDir(product);
- SetCurrentDirectory(installdir);
+ if (!SetCurrentDirectory(installdir)) {
+ str=bstr_new();
+ bstr_assign(str,"Could not access install directory ");
+ bstr_append(str,installdir);
+ DisplayError(str->text,TRUE,TRUE);
+/* Pointless to try to free the bstr, since DisplayError ends the process */
+ }
+
fin = CreateFile("install.log",GENERIC_READ,0,NULL,OPEN_EXISTING,0,NULL);
if (fin) {
t@@ -216,10 +228,22 @@ DWORD WINAPI DoUninstall(LPVOID lpParam) {
SetCurrentDirectory(desktop); /* Just make sure we're not in the install
directory any more */
- RemoveDirectory(installdir);
- RemoveDirectory(startmenu);
str=bstr_new();
+ if (!RemoveWholeDirectory(installdir)) {
+ bstr_assign(str,"Could not remove install directory:\n");
+ bstr_append(str,installdir);
+ bstr_append(str,"\nYou may wish to manually remove it later.");
+ DisplayError(str->text,FALSE,FALSE);
+ }
+
+ if (!RemoveWholeDirectory(startmenu)) {
+ bstr_assign(str,"Could not remove Start Menu directory:\n");
+ bstr_append(str,startmenu);
+ bstr_append(str,"\nYou may wish to manually remove it later.");
+ DisplayError(str->text,FALSE,FALSE);
+ }
+
bstr_assign(str,UninstallKey);
bstr_appendpath(str,product);
RegDeleteKey(HKEY_LOCAL_MACHINE,str->text);
t@@ -229,9 +253,15 @@ DWORD WINAPI DoUninstall(LPVOID lpParam) {
FreeInstData(idata,TRUE);
} else {
bfree(product); bfree(installdir); /* Normally FreeInstData frees these */
+ str=bstr_new();
+ bstr_assign(str,"Could not read install.log from ");
+ bstr_append(str,installdir);
+ DisplayError(str->text,TRUE,TRUE);
+/* Pointless to try to free the bstr, since DisplayError ends the process */
}
ShowWindow(GetDlgItem(mainDlg,ST_DELDONE),SW_SHOW);
EnableWindow(GetDlgItem(mainDlg,BT_DELOK),TRUE);
+ SetFocus(GetDlgItem(mainDlg,BT_DELOK));
return 0;
}
(DIR) diff --git a/win32/util.c b/win32/util.c
t@@ -1,6 +1,7 @@
#include <windows.h>
#include <stdio.h>
#include <string.h>
+#include <shlobj.h>
#include "util.h"
const char *UninstallKey=
t@@ -192,8 +193,9 @@ void DisplayError(const char *errtext,BOOL addsyserr,BOOL fatal) {
bstr_assign(str,errtext);
if (addsyserr) {
+ bstr_append(str,"; ");
bstr_append_long(str,syserr);
- bstr_append_c(str,' ');
+ bstr_append(str,": ");
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,
NULL,syserr,MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT),
(LPTSTR)&lpMsgBuf,0,NULL);
t@@ -330,13 +332,42 @@ void WriteFileList(HANDLE fout,InstFiles *listpt) {
bstr_free(str,TRUE);
}
+static char *GetSpecialDir(int dirtype) {
+ LPITEMIDLIST pidl;
+ LPMALLOC pmalloc;
+ char szDir[MAX_PATH];
+ BOOL doneOK=FALSE;
+
+ if (SUCCEEDED(SHGetMalloc(&pmalloc))) {
+ if (SUCCEEDED(SHGetSpecialFolderLocation(NULL,dirtype,&pidl))) {
+ if (SHGetPathFromIDList(pidl,szDir)) doneOK=TRUE;
+ pmalloc->lpVtbl->Free(pmalloc,pidl);
+ }
+ pmalloc->lpVtbl->Release(pmalloc);
+ }
+ return (doneOK ? bstrdup(szDir) : NULL);
+}
+
+char *GetStartMenuTopDir(void) {
+ return GetSpecialDir(CSIDL_STARTMENU);
+}
+
+char *GetDesktopDir(void) {
+ return GetSpecialDir(CSIDL_DESKTOPDIRECTORY);
+}
+
char *GetStartMenuDir(InstData *idata) {
bstr *str;
- char *retval;
+ char *topdir,*retval;
+
+ topdir=GetStartMenuTopDir();
str = bstr_new();
- bstr_assign_windir(str);
- bstr_appendpath(str,"Start Menu\\Programs");
+
+ bstr_assign(str,topdir);
+ bfree(topdir);
+
+ bstr_appendpath(str,"Programs");
bstr_appendpath(str,idata->startmenudir);
retval = str->text;
t@@ -344,15 +375,47 @@ char *GetStartMenuDir(InstData *idata) {
return retval;
}
-char *GetDesktopDir(void) {
- bstr *str;
- char *retval;
+BOOL CreateWholeDirectory(char *path) {
+ char *pt;
+ if (!path) return FALSE;
- str = bstr_new();
- bstr_assign_windir(str);
- bstr_appendpath(str,"Desktop");
+/* We may as well try the easy way first */
+ if (CreateDirectory(path,NULL)) return TRUE;
- retval = str->text;
- bstr_free(str,FALSE);
- return retval;
+ /* \\machine\share notation */
+ if (strlen(path)>2 && path[0]=='\\' && path[1]=='\\') {
+ pt=&path[2]; /* Skip initial "\\" */
+ } else {
+ pt=path;
+ }
+
+ while (*pt && *pt!='\\') pt++; /* Skip the first (root) '\' */
+
+ while (*pt) {
+ pt++;
+ if (*pt=='\\') {
+ *pt='\0';
+ if (!CreateDirectory(path,NULL)) {
+ *pt='\\'; return FALSE;
+ }
+ *pt='\\';
+ }
+ }
+ return CreateDirectory(path,NULL);
+}
+
+BOOL RemoveWholeDirectory(char *path) {
+ char *pt;
+ BOOL retval;
+ if (!path || !RemoveDirectory(path)) return FALSE;
+
+ for (pt=&path[strlen(path)-2];pt>path;pt--) {
+ if (*pt=='\\') {
+ *pt='\0';
+ retval=RemoveDirectory(path);
+ *pt='\\';
+ if (!retval) break;
+ }
+ }
+ return TRUE;
}
(DIR) diff --git a/win32/util.h b/win32/util.h
t@@ -61,5 +61,8 @@ 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 *GetStartMenuTopDir(void);
char *GetStartMenuDir(InstData *idata);
char *GetDesktopDir(void);
+BOOL CreateWholeDirectory(char *path);
+BOOL RemoveWholeDirectory(char *path);