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                    | 73 ++++++++++++++++++++++++++----
 CPP/Windows/FileDir.h                      |  1 +
 10 files changed, 117 insertions(+), 26 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 @@
+<?xml version="1.0" encoding="utf-8"?><assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"><compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1"><application><supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/><supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/><supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/><supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/><supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/></application></compatibility></assembly>
\ 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 <windows.h>
+#include <shlobj.h>
 
 #ifdef UNDER_CE
   #undef VARIANT_TRUE
diff --git a/CPP/Windows/FileDir.cpp b/CPP/Windows/FileDir.cpp
index da71b71..36d89fc 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;
@@ -670,10 +728,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;
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);