mirror of
https://github.com/Xevion/easy7zip.git
synced 2025-12-11 10:07:11 -06:00
311 lines
7.3 KiB
C++
Executable File
311 lines
7.3 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 "../../UI/GUI/ExtractGUI.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)); }
|
|
};
|
|
|
|
#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;
|
|
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();
|
|
}
|
|
|
|
#ifdef _SHELL_EXECUTE
|
|
bool executeMode = false;
|
|
#endif
|
|
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");
|
|
#ifdef _SHELL_EXECUTE
|
|
if (appLaunched.IsEmpty())
|
|
{
|
|
executeMode = true;
|
|
appLaunched = GetTextConfigValue(pairs, L"Execute");
|
|
}
|
|
#endif
|
|
}
|
|
|
|
NFile::NDirectory::CTempDirectory tempDir;
|
|
if (!tempDir.Create(kTempDirPrefix))
|
|
{
|
|
MyMessageBox(L"Can not create temp folder archive");
|
|
return 1;
|
|
}
|
|
|
|
COpenCallbackGUI openCallback;
|
|
|
|
UString tempDirPath = GetUnicodeString(tempDir.GetPath());
|
|
HRESULT result = ExtractArchive(fullPath, tempDirPath, &openCallback);
|
|
|
|
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)))
|
|
{
|
|
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);
|
|
|
|
|
|
HANDLE hProcess = 0;
|
|
#ifdef _SHELL_EXECUTE
|
|
if (executeMode)
|
|
{
|
|
CSysString filePath = GetSystemString(appLaunched);
|
|
SHELLEXECUTEINFO execInfo;
|
|
execInfo.cbSize = sizeof(execInfo);
|
|
execInfo.fMask = SEE_MASK_NOCLOSEPROCESS | SEE_MASK_FLAG_DDEWAIT;
|
|
execInfo.hwnd = NULL;
|
|
execInfo.lpVerb = NULL;
|
|
execInfo.lpFile = filePath;
|
|
|
|
CSysString switchesSys = GetSystemString(switches);
|
|
if (switchesSys.IsEmpty())
|
|
execInfo.lpParameters = NULL;
|
|
else
|
|
execInfo.lpParameters = switchesSys;
|
|
|
|
execInfo.lpDirectory = NULL;
|
|
execInfo.nShow = SW_SHOWNORMAL;
|
|
execInfo.hProcess = 0;
|
|
bool success = BOOLToBool(::ShellExecuteEx(&execInfo));
|
|
result = (UINT32)execInfo.hInstApp;
|
|
if(result <= 32)
|
|
{
|
|
MyMessageBox(L"Can not open file");
|
|
return 1;
|
|
}
|
|
hProcess = execInfo.hProcess;
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
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 = CSysString(TEXT(".\\")) + GetSystemString(appLaunched);
|
|
|
|
BOOL createResult = CreateProcess(NULL, (LPTSTR)(LPCTSTR)appLaunchedSys,
|
|
NULL, NULL, FALSE, 0, NULL, NULL /*tempDir.GetPath() */,
|
|
&startupInfo, &processInformation);
|
|
if (createResult == 0)
|
|
{
|
|
ShowLastErrorMessage();
|
|
return 1;
|
|
}
|
|
::CloseHandle(processInformation.hThread);
|
|
hProcess = processInformation.hProcess;
|
|
}
|
|
if (hProcess != 0)
|
|
{
|
|
WaitForSingleObject(hProcess, INFINITE);
|
|
::CloseHandle(hProcess);
|
|
}
|
|
return 0;
|
|
}
|