CPP/7zip/Bundles/SFXSetup/Compat.xml | 1 + CPP/7zip/Bundles/SFXSetup/SfxSetup.cpp | 51 +++++++++++++--- CPP/7zip/Bundles/SFXSetup/resource.rc | 4 +- CPP/7zip/UI/Explorer/MyMessages.cpp | 4 +- CPP/7zip/UI/Explorer/MyMessages.h | 2 +- CPP/7zip/UI/FileManager/FormatUtils.cpp | 2 +- CPP/7zip/UI/FileManager/ProgressDialog.cpp | 4 +- CPP/Common/MyWindows.h | 1 + CPP/Windows/FileDir.cpp | 97 ++++++++++++++++++++++++++---- CPP/Windows/FileDir.h | 1 + 10 files changed, 137 insertions(+), 30 deletions(-) diff --git a/CPP/7zip/Bundles/SFXSetup/Compat.xml b/CPP/7zip/Bundles/SFXSetup/Compat.xml new file mode 100644 index 0000000..76fecef --- /dev/null +++ b/CPP/7zip/Bundles/SFXSetup/Compat.xml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/CPP/7zip/Bundles/SFXSetup/SfxSetup.cpp b/CPP/7zip/Bundles/SFXSetup/SfxSetup.cpp index aef2e19..53608cf 100644 --- a/CPP/7zip/Bundles/SFXSetup/SfxSetup.cpp +++ b/CPP/7zip/Bundles/SFXSetup/SfxSetup.cpp @@ -37,6 +37,26 @@ static CFSTR kTempDirPrefix = FTEXT("7zS"); #define _SHELL_EXECUTE +static HWND GetCurrentHwnd(void) +{ + HWND result = ::GetActiveWindow(); + if(!(result && IsWindowVisible(result))) + { + for (int i = 0; i < 256; ++i) + { + ::Sleep(1); /*some delay*/ + if(const HWND hwnd = ::GetForegroundWindow()) + { + if(IsWindowVisible(result = hwnd)) + { + break; /*success*/ + } + } + } + } + return result; +} + static bool ReadDataString(CFSTR fileName, LPCSTR startID, LPCSTR endID, AString &stringResult) { @@ -145,7 +165,7 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */, UString archiveName, switches; #ifdef _SHELL_EXECUTE - UString executeFile, executeParameters; + UString executeFile, executeParameters, executeErrorMsg; #endif NCommandLineParser::SplitCommandLine(GetCommandLineW(), archiveName, switches); @@ -191,7 +211,7 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */, dirPrefix = pairs[index].String; if (!installPrompt.IsEmpty() && !assumeYes) { - if (MessageBoxW(0, installPrompt, friendlyName, MB_YESNO | + if (MessageBoxW(NULL, installPrompt, friendlyName, MB_YESNO | MB_SYSTEMMODAL | MB_ICONQUESTION) != IDYES) return 0; } @@ -200,6 +220,7 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */, #ifdef _SHELL_EXECUTE executeFile = GetTextConfigValue(pairs, L"ExecuteFile"); executeParameters = GetTextConfigValue(pairs, L"ExecuteParameters"); + executeErrorMsg = GetTextConfigValue(pairs, L"ExecuteErrorMsg"); #endif } @@ -243,7 +264,7 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */, { if (errorMessage.IsEmpty()) errorMessage = NError::MyFormatMessage(result); - ::MessageBoxW(0, errorMessage, NWindows::MyLoadString(IDS_EXTRACTION_ERROR_TITLE), MB_ICONERROR); + ::MessageBoxW(NULL, errorMessage, NWindows::MyLoadString(IDS_EXTRACTION_ERROR_TITLE), MB_ICONERROR | MB_SYSTEMMODAL); } } return 1; @@ -287,13 +308,25 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */, execInfo.lpDirectory = NULL; execInfo.nShow = SW_SHOWNORMAL; execInfo.hProcess = 0; - /* BOOL success = */ ::ShellExecuteEx(&execInfo); - UINT32 result = (UINT32)(UINT_PTR)execInfo.hInstApp; - if (result <= 32) + + for (;;) { - if (!assumeYes) - ShowErrorMessage(L"Can not open file"); - return 1; + execInfo.hwnd = GetCurrentHwnd(); /*prevent UAC dialog from appearing in the background!*/ + /* BOOL success = */ ::ShellExecuteEx(&execInfo); + UINT32 result = (UINT32)(UINT_PTR)execInfo.hInstApp; + if (result <= 32) + { + if (!assumeYes) + { + const wchar_t *const lpErrorMessage = executeErrorMsg.IsEmpty() ? L"Failed to launch installer. Please try again!" : executeErrorMsg; + if (MessageBoxW(NULL, lpErrorMessage, L"Setup", MB_SYSTEMMODAL | MB_ICONEXCLAMATION | MB_RETRYCANCEL) == IDRETRY) + { + continue; /*retry*/ + } + } + return 1; + } + break; /*success*/ } hProcess = execInfo.hProcess; } diff --git a/CPP/7zip/Bundles/SFXSetup/resource.rc b/CPP/7zip/Bundles/SFXSetup/resource.rc index 47e1b76..c796e65 100644 --- a/CPP/7zip/Bundles/SFXSetup/resource.rc +++ b/CPP/7zip/Bundles/SFXSetup/resource.rc @@ -1,14 +1,14 @@ #include "../../MyVersionInfo.rc" #include "resource.h" -MY_VERSION_INFO_APP("7z Setup SFX", "7zS.sfx") +MY_VERSION_INFO_APP("Setup SFX", "7zS.sfx") IDI_ICON ICON "setup.ico" STRINGTABLE BEGIN IDS_EXTRACTION_ERROR_TITLE "Extraction Failed" - IDS_EXTRACTION_ERROR_MESSAGE "File is corrupt" + IDS_EXTRACTION_ERROR_MESSAGE "File is corrupt. Please download again!" IDS_CANNOT_CREATE_FOLDER "Cannot create folder '{0}'" IDS_PROGRESS_EXTRACTING "Extracting" END diff --git a/CPP/7zip/UI/Explorer/MyMessages.cpp b/CPP/7zip/UI/Explorer/MyMessages.cpp index 70c2a46..84ac8f4 100644 --- a/CPP/7zip/UI/Explorer/MyMessages.cpp +++ b/CPP/7zip/UI/Explorer/MyMessages.cpp @@ -1,6 +1,6 @@ // MyMessages.cpp -#include "StdAfx.h" +//#include "StdAfx.h" #include "MyMessages.h" @@ -13,7 +13,7 @@ using namespace NWindows; void ShowErrorMessage(HWND window, LPCWSTR message) { - ::MessageBoxW(window, message, L"7-Zip", MB_OK | MB_ICONSTOP); + ::MessageBoxW(window, message, L"Setup", MB_OK | MB_SYSTEMMODAL | MB_ICONSTOP); } void ShowErrorMessageHwndRes(HWND window, UINT resID) diff --git a/CPP/7zip/UI/Explorer/MyMessages.h b/CPP/7zip/UI/Explorer/MyMessages.h index d5822f4..3bd6e2e 100644 --- a/CPP/7zip/UI/Explorer/MyMessages.h +++ b/CPP/7zip/UI/Explorer/MyMessages.h @@ -6,7 +6,7 @@ #include "../../../Common/MyString.h" void ShowErrorMessage(HWND window, LPCWSTR message); -inline void ShowErrorMessage(LPCWSTR message) { ShowErrorMessage(0, message); } +inline void ShowErrorMessage(LPCWSTR message) { ShowErrorMessage(NULL, message); } void ShowErrorMessageHwndRes(HWND window, UInt32 langID); void ShowErrorMessageRes(UInt32 langID); diff --git a/CPP/7zip/UI/FileManager/FormatUtils.cpp b/CPP/7zip/UI/FileManager/FormatUtils.cpp index 2143c3f..3a18712 100644 --- a/CPP/7zip/UI/FileManager/FormatUtils.cpp +++ b/CPP/7zip/UI/FileManager/FormatUtils.cpp @@ -1,6 +1,6 @@ // FormatUtils.cpp -#include "StdAfx.h" +//#include "StdAfx.h" #include "../../../Common/IntToString.h" diff --git a/CPP/7zip/UI/FileManager/ProgressDialog.cpp b/CPP/7zip/UI/FileManager/ProgressDialog.cpp index 65201a9..4d23499 100644 --- a/CPP/7zip/UI/FileManager/ProgressDialog.cpp +++ b/CPP/7zip/UI/FileManager/ProgressDialog.cpp @@ -1,6 +1,6 @@ // ProgressDialog.cpp -#include "StdAfx.h" +//#include "StdAfx.h" #include "../../../Common/IntToString.h" @@ -165,7 +165,7 @@ bool CProgressDialog::OnButtonClicked(int buttonID, HWND buttonHWND) bool paused = Sync.GetPaused(); Sync.SetPaused(true); _inCancelMessageBox = true; - int res = ::MessageBoxW(*this, L"Are you sure you want to cancel?", _title, MB_YESNOCANCEL); + int res = ::MessageBoxW(*this, L"Are you sure you want to cancel?", _title, MB_YESNOCANCEL | MB_SYSTEMMODAL); _inCancelMessageBox = false; Sync.SetPaused(paused); if (res == IDCANCEL || res == IDNO) diff --git a/CPP/Common/MyWindows.h b/CPP/Common/MyWindows.h index 139a4e8..c40767f 100644 --- a/CPP/Common/MyWindows.h +++ b/CPP/Common/MyWindows.h @@ -6,6 +6,7 @@ #ifdef _WIN32 #include +#include #ifdef UNDER_CE #undef VARIANT_TRUE diff --git a/CPP/Windows/FileDir.cpp b/CPP/Windows/FileDir.cpp index da71b71..dae9f93 100644 --- a/CPP/Windows/FileDir.cpp +++ b/CPP/Windows/FileDir.cpp @@ -14,6 +14,8 @@ extern bool g_IsNT; #endif +static CFSTR kTempDirName = FTEXT("TEMP"); + using namespace NWindows; using namespace NFile; using namespace NName; @@ -67,6 +69,36 @@ bool GetSystemDir(FString &path) } return (needLength > 0 && needLength <= MAX_PATH); } + +bool GetAppDataDir(FString &path) +{ + HRESULT hResult; + static const int FolderId[] = { CSIDL_LOCAL_APPDATA, CSIDL_APPDATA, CSIDL_PROFILE, NULL }; + for(size_t i = 0; i < 3; ++i) + { + #ifndef _UNICODE + if (!g_IsNT) + { + TCHAR s[MAX_PATH + 2]; + s[0] = 0; + hResult = ::SHGetFolderPath(NULL, FolderId[i] | CSIDL_FLAG_CREATE, NULL, 0, s); + path = fas2fs(s); + } + else + #endif + { + WCHAR s[MAX_PATH + 2]; + s[0] = 0; + hResult = ::SHGetFolderPathW(NULL, FolderId[i] | CSIDL_FLAG_CREATE, NULL, 0, s); + path = us2fs(s); + } + if(hResult == S_OK) + { + return true; /*success*/ + } + } + return false; +} #endif bool SetDirTime(CFSTR path, const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime) @@ -566,7 +598,7 @@ bool MyGetTempPath(FString &path) { WCHAR s[MAX_PATH + 2]; s[0] = 0; - needLength = ::GetTempPathW(MAX_PATH + 1, s);; + needLength = ::GetTempPathW(MAX_PATH + 1, s); path = us2fs(s); } return (needLength > 0 && needLength <= MAX_PATH); @@ -625,6 +657,35 @@ static bool CreateTempFile(CFSTR prefix, bool addRandom, FString &path, NIO::COu return false; } +static bool CreateTempFileSafely(CFSTR prefix, bool addRandom, FString &path, NIO::COutFile *outFile) +{ + FString tempPath; + if (MyGetTempPath(tempPath)) + { + if (CreateTempFile(tempPath + prefix, addRandom, path, outFile)) + { + return true; + } + } + for(Byte retry = 0; retry < 2; ++retry) + { + if (retry ? GetWindowsDir(tempPath) : GetAppDataDir(tempPath)) + { + tempPath.Add_PathSepar(); + tempPath += kTempDirName; + if(CreateComplexDir(tempPath)) + { + tempPath.Add_PathSepar(); + if (CreateTempFile(tempPath + prefix, addRandom, path, outFile)) + { + return true; + } + } + } + } + return false; +} + bool CTempFile::Create(CFSTR prefix, NIO::COutFile *outFile) { if (!Remove()) @@ -639,10 +700,7 @@ bool CTempFile::CreateRandomInTempFolder(CFSTR namePrefix, NIO::COutFile *outFil { if (!Remove()) return false; - FString tempPath; - if (!MyGetTempPath(tempPath)) - return false; - if (!CreateTempFile(tempPath + namePrefix, true, _path, outFile)) + if (!CreateTempFileSafely(namePrefix, true, _path, outFile)) return false; _mustBeDeleted = true; return true; @@ -652,8 +710,16 @@ bool CTempFile::Remove() { if (!_mustBeDeleted) return true; - _mustBeDeleted = !DeleteFileAlways(_path); - return !_mustBeDeleted; + for(UInt32 i = 0; i < 256; ++i) + { + if(DeleteFileAlways(_path)) + { + _mustBeDeleted = false; + return true; + } + ::Sleep(1); + } + return false; } bool CTempFile::MoveTo(CFSTR name, bool deleteDestBefore) @@ -670,10 +736,7 @@ bool CTempDir::Create(CFSTR prefix) { if (!Remove()) return false; - FString tempPath; - if (!MyGetTempPath(tempPath)) - return false; - if (!CreateTempFile(tempPath + prefix, true, _path, NULL)) + if (!CreateTempFileSafely(prefix, true, _path, NULL)) return false; _mustBeDeleted = true; return true; @@ -683,8 +746,16 @@ bool CTempDir::Remove() { if (!_mustBeDeleted) return true; - _mustBeDeleted = !RemoveDirWithSubItems(_path); - return !_mustBeDeleted; + for(UInt32 i = 0; i < 256; ++i) + { + if(RemoveDirWithSubItems(_path)) + { + _mustBeDeleted = false; + return true; + } + ::Sleep(1); + } + return false; } }}} diff --git a/CPP/Windows/FileDir.h b/CPP/Windows/FileDir.h index b13d1cc..1d87bbf 100644 --- a/CPP/Windows/FileDir.h +++ b/CPP/Windows/FileDir.h @@ -13,6 +13,7 @@ namespace NDir { bool GetWindowsDir(FString &path); bool GetSystemDir(FString &path); +bool GetAppDataDir(FString &path); bool SetDirTime(CFSTR path, const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime); bool SetFileAttrib(CFSTR path, DWORD attrib);