diff options
author | pkasting@chromium.org <pkasting@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-03-04 01:17:37 +0000 |
---|---|---|
committer | pkasting@chromium.org <pkasting@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-03-04 01:17:37 +0000 |
commit | 1e67c2be4d77333ab9f303c8d9fa5eb58ebc6c90 (patch) | |
tree | 80434934d6420f40ea3372dc1c148123c55f6a32 | |
parent | cf50836f5fff555ab9b8d2e961029a31514ea239 (diff) | |
download | chromium_src-1e67c2be4d77333ab9f303c8d9fa5eb58ebc6c90.zip chromium_src-1e67c2be4d77333ab9f303c8d9fa5eb58ebc6c90.tar.gz chromium_src-1e67c2be4d77333ab9f303c8d9fa5eb58ebc6c90.tar.bz2 |
Create a "GetWOW64Status()" utility function and make the rest of the codebase call it.
BUG=none
TEST=none
Review URL: http://codereview.chromium.org/6610029
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@76854 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | base/win/windows_version.cc | 20 | ||||
-rw-r--r-- | base/win/windows_version.h | 21 | ||||
-rw-r--r-- | chrome/browser/memory_details_win.cc | 22 | ||||
-rw-r--r-- | chrome/browser/nacl_host/nacl_process_host.cc | 26 | ||||
-rw-r--r-- | chrome/browser/nacl_host/nacl_process_host.h | 5 | ||||
-rw-r--r-- | chrome/installer/setup/install_worker.cc | 23 | ||||
-rw-r--r-- | sandbox/src/Wow64.cc | 50 | ||||
-rw-r--r-- | sandbox/src/Wow64.h | 16 | ||||
-rw-r--r-- | sandbox/src/Wow64_64.cc | 8 | ||||
-rw-r--r-- | sandbox/src/interception.cc | 8 | ||||
-rw-r--r-- | sandbox/src/service_resolver_unittest.cc | 21 | ||||
-rw-r--r-- | sandbox/tests/common/controller.cc | 13 |
12 files changed, 89 insertions, 144 deletions
diff --git a/base/win/windows_version.cc b/base/win/windows_version.cc index a80688c..9abf1d2 100644 --- a/base/win/windows_version.cc +++ b/base/win/windows_version.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -68,5 +68,23 @@ void GetServicePackLevel(int* major, int* minor) { *minor = service_pack_minor; } +WOW64Status GetWOW64Status() { + static WOW64Status wow64_status = + GetWOW64StatusForProcess(GetCurrentProcess()); + return wow64_status; +} + +WOW64Status GetWOW64StatusForProcess(HANDLE process_handle) { + typedef BOOL (WINAPI* IsWow64ProcessFunc)(HANDLE, PBOOL); + IsWow64ProcessFunc is_wow64_process = reinterpret_cast<IsWow64ProcessFunc>( + GetProcAddress(GetModuleHandle(L"kernel32.dll"), "IsWow64Process")); + if (!is_wow64_process) + return WOW64_DISABLED; + BOOL is_wow64 = FALSE; + if (!(*is_wow64_process)(process_handle, &is_wow64)) + return WOW64_UNKNOWN; + return is_wow64 ? WOW64_ENABLED : WOW64_DISABLED; +} + } // namespace win } // namespace base diff --git a/base/win/windows_version.h b/base/win/windows_version.h index 7e281a6..0cfb2c7 100644 --- a/base/win/windows_version.h +++ b/base/win/windows_version.h @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -6,6 +6,8 @@ #define BASE_WIN_WINDOWS_VERSION_H_ #pragma once +typedef void* HANDLE; + namespace base { namespace win { @@ -28,6 +30,23 @@ Version GetVersion(); // Returns the major and minor version of the service pack installed. void GetServicePackLevel(int* major, int* minor); +enum WOW64Status { + WOW64_DISABLED, + WOW64_ENABLED, + WOW64_UNKNOWN, +}; + +// Returns whether this process is running under WOW64 (the wrapper that allows +// 32-bit processes to run on 64-bit versions of Windows). This will return +// WOW64_DISABLED for both "32-bit Chrome on 32-bit Windows" and "64-bit Chrome +// on 64-bit Windows". WOW64_UNKNOWN means "an error occurred", e.g. the +// process does not have sufficient access rights to determine this. +WOW64Status GetWOW64Status(); + +// Like GetWOW64Status(), but for the supplied handle instead of the current +// process. +WOW64Status GetWOW64StatusForProcess(HANDLE process_handle); + } // namespace win } // namespace base diff --git a/chrome/browser/memory_details_win.cc b/chrome/browser/memory_details_win.cc index 0e9f063..edb53c8 100644 --- a/chrome/browser/memory_details_win.cc +++ b/chrome/browser/memory_details_win.cc @@ -11,6 +11,7 @@ #include "base/string_util.h" #include "base/utf_string_conversions.h" #include "base/win/scoped_handle.h" +#include "base/win/windows_version.h" #include "chrome/common/chrome_version_info.h" #include "chrome/common/url_constants.h" #include "content/browser/browser_child_process_host.h" @@ -89,19 +90,13 @@ void MemoryDetails::CollectProcessData( } do { base::ProcessId pid = process_entry.th32ProcessID; - base::win::ScopedHandle handle(::OpenProcess( + base::win::ScopedHandle process_handle(::OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid)); - if (!handle.Get()) + if (!process_handle.Get()) continue; - bool is_64bit_process = false; - // IsWow64Process() returns FALSE for a 32bit process on a 32bit OS. - // We need to check if the real OS is 64bit. - if (is_64bit_os) { - BOOL is_wow64 = FALSE; - // IsWow64Process() is supported by Windows XP SP2 or later. - IsWow64Process(handle, &is_wow64); - is_64bit_process = !is_wow64; - } + bool is_64bit_process = is_64bit_os && + (base::win::GetWOW64StatusForProcess(process_handle) == + base::win::WOW64_DISABLED); for (unsigned int index2 = 0; index2 < process_data_.size(); index2++) { if (_wcsicmp(process_data_[index2].process_name.c_str(), process_entry.szExeFile) != 0) @@ -117,7 +112,7 @@ void MemoryDetails::CollectProcessData( info.type = ChildProcessInfo::UNKNOWN_PROCESS; scoped_ptr<base::ProcessMetrics> metrics; - metrics.reset(base::ProcessMetrics::CreateProcessMetrics(handle)); + metrics.reset(base::ProcessMetrics::CreateProcessMetrics(process_handle)); metrics->GetCommittedKBytes(&info.committed); metrics->GetWorkingSetKBytes(&info.working_set); @@ -136,7 +131,8 @@ void MemoryDetails::CollectProcessData( info.type = child_info[child].type; break; } - } else if (GetModuleFileNameEx(handle, NULL, name, MAX_PATH - 1)) { + } else if (GetModuleFileNameEx(process_handle, NULL, name, + MAX_PATH - 1)) { std::wstring str_name(name); scoped_ptr<FileVersionInfo> version_info( FileVersionInfo::CreateFileVersionInfo(FilePath(str_name))); diff --git a/chrome/browser/nacl_host/nacl_process_host.cc b/chrome/browser/nacl_host/nacl_process_host.cc index 2064407..2b97881 100644 --- a/chrome/browser/nacl_host/nacl_process_host.cc +++ b/chrome/browser/nacl_host/nacl_process_host.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -13,6 +13,7 @@ #include "base/command_line.h" #include "base/metrics/nacl_histogram.h" #include "base/utf_string_conversions.h" +#include "base/win/windows_version.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/logging_chrome.h" #include "chrome/common/nacl_cmd_line.h" @@ -58,7 +59,7 @@ NaClProcessHost::NaClProcessHost( running_on_wow64_(false) { set_name(url); #if defined(OS_WIN) - CheckIsWow64(); + running_on_wow64_ = (base::win::GetWOW64Status() == base::win::WOW64_ENABLED); #endif } @@ -301,24 +302,3 @@ bool NaClProcessHost::OnMessageReceived(const IPC::Message& msg) { bool NaClProcessHost::CanShutdown() { return true; } - -#if defined(OS_WIN) -// TODO(gregoryd): invoke CheckIsWow64 only once, not for each NaClProcessHost -typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL); -void NaClProcessHost::CheckIsWow64() { - LPFN_ISWOW64PROCESS fnIsWow64Process; - - fnIsWow64Process = (LPFN_ISWOW64PROCESS) GetProcAddress( - GetModuleHandle(TEXT("kernel32")), - "IsWow64Process"); - - if (fnIsWow64Process != NULL) { - BOOL bIsWow64 = FALSE; - if (fnIsWow64Process(GetCurrentProcess(),&bIsWow64)) { - if (bIsWow64) { - running_on_wow64_ = true; - } - } - } -} -#endif diff --git a/chrome/browser/nacl_host/nacl_process_host.h b/chrome/browser/nacl_host/nacl_process_host.h index 46c5468..b4deaea 100644 --- a/chrome/browser/nacl_host/nacl_process_host.h +++ b/chrome/browser/nacl_host/nacl_process_host.h @@ -54,11 +54,6 @@ class NaClProcessHost : public BrowserChildProcessHost { virtual bool CanShutdown(); -#if defined(OS_WIN) - // Check whether the browser process is running on WOW64 - Windows only - void CheckIsWow64(); -#endif - private: ResourceDispatcherHost* resource_dispatcher_host_; diff --git a/chrome/installer/setup/install_worker.cc b/chrome/installer/setup/install_worker.cc index 495d3b1..70e1ab6 100644 --- a/chrome/installer/setup/install_worker.cc +++ b/chrome/installer/setup/install_worker.cc @@ -19,6 +19,7 @@ #include "base/utf_string_conversions.h" #include "base/version.h" #include "base/win/registry.h" +#include "base/win/windows_version.h" #include "chrome/common/chrome_constants.h" #include "chrome/installer/setup/install.h" #include "chrome/installer/setup/setup_constants.h" @@ -39,24 +40,6 @@ using base::win::RegKey; -namespace { - -// This method tells if we are running on 64 bit platform so that we can copy -// one extra exe. If the API call to determine 64 bit fails, we play it safe -// and return true anyway so that the executable can be copied. -bool Is64bit() { - typedef BOOL (WINAPI* WOW_FUNC)(HANDLE, BOOL*); - BOOL is_64 = FALSE; - - HMODULE module = GetModuleHandle(L"kernel32.dll"); - WOW_FUNC is_wow64 = reinterpret_cast<WOW_FUNC>( - GetProcAddress(module, "IsWow64Process")); - return (is_wow64 != NULL) && - (!(is_wow64)(GetCurrentProcess(), &is_64) || (is_64 != FALSE)); -} - -} // namespace - namespace installer { // Local helper to call AddRegisterComDllWorkItems for all DLLs in a set of @@ -556,7 +539,9 @@ void AddInstallWorkItems(const InstallationState& original_state, temp_path.value(), WorkItem::NEW_NAME_IF_IN_USE, new_chrome_exe.value()); // Extra executable for 64 bit systems. - if (Is64bit()) { + // NOTE: We check for "not disabled" so that if the API call fails, we play it + // safe and copy the executable anyway. + if (base::win::GetWOW64Status() != base::win::WOW64_DISABLED) { install_list->AddMoveTreeWorkItem( src_path.Append(installer::kWowHelperExe).value(), target_path.Append(installer::kWowHelperExe).value(), diff --git a/sandbox/src/Wow64.cc b/sandbox/src/Wow64.cc index dec5e50..79febe8 100644 --- a/sandbox/src/Wow64.cc +++ b/sandbox/src/Wow64.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -8,7 +8,7 @@ #include "base/logging.h" #include "base/scoped_ptr.h" -#include "sandbox/src/sandbox.h" +#include "base/win/windows_version.h" #include "sandbox/src/target_process.h" namespace { @@ -80,33 +80,6 @@ Wow64::~Wow64() { ::CloseHandle(continue_load_); } -bool Wow64::IsWow64() { - if (init_) - return is_wow64_; - - is_wow64_ = false; - - HMODULE kernel32 = ::GetModuleHandle(sandbox::kKerneldllName); - if (!kernel32) - return false; - - IsWow64ProcessFunction is_wow64_process = reinterpret_cast< - IsWow64ProcessFunction>(::GetProcAddress(kernel32, "IsWow64Process")); - - init_ = true; - if (!is_wow64_process) - return false; - - BOOL wow64; - if (!is_wow64_process(::GetCurrentProcess(), &wow64)) - return false; - - if (wow64) - is_wow64_ = true; - - return is_wow64_; -} - // The basic idea is to allocate one page of memory on the child, and initialize // the first part of it with our version of PatchInfo32. Then launch the helper // process passing it that address on the child. The helper process will patch @@ -114,9 +87,8 @@ bool Wow64::IsWow64() { // first event on the buffer. We'll be waiting on that event and after the 32 // bit version of ntdll is loaded, we'll remove the interception and return to // our caller. -bool Wow64::WaitForNtdll(DWORD timeout_ms) { - DCHECK(!init_); - if (!IsWow64()) +bool Wow64::WaitForNtdll() { + if (base::win::GetWOW64Status() != base::win::WOW64_ENABLED) return true; const size_t page_size = 4096; @@ -151,19 +123,19 @@ bool Wow64::WaitForNtdll(DWORD timeout_ms) { if (offsetof(PatchInfo32, section) != written) return false; - if (!RunWowHelper(buffer, timeout_ms)) + if (!RunWowHelper(buffer)) return false; // The child is intercepted on 64 bit, go on and wait for our event. - if (!DllMapped(timeout_ms)) + if (!DllMapped()) return false; // The 32 bit version is available, cleanup the child. return Restore64Code(child_->Process(), patch_info); } -bool Wow64::RunWowHelper(void* buffer, DWORD timeout_ms) { - COMPILE_ASSERT(sizeof(buffer) <= sizeof(timeout_ms), unsupported_64_bits); +bool Wow64::RunWowHelper(void* buffer) { + COMPILE_ASSERT(sizeof(buffer) <= sizeof DWORD, unsupported_64_bits); // Get the path to the helper (beside the exe). wchar_t prog_name[MAX_PATH]; @@ -188,7 +160,7 @@ bool Wow64::RunWowHelper(void* buffer, DWORD timeout_ms) { NULL, &startup_info, &process_info)) return false; - DWORD reason = ::WaitForSingleObject(process_info.hProcess, timeout_ms); + DWORD reason = ::WaitForSingleObject(process_info.hProcess, INFINITE); DWORD code; bool ok = ::GetExitCodeProcess(process_info.hProcess, &code) ? true : false; @@ -204,14 +176,14 @@ bool Wow64::RunWowHelper(void* buffer, DWORD timeout_ms) { // First we must wake up the child, then wait for dll loads on the child until // the one we care is loaded; at that point we must suspend the child again. -bool Wow64::DllMapped(DWORD timeout_ms) { +bool Wow64::DllMapped() { if (1 != ::ResumeThread(child_->MainThread())) { NOTREACHED(); return false; } for (;;) { - DWORD reason = ::WaitForSingleObject(dll_load_, timeout_ms); + DWORD reason = ::WaitForSingleObject(dll_load_, INFINITE); if (WAIT_TIMEOUT == reason || WAIT_ABANDONED == reason) return false; diff --git a/sandbox/src/Wow64.h b/sandbox/src/Wow64.h index 7ee981a..472297e 100644 --- a/sandbox/src/Wow64.h +++ b/sandbox/src/Wow64.h @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -19,25 +19,21 @@ class TargetProcess; class Wow64 { public: Wow64(TargetProcess* child, HMODULE ntdll) - : child_(child), ntdll_(ntdll), init_(false), dll_load_(NULL), - continue_load_(NULL) {} + : child_(child), ntdll_(ntdll), dll_load_(NULL), continue_load_(NULL) {} ~Wow64(); // Waits for the 32 bit DLL to get loaded on the child process. This function // will return immediately if not running under WOW, or launch the helper // process and wait until ntdll is ready. - bool WaitForNtdll(DWORD timeout_ms); - - // Returns true if this is a 32 bit process running on a 64 bit OS. - bool IsWow64(); + bool WaitForNtdll(); private: // Runs the WOW helper process, passing the address of a buffer allocated on // the child (one page). - bool RunWowHelper(void* buffer, DWORD timeout_ms); + bool RunWowHelper(void* buffer); // This method receives "notifications" whenever a DLL is mapped on the child. - bool DllMapped(DWORD timeout_ms); + bool DllMapped(); // Returns true if ntdll.dll is mapped on the child. bool NtdllPresent(); @@ -46,8 +42,6 @@ class Wow64 { HMODULE ntdll_; // ntdll on the parent. HANDLE dll_load_; // Event that is signaled on dll load. HANDLE continue_load_; // Event to signal to continue execution on the child. - bool init_; // Initialization control. - bool is_wow64_; // true on WOW64 environments. DISALLOW_IMPLICIT_CONSTRUCTORS(Wow64); }; diff --git a/sandbox/src/Wow64_64.cc b/sandbox/src/Wow64_64.cc index e188d68..5218077 100644 --- a/sandbox/src/Wow64_64.cc +++ b/sandbox/src/Wow64_64.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -11,11 +11,7 @@ namespace sandbox { Wow64::~Wow64() { } -bool Wow64::IsWow64() { - return false; -} - -bool Wow64::WaitForNtdll(DWORD timeout_ms) { +bool Wow64::WaitForNtdll() { return true; } diff --git a/sandbox/src/interception.cc b/sandbox/src/interception.cc index 6636cc3..e9f89dc 100644 --- a/sandbox/src/interception.cc +++ b/sandbox/src/interception.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -424,9 +424,9 @@ bool InterceptionManager::PatchClientFunctions(DllInterceptionData* thunks, return false; } - Wow64 WowHelper(child_, ntdll_base); if (base::win::GetVersion() <= base::win::VERSION_VISTA) { - if (!WowHelper.WaitForNtdll(INFINITE)) + Wow64 WowHelper(child_, ntdll_base); + if (!WowHelper.WaitForNtdll()) return false; } @@ -438,7 +438,7 @@ bool InterceptionManager::PatchClientFunctions(DllInterceptionData* thunks, #endif ServiceResolverThunk* thunk; - if (WowHelper.IsWow64()) + if (base::win::GetWOW64Status() == base::win::WOW64_ENABLED) thunk = new Wow64ResolverThunk(child_->Process(), relaxed_); else if (!IsXPSP2OrLater()) thunk = new Win2kResolverThunk(child_->Process(), relaxed_); diff --git a/sandbox/src/service_resolver_unittest.cc b/sandbox/src/service_resolver_unittest.cc index 793d4a1..777a5da 100644 --- a/sandbox/src/service_resolver_unittest.cc +++ b/sandbox/src/service_resolver_unittest.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -6,10 +6,10 @@ #include "base/basictypes.h" #include "base/scoped_ptr.h" +#include "base/win/windows_version.h" #include "sandbox/src/resolver.h" #include "sandbox/src/sandbox_utils.h" #include "sandbox/src/service_resolver.h" -#include "sandbox/src/wow64.h" #include "testing/gtest/include/gtest/gtest.h" namespace { @@ -120,18 +120,11 @@ NTSTATUS PatchNtdllWithResolver(const char* function, bool relaxed, } sandbox::ServiceResolverThunk* GetTestResolver(bool relaxed) { - HMODULE ntdll_base = ::GetModuleHandle(L"ntdll.dll"); - EXPECT_TRUE(NULL != ntdll_base); - sandbox::Wow64 WowHelper(NULL, ntdll_base); - - sandbox::ServiceResolverThunk* resolver; - if (WowHelper.IsWow64()) - resolver = new Wow64ResolverTest(relaxed); - else if (!sandbox::IsXPSP2OrLater()) - resolver = new Win2kResolverTest(relaxed); - else - resolver = new WinXpResolverTest(relaxed); - return resolver; + if (base::win::GetWOW64Status() == base::win::WOW64_ENABLED) + return new Wow64ResolverTest(relaxed); + if (!sandbox::IsXPSP2OrLater()) + return new Win2kResolverTest(relaxed); + return new WinXpResolverTest(relaxed); } NTSTATUS PatchNtdll(const char* function, bool relaxed) { diff --git a/sandbox/tests/common/controller.cc b/sandbox/tests/common/controller.cc index 6e0f080..7efd374 100644 --- a/sandbox/tests/common/controller.cc +++ b/sandbox/tests/common/controller.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -6,9 +6,9 @@ #include <string> +#include "base/win/windows_version.h" #include "sandbox/src/sandbox_factory.h" #include "sandbox/src/sandbox_utils.h" -#include "sandbox/src/wow64.h" namespace { @@ -55,11 +55,9 @@ std::wstring MakePathToSysWow64(const wchar_t* name, bool is_obj_man_path) { namespace sandbox { std::wstring MakePathToSys(const wchar_t* name, bool is_obj_man_path) { - Wow64 current_proc(NULL, NULL); - if (current_proc.IsWow64()) + if (base::win::GetWOW64Status() == base::win::WOW64_ENABLED) return MakePathToSysWow64(name, is_obj_man_path); - else - return MakePathToSys32(name, is_obj_man_path); + return MakePathToSys32(name, is_obj_man_path); } BrokerServices* GetBroker() { @@ -140,8 +138,7 @@ bool TestRunner::AddRuleSys32(TargetPolicy::Semantics semantics, if (!AddRule(TargetPolicy::SUBSYS_FILES, semantics, win32_path.c_str())) return false; - Wow64 current_proc(NULL, NULL); - if (!current_proc.IsWow64()) + if (base::win::GetWOW64Status() != base::win::WOW64_ENABLED) return true; win32_path = MakePathToSysWow64(pattern, false); |