1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/other-licenses/7zstub/src/7zip/Bundles/SFXSetup-moz/Main.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,437 @@ 1.4 +// Main.cpp 1.5 + 1.6 +#include "StdAfx.h" 1.7 + 1.8 +#include <initguid.h> 1.9 + 1.10 +#include "Common/StringConvert.h" 1.11 +#include "Common/Random.h" 1.12 +#include "Common/TextConfig.h" 1.13 +#include "Common/CommandLineParser.h" 1.14 + 1.15 +#include "Windows/FileDir.h" 1.16 +#include "Windows/FileIO.h" 1.17 +#include "Windows/FileFind.h" 1.18 +#include "Windows/FileName.h" 1.19 +#include "Windows/DLL.h" 1.20 +#include "Windows/ResourceString.h" 1.21 + 1.22 +#include "../../IPassword.h" 1.23 +#include "../../ICoder.h" 1.24 +#include "../../Archive/IArchive.h" 1.25 +#include "../../UI/Explorer/MyMessages.h" 1.26 + 1.27 +// #include "../../UI/GUI/ExtractGUI.h" 1.28 + 1.29 +#include "ExtractEngine.h" 1.30 + 1.31 +#include "resource.h" 1.32 + 1.33 +using namespace NWindows; 1.34 + 1.35 +HINSTANCE g_hInstance; 1.36 + 1.37 +static LPCTSTR kTempDirPrefix = TEXT("7zS"); 1.38 + 1.39 +#define _SHELL_EXECUTE 1.40 + 1.41 +static bool ReadDataString(LPCWSTR fileName, LPCSTR startID, 1.42 + LPCSTR endID, AString &stringResult) 1.43 +{ 1.44 + stringResult.Empty(); 1.45 + NFile::NIO::CInFile inFile; 1.46 + if (!inFile.Open(fileName)) 1.47 + return false; 1.48 + const int kBufferSize = (1 << 12); 1.49 + 1.50 + Byte buffer[kBufferSize]; 1.51 + int signatureStartSize = lstrlenA(startID); 1.52 + int signatureEndSize = lstrlenA(endID); 1.53 + 1.54 + UInt32 numBytesPrev = 0; 1.55 + bool writeMode = false; 1.56 + UInt64 posTotal = 0; 1.57 + while(true) 1.58 + { 1.59 + if (posTotal > (1 << 20)) 1.60 + return (stringResult.IsEmpty()); 1.61 + UInt32 numReadBytes = kBufferSize - numBytesPrev; 1.62 + UInt32 processedSize; 1.63 + if (!inFile.Read(buffer + numBytesPrev, numReadBytes, processedSize)) 1.64 + return false; 1.65 + if (processedSize == 0) 1.66 + return true; 1.67 + UInt32 numBytesInBuffer = numBytesPrev + processedSize; 1.68 + UInt32 pos = 0; 1.69 + while (true) 1.70 + { 1.71 + if (writeMode) 1.72 + { 1.73 + if (pos > numBytesInBuffer - signatureEndSize) 1.74 + break; 1.75 + if (memcmp(buffer + pos, endID, signatureEndSize) == 0) 1.76 + return true; 1.77 + char b = buffer[pos]; 1.78 + if (b == 0) 1.79 + return false; 1.80 + stringResult += b; 1.81 + pos++; 1.82 + } 1.83 + else 1.84 + { 1.85 + if (pos > numBytesInBuffer - signatureStartSize) 1.86 + break; 1.87 + if (memcmp(buffer + pos, startID, signatureStartSize) == 0) 1.88 + { 1.89 + writeMode = true; 1.90 + pos += signatureStartSize; 1.91 + } 1.92 + else 1.93 + pos++; 1.94 + } 1.95 + } 1.96 + numBytesPrev = numBytesInBuffer - pos; 1.97 + posTotal += pos; 1.98 + memmove(buffer, buffer + pos, numBytesPrev); 1.99 + } 1.100 +} 1.101 + 1.102 +static char kStartID[] = ",!@Install@!UTF-8!"; 1.103 +static char kEndID[] = ",!@InstallEnd@!"; 1.104 + 1.105 +class CInstallIDInit 1.106 +{ 1.107 +public: 1.108 + CInstallIDInit() 1.109 + { 1.110 + kStartID[0] = ';'; 1.111 + kEndID[0] = ';'; 1.112 + }; 1.113 +} g_CInstallIDInit; 1.114 + 1.115 + 1.116 +class CCurrentDirRestorer 1.117 +{ 1.118 + CSysString m_CurrentDirectory; 1.119 +public: 1.120 + CCurrentDirRestorer() 1.121 + { NFile::NDirectory::MyGetCurrentDirectory(m_CurrentDirectory); } 1.122 + ~CCurrentDirRestorer() 1.123 + { RestoreDirectory();} 1.124 + bool RestoreDirectory() 1.125 + { return BOOLToBool(::SetCurrentDirectory(m_CurrentDirectory)); } 1.126 +}; 1.127 + 1.128 +#ifndef _UNICODE 1.129 +bool g_IsNT = false; 1.130 +static inline bool IsItWindowsNT() 1.131 +{ 1.132 + OSVERSIONINFO versionInfo; 1.133 + versionInfo.dwOSVersionInfoSize = sizeof(versionInfo); 1.134 + if (!::GetVersionEx(&versionInfo)) 1.135 + return false; 1.136 + return (versionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT); 1.137 +} 1.138 +#endif 1.139 + 1.140 +// Delayed load libraries are loaded when the first symbol is used. 1.141 +// The following ensures that we load the delayed loaded libraries from the 1.142 +// system directory. 1.143 +struct AutoLoadSystemDependencies 1.144 +{ 1.145 + AutoLoadSystemDependencies() 1.146 + { 1.147 + static LPCWSTR delayDLLs[] = { L"dwmapi.dll", L"cryptbase.dll", 1.148 + L"SHCore.dll", L"uxtheme.dll", 1.149 + L"oleacc.dll", L"apphelp.dll" }; 1.150 + WCHAR systemDirectory[MAX_PATH + 1] = { L'\0' }; 1.151 + // If GetSystemDirectory fails we accept that we'll load the DLLs from the 1.152 + // normal search path. 1.153 + GetSystemDirectoryW(systemDirectory, MAX_PATH + 1); 1.154 + size_t systemDirLen = wcslen(systemDirectory); 1.155 + 1.156 + // Make the system directory path terminate with a slash 1.157 + if (systemDirectory[systemDirLen - 1] != L'\\' && systemDirLen) { 1.158 + systemDirectory[systemDirLen] = L'\\'; 1.159 + ++systemDirLen; 1.160 + // No need to re-NULL terminate 1.161 + } 1.162 + 1.163 + // For each known DLL ensure it is loaded from the system32 directory 1.164 + for (size_t i = 0; i < sizeof(delayDLLs) / sizeof(delayDLLs[0]); ++i) { 1.165 + size_t fileLen = wcslen(delayDLLs[i]); 1.166 + wcsncpy(systemDirectory + systemDirLen, delayDLLs[i], 1.167 + MAX_PATH - systemDirLen); 1.168 + if (systemDirLen + fileLen <= MAX_PATH) { 1.169 + systemDirectory[systemDirLen + fileLen] = L'\0'; 1.170 + } else { 1.171 + systemDirectory[MAX_PATH] = L'\0'; 1.172 + } 1.173 + LPCWSTR fullModulePath = systemDirectory; // just for code readability 1.174 + LoadLibraryW(fullModulePath); 1.175 + } 1.176 + } 1.177 +} loadDLLs; 1.178 + 1.179 +BOOL 1.180 +RemoveCurrentDirFromSearchPath() 1.181 +{ 1.182 + // kernel32.dll is in the knownDLL list so it is safe to load without a full path 1.183 + HMODULE kernel32 = LoadLibraryW(L"kernel32.dll"); 1.184 + if (!kernel32) { 1.185 + return FALSE; 1.186 + } 1.187 + 1.188 + typedef BOOL (WINAPI *SetDllDirectoryType)(LPCWSTR); 1.189 + SetDllDirectoryType SetDllDirectoryFn = 1.190 + (SetDllDirectoryType)GetProcAddress(kernel32, "SetDllDirectoryW"); 1.191 + if (!SetDllDirectoryFn) { 1.192 + FreeLibrary(kernel32); 1.193 + return FALSE; 1.194 + } 1.195 + 1.196 + // If this call fails we can't do much about it, so ignore it. 1.197 + // It is unlikely to fail and this is just a precaution anyway. 1.198 + SetDllDirectoryFn(L""); 1.199 + FreeLibrary(kernel32); 1.200 + return TRUE; 1.201 +} 1.202 + 1.203 +int APIENTRY WinMain( 1.204 + HINSTANCE hInstance, 1.205 + HINSTANCE hPrevInstance, 1.206 + LPSTR lpCmdLine, 1.207 + int nCmdShow) 1.208 +{ 1.209 + // Disable current directory from being in the search path. 1.210 + // This call does not help with implicitly loaded DLLs. 1.211 + if (!RemoveCurrentDirFromSearchPath()) { 1.212 + WCHAR minOSTitle[512] = { '\0' }; 1.213 + WCHAR minOSText[512] = { '\0' }; 1.214 + LoadStringW(NULL, IDS_MIN_OS_TITLE, minOSTitle, 1.215 + sizeof(minOSTitle) / sizeof(minOSTitle[0])); 1.216 + LoadStringW(NULL, IDS_MIN_OS_TEXT, minOSText, 1.217 + sizeof(minOSText) / sizeof(minOSText[0])); 1.218 + MessageBoxW(NULL, minOSText, minOSTitle, MB_OK | MB_ICONERROR); 1.219 + return 1; 1.220 + } 1.221 + 1.222 + g_hInstance = (HINSTANCE)hInstance; 1.223 + #ifndef _UNICODE 1.224 + g_IsNT = IsItWindowsNT(); 1.225 + #endif 1.226 + InitCommonControls(); 1.227 + 1.228 + UString archiveName, switches; 1.229 + #ifdef _SHELL_EXECUTE 1.230 + UString executeFile, executeParameters; 1.231 + #endif 1.232 + NCommandLineParser::SplitCommandLine(GetCommandLineW(), archiveName, switches); 1.233 + 1.234 + UString fullPath; 1.235 + NDLL::MyGetModuleFileName(g_hInstance, fullPath); 1.236 + 1.237 + switches.Trim(); 1.238 + bool assumeYes = false; 1.239 + if (switches.Left(2).CompareNoCase(UString(L"-y")) == 0) 1.240 + { 1.241 + assumeYes = true; 1.242 + switches = switches.Mid(2); 1.243 + switches.Trim(); 1.244 + } 1.245 + 1.246 + /* BEGIN Mozilla customizations */ 1.247 + bool showProgress = true; 1.248 + bool extractOnly = false; 1.249 + if (switches.Left(3).CompareNoCase(UString(L"-ms")) == 0 || 1.250 + switches.Left(4).CompareNoCase(UString(L"/ini")) == 0 || 1.251 + switches.Left(2).CompareNoCase(UString(L"/s")) == 0) { 1.252 + showProgress = false; 1.253 + } else if (switches.Left(12).CompareNoCase(UString(L"/extractdir=")) == 0) { 1.254 + assumeYes = true; 1.255 + showProgress = false; 1.256 + extractOnly = true; 1.257 + } 1.258 + /* END Mozilla customizations */ 1.259 + 1.260 + AString config; 1.261 + if (!ReadDataString(fullPath, kStartID, kEndID, config)) 1.262 + { 1.263 + if (!assumeYes) 1.264 + MyMessageBox(L"Can't load config info"); 1.265 + return 1; 1.266 + } 1.267 + 1.268 + UString dirPrefix = L".\\"; 1.269 + UString appLaunched; 1.270 + if (!config.IsEmpty()) 1.271 + { 1.272 + CObjectVector<CTextConfigPair> pairs; 1.273 + if (!GetTextConfig(config, pairs)) 1.274 + { 1.275 + if (!assumeYes) 1.276 + MyMessageBox(L"Config failed"); 1.277 + return 1; 1.278 + } 1.279 + UString friendlyName = GetTextConfigValue(pairs, L"Title"); 1.280 + UString installPrompt = GetTextConfigValue(pairs, L"BeginPrompt"); 1.281 + UString progress = GetTextConfigValue(pairs, L"Progress"); 1.282 + if (progress.CompareNoCase(L"no") == 0) 1.283 + showProgress = false; 1.284 + int index = FindTextConfigItem(pairs, L"Directory"); 1.285 + if (index >= 0) 1.286 + dirPrefix = pairs[index].String; 1.287 + if (!installPrompt.IsEmpty() && !assumeYes) 1.288 + { 1.289 + if (MessageBoxW(0, installPrompt, friendlyName, MB_YESNO | 1.290 + MB_ICONQUESTION) != IDYES) 1.291 + return 0; 1.292 + } 1.293 + appLaunched = GetTextConfigValue(pairs, L"RunProgram"); 1.294 + 1.295 + #ifdef _SHELL_EXECUTE 1.296 + executeFile = GetTextConfigValue(pairs, L"ExecuteFile"); 1.297 + executeParameters = GetTextConfigValue(pairs, L"ExecuteParameters") + switches; 1.298 + #endif 1.299 + } 1.300 + 1.301 + NFile::NDirectory::CTempDirectory tempDir; 1.302 + /* Mozilla customizations - Added !extractOnly */ 1.303 + if (!extractOnly && !tempDir.Create(kTempDirPrefix)) 1.304 + { 1.305 + if (!assumeYes) 1.306 + MyMessageBox(L"Can not create temp folder archive"); 1.307 + return 1; 1.308 + } 1.309 + 1.310 + /* BEGIN Mozilla customizations */ 1.311 + UString tempDirPath = (extractOnly ? switches.Mid(12) : GetUnicodeString(tempDir.GetPath())); 1.312 + /* END Mozilla customizations */ 1.313 + 1.314 + COpenCallbackGUI openCallback; 1.315 + 1.316 + bool isCorrupt = false; 1.317 + UString errorMessage; 1.318 + HRESULT result = ExtractArchive(fullPath, tempDirPath, &openCallback, showProgress, 1.319 + isCorrupt, errorMessage); 1.320 + 1.321 + if (result != S_OK) 1.322 + { 1.323 + if (!assumeYes) 1.324 + { 1.325 + if (result == S_FALSE || isCorrupt) 1.326 + { 1.327 + errorMessage = NWindows::MyLoadStringW(IDS_EXTRACTION_ERROR_MESSAGE); 1.328 + result = E_FAIL; 1.329 + } 1.330 + if (result != E_ABORT && !errorMessage.IsEmpty()) 1.331 + ::MessageBoxW(0, errorMessage, NWindows::MyLoadStringW(IDS_EXTRACTION_ERROR_TITLE), MB_ICONERROR); 1.332 + } 1.333 + return 1; 1.334 + } 1.335 + 1.336 + /* BEGIN Mozilla customizations */ 1.337 + // The code immediately above handles the error case for extraction. 1.338 + if (extractOnly) { 1.339 + return 0; 1.340 + } 1.341 + /* END Mozilla customizations */ 1.342 + 1.343 + CCurrentDirRestorer currentDirRestorer; 1.344 + 1.345 + if (!SetCurrentDirectory(tempDir.GetPath())) 1.346 + return 1; 1.347 + 1.348 + HANDLE hProcess = 0; 1.349 +#ifdef _SHELL_EXECUTE 1.350 + if (!executeFile.IsEmpty()) 1.351 + { 1.352 + CSysString filePath = GetSystemString(executeFile); 1.353 + SHELLEXECUTEINFO execInfo; 1.354 + execInfo.cbSize = sizeof(execInfo); 1.355 + execInfo.fMask = SEE_MASK_NOCLOSEPROCESS | SEE_MASK_FLAG_DDEWAIT; 1.356 + execInfo.hwnd = NULL; 1.357 + execInfo.lpVerb = NULL; 1.358 + execInfo.lpFile = filePath; 1.359 + 1.360 + if (!switches.IsEmpty()) 1.361 + executeParameters += switches; 1.362 + 1.363 + CSysString parametersSys = GetSystemString(executeParameters); 1.364 + if (parametersSys.IsEmpty()) 1.365 + execInfo.lpParameters = NULL; 1.366 + else 1.367 + execInfo.lpParameters = parametersSys; 1.368 + 1.369 + execInfo.lpDirectory = NULL; 1.370 + execInfo.nShow = SW_SHOWNORMAL; 1.371 + execInfo.hProcess = 0; 1.372 + bool success = BOOLToBool(::ShellExecuteEx(&execInfo)); 1.373 + result = (UINT32)execInfo.hInstApp; 1.374 + if(result <= 32) 1.375 + { 1.376 + if (!assumeYes) 1.377 + MyMessageBox(L"Can not open file"); 1.378 + return 1; 1.379 + } 1.380 + hProcess = execInfo.hProcess; 1.381 + } 1.382 + else 1.383 +#endif 1.384 + { 1.385 + if (appLaunched.IsEmpty()) 1.386 + { 1.387 + appLaunched = L"setup.exe"; 1.388 + if (!NFile::NFind::DoesFileExist(GetSystemString(appLaunched))) 1.389 + { 1.390 + if (!assumeYes) 1.391 + MyMessageBox(L"Can not find setup.exe"); 1.392 + return 1; 1.393 + } 1.394 + } 1.395 + 1.396 + { 1.397 + UString s2 = tempDirPath; 1.398 + NFile::NName::NormalizeDirPathPrefix(s2); 1.399 + appLaunched.Replace(L"%%T\\", s2); 1.400 + } 1.401 + 1.402 + appLaunched.Replace(L"%%T", tempDirPath); 1.403 + 1.404 + if (!switches.IsEmpty()) 1.405 + { 1.406 + appLaunched += L' '; 1.407 + appLaunched += switches; 1.408 + } 1.409 + STARTUPINFO startupInfo; 1.410 + startupInfo.cb = sizeof(startupInfo); 1.411 + startupInfo.lpReserved = 0; 1.412 + startupInfo.lpDesktop = 0; 1.413 + startupInfo.lpTitle = 0; 1.414 + startupInfo.dwFlags = 0; 1.415 + startupInfo.cbReserved2 = 0; 1.416 + startupInfo.lpReserved2 = 0; 1.417 + 1.418 + PROCESS_INFORMATION processInformation; 1.419 + 1.420 + CSysString appLaunchedSys = GetSystemString(dirPrefix + appLaunched); 1.421 + 1.422 + BOOL createResult = CreateProcess(NULL, (LPTSTR)(LPCTSTR)appLaunchedSys, 1.423 + NULL, NULL, FALSE, 0, NULL, NULL /*tempDir.GetPath() */, 1.424 + &startupInfo, &processInformation); 1.425 + if (createResult == 0) 1.426 + { 1.427 + if (!assumeYes) 1.428 + ShowLastErrorMessage(); 1.429 + return 1; 1.430 + } 1.431 + ::CloseHandle(processInformation.hThread); 1.432 + hProcess = processInformation.hProcess; 1.433 + } 1.434 + if (hProcess != 0) 1.435 + { 1.436 + WaitForSingleObject(hProcess, INFINITE); 1.437 + ::CloseHandle(hProcess); 1.438 + } 1.439 + return 0; 1.440 +}