Chromium Code Reviews| Index: chrome/app/close_handle_hook_win.cc |
| diff --git a/chrome/app/close_handle_hook_win.cc b/chrome/app/close_handle_hook_win.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..ca0b01e76c331c38192e97e3eba0e380147a2dfe |
| --- /dev/null |
| +++ b/chrome/app/close_handle_hook_win.cc |
| @@ -0,0 +1,118 @@ |
| +// Copyright 2014 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. |
| + |
| +#include "chrome/app/close_handle_hook_win.h" |
| + |
| +#include <Windows.h> |
| + |
| +#include <vector> |
| + |
| +#include "base/files/file_path.h" |
| +#include "base/lazy_instance.h" |
| +#include "base/strings/string16.h" |
| +#include "base/win/iat_patch_function.h" |
| +#include "base/win/scoped_handle.h" |
| +#include "chrome/common/chrome_version_info.h" |
| + |
| +namespace { |
| + |
| +typedef BOOL (WINAPI* CloseHandleType) (HANDLE handle); |
| +CloseHandleType g_close_function = NULL; |
| + |
| +// The entry point for CloseHandle interception. This function notifies the |
| +// verifier about the handle that is being closed, and calls the original |
| +// function. |
| +BOOL WINAPI CloseHandleHook(HANDLE handle) { |
| + base::win::OnHandleBeingClosed(handle); |
| + return g_close_function(handle); |
| +} |
| + |
| +// Keeps track of all the hooks needed to intercept CloseHandle. |
| +class CloseHandleHooks { |
| + public: |
| + CloseHandleHooks() {} |
| + ~CloseHandleHooks() {} |
| + |
| + void AddIATPatch(const base::string16& module); |
| + void Unpatch(); |
| + |
| + private: |
| + std::vector<base::win::IATPatchFunction*> hooks_; |
| + DISALLOW_COPY_AND_ASSIGN(CloseHandleHooks); |
| +}; |
| +base::LazyInstance<CloseHandleHooks> g_hooks = LAZY_INSTANCE_INITIALIZER; |
| + |
| +void CloseHandleHooks::AddIATPatch(const base::string16& module) { |
| + if (module.empty()) |
| + return; |
| + |
| + base::win::IATPatchFunction* patch = new base::win::IATPatchFunction; |
| + patch->Patch(module.c_str(), "kernel32.dll", "CloseHandle", CloseHandleHook); |
| + hooks_.push_back(patch); |
| + if (!g_close_function) { |
| + // Things are probably messed up if each intercepted function points to |
| + // a different place, but we need only one function to call. |
| + g_close_function = |
| + reinterpret_cast<CloseHandleType>(patch->original_function()); |
| + } |
| +} |
| + |
| +void CloseHandleHooks::Unpatch() { |
| + for (std::vector<base::win::IATPatchFunction*>::iterator it = hooks_.begin(); |
| + it != hooks_.end(); ++it) { |
| + (*it)->Unpatch(); |
| + } |
| +} |
| + |
| +bool UseHooks() { |
| + chrome::VersionInfo::Channel channel = chrome::VersionInfo::GetChannel(); |
| + if (channel == chrome::VersionInfo::CHANNEL_CANARY || |
| + channel == chrome::VersionInfo::CHANNEL_DEV) { |
| + return true; |
| + } |
| + |
| + return false; |
| +} |
| + |
| +base::string16 GetModuleName(HMODULE module) { |
| + base::string16 name; |
| + if (!module) |
| + return name; |
| + wchar_t buffer[MAX_PATH]; |
| + int rv = GetModuleFileName(module, buffer, MAX_PATH); |
| + if (rv == MAX_PATH) |
| + return name; |
| + |
| + buffer[MAX_PATH - 1] = L'\0'; |
| + name.assign(buffer); |
| + base::FilePath path(name); |
| + return path.BaseName().AsUTF16Unsafe(); |
| +} |
| + |
| +HMODULE GetChromeDLLModule() { |
| + HMODULE module; |
| + if (!GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | |
| + GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, |
| + reinterpret_cast<wchar_t*>(&GetChromeDLLModule), |
| + &module)) { |
| + return NULL; |
| + } |
| + return module; |
| +} |
| + |
| +} // namespace |
| + |
| +void InstallCloseHandleHooks() { |
| + if (!UseHooks()) |
| + return; |
| + |
| + base::win::EnableHandleVerifier(); |
| + CloseHandleHooks* hooks = g_hooks.Pointer(); |
| + hooks->AddIATPatch(L"chrome.exe"); |
| + hooks->AddIATPatch(GetModuleName(GetChromeDLLModule())); |
|
cpu_(ooo_6.6-7.5)
2014/08/22 01:52:05
can we just instead
AddIATPatch(L"chrome.dll") an
rvargas (doing something else)
2014/08/22 02:10:32
Patch() does LoadLibrary so it will not fail. And
cpu_(ooo_6.6-7.5)
2014/08/22 22:10:20
Acknowledged.
|
| +} |
| + |
| +void RemoveCloseHandleHooks() { |
| + g_hooks.Get().Unpatch(); |
| +} |