Files
easy7zip/7zip/Bundles/SFXSetup/Main.cpp
Igor Pavlov 8c1b5c7b7e 3.13
2016-05-28 00:15:41 +01:00

236 lines
5.8 KiB
C++
Executable File

// 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 "../../IPassword.h"
#include "../../ICoder.h"
#include "../../Archive/IArchive.h"
#include "../../UI/Explorer/MyMessages.h"
#include "ExtractEngine.h"
HINSTANCE g_hInstance;
using namespace NWindows;
static LPCTSTR kTempDirPrefix = TEXT("7zS");
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;
while(true)
{
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;
while (true)
{
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)); }
};
int APIENTRY WinMain(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
InitCommonControls();
g_hInstance = (HINSTANCE)hInstance;
UString archiveName, switches;
NCommandLineParser::SplitCommandLine(GetCommandLineW(), archiveName, switches);
UString fullPath;
NDLL::MyGetModuleFileName(g_hInstance, fullPath);
AString config;
if (!ReadDataString(fullPath, kStartID, kEndID, config))
{
MyMessageBox(L"Can't load config info");
return 1;
}
switches.Trim();
bool assumeYes = false;
if (switches.Left(2).CompareNoCase(UString(L"-y")) == 0)
{
assumeYes = true;
switches = switches.Mid(2);
switches.Trim();
}
UString appLaunched;
if (!config.IsEmpty())
{
CObjectVector<CTextConfigPair> pairs;
if (!GetTextConfig(config, pairs))
{
MyMessageBox(L"Config failed");
return 1;
}
UString friendlyName = GetTextConfigValue(pairs, L"Title");
UString installPrompt = GetTextConfigValue(pairs, L"BeginPrompt");
if (!installPrompt.IsEmpty() && !assumeYes)
{
if (MessageBoxW(0, installPrompt, friendlyName, MB_YESNO |
MB_ICONQUESTION) != IDYES)
return 0;
}
appLaunched = GetTextConfigValue(pairs, L"RunProgram");
}
NFile::NDirectory::CTempDirectory tempDir;
if (!tempDir.Create(kTempDirPrefix))
{
MyMessageBox(L"Can not create temp folder archive");
return 1;
}
HRESULT result = ExtractArchive(fullPath, GetUnicodeString(tempDir.GetPath()));
if (result != S_OK)
{
if (result == S_FALSE)
MyMessageBox(L"Can not open archive");
else if (result != E_ABORT)
ShowErrorMessage(result);
return 1;
}
CCurrentDirRestorer currentDirRestorer;
if (!SetCurrentDirectory(tempDir.GetPath()))
return 1;
if (appLaunched.IsEmpty())
{
appLaunched = L"Setup.exe";
if (!NFile::NFind::DoesFileExist(GetSystemString(appLaunched)))
return 1;
}
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 shortPath;
if (!NFile::NDirectory::MyGetShortPathName(tempDir.GetPath(), shortPath))
return 1;
UString appLaunchedSysU = appLaunched;
appLaunchedSysU.Replace(TEXT(L"%%T"), GetUnicodeString(shortPath));
appLaunchedSysU += L' ';
appLaunchedSysU += switches;
CSysString tempDirPathNormalized = shortPath;
NFile::NName::NormalizeDirPathPrefix(shortPath);
// CSysString appLaunchedSys = shortPath + GetSystemString(appLaunchedSysU);
CSysString appLaunchedSys = CSysString(TEXT(".\\")) + GetSystemString(appLaunchedSysU);
BOOL createResult = CreateProcess(NULL, (LPTSTR)(LPCTSTR)appLaunchedSys,
NULL, NULL, FALSE, 0, NULL, NULL /*tempDir.GetPath() */,
&startupInfo, &processInformation);
if (createResult == 0)
{
ShowLastErrorMessage();
return 1;
}
WaitForSingleObject(processInformation.hProcess, INFINITE);
::CloseHandle(processInformation.hThread);
::CloseHandle(processInformation.hProcess);
return 0;
}