Chromium Code Reviews| Index: util/win/process_info.cc |
| diff --git a/util/win/process_info.cc b/util/win/process_info.cc |
| index ca8277ed0308736ad257a3b5c9ef46deee356cb7..ba277ef34a40a3bc21c083a80cdd8e075f41faef 100644 |
| --- a/util/win/process_info.cc |
| +++ b/util/win/process_info.cc |
| @@ -17,7 +17,9 @@ |
| #include <winternl.h> |
| #include "base/logging.h" |
| +#include "base/strings/stringprintf.h" |
| #include "util/numeric/safe_assignment.h" |
| +#include "util/win/ntstatus_logging.h" |
| #include "util/win/process_structs.h" |
| namespace crashpad { |
| @@ -80,7 +82,8 @@ bool ReadUnicodeString(HANDLE process, |
| return true; |
| } |
| -template <class T> bool ReadStruct(HANDLE process, WinVMAddress at, T* into) { |
| +template <class T> |
| +bool ReadStruct(HANDLE process, WinVMAddress at, T* into) { |
| SIZE_T bytes_read; |
| if (!ReadProcessMemory(process, |
| reinterpret_cast<const void*>(at), |
| @@ -102,13 +105,71 @@ template <class T> bool ReadStruct(HANDLE process, WinVMAddress at, T* into) { |
| } // namespace |
| template <class Traits> |
| +bool GetProcessBasicInformation(HANDLE process, |
| + bool is_wow64, |
| + ProcessInfo* process_info, |
| + WinVMAddress* peb_address) { |
| + ULONG bytes_returned; |
| + process_types::PROCESS_BASIC_INFORMATION<Traits> process_basic_information; |
| + NTSTATUS status = |
| + crashpad::NtQueryInformationProcess(process, |
| + ProcessBasicInformation, |
| + &process_basic_information, |
| + sizeof(process_basic_information), |
| + &bytes_returned); |
| + if (!NT_SUCCESS(status)) { |
| + NTSTATUS_LOG(ERROR, status) << "NtQueryInformationProcess"; |
| + return false; |
| + } |
| + if (bytes_returned != sizeof(process_basic_information)) { |
| + LOG(ERROR) << "NtQueryInformationProcess incorrect size"; |
| + return false; |
| + } |
| + |
| + // See https://msdn.microsoft.com/en-us/library/windows/desktop/aa384203 on |
| + // 32 bit being the correct size for HANDLEs for proceses, even on Windows |
| + // x64. API functions (e.g. OpenProcess) take only a DWORD, so there's no |
| + // sense in maintaining the top bits. |
| + process_info->process_id_ = |
| + static_cast<DWORD>(process_basic_information.UniqueProcessId); |
| + process_info->inherited_from_process_id_ = static_cast<DWORD>( |
| + process_basic_information.InheritedFromUniqueProcessId); |
| + |
| + // We now want to read the PEB to gather the rest of our information. The |
| + // PebBaseAddress as returned above is what we want for 64-on-64 and 32-on-32, |
| + // but for Wow64, we want to read the 32 bit PEB (a Wow64 process has both). |
| + // The address of this is found by a second call to NtQueryInformationProcess. |
| + if (!is_wow64) { |
| + *peb_address = process_basic_information.PebBaseAddress; |
| + } else { |
| + ULONG_PTR wow64_peb_address; |
| + status = crashpad::NtQueryInformationProcess(process, |
| + ProcessWow64Information, |
| + &wow64_peb_address, |
| + sizeof(wow64_peb_address), |
| + &bytes_returned); |
| + if (!NT_SUCCESS(status)) { |
| + NTSTATUS_LOG(ERROR, status), "NtQueryInformationProcess"; |
| + return false; |
| + } |
| + if (bytes_returned != sizeof(wow64_peb_address)) { |
| + LOG(ERROR) << "NtQueryInformationProcess incorrect size"; |
| + return false; |
| + } |
| + *peb_address = wow64_peb_address; |
| + } |
| + |
| + return true; |
| +} |
| + |
| +template <class Traits> |
| bool ReadProcessData(HANDLE process, |
| WinVMAddress peb_address_vmaddr, |
| ProcessInfo* process_info) { |
| Traits::Pointer peb_address; |
| if (!AssignIfInRange(&peb_address, peb_address_vmaddr)) { |
| - LOG(ERROR) << "peb_address_vmaddr " << peb_address_vmaddr |
| - << " out of range"; |
| + LOG(ERROR) << base::StringPrintf("peb address 0x%x out of range", |
| + peb_address_vmaddr); |
| return false; |
| } |
| @@ -232,73 +293,28 @@ bool ProcessInfo::Initialize(HANDLE process) { |
| } |
| #endif |
| - ULONG bytes_returned; |
| - // We assume this process is not running on Wow64. The |
| - // PROCESS_BASIC_INFORMATION uses the OS size (that is, even Wow64 has a 64 |
| - // bit one.) |
| - // TODO(scottmg): Either support running as Wow64, or check/resolve this at a |
| - // higher level. |
| -#if ARCH_CPU_32_BITS |
| - process_types::PROCESS_BASIC_INFORMATION<process_types::internal::Traits32> |
| - process_basic_information; |
| + WinVMAddress peb_address; |
| +#if ARCH_CPU_64_BITS |
|
Mark Mentovai
2015/09/16 18:56:58
Much better. #include "build/build_config.h".
scottmg
2015/09/16 19:38:21
Done.
|
| + bool result = GetProcessBasicInformation<process_types::internal::Traits64>( |
| + process, is_wow64_, this, &peb_address); |
| #else |
| - process_types::PROCESS_BASIC_INFORMATION<process_types::internal::Traits64> |
| - process_basic_information; |
| -#endif |
| - NTSTATUS status = |
| - crashpad::NtQueryInformationProcess(process, |
| - ProcessBasicInformation, |
| - &process_basic_information, |
| - sizeof(process_basic_information), |
| - &bytes_returned); |
| - if (status < 0) { |
| - LOG(ERROR) << "NtQueryInformationProcess: status=" << status; |
| - return false; |
| - } |
| - if (bytes_returned != sizeof(process_basic_information)) { |
| - LOG(ERROR) << "NtQueryInformationProcess incorrect size"; |
| - return false; |
| - } |
| + bool result = GetProcessBasicInformation<process_types::internal::Traits32>( |
| + process, false, this, &peb_address); |
| +#endif // ARCH_CPU_64_BITS |
| - // See https://msdn.microsoft.com/en-us/library/windows/desktop/aa384203 on |
| - // 32 bit being the correct size for HANDLEs for proceses, even on Windows |
| - // x64. API functions (e.g. OpenProcess) take only a DWORD, so there's no |
| - // sense in maintaining the top bits. |
| - process_id_ = static_cast<DWORD>(process_basic_information.UniqueProcessId); |
| - inherited_from_process_id_ = static_cast<DWORD>( |
| - process_basic_information.InheritedFromUniqueProcessId); |
| - |
| - // We now want to read the PEB to gather the rest of our information. The |
| - // PebBaseAddress as returned above is what we want for 64-on-64 and 32-on-32, |
| - // but for Wow64, we want to read the 32 bit PEB (a Wow64 process has both). |
| - // The address of this is found by a second call to NtQueryInformationProcess. |
| - WinVMAddress peb_address = process_basic_information.PebBaseAddress; |
| - if (is_wow64_) { |
| - ULONG_PTR wow64_peb_address; |
| - status = |
| - crashpad::NtQueryInformationProcess(process, |
| - ProcessWow64Information, |
| - &wow64_peb_address, |
| - sizeof(wow64_peb_address), |
| - &bytes_returned); |
| - if (status < 0) { |
| - LOG(ERROR) << "NtQueryInformationProcess: status=" << status; |
| - return false; |
| - } |
| - if (bytes_returned != sizeof(wow64_peb_address)) { |
| - LOG(ERROR) << "NtQueryInformationProcess incorrect size"; |
| - return false; |
| - } |
| - peb_address = wow64_peb_address; |
| + if (!result) { |
| + LOG(ERROR) << "GetProcessBasicInformation failed"; |
| + return false; |
| } |
| - // Read the PEB data using the correct word size. |
| - bool result = is_64_bit_ ? ReadProcessData<process_types::internal::Traits64>( |
| + result = is_64_bit_ ? ReadProcessData<process_types::internal::Traits64>( |
| process, peb_address, this) |
| : ReadProcessData<process_types::internal::Traits32>( |
| process, peb_address, this); |
| - if (!result) |
| + if (!result) { |
| + LOG(ERROR) << "ReadProcessData failed"; |
| return false; |
| + } |
| INITIALIZATION_STATE_SET_VALID(initialized_); |
| return true; |