1370b324cSopenharmony_ci// Main.cpp 2370b324cSopenharmony_ci 3370b324cSopenharmony_ci#include "StdAfx.h" 4370b324cSopenharmony_ci 5370b324cSopenharmony_ci#include "../../../../C/DllSecur.h" 6370b324cSopenharmony_ci 7370b324cSopenharmony_ci#include "../../../Common/MyWindows.h" 8370b324cSopenharmony_ci#include "../../../Common/MyInitGuid.h" 9370b324cSopenharmony_ci 10370b324cSopenharmony_ci#include "../../../Common/CommandLineParser.h" 11370b324cSopenharmony_ci#include "../../../Common/StringConvert.h" 12370b324cSopenharmony_ci#include "../../../Common/TextConfig.h" 13370b324cSopenharmony_ci 14370b324cSopenharmony_ci#include "../../../Windows/DLL.h" 15370b324cSopenharmony_ci#include "../../../Windows/ErrorMsg.h" 16370b324cSopenharmony_ci#include "../../../Windows/FileDir.h" 17370b324cSopenharmony_ci#include "../../../Windows/FileFind.h" 18370b324cSopenharmony_ci#include "../../../Windows/FileIO.h" 19370b324cSopenharmony_ci#include "../../../Windows/FileName.h" 20370b324cSopenharmony_ci#include "../../../Windows/NtCheck.h" 21370b324cSopenharmony_ci#include "../../../Windows/ResourceString.h" 22370b324cSopenharmony_ci 23370b324cSopenharmony_ci#include "../../UI/Explorer/MyMessages.h" 24370b324cSopenharmony_ci 25370b324cSopenharmony_ci#include "ExtractEngine.h" 26370b324cSopenharmony_ci 27370b324cSopenharmony_ci#include "resource.h" 28370b324cSopenharmony_ci 29370b324cSopenharmony_ciusing namespace NWindows; 30370b324cSopenharmony_ciusing namespace NFile; 31370b324cSopenharmony_ciusing namespace NDir; 32370b324cSopenharmony_ci 33370b324cSopenharmony_ciextern 34370b324cSopenharmony_ciHINSTANCE g_hInstance; 35370b324cSopenharmony_ciHINSTANCE g_hInstance; 36370b324cSopenharmony_ci 37370b324cSopenharmony_cistatic CFSTR const kTempDirPrefix = FTEXT("7zS"); 38370b324cSopenharmony_ci 39370b324cSopenharmony_ci#define MY_SHELL_EXECUTE 40370b324cSopenharmony_ci 41370b324cSopenharmony_cistatic bool ReadDataString(CFSTR fileName, LPCSTR startID, 42370b324cSopenharmony_ci LPCSTR endID, AString &stringResult) 43370b324cSopenharmony_ci{ 44370b324cSopenharmony_ci stringResult.Empty(); 45370b324cSopenharmony_ci NIO::CInFile inFile; 46370b324cSopenharmony_ci if (!inFile.Open(fileName)) 47370b324cSopenharmony_ci return false; 48370b324cSopenharmony_ci const size_t kBufferSize = (1 << 12); 49370b324cSopenharmony_ci 50370b324cSopenharmony_ci Byte buffer[kBufferSize]; 51370b324cSopenharmony_ci const unsigned signatureStartSize = MyStringLen(startID); 52370b324cSopenharmony_ci const unsigned signatureEndSize = MyStringLen(endID); 53370b324cSopenharmony_ci 54370b324cSopenharmony_ci size_t numBytesPrev = 0; 55370b324cSopenharmony_ci bool writeMode = false; 56370b324cSopenharmony_ci UInt64 posTotal = 0; 57370b324cSopenharmony_ci for (;;) 58370b324cSopenharmony_ci { 59370b324cSopenharmony_ci if (posTotal > (1 << 20)) 60370b324cSopenharmony_ci return (stringResult.IsEmpty()); 61370b324cSopenharmony_ci const size_t numReadBytes = kBufferSize - numBytesPrev; 62370b324cSopenharmony_ci size_t processedSize; 63370b324cSopenharmony_ci if (!inFile.ReadFull(buffer + numBytesPrev, numReadBytes, processedSize)) 64370b324cSopenharmony_ci return false; 65370b324cSopenharmony_ci if (processedSize == 0) 66370b324cSopenharmony_ci return true; 67370b324cSopenharmony_ci const size_t numBytesInBuffer = numBytesPrev + processedSize; 68370b324cSopenharmony_ci UInt32 pos = 0; 69370b324cSopenharmony_ci for (;;) 70370b324cSopenharmony_ci { 71370b324cSopenharmony_ci if (writeMode) 72370b324cSopenharmony_ci { 73370b324cSopenharmony_ci if (pos + signatureEndSize > numBytesInBuffer) 74370b324cSopenharmony_ci break; 75370b324cSopenharmony_ci if (memcmp(buffer + pos, endID, signatureEndSize) == 0) 76370b324cSopenharmony_ci return true; 77370b324cSopenharmony_ci const Byte b = buffer[pos]; 78370b324cSopenharmony_ci if (b == 0) 79370b324cSopenharmony_ci return false; 80370b324cSopenharmony_ci stringResult += (char)b; 81370b324cSopenharmony_ci pos++; 82370b324cSopenharmony_ci } 83370b324cSopenharmony_ci else 84370b324cSopenharmony_ci { 85370b324cSopenharmony_ci if (pos + signatureStartSize > numBytesInBuffer) 86370b324cSopenharmony_ci break; 87370b324cSopenharmony_ci if (memcmp(buffer + pos, startID, signatureStartSize) == 0) 88370b324cSopenharmony_ci { 89370b324cSopenharmony_ci writeMode = true; 90370b324cSopenharmony_ci pos += signatureStartSize; 91370b324cSopenharmony_ci } 92370b324cSopenharmony_ci else 93370b324cSopenharmony_ci pos++; 94370b324cSopenharmony_ci } 95370b324cSopenharmony_ci } 96370b324cSopenharmony_ci numBytesPrev = numBytesInBuffer - pos; 97370b324cSopenharmony_ci posTotal += pos; 98370b324cSopenharmony_ci memmove(buffer, buffer + pos, numBytesPrev); 99370b324cSopenharmony_ci } 100370b324cSopenharmony_ci} 101370b324cSopenharmony_ci 102370b324cSopenharmony_cistatic char kStartID[] = { ',','!','@','I','n','s','t','a','l','l','@','!','U','T','F','-','8','!', 0 }; 103370b324cSopenharmony_cistatic char kEndID[] = { ',','!','@','I','n','s','t','a','l','l','E','n','d','@','!', 0 }; 104370b324cSopenharmony_ci 105370b324cSopenharmony_cistatic struct CInstallIDInit 106370b324cSopenharmony_ci{ 107370b324cSopenharmony_ci CInstallIDInit() 108370b324cSopenharmony_ci { 109370b324cSopenharmony_ci kStartID[0] = ';'; 110370b324cSopenharmony_ci kEndID[0] = ';'; 111370b324cSopenharmony_ci } 112370b324cSopenharmony_ci} g_CInstallIDInit; 113370b324cSopenharmony_ci 114370b324cSopenharmony_ci 115370b324cSopenharmony_ci#if defined(_WIN32) && defined(_UNICODE) && !defined(_WIN64) && !defined(UNDER_CE) 116370b324cSopenharmony_ci#define NT_CHECK_FAIL_ACTION ShowErrorMessage(L"Unsupported Windows version"); return 1; 117370b324cSopenharmony_ci#endif 118370b324cSopenharmony_ci 119370b324cSopenharmony_cistatic void ShowErrorMessageSpec(const UString &name) 120370b324cSopenharmony_ci{ 121370b324cSopenharmony_ci UString message = NError::MyFormatMessage(::GetLastError()); 122370b324cSopenharmony_ci const int pos = message.Find(L"%1"); 123370b324cSopenharmony_ci if (pos >= 0) 124370b324cSopenharmony_ci { 125370b324cSopenharmony_ci message.Delete((unsigned)pos, 2); 126370b324cSopenharmony_ci message.Insert((unsigned)pos, name); 127370b324cSopenharmony_ci } 128370b324cSopenharmony_ci ShowErrorMessage(NULL, message); 129370b324cSopenharmony_ci} 130370b324cSopenharmony_ci 131370b324cSopenharmony_ciint APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */, 132370b324cSopenharmony_ci #ifdef UNDER_CE 133370b324cSopenharmony_ci LPWSTR 134370b324cSopenharmony_ci #else 135370b324cSopenharmony_ci LPSTR 136370b324cSopenharmony_ci #endif 137370b324cSopenharmony_ci /* lpCmdLine */,int /* nCmdShow */) 138370b324cSopenharmony_ci{ 139370b324cSopenharmony_ci g_hInstance = (HINSTANCE)hInstance; 140370b324cSopenharmony_ci 141370b324cSopenharmony_ci NT_CHECK 142370b324cSopenharmony_ci 143370b324cSopenharmony_ci #ifdef _WIN32 144370b324cSopenharmony_ci LoadSecurityDlls(); 145370b324cSopenharmony_ci #endif 146370b324cSopenharmony_ci 147370b324cSopenharmony_ci // InitCommonControls(); 148370b324cSopenharmony_ci 149370b324cSopenharmony_ci UString archiveName, switches; 150370b324cSopenharmony_ci #ifdef MY_SHELL_EXECUTE 151370b324cSopenharmony_ci UString executeFile, executeParameters; 152370b324cSopenharmony_ci #endif 153370b324cSopenharmony_ci NCommandLineParser::SplitCommandLine(GetCommandLineW(), archiveName, switches); 154370b324cSopenharmony_ci 155370b324cSopenharmony_ci FString fullPath; 156370b324cSopenharmony_ci NDLL::MyGetModuleFileName(fullPath); 157370b324cSopenharmony_ci 158370b324cSopenharmony_ci switches.Trim(); 159370b324cSopenharmony_ci bool assumeYes = false; 160370b324cSopenharmony_ci if (switches.IsPrefixedBy_Ascii_NoCase("-y")) 161370b324cSopenharmony_ci { 162370b324cSopenharmony_ci assumeYes = true; 163370b324cSopenharmony_ci switches = switches.Ptr(2); 164370b324cSopenharmony_ci switches.Trim(); 165370b324cSopenharmony_ci } 166370b324cSopenharmony_ci 167370b324cSopenharmony_ci AString config; 168370b324cSopenharmony_ci if (!ReadDataString(fullPath, kStartID, kEndID, config)) 169370b324cSopenharmony_ci { 170370b324cSopenharmony_ci if (!assumeYes) 171370b324cSopenharmony_ci ShowErrorMessage(L"Can't load config info"); 172370b324cSopenharmony_ci return 1; 173370b324cSopenharmony_ci } 174370b324cSopenharmony_ci 175370b324cSopenharmony_ci UString dirPrefix ("." STRING_PATH_SEPARATOR); 176370b324cSopenharmony_ci UString appLaunched; 177370b324cSopenharmony_ci bool showProgress = true; 178370b324cSopenharmony_ci if (!config.IsEmpty()) 179370b324cSopenharmony_ci { 180370b324cSopenharmony_ci CObjectVector<CTextConfigPair> pairs; 181370b324cSopenharmony_ci if (!GetTextConfig(config, pairs)) 182370b324cSopenharmony_ci { 183370b324cSopenharmony_ci if (!assumeYes) 184370b324cSopenharmony_ci ShowErrorMessage(L"Config failed"); 185370b324cSopenharmony_ci return 1; 186370b324cSopenharmony_ci } 187370b324cSopenharmony_ci const UString friendlyName = GetTextConfigValue(pairs, "Title"); 188370b324cSopenharmony_ci const UString installPrompt = GetTextConfigValue(pairs, "BeginPrompt"); 189370b324cSopenharmony_ci const UString progress = GetTextConfigValue(pairs, "Progress"); 190370b324cSopenharmony_ci if (progress.IsEqualTo_Ascii_NoCase("no")) 191370b324cSopenharmony_ci showProgress = false; 192370b324cSopenharmony_ci const int index = FindTextConfigItem(pairs, "Directory"); 193370b324cSopenharmony_ci if (index >= 0) 194370b324cSopenharmony_ci dirPrefix = pairs[index].String; 195370b324cSopenharmony_ci if (!installPrompt.IsEmpty() && !assumeYes) 196370b324cSopenharmony_ci { 197370b324cSopenharmony_ci if (MessageBoxW(NULL, installPrompt, friendlyName, MB_YESNO | 198370b324cSopenharmony_ci MB_ICONQUESTION) != IDYES) 199370b324cSopenharmony_ci return 0; 200370b324cSopenharmony_ci } 201370b324cSopenharmony_ci appLaunched = GetTextConfigValue(pairs, "RunProgram"); 202370b324cSopenharmony_ci 203370b324cSopenharmony_ci #ifdef MY_SHELL_EXECUTE 204370b324cSopenharmony_ci executeFile = GetTextConfigValue(pairs, "ExecuteFile"); 205370b324cSopenharmony_ci executeParameters = GetTextConfigValue(pairs, "ExecuteParameters"); 206370b324cSopenharmony_ci #endif 207370b324cSopenharmony_ci } 208370b324cSopenharmony_ci 209370b324cSopenharmony_ci CTempDir tempDir; 210370b324cSopenharmony_ci if (!tempDir.Create(kTempDirPrefix)) 211370b324cSopenharmony_ci { 212370b324cSopenharmony_ci if (!assumeYes) 213370b324cSopenharmony_ci ShowErrorMessage(L"Cannot create temp folder archive"); 214370b324cSopenharmony_ci return 1; 215370b324cSopenharmony_ci } 216370b324cSopenharmony_ci 217370b324cSopenharmony_ci CCodecs *codecs = new CCodecs; 218370b324cSopenharmony_ci CMyComPtr<IUnknown> compressCodecsInfo = codecs; 219370b324cSopenharmony_ci { 220370b324cSopenharmony_ci const HRESULT result = codecs->Load(); 221370b324cSopenharmony_ci if (result != S_OK) 222370b324cSopenharmony_ci { 223370b324cSopenharmony_ci ShowErrorMessage(L"Cannot load codecs"); 224370b324cSopenharmony_ci return 1; 225370b324cSopenharmony_ci } 226370b324cSopenharmony_ci } 227370b324cSopenharmony_ci 228370b324cSopenharmony_ci const FString tempDirPath = tempDir.GetPath(); 229370b324cSopenharmony_ci // tempDirPath = L"M:\\1\\"; // to test low disk space 230370b324cSopenharmony_ci { 231370b324cSopenharmony_ci bool isCorrupt = false; 232370b324cSopenharmony_ci UString errorMessage; 233370b324cSopenharmony_ci HRESULT result = ExtractArchive(codecs, fullPath, tempDirPath, showProgress, 234370b324cSopenharmony_ci isCorrupt, errorMessage); 235370b324cSopenharmony_ci 236370b324cSopenharmony_ci if (result != S_OK) 237370b324cSopenharmony_ci { 238370b324cSopenharmony_ci if (!assumeYes) 239370b324cSopenharmony_ci { 240370b324cSopenharmony_ci if (result == S_FALSE || isCorrupt) 241370b324cSopenharmony_ci { 242370b324cSopenharmony_ci NWindows::MyLoadString(IDS_EXTRACTION_ERROR_MESSAGE, errorMessage); 243370b324cSopenharmony_ci result = E_FAIL; 244370b324cSopenharmony_ci } 245370b324cSopenharmony_ci if (result != E_ABORT) 246370b324cSopenharmony_ci { 247370b324cSopenharmony_ci if (errorMessage.IsEmpty()) 248370b324cSopenharmony_ci errorMessage = NError::MyFormatMessage(result); 249370b324cSopenharmony_ci ::MessageBoxW(NULL, errorMessage, NWindows::MyLoadString(IDS_EXTRACTION_ERROR_TITLE), MB_ICONERROR); 250370b324cSopenharmony_ci } 251370b324cSopenharmony_ci } 252370b324cSopenharmony_ci return 1; 253370b324cSopenharmony_ci } 254370b324cSopenharmony_ci } 255370b324cSopenharmony_ci 256370b324cSopenharmony_ci #ifndef UNDER_CE 257370b324cSopenharmony_ci CCurrentDirRestorer currentDirRestorer; 258370b324cSopenharmony_ci if (!SetCurrentDir(tempDirPath)) 259370b324cSopenharmony_ci return 1; 260370b324cSopenharmony_ci #endif 261370b324cSopenharmony_ci 262370b324cSopenharmony_ci HANDLE hProcess = NULL; 263370b324cSopenharmony_ci#ifdef MY_SHELL_EXECUTE 264370b324cSopenharmony_ci if (!executeFile.IsEmpty()) 265370b324cSopenharmony_ci { 266370b324cSopenharmony_ci CSysString filePath (GetSystemString(executeFile)); 267370b324cSopenharmony_ci SHELLEXECUTEINFO execInfo; 268370b324cSopenharmony_ci execInfo.cbSize = sizeof(execInfo); 269370b324cSopenharmony_ci execInfo.fMask = SEE_MASK_NOCLOSEPROCESS 270370b324cSopenharmony_ci #ifndef UNDER_CE 271370b324cSopenharmony_ci | SEE_MASK_FLAG_DDEWAIT 272370b324cSopenharmony_ci #endif 273370b324cSopenharmony_ci ; 274370b324cSopenharmony_ci execInfo.hwnd = NULL; 275370b324cSopenharmony_ci execInfo.lpVerb = NULL; 276370b324cSopenharmony_ci execInfo.lpFile = filePath; 277370b324cSopenharmony_ci 278370b324cSopenharmony_ci if (!switches.IsEmpty()) 279370b324cSopenharmony_ci { 280370b324cSopenharmony_ci executeParameters.Add_Space_if_NotEmpty(); 281370b324cSopenharmony_ci executeParameters += switches; 282370b324cSopenharmony_ci } 283370b324cSopenharmony_ci 284370b324cSopenharmony_ci const CSysString parametersSys (GetSystemString(executeParameters)); 285370b324cSopenharmony_ci if (parametersSys.IsEmpty()) 286370b324cSopenharmony_ci execInfo.lpParameters = NULL; 287370b324cSopenharmony_ci else 288370b324cSopenharmony_ci execInfo.lpParameters = parametersSys; 289370b324cSopenharmony_ci 290370b324cSopenharmony_ci execInfo.lpDirectory = NULL; 291370b324cSopenharmony_ci execInfo.nShow = SW_SHOWNORMAL; 292370b324cSopenharmony_ci execInfo.hProcess = NULL; 293370b324cSopenharmony_ci /* BOOL success = */ ::ShellExecuteEx(&execInfo); 294370b324cSopenharmony_ci UINT32 result = (UINT32)(UINT_PTR)execInfo.hInstApp; 295370b324cSopenharmony_ci if (result <= 32) 296370b324cSopenharmony_ci { 297370b324cSopenharmony_ci if (!assumeYes) 298370b324cSopenharmony_ci ShowErrorMessage(L"Cannot open file"); 299370b324cSopenharmony_ci return 1; 300370b324cSopenharmony_ci } 301370b324cSopenharmony_ci hProcess = execInfo.hProcess; 302370b324cSopenharmony_ci } 303370b324cSopenharmony_ci else 304370b324cSopenharmony_ci#endif 305370b324cSopenharmony_ci { 306370b324cSopenharmony_ci if (appLaunched.IsEmpty()) 307370b324cSopenharmony_ci { 308370b324cSopenharmony_ci appLaunched = L"setup.exe"; 309370b324cSopenharmony_ci if (!NFind::DoesFileExist_FollowLink(us2fs(appLaunched))) 310370b324cSopenharmony_ci { 311370b324cSopenharmony_ci if (!assumeYes) 312370b324cSopenharmony_ci ShowErrorMessage(L"Cannot find setup.exe"); 313370b324cSopenharmony_ci return 1; 314370b324cSopenharmony_ci } 315370b324cSopenharmony_ci } 316370b324cSopenharmony_ci 317370b324cSopenharmony_ci { 318370b324cSopenharmony_ci FString s2 = tempDirPath; 319370b324cSopenharmony_ci NName::NormalizeDirPathPrefix(s2); 320370b324cSopenharmony_ci appLaunched.Replace(L"%%T" WSTRING_PATH_SEPARATOR, fs2us(s2)); 321370b324cSopenharmony_ci } 322370b324cSopenharmony_ci 323370b324cSopenharmony_ci const UString appNameForError = appLaunched; // actually we need to rtemove parameters also 324370b324cSopenharmony_ci 325370b324cSopenharmony_ci appLaunched.Replace(L"%%T", fs2us(tempDirPath)); 326370b324cSopenharmony_ci 327370b324cSopenharmony_ci if (!switches.IsEmpty()) 328370b324cSopenharmony_ci { 329370b324cSopenharmony_ci appLaunched.Add_Space(); 330370b324cSopenharmony_ci appLaunched += switches; 331370b324cSopenharmony_ci } 332370b324cSopenharmony_ci STARTUPINFO startupInfo; 333370b324cSopenharmony_ci startupInfo.cb = sizeof(startupInfo); 334370b324cSopenharmony_ci startupInfo.lpReserved = NULL; 335370b324cSopenharmony_ci startupInfo.lpDesktop = NULL; 336370b324cSopenharmony_ci startupInfo.lpTitle = NULL; 337370b324cSopenharmony_ci startupInfo.dwFlags = 0; 338370b324cSopenharmony_ci startupInfo.cbReserved2 = 0; 339370b324cSopenharmony_ci startupInfo.lpReserved2 = NULL; 340370b324cSopenharmony_ci 341370b324cSopenharmony_ci PROCESS_INFORMATION processInformation; 342370b324cSopenharmony_ci 343370b324cSopenharmony_ci const CSysString appLaunchedSys (GetSystemString(dirPrefix + appLaunched)); 344370b324cSopenharmony_ci 345370b324cSopenharmony_ci const BOOL createResult = CreateProcess(NULL, 346370b324cSopenharmony_ci appLaunchedSys.Ptr_non_const(), 347370b324cSopenharmony_ci NULL, NULL, FALSE, 0, NULL, NULL /*tempDir.GetPath() */, 348370b324cSopenharmony_ci &startupInfo, &processInformation); 349370b324cSopenharmony_ci if (createResult == 0) 350370b324cSopenharmony_ci { 351370b324cSopenharmony_ci if (!assumeYes) 352370b324cSopenharmony_ci { 353370b324cSopenharmony_ci // we print name of exe file, if error message is 354370b324cSopenharmony_ci // ERROR_BAD_EXE_FORMAT: "%1 is not a valid Win32 application". 355370b324cSopenharmony_ci ShowErrorMessageSpec(appNameForError); 356370b324cSopenharmony_ci } 357370b324cSopenharmony_ci return 1; 358370b324cSopenharmony_ci } 359370b324cSopenharmony_ci ::CloseHandle(processInformation.hThread); 360370b324cSopenharmony_ci hProcess = processInformation.hProcess; 361370b324cSopenharmony_ci } 362370b324cSopenharmony_ci if (hProcess) 363370b324cSopenharmony_ci { 364370b324cSopenharmony_ci WaitForSingleObject(hProcess, INFINITE); 365370b324cSopenharmony_ci ::CloseHandle(hProcess); 366370b324cSopenharmony_ci } 367370b324cSopenharmony_ci return 0; 368370b324cSopenharmony_ci} 369