other-licenses/7zstub/src/7zip/Bundles/SFXSetup-moz/Main.cpp

changeset 0
6474c204b198
     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 +}

mercurial