Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(6395)

Unified Diff: chrome_frame/vtable_patch_manager.cc

Issue 218019: Initial import of the Chrome Frame codebase. Integration in chrome.gyp coming... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 11 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chrome_frame/vtable_patch_manager.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome_frame/vtable_patch_manager.cc
===================================================================
--- chrome_frame/vtable_patch_manager.cc (revision 0)
+++ chrome_frame/vtable_patch_manager.cc (revision 0)
@@ -0,0 +1,82 @@
+// Copyright (c) 2009 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_frame/vtable_patch_manager.h"
+
+#include "base/logging.h"
+
+#include "chrome_frame/function_stub.h"
+
+namespace vtable_patch {
+
+// Convenient definition of a VTABLE
+typedef PROC* Vtable;
+
+// Returns a pointer to the VTable of a COM interface.
+// @param unknown [in] The pointer of the COM interface.
+inline Vtable GetIFVTable(void* unknown) {
+ return reinterpret_cast<Vtable>(*reinterpret_cast<void**>(unknown));
+}
+
+HRESULT PatchInterfaceMethods(void* unknown, MethodPatchInfo* patches) {
+ // Do some sanity checking of the input arguments.
+ if (NULL == unknown || NULL == patches) {
+ NOTREACHED();
+ return E_INVALIDARG;
+ }
+
+ Vtable vtable = GetIFVTable(unknown);
+ DCHECK(vtable);
+
+ for (MethodPatchInfo* it = patches; it->index_ != -1; ++it) {
+ PROC original_fn = vtable[it->index_];
+ FunctionStub* stub = FunctionStub::FromCode(original_fn);
+ if (stub != NULL) {
+ DLOG(ERROR) << "attempt to patch a function that's already patched";
+ DCHECK(stub->absolute_target() ==
+ reinterpret_cast<uintptr_t>(it->method_)) <<
+ "patching the same method multiple times with different hooks?";
+ continue;
+ }
+
+ stub = FunctionStub::Create(reinterpret_cast<uintptr_t>(original_fn),
+ it->method_);
+ if (!stub) {
+ NOTREACHED();
+ return E_OUTOFMEMORY;
+ } else {
+ DWORD protect = 0;
+ if (::VirtualProtect(&vtable[it->index_], sizeof(PROC),
+ PAGE_EXECUTE_READWRITE, &protect)) {
+ it->stub_ = stub; // save the stub
+ vtable[it->index_] = stub->code();
+ ::VirtualProtect(&vtable[it->index_], sizeof(PROC), protect,
+ &protect);
+ } else {
+ NOTREACHED();
+ }
+ }
+ }
+
+ return S_OK;
+}
+
+HRESULT UnpatchInterfaceMethods(MethodPatchInfo* patches) {
+ for (MethodPatchInfo* it = patches; it->index_ != -1; ++it) {
+ if (it->stub_) {
+ DCHECK(it->stub_->absolute_target() ==
+ reinterpret_cast<uintptr_t>(it->method_));
+ // Modify the stub to just jump directly to the original function.
+ it->stub_->BypassStub(reinterpret_cast<void*>(it->stub_->argument()));
+ it->stub_ = NULL;
+ // Leave the stub in memory so that we won't break any possible chains.
+ } else {
+ DLOG(WARNING) << "attempt to unpatch a function that wasn't patched";
+ }
+ }
+
+ return S_OK;
+}
+
+} // namespace vtable_patch
« no previous file with comments | « chrome_frame/vtable_patch_manager.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698