0

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
This commit is contained in:
pkasting@chromium.org
2011-03-04 01:17:37 +00:00
parent cf50836f5f
commit 1e67c2be4d
12 changed files with 89 additions and 144 deletions

@ -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

@ -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

@ -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)));

@ -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

@ -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_;

@ -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(),

@ -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;

@ -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);
};

@ -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;
}

@ -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_);

@ -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) {

@ -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);