mirror of
https://github.com/Xevion/easy7zip.git
synced 2025-12-12 16:11:35 -06:00
4.44 beta
This commit is contained in:
committed by
Kornel Lesiński
parent
804edc5756
commit
d9666cf046
335
CPP/7zip/Bundles/SFXSetup/Main.cpp
Executable file
335
CPP/7zip/Bundles/SFXSetup/Main.cpp
Executable file
@@ -0,0 +1,335 @@
|
||||
// Main.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include <initguid.h>
|
||||
|
||||
#include "Common/StringConvert.h"
|
||||
#include "Common/Random.h"
|
||||
#include "Common/TextConfig.h"
|
||||
#include "Common/CommandLineParser.h"
|
||||
|
||||
#include "Windows/FileDir.h"
|
||||
#include "Windows/FileIO.h"
|
||||
#include "Windows/FileFind.h"
|
||||
#include "Windows/FileName.h"
|
||||
#include "Windows/DLL.h"
|
||||
#include "Windows/ResourceString.h"
|
||||
|
||||
#include "../../IPassword.h"
|
||||
#include "../../ICoder.h"
|
||||
#include "../../Archive/IArchive.h"
|
||||
#include "../../UI/Explorer/MyMessages.h"
|
||||
|
||||
// #include "../../UI/GUI/ExtractGUI.h"
|
||||
|
||||
#include "ExtractEngine.h"
|
||||
|
||||
#include "resource.h"
|
||||
|
||||
using namespace NWindows;
|
||||
|
||||
HINSTANCE g_hInstance;
|
||||
|
||||
static LPCTSTR kTempDirPrefix = TEXT("7zS");
|
||||
|
||||
#define _SHELL_EXECUTE
|
||||
|
||||
static bool ReadDataString(LPCWSTR fileName, LPCSTR startID,
|
||||
LPCSTR endID, AString &stringResult)
|
||||
{
|
||||
stringResult.Empty();
|
||||
NFile::NIO::CInFile inFile;
|
||||
if (!inFile.Open(fileName))
|
||||
return false;
|
||||
const int kBufferSize = (1 << 12);
|
||||
|
||||
Byte buffer[kBufferSize];
|
||||
int signatureStartSize = lstrlenA(startID);
|
||||
int signatureEndSize = lstrlenA(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;
|
||||
|
||||
|
||||
class CCurrentDirRestorer
|
||||
{
|
||||
CSysString m_CurrentDirectory;
|
||||
public:
|
||||
CCurrentDirRestorer()
|
||||
{ NFile::NDirectory::MyGetCurrentDirectory(m_CurrentDirectory); }
|
||||
~CCurrentDirRestorer()
|
||||
{ RestoreDirectory();}
|
||||
bool RestoreDirectory()
|
||||
{ return BOOLToBool(::SetCurrentDirectory(m_CurrentDirectory)); }
|
||||
};
|
||||
|
||||
#ifndef _UNICODE
|
||||
bool g_IsNT = false;
|
||||
static inline bool IsItWindowsNT()
|
||||
{
|
||||
OSVERSIONINFO versionInfo;
|
||||
versionInfo.dwOSVersionInfoSize = sizeof(versionInfo);
|
||||
if (!::GetVersionEx(&versionInfo))
|
||||
return false;
|
||||
return (versionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT);
|
||||
}
|
||||
#endif
|
||||
|
||||
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */, LPSTR /* lpCmdLine */,int /* nCmdShow */)
|
||||
{
|
||||
g_hInstance = (HINSTANCE)hInstance;
|
||||
#ifndef _UNICODE
|
||||
g_IsNT = IsItWindowsNT();
|
||||
#endif
|
||||
InitCommonControls();
|
||||
|
||||
UString archiveName, switches;
|
||||
#ifdef _SHELL_EXECUTE
|
||||
UString executeFile, executeParameters;
|
||||
#endif
|
||||
NCommandLineParser::SplitCommandLine(GetCommandLineW(), archiveName, switches);
|
||||
|
||||
UString fullPath;
|
||||
NDLL::MyGetModuleFileName(g_hInstance, fullPath);
|
||||
|
||||
switches.Trim();
|
||||
bool assumeYes = false;
|
||||
if (switches.Left(2).CompareNoCase(UString(L"-y")) == 0)
|
||||
{
|
||||
assumeYes = true;
|
||||
switches = switches.Mid(2);
|
||||
switches.Trim();
|
||||
}
|
||||
|
||||
AString config;
|
||||
if (!ReadDataString(fullPath, kStartID, kEndID, config))
|
||||
{
|
||||
if (!assumeYes)
|
||||
MyMessageBox(L"Can't load config info");
|
||||
return 1;
|
||||
}
|
||||
|
||||
UString dirPrefix = L".\\";
|
||||
UString appLaunched;
|
||||
bool showProgress = true;
|
||||
if (!config.IsEmpty())
|
||||
{
|
||||
CObjectVector<CTextConfigPair> pairs;
|
||||
if (!GetTextConfig(config, pairs))
|
||||
{
|
||||
if (!assumeYes)
|
||||
MyMessageBox(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.CompareNoCase(L"no") == 0)
|
||||
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") + switches;
|
||||
#endif
|
||||
}
|
||||
|
||||
NFile::NDirectory::CTempDirectory tempDir;
|
||||
if (!tempDir.Create(kTempDirPrefix))
|
||||
{
|
||||
if (!assumeYes)
|
||||
MyMessageBox(L"Can not create temp folder archive");
|
||||
return 1;
|
||||
}
|
||||
|
||||
COpenCallbackGUI openCallback;
|
||||
|
||||
UString tempDirPath = GetUnicodeString(tempDir.GetPath());
|
||||
{
|
||||
bool isCorrupt = false;
|
||||
UString errorMessage;
|
||||
HRESULT result = ExtractArchive(fullPath, tempDirPath, &openCallback, showProgress,
|
||||
isCorrupt, errorMessage);
|
||||
|
||||
if (result != S_OK)
|
||||
{
|
||||
if (!assumeYes)
|
||||
{
|
||||
if (result == S_FALSE || isCorrupt)
|
||||
{
|
||||
errorMessage = NWindows::MyLoadStringW(IDS_EXTRACTION_ERROR_MESSAGE);
|
||||
result = E_FAIL;
|
||||
}
|
||||
if (result != E_ABORT && !errorMessage.IsEmpty())
|
||||
::MessageBoxW(0, errorMessage, NWindows::MyLoadStringW(IDS_EXTRACTION_ERROR_TITLE), MB_ICONERROR);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
CCurrentDirRestorer currentDirRestorer;
|
||||
|
||||
if (!SetCurrentDirectory(tempDir.GetPath()))
|
||||
return 1;
|
||||
|
||||
HANDLE hProcess = 0;
|
||||
#ifdef _SHELL_EXECUTE
|
||||
if (!executeFile.IsEmpty())
|
||||
{
|
||||
CSysString filePath = GetSystemString(executeFile);
|
||||
SHELLEXECUTEINFO execInfo;
|
||||
execInfo.cbSize = sizeof(execInfo);
|
||||
execInfo.fMask = SEE_MASK_NOCLOSEPROCESS | SEE_MASK_FLAG_DDEWAIT;
|
||||
execInfo.hwnd = NULL;
|
||||
execInfo.lpVerb = NULL;
|
||||
execInfo.lpFile = filePath;
|
||||
|
||||
if (!switches.IsEmpty())
|
||||
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)
|
||||
MyMessageBox(L"Can not open file");
|
||||
return 1;
|
||||
}
|
||||
hProcess = execInfo.hProcess;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
if (appLaunched.IsEmpty())
|
||||
{
|
||||
appLaunched = L"setup.exe";
|
||||
if (!NFile::NFind::DoesFileExist(GetSystemString(appLaunched)))
|
||||
{
|
||||
if (!assumeYes)
|
||||
MyMessageBox(L"Can not find setup.exe");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
UString s2 = tempDirPath;
|
||||
NFile::NName::NormalizeDirPathPrefix(s2);
|
||||
appLaunched.Replace(L"%%T\\", s2);
|
||||
}
|
||||
|
||||
appLaunched.Replace(L"%%T", 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)
|
||||
ShowLastErrorMessage();
|
||||
return 1;
|
||||
}
|
||||
::CloseHandle(processInformation.hThread);
|
||||
hProcess = processInformation.hProcess;
|
||||
}
|
||||
if (hProcess != 0)
|
||||
{
|
||||
WaitForSingleObject(hProcess, INFINITE);
|
||||
::CloseHandle(hProcess);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user