Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(991)

Unified Diff: mi_exe_stub/mi.cc

Issue 624713003: Keep only base/extractor.[cc|h]. (Closed) Base URL: https://chromium.googlesource.com/external/omaha.git@master
Patch Set: Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « mi_exe_stub/build.scons ('k') | mi_exe_stub/mi.grh » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: mi_exe_stub/mi.cc
diff --git a/mi_exe_stub/mi.cc b/mi_exe_stub/mi.cc
deleted file mode 100644
index 474cb99b4437078ff8cd46d41c413006648b0aee..0000000000000000000000000000000000000000
--- a/mi_exe_stub/mi.cc
+++ /dev/null
@@ -1,501 +0,0 @@
-// Copyright 2006-2009 Google Inc.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-// ========================================================================
-//
-// Implementation of the metainstaller logic.
-// Untars a tarball and executes the extracted executable.
-// If no command line is specified, "/install" is passed to the executable
-// along with a .gup file if one is extracted.
-// If found, the contents of the signature tag are also passed to the
-// executable unmodified.
-
-#include <tchar.h>
-#include <atlsimpcoll.h>
-#include <atlstr.h>
-#include <shellapi.h>
-#include <shlwapi.h>
-#include <windows.h>
-
-#pragma warning(push)
-// C4310: cast truncates constant value
-#pragma warning(disable : 4310)
-#include "base/basictypes.h"
-#pragma warning(pop)
-#include "base/scoped_ptr.h"
-#include "omaha/base/constants.h"
-#include "omaha/base/error.h"
-#include "omaha/base/extractor.h"
-#include "omaha/base/scoped_any.h"
-#include "omaha/base/system_info.h"
-#include "omaha/common/const_cmd_line.h"
-#include "omaha/mi_exe_stub/process.h"
-#include "omaha/mi_exe_stub/mi.grh"
-#include "omaha/mi_exe_stub/tar.h"
-extern "C" {
-#include "third_party/lzma/v4_65/files/C/Bcj2.h"
-#include "third_party/lzma/v4_65/files/C/LzmaDec.h"
-}
-
-namespace omaha {
-
-// Resource ID of the goopdate payload inside the meta-installer.
-#define IDR_PAYLOAD 102
-
-namespace {
-
-HRESULT HandleError(HRESULT hr);
-
-// The function assumes that the extractor has already been opened.
-// The buffer must be deleted by the caller.
-char* ReadTag(TagExtractor* extractor) {
- const int kMaxTagLength = 0x10000; // 64KB
-
- int tag_buffer_size = 0;
- if (!extractor->ExtractTag(NULL, &tag_buffer_size)) {
- return NULL;
- }
- if (!tag_buffer_size || (tag_buffer_size >= kMaxTagLength)) {
- return NULL;
- }
-
- scoped_array<char> tag_buffer(new char[tag_buffer_size]);
- if (!tag_buffer.get()) {
- return NULL;
- }
-
- if (!extractor->ExtractTag(tag_buffer.get(), &tag_buffer_size)) {
- _ASSERTE(false);
- return NULL;
- }
-
- // Do a sanity check of the tag string. The double quote '"'
- // is a special character that should not be included in the tag string.
- for (const char* tag_char = tag_buffer.get(); *tag_char; ++tag_char) {
- if (*tag_char == '"') {
- _ASSERTE(false);
- return NULL;
- }
- }
-
- return tag_buffer.release();
-}
-
-// Extract the tag containing the extra information written by the server.
-// The memory returned by the function will have to be freed using delete[]
-// operator.
-char* ExtractTag(const TCHAR* module_file_name) {
- if (!module_file_name) {
- return NULL;
- }
-
- TagExtractor extractor;
- if (!extractor.OpenFile(module_file_name)) {
- return NULL;
- }
- char* ret = ReadTag(&extractor);
- extractor.CloseFile();
-
- return ret;
-}
-
-class MetaInstaller {
- public:
- MetaInstaller(HINSTANCE instance, LPCSTR cmd_line)
- : instance_(instance),
- cmd_line_(cmd_line),
- exit_code_(0) {
- }
-
- ~MetaInstaller() {
- // When a crash happens while running GoogleUpdate and breakpad gets it
- // GooogleUpdate.exe is started with the /report to report the crash.
- // In a crash, the temp directory and the contained files can't be deleted.
- if (exit_code_ != GOOPDATE_E_CRASH) {
- CleanUpTempDirectory();
- }
- }
-
- int ExtractAndRun() {
- if (CreateUniqueTempDirectory() != 0) {
- return -1;
- }
- scoped_hfile tarball_file(ExtractTarballToTempLocation());
- if (!valid(tarball_file)) {
- return -1;
- }
-
- // Extract files from the archive and run the first EXE we find in it.
- Tar tar(temp_dir_, get(tarball_file), true);
- tar.SetCallback(TarFileCallback, this);
- if (!tar.ExtractToDir()) {
- return -1;
- }
-
- exit_code_ = ULONG_MAX;
- if (!exe_path_.IsEmpty()) {
- // Build the command line. There are three scenarios we consider:
- // 1. Run by the user, in which case the MI does not receive any
- // argument on its command line. In this case the command line
- // to run is: "exe_path" /install [["]manifest["]]
- // 2. Run with command line arguments. The tag, if present, will be
- // appended to the command line.
- // The command line is: "exe_path" args <tag>
- // For example, pass "/silent /install" to the metainstaller to
- // initiate a silent install using the extra args in the tag.
- // If a command line does not take a tag or a custom tag is needed,
- // use an untagged file.
- CString command_line(exe_path_);
- ::PathQuoteSpaces(CStrBuf(command_line, MAX_PATH));
-
- scoped_array<char> tag(GetTag());
- if (cmd_line_.IsEmpty()) {
- // Run-by-user case.
- if (!tag.get()) {
- _ASSERTE(!_T("Must provide arguments with untagged metainstaller."));
- HRESULT hr = GOOPDATE_E_UNTAGGED_METAINSTALLER;
- HandleError(hr);
- return hr;
- }
- command_line.AppendFormat(_T(" /%s %s /%s"),
- kCmdLineInstallSource,
- kCmdLineInstallSource_TaggedMetainstaller,
- kCmdLineInstall);
- } else {
- command_line.AppendFormat(_T(" %s"), cmd_line_);
-
- CheckAndHandleRecoveryCase(&command_line);
- }
-
- if (tag.get()) {
- command_line.AppendFormat(_T(" \"%s\""), CString(tag.get()));
- }
-
- RunAndWait(command_line, &exit_code_);
- }
- // Propagate up the exit code of the program we have run.
- return exit_code_;
- }
-
- private:
- void CleanUpTempDirectory() {
- // Delete our temp directory and its contents.
- for (int i = 0; i != files_to_delete_.GetSize(); ++i) {
- DeleteFile(files_to_delete_[i]);
- }
- files_to_delete_.RemoveAll();
-
- ::RemoveDirectory(temp_dir_);
- temp_dir_.Empty();
- }
-
- // Determines whether this is a silent install.
- bool IsSilentInstall() {
- CString silent_argument;
- silent_argument.Format(_T("/%s"), kCmdLineSilent);
-
- return silent_argument == cmd_line_;
- }
-
- // Determines whether the MI is being invoked for recovery purposes, and,
- // if so, appends the MI's full path to the command line.
- // cmd_line_ must begin with "/recover" in order for the recovery case to be
- // detected.
- void CheckAndHandleRecoveryCase(CString* command_line) {
- _ASSERTE(command_line);
-
- CString recover_argument;
- recover_argument.Format(_T("/%s"), kCmdLineRecover);
-
- if (cmd_line_.Left(recover_argument.GetLength()) == recover_argument) {
- TCHAR current_path[MAX_PATH] = {};
- if (::GetModuleFileName(NULL, current_path, arraysize(current_path))) {
- command_line->AppendFormat(_T(" \"%s\""), current_path);
- }
- }
- }
-
- // Create a temp directory to hold the embedded setup files.
- // This is a bit of a hack: we ask the system to create a temporary
- // filename for us, and instead we use that name for a subdirectory name.
- int CreateUniqueTempDirectory() {
- ::GetTempPath(MAX_PATH, CStrBuf(temp_root_dir_, MAX_PATH));
- if (::CreateDirectory(temp_root_dir_, NULL) != 0 ||
- ::GetLastError() == ERROR_ALREADY_EXISTS) {
- if (!::GetTempFileName(temp_root_dir_,
- _T("GUM"),
- 0, // form a unique filename
- CStrBuf(temp_dir_, MAX_PATH))) {
- return -1;
- }
- // GetTempFileName() actually creates the temp file, so delete it.
- ::DeleteFile(temp_dir_);
- ::CreateDirectory(temp_dir_, NULL);
- } else {
- return -1;
- }
- return 0;
- }
-
- HANDLE ExtractTarballToTempLocation() {
- HANDLE tarball_file = INVALID_HANDLE_VALUE;
- TCHAR tarball_filename[MAX_PATH] = {0};
- if (::GetTempFileName(temp_root_dir_,
- _T("GUT"),
- 0, // form a unique filename
- tarball_filename)) {
- files_to_delete_.Add(tarball_filename);
- HRSRC res_info = ::FindResource(NULL,
- MAKEINTRESOURCE(IDR_PAYLOAD),
- _T("B"));
- if (NULL != res_info) {
- HGLOBAL resource = ::LoadResource(NULL, res_info);
- if (NULL != resource) {
- LPVOID resource_pointer = ::LockResource(resource);
- if (NULL != resource_pointer) {
- tarball_file = ::CreateFile(tarball_filename,
- GENERIC_READ | GENERIC_WRITE,
- 0,
- NULL,
- OPEN_ALWAYS,
- 0,
- NULL);
- if (INVALID_HANDLE_VALUE != tarball_file) {
- LARGE_INTEGER file_position = {};
- if (0 != DecompressBufferToFile(
- static_cast<const uint8*>(resource_pointer),
- ::SizeofResource(NULL, res_info),
- tarball_file) ||
- !::SetFilePointerEx(tarball_file, file_position, NULL,
- FILE_BEGIN)) {
- ::CloseHandle(tarball_file);
- tarball_file = INVALID_HANDLE_VALUE;
- }
- }
- }
- }
- }
- }
- return tarball_file;
- }
-
- char* GetTag() const {
- // Get this module file name.
- TCHAR module_file_name[MAX_PATH] = {};
- if (!::GetModuleFileName(instance_, module_file_name,
- arraysize(module_file_name))) {
- _ASSERTE(false);
- return NULL;
- }
-
- return ExtractTag(module_file_name);
- }
-
- static CString GetFilespec(const CString& path) {
- int pos = path.ReverseFind('\\');
- if (pos >= 0) {
- return path.Mid(pos + 1);
- }
- return path;
- }
-
- void HandleTarFile(const TCHAR* filename) {
- CString new_filename(filename);
- files_to_delete_.Add(new_filename);
- CString filespec(GetFilespec(new_filename));
- filespec.MakeLower();
-
- if (filespec.GetLength() > 4) {
- CString extension(filespec.Mid(filespec.GetLength() - 4));
-
- if (extension == _T(".exe")) {
- // We're interested in remembering only the first exe in the tarball.
- if (exe_path_.IsEmpty()) {
- exe_path_ = new_filename;
- }
- }
- }
- }
-
- static void TarFileCallback(void* context, const TCHAR* filename) {
- MetaInstaller* mi = reinterpret_cast<MetaInstaller*>(context);
- mi->HandleTarFile(filename);
- }
-
- // TODO(omaha): reimplement the relevant files in the LZMA SDK to optimize
- // for size. We'll have to release the modifications (LZMA SDK is CDDL/CDL),
- // which shouldn't be a problem.
- static void* MyAlloc(void* p, size_t size) {
- UNREFERENCED_PARAMETER(p);
- return new uint8[size];
- }
-
- static void MyFree(void* p, void* address) {
- UNREFERENCED_PARAMETER(p);
- delete[] address;
- }
-
- // Decompress the content of the memory buffer into the file
- static int DecompressBufferToFile(const uint8* packed_buffer,
- size_t packed_size,
- HANDLE file) {
- // need header and len minimally
- if (packed_size < LZMA_PROPS_SIZE + 8) {
- return -1;
- }
-
- // Note this code won't properly handle decoding large files, since uint32
- // is used in several places to count size.
- ISzAlloc allocators = { &MyAlloc, &MyFree };
- CLzmaDec lzma_state;
- LzmaDec_Construct(&lzma_state);
- LzmaDec_Allocate(&lzma_state, packed_buffer, LZMA_PROPS_SIZE, &allocators);
- LzmaDec_Init(&lzma_state);
- packed_buffer += LZMA_PROPS_SIZE;
- packed_size -= LZMA_PROPS_SIZE;
-
- // TODO(omaha): make this independent of endianness.
- uint64 unpacked_size_64 = *reinterpret_cast<const uint64*>(packed_buffer);
- size_t unpacked_size = static_cast<size_t>(unpacked_size_64);
- packed_buffer += sizeof(unpacked_size_64);
- packed_size -= sizeof(unpacked_size_64);
-
- scoped_array<uint8> unpacked_buffer(new uint8[unpacked_size]);
-
- ELzmaStatus status = static_cast<ELzmaStatus>(0);
- SRes result = LzmaDec_DecodeToBuf(
- &lzma_state,
- unpacked_buffer.get(),
- &unpacked_size,
- packed_buffer,
- &packed_size,
- LZMA_FINISH_END,
- &status);
- LzmaDec_Free(&lzma_state, &allocators);
- if (SZ_OK != result) {
- return -1;
- }
-
-#if 0
- // Reverse BCJ coding.
- uint32 x86_conversion_state;
- x86_Convert_Init(x86_conversion_state);
- x86_Convert(unpacked_buffer.get(), unpacked_size, 0, &x86_conversion_state,
- 0 /* decoding */);
-#else
- // Reverse BCJ2 coding.
- const uint8* p = unpacked_buffer.get();
- uint32 original_size = *reinterpret_cast<const uint32*>(p);
- p += sizeof(uint32); // NOLINT
- uint32 stream0_size = *reinterpret_cast<const uint32*>(p);
- p += sizeof(uint32); // NOLINT
- uint32 stream1_size = *reinterpret_cast<const uint32*>(p);
- p += sizeof(uint32); // NOLINT
- uint32 stream2_size = *reinterpret_cast<const uint32*>(p);
- p += sizeof(uint32); // NOLINT
- uint32 stream3_size = *reinterpret_cast<const uint32*>(p);
- p += sizeof(uint32); // NOLINT
-
- scoped_array<uint8> output_buffer(new uint8[original_size]);
- if (SZ_OK != Bcj2_Decode(p,
- stream0_size,
- p + stream0_size,
- stream1_size,
- p + stream0_size + stream1_size,
- stream2_size,
- p + stream0_size + stream1_size + stream2_size,
- stream3_size,
- output_buffer.get(), original_size)) {
- return 1;
- }
-#endif
-
- DWORD written;
- if (!::WriteFile(file, output_buffer.get(), original_size, &written,
- NULL) ||
- written != original_size) {
- return -1;
- }
-
- return 0;
- }
-
- HINSTANCE instance_;
- CString cmd_line_;
- CString exe_path_;
- DWORD exit_code_;
- CSimpleArray<CString> files_to_delete_;
- CString temp_dir_;
- CString temp_root_dir_;
-};
-
-HRESULT CheckOSRequirements() {
- return SystemInfo::OSWin2KSP4OrLater() ? S_OK :
- GOOPDATE_E_RUNNING_INFERIOR_WINDOWS;
-}
-
-CString GetCompanyDisplayName() {
- CString company_name;
- company_name.LoadString(IDS_FRIENDLY_COMPANY_NAME);
- _ASSERTE(!company_name.IsEmpty());
- return company_name;
-}
-
-CString GetUiTitle() {
- CString title;
- title.FormatMessage(IDS_INSTALLER_DISPLAY_NAME, GetCompanyDisplayName());
- return title;
-}
-
-HRESULT HandleError(HRESULT result) {
- _ASSERTE(FAILED(result));
- CString msg_box_text;
-
- switch (result) {
- case GOOPDATE_E_RUNNING_INFERIOR_WINDOWS:
- msg_box_text.FormatMessage(IDS_RUNNING_INFERIOR_WINDOWS,
- GetCompanyDisplayName());
- break;
-
- case GOOPDATE_E_UNTAGGED_METAINSTALLER:
- default:
- msg_box_text.LoadString(IDS_GENERIC_ERROR);
- _ASSERTE(!msg_box_text.IsEmpty());
- break;
- }
-
- ::MessageBox(NULL, msg_box_text, GetUiTitle(), MB_OK);
- return result;
-}
-
-} // namespace
-
-} // namespace omaha
-
-int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR lpCmdLine, int) {
- scoped_co_init init_com_apt;
- HRESULT hr(init_com_apt.hresult());
- if (FAILED(hr)) {
- return omaha::HandleError(hr);
- }
-
- hr = omaha::CheckOSRequirements();
- if (FAILED(hr)) {
- return omaha::HandleError(hr);
- }
-
- omaha::MetaInstaller mi(hInstance, lpCmdLine);
- int result = mi.ExtractAndRun();
- return result;
-}
-
« no previous file with comments | « mi_exe_stub/build.scons ('k') | mi_exe_stub/mi.grh » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698