Index: util/win/process_info.cc |
diff --git a/util/win/process_info.cc b/util/win/process_info.cc |
index ca8277ed0308736ad257a3b5c9ef46deee356cb7..f7d1c5de839fe94c52dfa3a970e81e44f37dfd00 100644 |
--- a/util/win/process_info.cc |
+++ b/util/win/process_info.cc |
@@ -17,7 +17,10 @@ |
#include <winternl.h> |
#include "base/logging.h" |
+#include "base/strings/stringprintf.h" |
+#include "build/build_config.h" |
#include "util/numeric/safe_assignment.h" |
+#include "util/win/ntstatus_logging.h" |
#include "util/win/process_structs.h" |
namespace crashpad { |
@@ -80,7 +83,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 +106,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 +294,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 |
+ 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; |