Commit 7510e601 authored by Etienne Pierre-Doray's avatar Etienne Pierre-Doray Committed by Commit Bot

[Setup]: Refactor error code.

This refactors UnPackArchive to return UnPackStatus instead
of GetLaastError(). Some errors don't have a clear DWORD mapping
and it's more straigthforward to return UnPackStatus as the main result,
and use it to decide success/failure at call sites.

Change-Id: I0aef82ba65a7cd134a2ecd552cee9b600f188e89
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1846312Reviewed-by: default avatarSorin Jianu <sorin@chromium.org>
Reviewed-by: default avatarGreg Thompson <grt@chromium.org>
Commit-Queue: Etienne Pierre-Doray <etiennep@chromium.org>
Cr-Commit-Position: refs/heads/master@{#709208}
parent 91ac929b
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include "base/files/file_util.h" #include "base/files/file_util.h"
#include "base/logging.h" #include "base/logging.h"
#include "base/optional.h"
#include "chrome/installer/setup/buildflags.h" #include "chrome/installer/setup/buildflags.h"
#include "chrome/installer/util/lzma_util.h" #include "chrome/installer/util/lzma_util.h"
#include "components/zucchini/zucchini.h" #include "components/zucchini/zucchini.h"
...@@ -48,12 +49,13 @@ bool ArchivePatchHelper::Uncompress(base::FilePath* last_uncompressed_file) { ...@@ -48,12 +49,13 @@ bool ArchivePatchHelper::Uncompress(base::FilePath* last_uncompressed_file) {
// UnPackArchive takes care of logging. // UnPackArchive takes care of logging.
base::FilePath output_file; base::FilePath output_file;
UnPackStatus unpack_status = UNPACK_NO_ERROR; base::Optional<DWORD> error_code;
int32_t ntstatus = 0; base::Optional<int32_t> ntstatus;
DWORD lzma_result = UnPackArchive(compressed_archive_, working_directory_, UnPackStatus unpack_status =
&output_file, &unpack_status, &ntstatus); UnPackArchive(compressed_archive_, working_directory_, &output_file,
RecordUnPackMetrics(unpack_status, ntstatus, lzma_result, consumer_); &error_code, &ntstatus);
if (lzma_result != ERROR_SUCCESS) RecordUnPackMetrics(unpack_status, ntstatus, error_code, consumer_);
if (unpack_status != UNPACK_NO_ERROR)
return false; return false;
last_uncompressed_file_ = output_file; last_uncompressed_file_ = output_file;
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include "base/metrics/histogram_macros.h" #include "base/metrics/histogram_macros.h"
#include "base/metrics/persistent_histogram_storage.h" #include "base/metrics/persistent_histogram_storage.h"
#include "base/numerics/safe_conversions.h" #include "base/numerics/safe_conversions.h"
#include "base/optional.h"
#include "base/path_service.h" #include "base/path_service.h"
#include "base/process/launch.h" #include "base/process/launch.h"
#include "base/process/memory.h" #include "base/process/memory.h"
...@@ -1098,13 +1099,13 @@ InstallStatus InstallProductsHelper(const InstallationState& original_state, ...@@ -1098,13 +1099,13 @@ InstallStatus InstallProductsHelper(const InstallationState& original_state,
// --- Background --- // --- Background ---
// ~14s (50%ile) / >3m (99%ile) // ~14s (50%ile) / >3m (99%ile)
installer_state.SetStage(UNPACKING); installer_state.SetStage(UNPACKING);
UnPackStatus unpack_status = UNPACK_NO_ERROR; base::Optional<DWORD> error_code;
int32_t ntstatus = 0; base::Optional<int32_t> ntstatus;
DWORD lzma_result = UnPackArchive(uncompressed_archive, unpack_path, NULL, UnPackStatus unpack_status = UnPackArchive(uncompressed_archive, unpack_path,
&unpack_status, &ntstatus); nullptr, &error_code, &ntstatus);
RecordUnPackMetrics(unpack_status, ntstatus, lzma_result, RecordUnPackMetrics(unpack_status, ntstatus, error_code,
UnPackConsumer::UNCOMPRESSED_CHROME_ARCHIVE); UnPackConsumer::UNCOMPRESSED_CHROME_ARCHIVE);
if (lzma_result) { if (unpack_status != UNPACK_NO_ERROR) {
installer_state.WriteInstallerResult( installer_state.WriteInstallerResult(
UNPACKING_FAILED, UNPACKING_FAILED,
IDS_INSTALL_UNCOMPRESSION_FAILED_BASE, IDS_INSTALL_UNCOMPRESSION_FAILED_BASE,
......
...@@ -701,8 +701,8 @@ int GetInstallAge(const InstallerState& installer_state) { ...@@ -701,8 +701,8 @@ int GetInstallAge(const InstallerState& installer_state) {
} }
void RecordUnPackMetrics(UnPackStatus unpack_status, void RecordUnPackMetrics(UnPackStatus unpack_status,
int32_t status, base::Optional<int32_t> ntstatus,
DWORD lzma_result, base::Optional<DWORD> error_code,
UnPackConsumer consumer) { UnPackConsumer consumer) {
std::string consumer_name = ""; std::string consumer_name = "";
...@@ -725,11 +725,16 @@ void RecordUnPackMetrics(UnPackStatus unpack_status, ...@@ -725,11 +725,16 @@ void RecordUnPackMetrics(UnPackStatus unpack_status,
std::string(std::string(kUnPackStatusMetricsName) + "_" + consumer_name), std::string(std::string(kUnPackStatusMetricsName) + "_" + consumer_name),
unpack_status, UNPACK_STATUS_COUNT); unpack_status, UNPACK_STATUS_COUNT);
base::UmaHistogramSparse( if (error_code.has_value()) {
std::string(kUnPackResultMetricsName) + "_" + consumer_name, lzma_result); base::UmaHistogramSparse(
std::string(kUnPackResultMetricsName) + "_" + consumer_name,
base::UmaHistogramSparse( *error_code);
std::string(kUnPackNTSTATUSMetricsName) + "_" + consumer_name, status); }
if (ntstatus.has_value()) {
base::UmaHistogramSparse(
std::string(kUnPackNTSTATUSMetricsName) + "_" + consumer_name,
*ntstatus);
}
} }
void RegisterEventLogProvider(const base::FilePath& install_directory, void RegisterEventLogProvider(const base::FilePath& install_directory,
......
...@@ -123,8 +123,8 @@ int GetInstallAge(const InstallerState& installer_state); ...@@ -123,8 +123,8 @@ int GetInstallAge(const InstallerState& installer_state);
// Records UMA metrics for unpack result. // Records UMA metrics for unpack result.
void RecordUnPackMetrics(UnPackStatus unpack_status, void RecordUnPackMetrics(UnPackStatus unpack_status,
int32_t status, base::Optional<int32_t> ntstatus,
DWORD lzma_result, base::Optional<DWORD> error_code,
UnPackConsumer consumer); UnPackConsumer consumer);
// Register Chrome's EventLog message provider dll. // Register Chrome's EventLog message provider dll.
......
...@@ -649,7 +649,7 @@ bool GenerateAlternateVersion(const base::FilePath& original_installer_path, ...@@ -649,7 +649,7 @@ bool GenerateAlternateVersion(const base::FilePath& original_installer_path,
// Unpack chrome.packed.7z (static build only). // Unpack chrome.packed.7z (static build only).
if (!chrome_packed_7z.empty()) { if (!chrome_packed_7z.empty()) {
if (UnPackArchive(chrome_packed_7z, work_dir.directory(), &chrome_7z, if (UnPackArchive(chrome_packed_7z, work_dir.directory(), &chrome_7z,
nullptr, nullptr) != ERROR_SUCCESS) { nullptr, nullptr) != UNPACK_NO_ERROR) {
LOG(DFATAL) << "Failed unpacking \"" << chrome_packed_7z.value() << "\""; LOG(DFATAL) << "Failed unpacking \"" << chrome_packed_7z.value() << "\"";
return false; return false;
} }
...@@ -658,7 +658,7 @@ bool GenerateAlternateVersion(const base::FilePath& original_installer_path, ...@@ -658,7 +658,7 @@ bool GenerateAlternateVersion(const base::FilePath& original_installer_path,
// Unpack chrome.7z // Unpack chrome.7z
if (UnPackArchive(chrome_7z, work_dir.directory(), nullptr, nullptr, if (UnPackArchive(chrome_7z, work_dir.directory(), nullptr, nullptr,
nullptr) != ERROR_SUCCESS) { nullptr) != UNPACK_NO_ERROR) {
LOG(DFATAL) << "Failed unpacking \"" << chrome_7z.value() << "\""; LOG(DFATAL) << "Failed unpacking \"" << chrome_7z.value() << "\"";
return false; return false;
} }
......
...@@ -4,6 +4,8 @@ ...@@ -4,6 +4,8 @@
#include "chrome/installer/util/lzma_util.h" #include "chrome/installer/util/lzma_util.h"
#include <windows.h>
#include <stddef.h> #include <stddef.h>
#include <vector> #include <vector>
...@@ -102,71 +104,62 @@ DWORD FilterPageError(const LzmaFileAllocator& file_allocator, ...@@ -102,71 +104,62 @@ DWORD FilterPageError(const LzmaFileAllocator& file_allocator,
} // namespace } // namespace
DWORD UnPackArchive(const base::FilePath& archive, UnPackStatus UnPackArchive(const base::FilePath& archive,
const base::FilePath& output_dir, const base::FilePath& output_dir,
base::FilePath* output_file, base::FilePath* output_file,
UnPackStatus* unpack_status, base::Optional<DWORD>* error_code,
int32_t* ntstatus) { base::Optional<int32_t>* ntstatus) {
VLOG(1) << "Opening archive " << archive.value(); VLOG(1) << "Opening archive " << archive.value();
LzmaUtilImpl lzma_util; LzmaUtilImpl lzma_util;
DWORD ret; UnPackStatus status;
if ((ret = lzma_util.OpenArchive(archive)) != ERROR_SUCCESS) { if ((status = lzma_util.OpenArchive(archive)) != UNPACK_NO_ERROR) {
PLOG(ERROR) << "Unable to open install archive: " << archive.value(); PLOG(ERROR) << "Unable to open install archive: " << archive.value();
} else { } else {
VLOG(1) << "Uncompressing archive to path " << output_dir.value(); VLOG(1) << "Uncompressing archive to path " << output_dir.value();
if ((ret = lzma_util.UnPack(output_dir, output_file)) != ERROR_SUCCESS) if ((status = lzma_util.UnPack(output_dir, output_file)) != UNPACK_NO_ERROR)
PLOG(ERROR) << "Unable to uncompress archive: " << archive.value(); PLOG(ERROR) << "Unable to uncompress archive: " << archive.value();
lzma_util.CloseArchive();
} }
if (unpack_status) if (error_code)
*unpack_status = lzma_util.GetUnPackStatus(); *error_code = lzma_util.GetErrorCode();
if (ntstatus) if (ntstatus)
*ntstatus = lzma_util.GetNTSTATUSCode(); *ntstatus = lzma_util.GetNTSTATUSCode();
return ret; return status;
} }
LzmaUtilImpl::LzmaUtilImpl() {} LzmaUtilImpl::LzmaUtilImpl() = default;
LzmaUtilImpl::~LzmaUtilImpl() { LzmaUtilImpl::~LzmaUtilImpl() = default;
CloseArchive();
}
DWORD LzmaUtilImpl::OpenArchive(const base::FilePath& archivePath) { UnPackStatus LzmaUtilImpl::OpenArchive(const base::FilePath& archivePath) {
// Make sure file is not already open. // Make sure file is not already open.
CloseArchive(); CloseArchive();
DWORD ret = ERROR_SUCCESS; archive_file_.Initialize(archivePath, base::File::FLAG_OPEN |
archive_handle_ = base::File::FLAG_READ |
CreateFile(archivePath.value().c_str(), GENERIC_READ, FILE_SHARE_READ, base::File::FLAG_EXCLUSIVE_WRITE);
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (archive_file_.IsValid())
if (archive_handle_ == INVALID_HANDLE_VALUE) { return UNPACK_NO_ERROR;
archive_handle_ = NULL; // The rest of the code only checks for NULL. error_code_ = ::GetLastError();
ret = GetLastError(); return archive_file_.error_details() == base::File::FILE_ERROR_NOT_FOUND
if (ret == ERROR_FILE_NOT_FOUND) ? UNPACK_ARCHIVE_NOT_FOUND
unpack_status_ = UNPACK_ARCHIVE_NOT_FOUND; : UNPACK_ARCHIVE_CANNOT_OPEN;
else
unpack_status_ = UNPACK_ARCHIVE_CANNOT_OPEN;
}
return ret;
} }
DWORD LzmaUtilImpl::UnPack(const base::FilePath& location) { UnPackStatus LzmaUtilImpl::UnPack(const base::FilePath& location) {
return UnPack(location, NULL); return UnPack(location, NULL);
} }
DWORD LzmaUtilImpl::UnPack(const base::FilePath& location, UnPackStatus LzmaUtilImpl::UnPack(const base::FilePath& location,
base::FilePath* output_file) { base::FilePath* output_file) {
if (!archive_handle_) DCHECK(archive_file_.IsValid());
return ERROR_INVALID_HANDLE;
CFileInStream archiveStream; CFileInStream archiveStream;
CLookToRead lookStream; CLookToRead lookStream;
CSzArEx db; CSzArEx db;
ISzAlloc allocImp; ISzAlloc allocImp;
ISzAlloc allocTempImp; ISzAlloc allocTempImp;
DWORD ret = ERROR_SUCCESS;
SRes sz_res = SZ_OK; SRes sz_res = SZ_OK;
archiveStream.file.handle = archive_handle_; archiveStream.file.handle = archive_file_.GetPlatformFile();
archiveStream.s.Read = SzFileReadImp; archiveStream.s.Read = SzFileReadImp;
archiveStream.s.Seek = SzFileSeekImp; archiveStream.s.Seek = SzFileSeekImp;
LookToRead_CreateVTable(&lookStream, false); LookToRead_CreateVTable(&lookStream, false);
...@@ -179,12 +172,14 @@ DWORD LzmaUtilImpl::UnPack(const base::FilePath& location, ...@@ -179,12 +172,14 @@ DWORD LzmaUtilImpl::UnPack(const base::FilePath& location,
CrcGenerateTable(); CrcGenerateTable();
SzArEx_Init(&db); SzArEx_Init(&db);
::SetLastError(ERROR_SUCCESS);
if ((sz_res = SzArEx_Open(&db, &lookStream.s, &allocImp, &allocTempImp)) != if ((sz_res = SzArEx_Open(&db, &lookStream.s, &allocImp, &allocTempImp)) !=
SZ_OK) { SZ_OK) {
LOG(ERROR) << L"Error returned by SzArchiveOpen: " << sz_res; LOG(ERROR) << L"Error returned by SzArchiveOpen: " << sz_res;
auto error_code = ::GetLastError();
unpack_status_ = UNPACK_SZAREX_OPEN_ERROR; if (error_code != ERROR_SUCCESS)
return ERROR_INVALID_HANDLE; error_code_ = error_code;
return UNPACK_SZAREX_OPEN_ERROR;
} }
Byte* outBuffer = 0; // it must be 0 before first call for each new archive Byte* outBuffer = 0; // it must be 0 before first call for each new archive
...@@ -193,41 +188,40 @@ DWORD LzmaUtilImpl::UnPack(const base::FilePath& location, ...@@ -193,41 +188,40 @@ DWORD LzmaUtilImpl::UnPack(const base::FilePath& location,
LzmaFileAllocator fileAllocator(location); LzmaFileAllocator fileAllocator(location);
unpack_status_ = UNPACK_NO_ERROR; UnPackStatus status = UNPACK_NO_ERROR;
for (unsigned int i = 0; i < db.NumFiles; i++) { for (unsigned int i = 0; i < db.NumFiles; i++) {
DWORD written; DWORD written;
size_t offset = 0; size_t offset = 0;
size_t outSizeProcessed = 0; size_t outSizeProcessed = 0;
int32_t status = 0; // STATUS_SUCCESS int32_t ntstatus = 0; // STATUS_SUCCESS
::SetLastError(ERROR_SUCCESS);
__try { __try {
if ((sz_res = if ((sz_res =
SzArEx_Extract(&db, &lookStream.s, i, &blockIndex, &outBuffer, SzArEx_Extract(&db, &lookStream.s, i, &blockIndex, &outBuffer,
&outBufferSize, &offset, &outSizeProcessed, &outBufferSize, &offset, &outSizeProcessed,
&fileAllocator, &allocTempImp)) != SZ_OK) { &fileAllocator, &allocTempImp)) != SZ_OK) {
LOG(ERROR) << L"Error returned by SzExtract: " << sz_res; LOG(ERROR) << L"Error returned by SzExtract: " << sz_res;
auto error_code = ::GetLastError();
ret = ERROR_INVALID_HANDLE; if (error_code != ERROR_SUCCESS)
unpack_status_ = UNPACK_EXTRACT_ERROR; error_code_ = error_code;
status = UNPACK_EXTRACT_ERROR;
} }
} __except(FilterPageError(fileAllocator, GetExceptionCode(), } __except(FilterPageError(fileAllocator, GetExceptionCode(),
GetExceptionInformation(), &status)) { GetExceptionInformation(), &ntstatus)) {
ret = ERROR_IO_DEVICE; ntstatus_ = ntstatus;
ntstatus_ = status; status = UNPACK_EXTRACT_EXCEPTION;
LOG(ERROR) << L"EXCEPTION_IN_PAGE_ERROR while accessing mapped memory; " LOG(ERROR) << L"EXCEPTION_IN_PAGE_ERROR while accessing mapped memory; "
L"NTSTATUS = " L"NTSTATUS = "
<< ntstatus_; << ntstatus;
unpack_status_ = UNPACK_EXTRACT_EXCEPTION;
} }
if (ret != ERROR_SUCCESS) if (status != UNPACK_NO_ERROR)
break; break;
size_t file_name_length = SzArEx_GetFileNameUtf16(&db, i, NULL); size_t file_name_length = SzArEx_GetFileNameUtf16(&db, i, NULL);
if (file_name_length < 1) { if (file_name_length < 1) {
LOG(ERROR) << L"Couldn't get file name"; LOG(ERROR) << L"Couldn't get file name";
ret = ERROR_INVALID_HANDLE; status = UNPACK_NO_FILENAME_ERROR;
unpack_status_ = UNPACK_NO_FILENAME_ERROR;
break; break;
} }
...@@ -242,7 +236,11 @@ DWORD LzmaUtilImpl::UnPack(const base::FilePath& location, ...@@ -242,7 +236,11 @@ DWORD LzmaUtilImpl::UnPack(const base::FilePath& location,
// If archive entry is directory create it and move on to the next entry. // If archive entry is directory create it and move on to the next entry.
if (SzArEx_IsDir(&db, i)) { if (SzArEx_IsDir(&db, i)) {
CreateDirectory(file_path); if (!CreateDirectory(file_path)) {
error_code_ = ::GetLastError();
status = UNPACK_CREATE_FILE_ERROR;
break;
}
continue; continue;
} }
...@@ -252,9 +250,9 @@ DWORD LzmaUtilImpl::UnPack(const base::FilePath& location, ...@@ -252,9 +250,9 @@ DWORD LzmaUtilImpl::UnPack(const base::FilePath& location,
hFile = CreateFile(file_path.value().c_str(), GENERIC_WRITE, 0, NULL, hFile = CreateFile(file_path.value().c_str(), GENERIC_WRITE, 0, NULL,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE) { if (hFile == INVALID_HANDLE_VALUE) {
ret = GetLastError(); error_code_ = ::GetLastError();
LOG(ERROR) << L"Error returned by CreateFile: " << ret; status = UNPACK_CREATE_FILE_ERROR;
unpack_status_ = UNPACK_CREATE_FILE_ERROR; PLOG(ERROR) << L"CreateFile failed";
break; break;
} }
...@@ -268,57 +266,56 @@ DWORD LzmaUtilImpl::UnPack(const base::FilePath& location, ...@@ -268,57 +266,56 @@ DWORD LzmaUtilImpl::UnPack(const base::FilePath& location,
if ((!WriteFile(hFile, outBuffer + offset + total_written, if ((!WriteFile(hFile, outBuffer + offset + total_written,
static_cast<DWORD>(write_amount), &written, nullptr)) || static_cast<DWORD>(write_amount), &written, nullptr)) ||
(written != write_amount)) { (written != write_amount)) {
ret = GetLastError(); error_code_ = ::GetLastError();
status = UNPACK_WRITE_FILE_ERROR;
PLOG(ERROR) << L"Error returned by WriteFile"; PLOG(ERROR) << L"Error returned by WriteFile";
CloseHandle(hFile); CloseHandle(hFile);
unpack_status_ = UNPACK_WRITE_FILE_ERROR;
break; break;
} }
total_written += write_amount; total_written += write_amount;
} }
// Break out of the file loop if the write loop failed. // Break out of the file loop if the write loop failed.
if (unpack_status_ != UNPACK_NO_ERROR) if (status != UNPACK_NO_ERROR)
break; break;
if (SzBitWithVals_Check(&db.MTime, i)) { if (SzBitWithVals_Check(&db.MTime, i)) {
if (!SetFileTime(hFile, NULL, NULL, if (!SetFileTime(hFile, NULL, NULL,
(const FILETIME*)(&db.MTime.Vals[i]))) { (const FILETIME*)(&db.MTime.Vals[i]))) {
ret = GetLastError(); error_code_ = ::GetLastError();
status = UNPACK_SET_FILE_TIME_ERROR;
PLOG(ERROR) << L"Error returned by SetFileTime"; PLOG(ERROR) << L"Error returned by SetFileTime";
CloseHandle(hFile); CloseHandle(hFile);
unpack_status_ = UNPACK_SET_FILE_TIME_ERROR;
break; break;
} }
} }
if (!CloseHandle(hFile)) { if (!CloseHandle(hFile)) {
ret = GetLastError(); error_code_ = ::GetLastError();
status = UNPACK_CLOSE_FILE_ERROR;
PLOG(ERROR) << L"Error returned by CloseHandle"; PLOG(ERROR) << L"Error returned by CloseHandle";
unpack_status_ = UNPACK_CLOSE_FILE_ERROR;
break; break;
} }
} // for loop } // for loop
IAlloc_Free(&fileAllocator, outBuffer); IAlloc_Free(&fileAllocator, outBuffer);
SzArEx_Free(&db, &allocImp); SzArEx_Free(&db, &allocImp);
DCHECK_EQ(ret == static_cast<DWORD>(ERROR_SUCCESS), DCHECK(status != UNPACK_NO_ERROR || !error_code_.has_value());
unpack_status_ == UNPACK_NO_ERROR); DCHECK(status != UNPACK_NO_ERROR || !ntstatus_.has_value());
return ret; return status;
} }
void LzmaUtilImpl::CloseArchive() { void LzmaUtilImpl::CloseArchive() {
if (archive_handle_) { archive_file_.Close();
CloseHandle(archive_handle_); error_code_ = base::nullopt;
archive_handle_ = NULL; ntstatus_ = base::nullopt;
}
} }
bool LzmaUtilImpl::CreateDirectory(const base::FilePath& dir) { bool LzmaUtilImpl::CreateDirectory(const base::FilePath& dir) {
bool ret = true; bool result = true;
if (directories_created_.find(dir.value()) == directories_created_.end()) { if (directories_created_.find(dir) == directories_created_.end()) {
ret = base::CreateDirectory(dir); result = base::CreateDirectory(dir);
if (ret) if (result)
directories_created_.insert(dir.value()); directories_created_.insert(dir);
} }
return ret; return result;
} }
...@@ -5,13 +5,13 @@ ...@@ -5,13 +5,13 @@
#ifndef CHROME_INSTALLER_UTIL_LZMA_UTIL_H_ #ifndef CHROME_INSTALLER_UTIL_LZMA_UTIL_H_
#define CHROME_INSTALLER_UTIL_LZMA_UTIL_H_ #define CHROME_INSTALLER_UTIL_LZMA_UTIL_H_
#include <windows.h>
#include <set> #include <set>
#include "base/files/file.h"
#include "base/files/file_path.h" #include "base/files/file_path.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/strings/string16.h" #include "base/optional.h"
#include "base/win/windows_types.h"
// The error status of LzmaUtil::Unpack which is used to publish metrics. Do not // The error status of LzmaUtil::Unpack which is used to publish metrics. Do not
// change the order. // change the order.
...@@ -32,14 +32,15 @@ enum UnPackStatus { ...@@ -32,14 +32,15 @@ enum UnPackStatus {
// Unpacks the contents of |archive| into |output_dir|. |output_file|, if not // Unpacks the contents of |archive| into |output_dir|. |output_file|, if not
// null, is populated with the name of the last (or only) member extracted from // null, is populated with the name of the last (or only) member extracted from
// the archive. Returns ERROR_SUCCESS on success. Otherwise, returns a Windows // the archive. Returns UNPACK_NO_ERROR on success. Otherwise, returns a status
// error code and populates |unpack_status| (if not null) with a status value // value indicating the operation that failed, populates |error_code| (if not
// indicating the operation that failed. // null) with a Windows error code and |ntstatus| with an exception code, if
DWORD UnPackArchive(const base::FilePath& archive, // any.
const base::FilePath& output_dir, UnPackStatus UnPackArchive(const base::FilePath& archive,
base::FilePath* output_file, const base::FilePath& output_dir,
UnPackStatus* unpack_status, base::FilePath* output_file,
int32_t* ntstatus); base::Optional<DWORD>* error_code,
base::Optional<int32_t>* ntstatus);
// A utility class that wraps LZMA SDK library. Prefer UnPackArchive over using // A utility class that wraps LZMA SDK library. Prefer UnPackArchive over using
// this class directly. // this class directly.
...@@ -48,29 +49,30 @@ class LzmaUtilImpl { ...@@ -48,29 +49,30 @@ class LzmaUtilImpl {
LzmaUtilImpl(); LzmaUtilImpl();
~LzmaUtilImpl(); ~LzmaUtilImpl();
DWORD OpenArchive(const base::FilePath& archivePath); UnPackStatus OpenArchive(const base::FilePath& archivePath);
// Unpacks the archive to the given location // Unpacks the archive to the given location
DWORD UnPack(const base::FilePath& location); UnPackStatus UnPack(const base::FilePath& location);
void CloseArchive();
// Unpacks the archive to the given location and returns the last file // Unpacks the archive to the given location and returns the last file
// extracted from archive. // extracted from archive.
DWORD UnPack(const base::FilePath& location, base::FilePath* output_file); UnPackStatus UnPack(const base::FilePath& location,
base::FilePath* output_file);
void CloseArchive();
UnPackStatus GetUnPackStatus() { return unpack_status_; } base::Optional<DWORD> GetErrorCode() { return error_code_; }
int32_t GetNTSTATUSCode() { return ntstatus_; } base::Optional<int32_t> GetNTSTATUSCode() { return ntstatus_; }
protected: protected:
bool CreateDirectory(const base::FilePath& dir); bool CreateDirectory(const base::FilePath& dir);
private: private:
HANDLE archive_handle_ = nullptr; base::File archive_file_;
std::set<base::string16> directories_created_; std::set<base::FilePath> directories_created_;
UnPackStatus unpack_status_ = UNPACK_NO_ERROR; base::Optional<DWORD> error_code_;
// Can't include ntstatus.h as it's conflicted with winnt.h // Can't include ntstatus.h as it's conflicted with winnt.h
int32_t ntstatus_ = 0; // STATUS_SUCCESS. base::Optional<int32_t> ntstatus_;
DISALLOW_COPY_AND_ASSIGN(LzmaUtilImpl); DISALLOW_COPY_AND_ASSIGN(LzmaUtilImpl);
}; };
......
...@@ -36,22 +36,21 @@ class LzmaUtilTest : public testing::Test { ...@@ -36,22 +36,21 @@ class LzmaUtilTest : public testing::Test {
TEST_F(LzmaUtilTest, OpenArchiveTest) { TEST_F(LzmaUtilTest, OpenArchiveTest) {
base::FilePath archive = data_dir_.AppendASCII("archive1.7z"); base::FilePath archive = data_dir_.AppendASCII("archive1.7z");
LzmaUtilImpl lzma_util; LzmaUtilImpl lzma_util;
EXPECT_EQ(static_cast<DWORD>(ERROR_SUCCESS), lzma_util.OpenArchive(archive)); EXPECT_EQ(UNPACK_NO_ERROR, lzma_util.OpenArchive(archive));
// We allow opening another archive (which will automatically close the first // We allow opening another archive (which will automatically close the first
// archive). // archive).
archive = data_dir_.AppendASCII("archive2.7z"); archive = data_dir_.AppendASCII("archive2.7z");
EXPECT_EQ(static_cast<DWORD>(ERROR_SUCCESS), lzma_util.OpenArchive(archive)); EXPECT_EQ(UNPACK_NO_ERROR, lzma_util.OpenArchive(archive));
// Explicitly close and open the first archive again. // Explicitly close and open the first archive again.
lzma_util.CloseArchive(); lzma_util.CloseArchive();
archive = data_dir_.AppendASCII("archive1.7z"); archive = data_dir_.AppendASCII("archive1.7z");
EXPECT_EQ(static_cast<DWORD>(ERROR_SUCCESS), lzma_util.OpenArchive(archive)); EXPECT_EQ(UNPACK_NO_ERROR, lzma_util.OpenArchive(archive));
// Make sure non-existent archive returns error. // Make sure non-existent archive returns error.
archive = data_dir_.AppendASCII("archive.non_existent.7z"); archive = data_dir_.AppendASCII("archive.non_existent.7z");
EXPECT_EQ(static_cast<DWORD>(ERROR_FILE_NOT_FOUND), EXPECT_EQ(UNPACK_ARCHIVE_NOT_FOUND, lzma_util.OpenArchive(archive));
lzma_util.OpenArchive(archive));
} }
// Test that we can extract archives successfully. // Test that we can extract archives successfully.
...@@ -64,38 +63,33 @@ TEST_F(LzmaUtilTest, UnPackTest) { ...@@ -64,38 +63,33 @@ TEST_F(LzmaUtilTest, UnPackTest) {
base::FilePath archive = data_dir_.AppendASCII("archive1.7z"); base::FilePath archive = data_dir_.AppendASCII("archive1.7z");
LzmaUtilImpl lzma_util; LzmaUtilImpl lzma_util;
EXPECT_EQ(static_cast<DWORD>(ERROR_SUCCESS), lzma_util.OpenArchive(archive)); EXPECT_EQ(UNPACK_NO_ERROR, lzma_util.OpenArchive(archive));
base::FilePath unpacked_file; base::FilePath unpacked_file;
EXPECT_EQ(static_cast<DWORD>(ERROR_SUCCESS), EXPECT_EQ(UNPACK_NO_ERROR, lzma_util.UnPack(extract_dir, &unpacked_file));
lzma_util.UnPack(extract_dir, &unpacked_file)); EXPECT_FALSE(lzma_util.GetErrorCode());
EXPECT_EQ(lzma_util.GetUnPackStatus(), UNPACK_NO_ERROR);
EXPECT_TRUE(base::PathExists(extract_dir.AppendASCII("a.exe"))); EXPECT_TRUE(base::PathExists(extract_dir.AppendASCII("a.exe")));
EXPECT_TRUE(unpacked_file == extract_dir.AppendASCII("a.exe")); EXPECT_TRUE(unpacked_file == extract_dir.AppendASCII("a.exe"));
archive = data_dir_.AppendASCII("archive2.7z"); archive = data_dir_.AppendASCII("archive2.7z");
EXPECT_EQ(static_cast<DWORD>(ERROR_SUCCESS), lzma_util.OpenArchive(archive)); EXPECT_EQ(UNPACK_NO_ERROR, lzma_util.OpenArchive(archive));
EXPECT_EQ(static_cast<DWORD>(ERROR_SUCCESS), EXPECT_EQ(UNPACK_NO_ERROR, lzma_util.UnPack(extract_dir, &unpacked_file));
lzma_util.UnPack(extract_dir, &unpacked_file));
EXPECT_TRUE(base::PathExists(extract_dir.AppendASCII("b.exe"))); EXPECT_TRUE(base::PathExists(extract_dir.AppendASCII("b.exe")));
EXPECT_TRUE(unpacked_file == extract_dir.AppendASCII("b.exe")); EXPECT_TRUE(unpacked_file == extract_dir.AppendASCII("b.exe"));
EXPECT_EQ(lzma_util.GetUnPackStatus(), UNPACK_NO_ERROR); EXPECT_FALSE(lzma_util.GetErrorCode());
lzma_util.CloseArchive(); lzma_util.CloseArchive();
archive = data_dir_.AppendASCII("invalid_archive.7z"); archive = data_dir_.AppendASCII("invalid_archive.7z");
EXPECT_EQ(static_cast<DWORD>(ERROR_INVALID_HANDLE), EXPECT_EQ(UNPACK_NO_ERROR, lzma_util.OpenArchive(archive));
lzma_util.UnPack(extract_dir, &unpacked_file)); EXPECT_EQ(UNPACK_SZAREX_OPEN_ERROR,
EXPECT_EQ(static_cast<DWORD>(ERROR_SUCCESS), lzma_util.OpenArchive(archive));
EXPECT_EQ(static_cast<DWORD>(ERROR_INVALID_HANDLE),
lzma_util.UnPack(extract_dir, &unpacked_file)); lzma_util.UnPack(extract_dir, &unpacked_file));
EXPECT_EQ(static_cast<DWORD>(ERROR_INVALID_HANDLE), EXPECT_EQ(UNPACK_SZAREX_OPEN_ERROR,
lzma_util.UnPack(extract_dir, &unpacked_file)); lzma_util.UnPack(extract_dir, &unpacked_file));
archive = data_dir_.AppendASCII("archive3.7z"); archive = data_dir_.AppendASCII("archive3.7z");
EXPECT_EQ(static_cast<DWORD>(ERROR_SUCCESS), lzma_util.OpenArchive(archive)); EXPECT_EQ(UNPACK_NO_ERROR, lzma_util.OpenArchive(archive));
EXPECT_EQ(static_cast<DWORD>(ERROR_SUCCESS), EXPECT_EQ(UNPACK_NO_ERROR, lzma_util.UnPack(extract_dir, &unpacked_file));
lzma_util.UnPack(extract_dir, &unpacked_file));
EXPECT_TRUE(base::PathExists(extract_dir.AppendASCII("archive\\a.exe"))); EXPECT_TRUE(base::PathExists(extract_dir.AppendASCII("archive\\a.exe")));
EXPECT_TRUE(base::PathExists( EXPECT_TRUE(base::PathExists(
extract_dir.AppendASCII("archive\\sub_dir\\text.txt"))); extract_dir.AppendASCII("archive\\sub_dir\\text.txt")));
...@@ -112,23 +106,21 @@ TEST_F(LzmaUtilTest, UnPackArchiveTest) { ...@@ -112,23 +106,21 @@ TEST_F(LzmaUtilTest, UnPackArchiveTest) {
base::FilePath archive = data_dir_.AppendASCII("archive1.7z"); base::FilePath archive = data_dir_.AppendASCII("archive1.7z");
base::FilePath unpacked_file; base::FilePath unpacked_file;
EXPECT_EQ( EXPECT_EQ(UNPACK_NO_ERROR, UnPackArchive(archive, extract_dir, &unpacked_file,
static_cast<DWORD>(ERROR_SUCCESS), nullptr, nullptr));
UnPackArchive(archive, extract_dir, &unpacked_file, nullptr, nullptr));
EXPECT_TRUE(base::PathExists(extract_dir.AppendASCII("a.exe"))); EXPECT_TRUE(base::PathExists(extract_dir.AppendASCII("a.exe")));
EXPECT_TRUE(unpacked_file == extract_dir.AppendASCII("a.exe")); EXPECT_TRUE(unpacked_file == extract_dir.AppendASCII("a.exe"));
archive = data_dir_.AppendASCII("archive2.7z"); archive = data_dir_.AppendASCII("archive2.7z");
EXPECT_EQ( EXPECT_EQ(UNPACK_NO_ERROR, UnPackArchive(archive, extract_dir, &unpacked_file,
static_cast<DWORD>(ERROR_SUCCESS), nullptr, nullptr));
UnPackArchive(archive, extract_dir, &unpacked_file, nullptr, nullptr));
EXPECT_TRUE(base::PathExists(extract_dir.AppendASCII("b.exe"))); EXPECT_TRUE(base::PathExists(extract_dir.AppendASCII("b.exe")));
EXPECT_TRUE(unpacked_file == extract_dir.AppendASCII("b.exe")); EXPECT_TRUE(unpacked_file == extract_dir.AppendASCII("b.exe"));
archive = data_dir_.AppendASCII("invalid_archive.7z"); archive = data_dir_.AppendASCII("invalid_archive.7z");
EXPECT_EQ( EXPECT_EQ(
static_cast<DWORD>(ERROR_INVALID_HANDLE), UNPACK_SZAREX_OPEN_ERROR,
UnPackArchive(archive, extract_dir, &unpacked_file, nullptr, nullptr)); UnPackArchive(archive, extract_dir, &unpacked_file, nullptr, nullptr));
} }
...@@ -423,20 +423,18 @@ ProcessExitResult WMain(HMODULE module) { ...@@ -423,20 +423,18 @@ ProcessExitResult WMain(HMODULE module) {
return ProcessExitResult(static_cast<DWORD>(installer::TEMP_DIR_FAILED)); return ProcessExitResult(static_cast<DWORD>(installer::TEMP_DIR_FAILED));
// Unpack the compressed archive to extract the uncompressed archive file. // Unpack the compressed archive to extract the uncompressed archive file.
UnPackStatus unpack_status = UNPACK_NO_ERROR; UnPackStatus unpack_status =
int32_t ntstatus = 0;
auto lzma_result =
UnPackArchive(base::FilePath(compressed_archive.get()), unpack_path, UnPackArchive(base::FilePath(compressed_archive.get()), unpack_path,
nullptr, &unpack_status, &ntstatus); nullptr, nullptr, nullptr);
if (lzma_result) if (unpack_status != UNPACK_NO_ERROR)
return ProcessExitResult(static_cast<DWORD>(installer::UNPACKING_FAILED)); return ProcessExitResult(static_cast<DWORD>(installer::UNPACKING_FAILED));
// Unpack the uncompressed archive to extract the updater files. // Unpack the uncompressed archive to extract the updater files.
base::FilePath uncompressed_archive = base::FilePath uncompressed_archive =
unpack_path.Append(FILE_PATH_LITERAL("updater.7z")); unpack_path.Append(FILE_PATH_LITERAL("updater.7z"));
lzma_result = UnPackArchive(uncompressed_archive, unpack_path, nullptr, unpack_status = UnPackArchive(uncompressed_archive, unpack_path, nullptr,
&unpack_status, &ntstatus); nullptr, nullptr);
if (lzma_result) if (unpack_status != UNPACK_NO_ERROR)
return ProcessExitResult(static_cast<DWORD>(installer::UNPACKING_FAILED)); return ProcessExitResult(static_cast<DWORD>(installer::UNPACKING_FAILED));
// While unpacking the binaries, we paged in a whole bunch of memory that // While unpacking the binaries, we paged in a whole bunch of memory that
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment