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..afba0cae16071420d0eec6c128340e6f2ce21dca 100644 |
| --- a/util/win/process_info.cc |
| +++ b/util/win/process_info.cc |
| @@ -1,4 +1,3 @@ |
| -// Copyright 2015 The Crashpad Authors. All rights reserved. |
|
Mark Mentovai
2015/09/16 02:57:20
Pretty sure we still own this file.
scottmg
2015/09/16 18:05:07
Done.
|
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| @@ -18,6 +17,7 @@ |
| #include "base/logging.h" |
| #include "util/numeric/safe_assignment.h" |
| +#include "util/win/ntstatus_logging.h" |
| #include "util/win/process_structs.h" |
| namespace crashpad { |
| @@ -80,7 +80,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 +103,70 @@ 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. |
| + *peb_address = process_basic_information.PebBaseAddress; |
|
Mark Mentovai
2015/09/16 02:57:20
if (!is_wow64) {
// this assignment
} else {
/
scottmg
2015/09/16 18:05:07
Done.
|
| + if (is_wow64) { |
| + ULONG_PTR wow64_peb_address; |
| + status = crashpad::NtQueryInformationProcess(process, |
| + ProcessWow64Information, |
|
Mark Mentovai
2015/09/16 02:57:20
It’s a little weird that the thing named this way
scottmg
2015/09/16 18:05:07
Yeah, the limited bit that MSDN documented is conf
|
| + &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) { |
| + |
|
Mark Mentovai
2015/09/16 02:57:20
Unnecessary new blank line.
scottmg
2015/09/16 18:05:06
Done.
|
| Traits::Pointer peb_address; |
| if (!AssignIfInRange(&peb_address, peb_address_vmaddr)) { |
| - LOG(ERROR) << "peb_address_vmaddr " << peb_address_vmaddr |
| - << " out of range"; |
| + LOG(ERROR) << "peb address" << peb_address_vmaddr << " out of range"; |
|
Mark Mentovai
2015/09/16 02:57:20
Need a space after the word “address”.
peb_addres
scottmg
2015/09/16 18:05:06
Done.
|
| return false; |
| } |
| @@ -212,6 +270,7 @@ bool ProcessInfo::Initialize(HANDLE process) { |
| INITIALIZATION_STATE_SET_INITIALIZING(initialized_); |
| is_wow64_ = IsProcessWow64(process); |
| + bool self_is_wow64 = IsProcessWow64(GetCurrentProcess()); |
|
Mark Mentovai
2015/09/16 02:57:20
Don’t declare it ’til you need it. Since you only
scottmg
2015/09/16 18:05:07
Gone.
|
| if (is_wow64_) { |
| // If it's WoW64, then it's 32-on-64. |
| @@ -232,73 +291,26 @@ 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; |
| -#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; |
| + WinVMAddress peb_address; |
| + bool result = |
| + (is_64_bit_ || (is_wow64_ && !self_is_wow64)) |
|
Mark Mentovai
2015/09/16 02:57:20
This condition makes my head hurt. It seems like i
scottmg
2015/09/16 18:05:07
Me too! I think what it really needed to be was ba
|
| + ? GetProcessBasicInformation<process_types::internal::Traits64>( |
| + process, is_wow64_, this, &peb_address) |
| + : GetProcessBasicInformation<process_types::internal::Traits32>( |
| + process, is_wow64_, this, &peb_address); |
| + if (!result) { |
| + LOG(ERROR) << "GetProcessBasicInformation failed"; |
| 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_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; |
| - } |
| - // 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; |