aboutsummaryrefslogtreecommitdiff
path: root/CPP/7zip/Bundles/SFXSetup/SfxSetup.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'CPP/7zip/Bundles/SFXSetup/SfxSetup.cpp')
-rw-r--r--CPP/7zip/Bundles/SFXSetup/SfxSetup.cpp356
1 files changed, 356 insertions, 0 deletions
diff --git a/CPP/7zip/Bundles/SFXSetup/SfxSetup.cpp b/CPP/7zip/Bundles/SFXSetup/SfxSetup.cpp
new file mode 100644
index 0000000..202c262
--- /dev/null
+++ b/CPP/7zip/Bundles/SFXSetup/SfxSetup.cpp
@@ -0,0 +1,356 @@
+// Main.cpp
+
+#include "StdAfx.h"
+
+#include "../../../Common/MyInitGuid.h"
+
+#include "../../../Common/CommandLineParser.h"
+#include "../../../Common/StringConvert.h"
+#include "../../../Common/TextConfig.h"
+
+#include "../../../Windows/DLL.h"
+#include "../../../Windows/ErrorMsg.h"
+#include "../../../Windows/FileDir.h"
+#include "../../../Windows/FileFind.h"
+#include "../../../Windows/FileIO.h"
+#include "../../../Windows/FileName.h"
+#include "../../../Windows/NtCheck.h"
+#include "../../../Windows/ResourceString.h"
+
+#include "../../UI/Explorer/MyMessages.h"
+
+#include "ExtractEngine.h"
+
+#include "resource.h"
+
+using namespace NWindows;
+using namespace NFile;
+using namespace NDir;
+
+HINSTANCE g_hInstance;
+
+static CFSTR kTempDirPrefix = FTEXT("7zS");
+
+#define _SHELL_EXECUTE
+
+static bool ReadDataString(CFSTR fileName, LPCSTR startID,
+ LPCSTR endID, AString &stringResult)
+{
+ stringResult.Empty();
+ NIO::CInFile inFile;
+ if (!inFile.Open(fileName))
+ return false;
+ const int kBufferSize = (1 << 12);
+
+ Byte buffer[kBufferSize];
+ int signatureStartSize = MyStringLen(startID);
+ int signatureEndSize = MyStringLen(endID);
+
+ UInt32 numBytesPrev = 0;
+ bool writeMode = false;
+ UInt64 posTotal = 0;
+ for (;;)
+ {
+ if (posTotal > (1 << 20))
+ return (stringResult.IsEmpty());
+ UInt32 numReadBytes = kBufferSize - numBytesPrev;
+ UInt32 processedSize;
+ if (!inFile.Read(buffer + numBytesPrev, numReadBytes, processedSize))
+ return false;
+ if (processedSize == 0)
+ return true;
+ UInt32 numBytesInBuffer = numBytesPrev + processedSize;
+ UInt32 pos = 0;
+ for (;;)
+ {
+ if (writeMode)
+ {
+ if (pos > numBytesInBuffer - signatureEndSize)
+ break;
+ if (memcmp(buffer + pos, endID, signatureEndSize) == 0)
+ return true;
+ char b = buffer[pos];
+ if (b == 0)
+ return false;
+ stringResult += b;
+ pos++;
+ }
+ else
+ {
+ if (pos > numBytesInBuffer - signatureStartSize)
+ break;
+ if (memcmp(buffer + pos, startID, signatureStartSize) == 0)
+ {
+ writeMode = true;
+ pos += signatureStartSize;
+ }
+ else
+ pos++;
+ }
+ }
+ numBytesPrev = numBytesInBuffer - pos;
+ posTotal += pos;
+ memmove(buffer, buffer + pos, numBytesPrev);
+ }
+}
+
+static char kStartID[] = ",!@Install@!UTF-8!";
+static char kEndID[] = ",!@InstallEnd@!";
+
+class CInstallIDInit
+{
+public:
+ CInstallIDInit()
+ {
+ kStartID[0] = ';';
+ kEndID[0] = ';';
+ };
+} g_CInstallIDInit;
+
+
+#define NT_CHECK_FAIL_ACTION ShowErrorMessage(L"Unsupported Windows version"); return 1;
+
+static void ShowErrorMessageSpec(const UString &name)
+{
+ UString message = NError::MyFormatMessage(::GetLastError());
+ int pos = message.Find(L"%1");
+ if (pos >= 0)
+ {
+ message.Delete(pos, 2);
+ message.Insert(pos, name);
+ }
+ ShowErrorMessage(NULL, message);
+}
+
+int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */,
+ #ifdef UNDER_CE
+ LPWSTR
+ #else
+ LPSTR
+ #endif
+ /* lpCmdLine */,int /* nCmdShow */)
+{
+ g_hInstance = (HINSTANCE)hInstance;
+
+ NT_CHECK
+
+ // InitCommonControls();
+
+ UString archiveName, switches;
+ #ifdef _SHELL_EXECUTE
+ UString executeFile, executeParameters;
+ #endif
+ NCommandLineParser::SplitCommandLine(GetCommandLineW(), archiveName, switches);
+
+ FString fullPath;
+ NDLL::MyGetModuleFileName(fullPath);
+
+ switches.Trim();
+ bool assumeYes = false;
+ if (MyStringCompareNoCase_N(switches, L"-y", 2) == 0)
+ {
+ assumeYes = true;
+ switches = switches.Ptr(2);
+ switches.Trim();
+ }
+
+ AString config;
+ if (!ReadDataString(fullPath, kStartID, kEndID, config))
+ {
+ if (!assumeYes)
+ ShowErrorMessage(L"Can't load config info");
+ return 1;
+ }
+
+ UString dirPrefix = L"." WSTRING_PATH_SEPARATOR;
+ UString appLaunched;
+ bool showProgress = true;
+ if (!config.IsEmpty())
+ {
+ CObjectVector<CTextConfigPair> pairs;
+ if (!GetTextConfig(config, pairs))
+ {
+ if (!assumeYes)
+ ShowErrorMessage(L"Config failed");
+ return 1;
+ }
+ UString friendlyName = GetTextConfigValue(pairs, L"Title");
+ UString installPrompt = GetTextConfigValue(pairs, L"BeginPrompt");
+ UString progress = GetTextConfigValue(pairs, L"Progress");
+ if (progress.IsEqualToNoCase(L"no"))
+ showProgress = false;
+ int index = FindTextConfigItem(pairs, L"Directory");
+ if (index >= 0)
+ dirPrefix = pairs[index].String;
+ if (!installPrompt.IsEmpty() && !assumeYes)
+ {
+ if (MessageBoxW(0, installPrompt, friendlyName, MB_YESNO |
+ MB_ICONQUESTION) != IDYES)
+ return 0;
+ }
+ appLaunched = GetTextConfigValue(pairs, L"RunProgram");
+
+ #ifdef _SHELL_EXECUTE
+ executeFile = GetTextConfigValue(pairs, L"ExecuteFile");
+ executeParameters = GetTextConfigValue(pairs, L"ExecuteParameters");
+ #endif
+ }
+
+ CTempDir tempDir;
+ if (!tempDir.Create(kTempDirPrefix))
+ {
+ if (!assumeYes)
+ ShowErrorMessage(L"Can not create temp folder archive");
+ return 1;
+ }
+
+ CCodecs *codecs = new CCodecs;
+ CMyComPtr<IUnknown> compressCodecsInfo = codecs;
+ HRESULT result = codecs->Load();
+ if (result != S_OK)
+ {
+ ShowErrorMessage(L"Can not load codecs");
+ return 1;
+ }
+
+ const FString tempDirPath = tempDir.GetPath();
+ // tempDirPath = L"M:\\1\\"; // to test low disk space
+ {
+ bool isCorrupt = false;
+ UString errorMessage;
+ HRESULT result = ExtractArchive(codecs, fullPath, tempDirPath, showProgress,
+ isCorrupt, errorMessage);
+
+ if (result != S_OK)
+ {
+ if (!assumeYes)
+ {
+ if (result == S_FALSE || isCorrupt)
+ {
+ NWindows::MyLoadString(IDS_EXTRACTION_ERROR_MESSAGE, errorMessage);
+ result = E_FAIL;
+ }
+ if (result != E_ABORT)
+ {
+ if (errorMessage.IsEmpty())
+ errorMessage = NError::MyFormatMessage(result);
+ ::MessageBoxW(0, errorMessage, NWindows::MyLoadString(IDS_EXTRACTION_ERROR_TITLE), MB_ICONERROR);
+ }
+ }
+ return 1;
+ }
+ }
+
+ #ifndef UNDER_CE
+ CCurrentDirRestorer currentDirRestorer;
+ if (!SetCurrentDir(tempDirPath))
+ return 1;
+ #endif
+
+ HANDLE hProcess = 0;
+#ifdef _SHELL_EXECUTE
+ if (!executeFile.IsEmpty())
+ {
+ CSysString filePath = GetSystemString(executeFile);
+ SHELLEXECUTEINFO execInfo;
+ execInfo.cbSize = sizeof(execInfo);
+ execInfo.fMask = SEE_MASK_NOCLOSEPROCESS
+ #ifndef UNDER_CE
+ | SEE_MASK_FLAG_DDEWAIT
+ #endif
+ ;
+ execInfo.hwnd = NULL;
+ execInfo.lpVerb = NULL;
+ execInfo.lpFile = filePath;
+
+ if (!switches.IsEmpty())
+ {
+ if (!executeParameters.IsEmpty())
+ executeParameters += L' ';
+ executeParameters += switches;
+ }
+
+ CSysString parametersSys = GetSystemString(executeParameters);
+ if (parametersSys.IsEmpty())
+ execInfo.lpParameters = NULL;
+ else
+ execInfo.lpParameters = parametersSys;
+
+ execInfo.lpDirectory = NULL;
+ execInfo.nShow = SW_SHOWNORMAL;
+ execInfo.hProcess = 0;
+ /* BOOL success = */ ::ShellExecuteEx(&execInfo);
+ UINT32 result = (UINT32)(UINT_PTR)execInfo.hInstApp;
+ if(result <= 32)
+ {
+ if (!assumeYes)
+ ShowErrorMessage(L"Can not open file");
+ return 1;
+ }
+ hProcess = execInfo.hProcess;
+ }
+ else
+#endif
+ {
+ if (appLaunched.IsEmpty())
+ {
+ appLaunched = L"setup.exe";
+ if (!NFind::DoesFileExist(us2fs(appLaunched)))
+ {
+ if (!assumeYes)
+ ShowErrorMessage(L"Can not find setup.exe");
+ return 1;
+ }
+ }
+
+ {
+ FString s2 = tempDirPath;
+ NName::NormalizeDirPathPrefix(s2);
+ appLaunched.Replace(L"%%T" WSTRING_PATH_SEPARATOR, fs2us(s2));
+ }
+
+ UString appNameForError = appLaunched; // actually we need to rtemove parameters also
+
+ appLaunched.Replace(L"%%T", fs2us(tempDirPath));
+
+ if (!switches.IsEmpty())
+ {
+ appLaunched += L' ';
+ appLaunched += switches;
+ }
+ STARTUPINFO startupInfo;
+ startupInfo.cb = sizeof(startupInfo);
+ startupInfo.lpReserved = 0;
+ startupInfo.lpDesktop = 0;
+ startupInfo.lpTitle = 0;
+ startupInfo.dwFlags = 0;
+ startupInfo.cbReserved2 = 0;
+ startupInfo.lpReserved2 = 0;
+
+ PROCESS_INFORMATION processInformation;
+
+ CSysString appLaunchedSys = GetSystemString(dirPrefix + appLaunched);
+
+ BOOL createResult = CreateProcess(NULL, (LPTSTR)(LPCTSTR)appLaunchedSys,
+ NULL, NULL, FALSE, 0, NULL, NULL /*tempDir.GetPath() */,
+ &startupInfo, &processInformation);
+ if (createResult == 0)
+ {
+ if (!assumeYes)
+ {
+ // we print name of exe file, if error message is
+ // ERROR_BAD_EXE_FORMAT: "%1 is not a valid Win32 application".
+ ShowErrorMessageSpec(appNameForError);
+ }
+ return 1;
+ }
+ ::CloseHandle(processInformation.hThread);
+ hProcess = processInformation.hProcess;
+ }
+ if (hProcess != 0)
+ {
+ WaitForSingleObject(hProcess, INFINITE);
+ ::CloseHandle(hProcess);
+ }
+ return 0;
+}