tWin32 installer handling of directories and errors now much improved - vaccine… | |
git clone git://src.adamsgaard.dk/vaccinewars | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
commit b303528750c77ad6dad59ead543ac18f856e52eb | |
parent b3875bd825494c795438861554e458bd7976bb45 | |
Author: Ben Webb <[email protected]> | |
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(-) | |
--- | |
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 | |
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_VISIBL… | |
LTEXT "dopewars will be installed into the directory given below.", -1… | |
LTEXT "To install in this directory, select ""Next"".", -1, 22, 33, 19… | |
- LTEXT "To install in a different directory, select ""Browse"" and sele… | |
+ LTEXT "To install in a different directory, enter the new directory in… | |
GROUPBOX "Destination directory", 105, 22, 84, 195, 35, WS_CHILD | WS_… | |
- 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… | |
+ CONTROL "", ED_INSTDIR, "EDIT", ES_LEFT | ES_AUTOHSCROLL | WS_CHILD | … | |
+ PUSHBUTTON "B&rowse...", BT_BROWSE, 173, 98, 39, 13, WS_CHILD | WS_VIS… | |
END | |
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 hPrev… | |
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 hPrevIn… | |
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); | |
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; | |
} | |
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 … | |
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; | |
} | |
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); |