win: Retrieve module version/type information

Refactor version retrieval from system snapshot to use when
retrieving the module version information.

Follows https://codereview.chromium.org/1133203002/.

R=cpu@chromium.org, rsesek@chromium.org
TBR=mark@chromium.org
BUG=crashpad:1

Review URL: https://codereview.chromium.org/1126273003
This commit is contained in:
Scott Graham 2015-05-14 17:43:49 -07:00
parent 5a21de6a1b
commit b0889f61ee
7 changed files with 154 additions and 49 deletions

View File

@ -18,6 +18,7 @@
#include "snapshot/win/pe_image_reader.h"
#include "util/misc/tri_state.h"
#include "util/misc/uuid.h"
#include "util/win/module_version.h"
namespace crashpad {
namespace internal {
@ -39,13 +40,13 @@ bool ModuleSnapshotWin::Initialize(
INITIALIZATION_STATE_SET_INITIALIZING(initialized_);
process_reader_ = process_reader;
name_ = base::UTF16ToUTF8(process_reader_module.name);
name_ = process_reader_module.name;
timestamp_ = process_reader_module.timestamp;
pe_image_reader_.reset(new PEImageReader());
if (!pe_image_reader_->Initialize(process_reader_,
process_reader_module.dll_base,
process_reader_module.size,
name_)) {
base::UTF16ToUTF8(name_))) {
return false;
}
@ -74,7 +75,7 @@ void ModuleSnapshotWin::GetCrashpadOptions(CrashpadInfoClientOptions* options) {
std::string ModuleSnapshotWin::Name() const {
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
return name_;
return base::UTF16ToUTF8(name_);
}
uint64_t ModuleSnapshotWin::Address() const {
@ -97,7 +98,18 @@ void ModuleSnapshotWin::FileVersion(uint16_t* version_0,
uint16_t* version_2,
uint16_t* version_3) const {
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
CHECK(false) << "TODO(scottmg)";
VS_FIXEDFILEINFO ffi;
if (GetModuleVersionAndType(base::FilePath(name_), &ffi)) {
*version_0 = ffi.dwFileVersionMS >> 16;
*version_1 = ffi.dwFileVersionMS & 0xffff;
*version_2 = ffi.dwFileVersionLS >> 16;
*version_3 = ffi.dwFileVersionLS & 0xffff;
} else {
*version_0 = 0;
*version_1 = 0;
*version_2 = 0;
*version_3 = 0;
}
}
void ModuleSnapshotWin::SourceVersion(uint16_t* version_0,
@ -105,13 +117,32 @@ void ModuleSnapshotWin::SourceVersion(uint16_t* version_0,
uint16_t* version_2,
uint16_t* version_3) const {
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
CHECK(false) << "TODO(scottmg)";
VS_FIXEDFILEINFO ffi;
if (GetModuleVersionAndType(base::FilePath(name_), &ffi)) {
*version_0 = ffi.dwProductVersionMS >> 16;
*version_1 = ffi.dwProductVersionMS & 0xffff;
*version_2 = ffi.dwProductVersionLS >> 16;
*version_3 = ffi.dwProductVersionLS & 0xffff;
} else {
*version_0 = 0;
*version_1 = 0;
*version_2 = 0;
*version_3 = 0;
}
}
ModuleSnapshot::ModuleType ModuleSnapshotWin::GetModuleType() const {
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
CHECK(false) << "TODO(scottmg)";
return ModuleSnapshot::ModuleType();
VS_FIXEDFILEINFO ffi;
if (GetModuleVersionAndType(base::FilePath(name_), &ffi)) {
if (ffi.dwFileType == VFT_APP)
return ModuleSnapshot::kModuleTypeExecutable;
if (ffi.dwFileType == VFT_DLL)
return ModuleSnapshot::kModuleTypeSharedLibrary;
if (ffi.dwFileType == VFT_DRV || ffi.dwFileType == VFT_VXD)
return ModuleSnapshot::kModuleTypeLoadableModule;
}
return ModuleSnapshot::kModuleTypeUnknown;
}
void ModuleSnapshotWin::UUID(crashpad::UUID* uuid) const {

View File

@ -81,7 +81,7 @@ class ModuleSnapshotWin final : public ModuleSnapshot {
std::map<std::string, std::string> AnnotationsSimpleMap() const override;
private:
std::string name_;
std::wstring name_;
time_t timestamp_;
scoped_ptr<PEImageReader> pe_image_reader_;
ProcessReaderWin* process_reader_; // weak

View File

@ -23,10 +23,10 @@
#include <utility>
#include <vector>
#include "base/memory/scoped_ptr.h"
#include "base/numerics/safe_conversions.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "util/win/module_version.h"
namespace crashpad {
@ -95,45 +95,25 @@ void SystemSnapshotWin::Initialize(ProcessReaderWin* process_reader) {
PLOG(WARNING) << "GetVersionEx";
} else {
const wchar_t kSystemDll[] = L"kernel32.dll";
DWORD size = GetFileVersionInfoSize(kSystemDll, nullptr);
if (!size) {
PLOG(WARNING) << "GetFileVersionInfoSize";
} else {
scoped_ptr<uint8_t[]> data(new uint8_t[size]);
if (!GetFileVersionInfo(kSystemDll, 0, size, data.get())) {
PLOG(WARNING) << "GetFileVersionInfo";
} else {
VS_FIXEDFILEINFO* fixed_file_info;
UINT size;
if (!VerQueryValue(data.get(),
L"\\",
reinterpret_cast<void**>(&fixed_file_info),
&size)) {
PLOG(WARNING) << "VerQueryValue";
} else {
uint32_t valid_flags =
fixed_file_info->dwFileFlags & fixed_file_info->dwFileFlagsMask;
std::string flags_string = GetStringForFileFlags(valid_flags);
os_version_major_ =
(fixed_file_info->dwFileVersionMS & 0xffff0000) >> 16;
os_version_minor_ = fixed_file_info->dwFileVersionMS & 0xffff;
os_version_bugfix_ =
(fixed_file_info->dwFileVersionLS & 0xffff0000) >> 16;
os_version_build_ = base::StringPrintf(
"%d", fixed_file_info->dwFileVersionLS & 0xffff);
os_server_ = version_info.wProductType != VER_NT_WORKSTATION;
std::string os_name = GetStringForFileOS(fixed_file_info->dwFileOS);
os_version_full_ = base::StringPrintf(
"%s %d.%d.%d.%s%s",
os_name.c_str(),
os_version_major_,
os_version_minor_,
os_version_bugfix_,
os_version_build_.c_str(),
flags_string.empty() ? "" : (std::string(" (") + flags_string +
")").c_str());
}
}
VS_FIXEDFILEINFO ffi;
if (GetModuleVersionAndType(base::FilePath(kSystemDll), &ffi)) {
std::string flags_string = GetStringForFileFlags(ffi.dwFileFlags);
os_server_ = version_info.wProductType != VER_NT_WORKSTATION;
std::string os_name = GetStringForFileOS(ffi.dwFileOS);
os_version_major_ = ffi.dwFileVersionMS >> 16;
os_version_minor_ = ffi.dwFileVersionMS & 0xffff;
os_version_bugfix_ = ffi.dwFileVersionLS >> 16;
os_version_build_ =
base::StringPrintf("%d", ffi.dwFileVersionLS & 0xffff);
os_version_full_ = base::StringPrintf(
"%s %d.%d.%d.%s%s",
os_name.c_str(),
os_version_major_,
os_version_minor_,
os_version_bugfix_,
os_version_build_.c_str(),
flags_string.empty() ? "" : (std::string(" (") + flags_string + ")")
.c_str());
}
}

View File

@ -147,6 +147,8 @@
'thread/thread_win.cc',
'win/address_types.h',
'win/checked_win_address_range.h',
'win/module_version.cc',
'win/module_version.h',
'win/process_info.cc',
'win/process_info.h',
'win/process_structs.h',

View File

@ -0,0 +1,55 @@
// Copyright 2015 The Crashpad Authors. All rights reserved.
//
// 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.
#include "util/win/module_version.h"
#include <windows.h>
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/strings/utf_string_conversions.h"
namespace crashpad {
bool GetModuleVersionAndType(const base::FilePath& path,
VS_FIXEDFILEINFO* vs_fixedfileinfo) {
DWORD size = GetFileVersionInfoSize(path.value().c_str(), nullptr);
if (!size) {
PLOG(WARNING) << "GetFileVersionInfoSize: "
<< base::UTF16ToUTF8(path.value());
} else {
scoped_ptr<uint8_t[]> data(new uint8_t[size]);
if (!GetFileVersionInfo(path.value().c_str(), 0, size, data.get())) {
PLOG(WARNING) << "GetFileVersionInfo: "
<< base::UTF16ToUTF8(path.value());
} else {
VS_FIXEDFILEINFO* fixed_file_info;
UINT size;
if (!VerQueryValue(data.get(),
L"\\",
reinterpret_cast<void**>(&fixed_file_info),
&size)) {
PLOG(WARNING) << "VerQueryValue";
} else {
*vs_fixedfileinfo = *fixed_file_info;
vs_fixedfileinfo->dwFileFlags &= vs_fixedfileinfo->dwFileFlagsMask;
return true;
}
}
}
return false;
}
} // namespace crashpad

37
util/win/module_version.h Normal file
View File

@ -0,0 +1,37 @@
// Copyright 2015 The Crashpad Authors. All rights reserved.
//
// 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.
#ifndef CRASHPAD_UTIL_WIN_MODULE_VERSION_H_
#define CRASHPAD_UTIL_WIN_MODULE_VERSION_H_
#include <windows.h>
#include "base/files/file_path.h"
namespace crashpad {
//! \brief Retrieve the type and version information from a given module (exe,
//! dll, etc.)
//!
//! \param[in] path The path to the module to be inspected.
//! \param[out] vs_fixedfileinfo The VS_FIXEDFILEINFO on success. `dwFileFlags`
//! will have been masked with `dwFileFlagsMask` already.
//!
//! \return `true` on success, or `false` on failure with a message logged.
bool GetModuleVersionAndType(const base::FilePath& path,
VS_FIXEDFILEINFO* vs_fixedfileinfo);
} // namespace crashpad
#endif // CRASHPAD_UTIL_WIN_MODULE_VERSION_H_