From caa31c9cd58b17762d5626f39602a45b8ac4172c Mon Sep 17 00:00:00 2001 From: kichik Date: Fri, 18 Jul 2003 14:22:17 +0000 Subject: [PATCH] - Fixed all known problems with temporary files and directoroes - Command line switches work again (/NCRC and /S) - GetTempFileName now takes another argument as base directory (default is $TEMP) - Message boxes work from .onGUIEnd - Some more optimizations git-svn-id: https://svn.code.sf.net/p/nsis/code/NSIS/trunk@2739 212acab6-be3b-0410-9dea-997c60f758d6 --- Source/build.cpp | 10 +- Source/exehead/Main.c | 234 +++++--------------------------------- Source/exehead/Ui.c | 1 + Source/exehead/exec.c | 18 ++- Source/exehead/fileform.c | 209 ++++++++++++++++++++++++++++------ Source/exehead/fileform.h | 14 ++- Source/exehead/util.c | 15 ++- Source/exehead/util.h | 1 + Source/script.cpp | 4 + Source/tokens.cpp | 2 +- TODO.txt | 2 - 11 files changed, 245 insertions(+), 265 deletions(-) diff --git a/Source/build.cpp b/Source/build.cpp index a576a23a..36fff032 100644 --- a/Source/build.cpp +++ b/Source/build.cpp @@ -1985,8 +1985,7 @@ int CEXEBuild::write_output(void) fh.nsinst[1]=FH_INT2; fh.nsinst[2]=FH_INT3; - fh.flags=(build_crcchk?FH_FLAGS_CRC:0); - fh.flags|=(build_crcchk==2?FH_FLAGS_FORCE_CRC:0); + fh.flags=(build_crcchk?(build_crcchk==2?FH_FLAGS_FORCE_CRC:0):FH_FLAGS_NO_CRC); #ifdef NSIS_CONFIG_SILENT_SUPPORT if (build_header.common.flags&(CH_FLAGS_SILENT|CH_FLAGS_SILENT_LOG)) fh.flags |= FH_FLAGS_SILENT; #endif @@ -2355,8 +2354,7 @@ int CEXEBuild::uninstall_generate() fh.nsinst[0]=FH_INT1; fh.nsinst[1]=FH_INT2; fh.nsinst[2]=FH_INT3; - fh.flags = FH_FLAGS_UNINSTALL | (build_crcchk?FH_FLAGS_CRC:0); - fh.flags |= (build_crcchk==2?FH_FLAGS_FORCE_CRC:0); + fh.flags=(build_crcchk?(build_crcchk==2?FH_FLAGS_FORCE_CRC:0):FH_FLAGS_NO_CRC); #ifdef NSIS_CONFIG_SILENT_SUPPORT if (build_uninst.common.flags&(CH_FLAGS_SILENT|CH_FLAGS_SILENT_LOG)) fh.flags |= FH_FLAGS_SILENT; #endif @@ -2611,9 +2609,9 @@ again: if (ret != PS_OK) return ret; // GetTempFileName $0 #ifdef NSIS_SUPPORT_NAMED_USERVARS - ret=add_entry_direct(EW_GETTEMPFILENAME, var_zero); + ret=add_entry_direct(EW_GETTEMPFILENAME, var_zero, add_string("$TEMP")); #else - ret=add_entry_direct(EW_GETTEMPFILENAME); + ret=add_entry_direct(EW_GETTEMPFILENAME, 0, add_string("$TEMP")); #endif if (ret != PS_OK) return ret; // Delete $0 - the temp file created diff --git a/Source/exehead/Main.c b/Source/exehead/Main.c index 849a5e01..9fa8bb10 100644 --- a/Source/exehead/Main.c +++ b/Source/exehead/Main.c @@ -34,8 +34,6 @@ #include "lang.h" #include "state.h" -extern unsigned long NSISCALL CRC32(unsigned long crc, const unsigned char *buf, unsigned int len); - #if !defined(NSIS_CONFIG_VISIBLE_SUPPORT) && !defined(NSIS_CONFIG_SILENT_SUPPORT) #error One of NSIS_CONFIG_SILENT_SUPPORT or NSIS_CONFIG_VISIBLE_SUPPORT must be defined. #endif @@ -43,220 +41,46 @@ extern unsigned long NSISCALL CRC32(unsigned long crc, const unsigned char *buf, extern HANDLE dbd_hFile; #endif -#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT -static const char *g_errorcopyinginstall=_LANG_UNINSTINITERROR; -#endif - char g_caption[NSIS_MAX_STRLEN*2]; int g_filehdrsize; HWND g_hwnd; -int m_length; -int m_pos; - -#ifdef NSIS_CONFIG_VISIBLE_SUPPORT -#if defined(NSIS_CONFIG_CRC_SUPPORT) || defined(NSIS_COMPRESS_WHOLE) -BOOL CALLBACK verProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - static char *msg; - if (uMsg == WM_INITDIALOG) - { - SetTimer(hwndDlg,1,250,NULL); - msg = (char*)lParam; - uMsg = WM_TIMER; - } - if (uMsg == WM_TIMER) - { - static char bt[64]; - wsprintf(bt,msg,MulDiv(m_pos,100,m_length)); - - my_SetWindowText(hwndDlg,bt); - my_SetDialogItemText(hwndDlg,IDC_STR,bt); - } - return 0; -} -#endif//NSIS_CONFIG_CRC_SUPPORT -#endif//NSIS_CONFIG_VISIBLE_SUPPORT - int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInst,LPSTR lpszCmdParam, int nCmdShow) { int ret; const char *m_Err = 0; -#ifdef NSIS_CONFIG_CRC_SUPPORT -#ifdef NSIS_CONFIG_VISIBLE_SUPPORT - static HWND hwnd; -#endif - static int crc; - static char no_crc; - static char do_crc; -#endif//NSIS_CONFIG_CRC_SUPPORT -#if defined(NSIS_CONFIG_SILENT_SUPPORT) && defined(NSIS_CONFIG_VISIBLE_SUPPORT) - char silent = 0; -#endif//NSIS_CONFIG_SILENT_SUPPORT && NSIS_CONFIG_VISIBLE_SUPPORT - int left; -#ifdef NSIS_CONFIG_VISIBLE_SUPPORT - unsigned int verify_time=GetTickCount()+1000; -#endif - + int cl_flags = 0; + char *realcmds; char seekchar=' '; char *cmdline; - //WIN32_FIND_DATA *pfd; InitCommonControls(); - - mystrcpy(g_caption,_LANG_GENERIC_ERROR); GetTempPath(sizeof(state_temp_dir), state_temp_dir); validate_filename(state_temp_dir); + CreateDirectory(state_temp_dir, NULL); - // This is not so effective...!!??! - // The perfect way is: - // - Test Access for filewrite - // - Test Access for folder creation (needed for plugins) - // - And if one of the above tests fail, change to "$WINDIR\TEMP" and re-test - // but this will take to much size in exehead and is unreliable too - /* - pfd = file_exists(state_temp_dir); - if (!pfd || !(pfd->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) + // g_caption is used as a temp var here + if (!my_GetTempFileName(g_caption, state_temp_dir)) { - // Setup temp dir to "$WINDIR\TEMP" - mystrcpy(state_temp_dir+GetWindowsDirectory(state_temp_dir, sizeof(state_temp_dir)), "\\Temp"); - if ( !file_exists(state_temp_dir) || !CreateDirectory(state_temp_dir, NULL) ) + mystrcpy(state_temp_dir + GetWindowsDirectory(state_temp_dir, sizeof(state_temp_dir)), "\\Temp"); + validate_filename(state_temp_dir); + CreateDirectory(state_temp_dir, NULL); + if (!my_GetTempFileName(g_caption, state_temp_dir)) { m_Err = _LANG_ERRORWRITINGTEMP; goto end; } } - */ + DeleteFile(g_caption); - lstrcpyn(state_command_line,GetCommandLine(),NSIS_MAX_STRLEN); + mystrcpy(g_caption,_LANG_GENERIC_ERROR); - g_hInstance=GetModuleHandle(NULL); - GetModuleFileName(g_hInstance,state_exe_directory,NSIS_MAX_STRLEN); + lstrcpyn(state_command_line, GetCommandLine(), NSIS_MAX_STRLEN); - g_db_hFile=myOpenFile(state_exe_directory,GENERIC_READ,OPEN_EXISTING); - if (g_db_hFile==INVALID_HANDLE_VALUE) - { - m_Err = _LANG_CANTOPENSELF; - goto end; - } - - // make state_exe_directory point to dir, not full exe. - - trimslashtoend(state_exe_directory); - - left = m_length = GetFileSize(g_db_hFile,NULL); - while (left > 0) - { - static char temp[512]; - DWORD l=left; - if (l > 512) l=512; - if (!ReadSelfFile(temp,l)) - { - m_Err=_LANG_INVALIDCRC; -#if defined(NSIS_CONFIG_CRC_SUPPORT) && defined(NSIS_CONFIG_VISIBLE_SUPPORT) - if (hwnd) DestroyWindow(hwnd); -#endif//NSIS_CONFIG_CRC_SUPPORT - goto end; - } - - if (!g_filehdrsize) - { - int dbl; - dbl=isheader((firstheader*)temp); - if (dbl) - { - int a=*(int*)temp; - g_filehdrsize=m_pos; - if (dbl > left) - { - m_Err=_LANG_INVALIDCRC; - goto end; - } -#if defined(NSIS_CONFIG_SILENT_SUPPORT) && defined(NSIS_CONFIG_VISIBLE_SUPPORT) - if (a&FH_FLAGS_SILENT) silent++; -#endif//NSIS_CONFIG_SILENT_SUPPORT && NSIS_CONFIG_VISIBLE_SUPPORT - -#ifdef NSIS_CONFIG_CRC_SUPPORT - // Changed by Amir Szekely 23rd July 2002 (CRCCheck force) - if ((no_crc && !(a&FH_FLAGS_FORCE_CRC)) || !(a&FH_FLAGS_CRC)) break; // if first bit is not set, then no crc checking. - - do_crc++; - -#ifndef NSIS_CONFIG_CRC_ANAL - left=dbl-4; - // end crc checking at crc :) this means you can tack shit on the end and it'll still work. -#else //!NSIS_CONFIG_CRC_ANAL - left-=4; -#endif//NSIS_CONFIG_CRC_ANAL - // this is in case the end part is < 512 bytes. - if (l > (DWORD)left) l=(DWORD)left; - -#else//!NSIS_CONFIG_CRC_SUPPORT - break; -#endif//!NSIS_CONFIG_CRC_SUPPORT - } - } -#ifdef NSIS_CONFIG_CRC_SUPPORT - -#ifdef NSIS_CONFIG_VISIBLE_SUPPORT - -#ifdef NSIS_CONFIG_SILENT_SUPPORT - else if (!silent) -#endif//NSIS_CONFIG_SILENT_SUPPORT - { - if (hwnd) - { - MSG msg; - while (PeekMessage(&msg,NULL,0,0,PM_REMOVE)) DispatchMessage(&msg); - } - else if (GetTickCount() > verify_time) - hwnd=CreateDialogParam( - g_hInstance, - MAKEINTRESOURCE(IDD_VERIFY), - 0, - verProc, - (LPARAM)_LANG_VERIFYINGINST - ); - } -#endif//NSIS_CONFIG_VISIBLE_SUPPORT - -#ifndef NSIS_CONFIG_CRC_ANAL - if (left left) + return "not enough data"; + + g_filehdrsize = m_pos; + +#if defined(NSIS_CONFIG_SILENT_SUPPORT) && defined(NSIS_CONFIG_VISIBLE_SUPPORT) + cl_flags |= h.flags & FH_FLAGS_SILENT; +#endif//NSIS_CONFIG_SILENT_SUPPORT && NSIS_CONFIG_VISIBLE_SUPPORT + +#ifdef NSIS_CONFIG_CRC_SUPPORT + if ((h.flags & FH_FLAGS_FORCE_CRC) == 0) + { + if ((cl_flags & FH_FLAGS_NO_CRC) | (h.flags & FH_FLAGS_NO_CRC)) + break; + } + + do_crc++; + +#ifndef NSIS_CONFIG_CRC_ANAL + left = h.length_of_all_following_data - 4; + // end crc checking at crc :) this means you can tack shit on the end and it'll still work. +#else //!NSIS_CONFIG_CRC_ANAL + left -= 4; +#endif//NSIS_CONFIG_CRC_ANAL + // this is in case the end part is < 512 bytes. + if (l > (DWORD)left) l=(DWORD)left; + +#else//!NSIS_CONFIG_CRC_SUPPORT + // no crc support, no need to keep on reading + break; +#endif//!NSIS_CONFIG_CRC_SUPPORT + } + } +#ifdef NSIS_CONFIG_CRC_SUPPORT + +#ifdef NSIS_CONFIG_VISIBLE_SUPPORT + +#ifdef NSIS_CONFIG_SILENT_SUPPORT + else if (cl_flags & FH_FLAGS_SILENT == 0) +#endif//NSIS_CONFIG_SILENT_SUPPORT + { + if (hwnd) + { + MSG msg; + while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) DispatchMessage(&msg); + } + else if (GetTickCount() > verify_time) + hwnd = CreateDialogParam( + g_hInstance, + MAKEINTRESOURCE(IDD_VERIFY), + 0, + verProc, + (LPARAM)_LANG_VERIFYINGINST + ); + } +#endif//NSIS_CONFIG_VISIBLE_SUPPORT + +#ifndef NSIS_CONFIG_CRC_ANAL + if (left < m_length) +#endif//NSIS_CONFIG_CRC_ANAL + crc = CRC32(crc, temp, l); + +#endif//NSIS_CONFIG_CRC_SUPPORT + m_pos += l; + left -= l; + } +#ifdef NSIS_CONFIG_VISIBLE_SUPPORT +#ifdef NSIS_CONFIG_CRC_SUPPORT + if (hwnd) DestroyWindow(hwnd); +#endif//NSIS_CONFIG_CRC_SUPPORT +#endif//NSIS_CONFIG_VISIBLE_SUPPORT + if (!g_filehdrsize) return "couldn't find header"; + +#ifdef NSIS_CONFIG_CRC_SUPPORT + if (do_crc) + { + int fcrc; + if (!ReadSelfFile(&fcrc, sizeof(int)) || crc != fcrc) + return "bad crc"; + } +#endif//NSIS_CONFIG_CRC_SUPPORT + + data = (void *)my_GlobalAlloc(h.length_of_header); + +#if defined(NSIS_CONFIG_COMPRESSION_SUPPORT) && defined(NSIS_COMPRESS_WHOLE) inflateReset(&g_inflate_stream); { char fno[MAX_PATH]; - GetTempFileName(state_temp_dir,"nst",0,fno); + my_GetTempFileName(fno, state_temp_dir); dbd_hFile=CreateFile(fno,GENERIC_WRITE|GENERIC_READ,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_TEMPORARY|FILE_FLAG_DELETE_ON_CLOSE,NULL); if (dbd_hFile == INVALID_HANDLE_VALUE) - { return _LANG_ERRORWRITINGTEMP; - } } - dbd_srcpos=SetSelfFilePointer(0,FILE_CURRENT); - dbd_fulllen=dbd_srcpos-sizeof(h)+h.length_of_all_following_data-((h.flags&FH_FLAGS_CRC)?4:0); -#endif + dbd_srcpos = SetSelfFilePointer(g_filehdrsize + sizeof(firstheader), FILE_BEGIN); + dbd_fulllen = dbd_srcpos - sizeof(h) + h.length_of_all_following_data - ((cl_flags & FH_FLAGS_NO_CRC) ? 0 : sizeof(int)); +#else + SetSelfFilePointer(g_filehdrsize + sizeof(firstheader), FILE_BEGIN); #endif - if (GetCompressedDataFromDataBlockToMemory(-1,data,h.length_of_header) != h.length_of_header) + if ((crc = GetCompressedDataFromDataBlockToMemory(-1, data, h.length_of_header)) != h.length_of_header) { GlobalFree((HGLOBAL)data); - return _LANG_INVALIDCRC; + wsprintf(g_caption, "can't read headers %d", crc); + return g_caption; } #if !defined(NSIS_COMPRESS_WHOLE) || !defined(NSIS_CONFIG_COMPRESSION_SUPPORT) - g_db_offset=SetSelfFilePointer(0,FILE_CURRENT); + g_db_offset = SetSelfFilePointer(0,FILE_CURRENT); #else - g_db_offset=dbd_pos; + g_db_offset = dbd_pos; #endif - g_inst_combinedheader=data; + g_inst_combinedheader = data; - inst_flags=((common_header *)data)->flags; + inst_flags = g_inst_cmnheader->flags; +#ifdef NSIS_CONFIG_SILENT_SUPPORT + if (cl_flags & FH_FLAGS_SILENT) inst_flags |= CH_FLAGS_SILENT; +#endif #ifdef NSIS_CONFIG_UNINSTALL_SUPPORT - if (h.flags&FH_FLAGS_UNINSTALL) + if (h.flags & FH_FLAGS_UNINSTALL) { g_is_uninstaller++; - g_inst_page=(page *) (g_inst_uninstheader + 1); + g_inst_page = (page *) (g_inst_uninstheader + 1); } else #endif @@ -111,7 +256,7 @@ const char * NSISCALL loadHeaders(void) num_sections=g_inst_header->num_sections; g_inst_page=(page *) (g_inst_section + num_sections); } - g_inst_entry=(entry *) (g_inst_page + g_inst_cmnheader->num_pages); + g_inst_entry = (entry *) (g_inst_page + g_inst_cmnheader->num_pages); g_db_strtab = (char *) (g_inst_entry + g_inst_cmnheader->num_entries); return 0; } @@ -267,8 +412,8 @@ static int NSISCALL __ensuredata(int amount) m_pos=m_length-(amount-(dbd_size-dbd_pos)); while (PeekMessage(&msg,NULL,0,0,PM_REMOVE)) DispatchMessage(&msg); } - else if (GetWindowLong(g_hwnd,DWL_DLGPROC) != (long)DialogProc && GetTickCount() > verify_time) - hwnd=CreateDialogParam( + else if (g_hwnd && GetTickCount() > verify_time) + hwnd = CreateDialogParam( g_hInstance, MAKEINTRESOURCE(IDD_VERIFY), 0, diff --git a/Source/exehead/fileform.h b/Source/exehead/fileform.h index 278b04be..47bc9669 100644 --- a/Source/exehead/fileform.h +++ b/Source/exehead/fileform.h @@ -53,7 +53,7 @@ enum #ifdef NSIS_SUPPORT_FNUTIL EW_GETFULLPATHNAME, // GetFullPathName: 2 [output, input, ?lfn:sfn] EW_SEARCHPATH, // SearchPath: 2 [output, filename] - EW_GETTEMPFILENAME, // GetTempFileName: 1 [output] + EW_GETTEMPFILENAME, // GetTempFileName: 2 [output, base_dir] #endif #ifdef NSIS_SUPPORT_FILE EW_EXTRACTFILE, // File to extract: 6 [overwriteflag, output filename, compressed filedata, filedatetimelow, filedatetimehigh, allow ignore] @@ -181,12 +181,14 @@ enum }; #define FH_FLAGS_MASK 15 -#define FH_FLAGS_CRC 1 -#define FH_FLAGS_UNINSTALL 2 +#define FH_FLAGS_UNINSTALL 1 #ifdef NSIS_CONFIG_SILENT_SUPPORT -#define FH_FLAGS_SILENT 4 +# define FH_FLAGS_SILENT 2 +#endif +#ifdef NSIS_CONFIG_CRC_SUPPORT +# define FH_FLAGS_NO_CRC 4 +# define FH_FLAGS_FORCE_CRC 8 #endif -#define FH_FLAGS_FORCE_CRC 8 #define FH_SIG 0xDEADBEEF @@ -498,7 +500,7 @@ int NSISCALL isheader(firstheader *h); // returns 0 on not header, length_of_dat // returns 0 on success // on success, m_header will be set to a pointer that should eventually be GlobalFree()'d. // (or m_uninstheader) -const char * NSISCALL loadHeaders(void); +const char * NSISCALL loadHeaders(int cl_flags); int NSISCALL _dodecomp(int offset, HANDLE hFileOut, char *outbuf, int outbuflen); diff --git a/Source/exehead/util.c b/Source/exehead/util.c index 872cc18b..79e3d869 100644 --- a/Source/exehead/util.c +++ b/Source/exehead/util.c @@ -118,7 +118,6 @@ void NSISCALL doRMDir(char *buf, int flags) // 1 - recurse, 2 - rebootok #endif } log_printf2("RMDir: RemoveDirectory(\"%s\")",buf); - update_status_text_from_lang(LANG_REMOVEDIR,buf); } #endif//NSIS_SUPPORT_RMDIR @@ -226,6 +225,20 @@ HANDLE NSISCALL myOpenFile(const char *fn, DWORD da, DWORD cd) return CreateFile(fn,da,FILE_SHARE_READ,NULL,cd,0,NULL); } +char * NSISCALL my_GetTempFileName(char *buf, const char *dir) +{ + int n = 100; + while (n--) + { + char prefix[4] = "nsa"; + prefix[2] = 'a' + (char)(GetTickCount() % 26); + if (GetTempFileName(dir, prefix, 0, buf)) + return buf; + } + *buf = 0; + return 0; +} + #ifdef NSIS_SUPPORT_MOVEONREBOOT BOOL NSISCALL MoveFileOnReboot(LPCTSTR pszExisting, LPCTSTR pszNew) { diff --git a/Source/exehead/util.h b/Source/exehead/util.h index 8a2b6329..fb054382 100644 --- a/Source/exehead/util.h +++ b/Source/exehead/util.h @@ -14,6 +14,7 @@ char * NSISCALL mystrcpy(char *out, const char *in); int NSISCALL mystrlen(const char *in); char * NSISCALL mystrstr(char *a, char *b); WIN32_FIND_DATA * NSISCALL file_exists(char *buf); +char * NSISCALL my_GetTempFileName(char *buf, const char *dir); //BOOL NSISCALL my_SetWindowText(HWND hWnd, const char *val); #define my_SetWindowText SetWindowText diff --git a/Source/script.cpp b/Source/script.cpp index 67b8c0a5..8a9062dc 100644 --- a/Source/script.cpp +++ b/Source/script.cpp @@ -3914,6 +3914,10 @@ int CEXEBuild::doCommand(int which_token, LineParser &line) case TOK_GETTEMPFILENAME: ent.which=EW_GETTEMPFILENAME; ent.offsets[0]=GetUserVarIndex(line, 1); + if (line.getnumtokens() == 3) + ent.offsets[1]=add_string(line.gettoken_str(2)); + else + ent.offsets[1]=add_string("$TEMP"); if (ent.offsets[0]<0) PRINTHELP() SCRIPT_MSG("GetTempFileName -> %s\n",line.gettoken_str(1)); return add_entry(&ent); diff --git a/Source/tokens.cpp b/Source/tokens.cpp index 17ccde3e..8e645b1d 100644 --- a/Source/tokens.cpp +++ b/Source/tokens.cpp @@ -77,7 +77,7 @@ static tokenType tokenlist[TOK__LAST] = {TOK_FUNCTIONEND,"FunctionEnd",0,0,""}, {TOK_GETDLGITEM,"GetDlgItem",3,0,"$(user_var: handle output) dialog item_id"}, {TOK_GETFULLPATHNAME,"GetFullPathName",2,1,"[/SHORT] $(user_var: result) path_or_file"}, -{TOK_GETTEMPFILENAME,"GetTempFileName",1,0,"$(user_var: name output)"}, +{TOK_GETTEMPFILENAME,"GetTempFileName",1,1,"$(user_var: name output) [base_dir]"}, {TOK_GETWINTEXT,"GetWindowText",2,0,"$(user_var: handle output) hwnd"}, {TOK_HIDEWINDOW,"HideWindow",0,0,""}, {TOK_ICON,"Icon",1,0,"local_icon.ico"}, diff --git a/TODO.txt b/TODO.txt index 99bb67b6..8ebe16ed 100644 --- a/TODO.txt +++ b/TODO.txt @@ -12,8 +12,6 @@ NSIS * all installer strings should be language strings -* make temp (for compress whole) creation better (and verify it exists) - * move no custom to compiler (custom as just another inst type) * empty subsections should not show