1 // Copyright (c) 2009 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #ifndef CHROME_FRAME_VTABLE_PATCH_MANAGER_H_
6 #define CHROME_FRAME_VTABLE_PATCH_MANAGER_H_
12 #include "base/synchronization/lock.h"
16 // This namespace provides methods to patch VTable methods of COM interfaces.
17 namespace vtable_patch
{
19 // Internal implementation, exposed only for testing.
22 // Replaces *entry with new_proc iff *entry is curr_proc.
23 // Returns true iff *entry was rewritten.
24 // Note: does not crash on access violation.
25 bool ReplaceFunctionPointer(void** entry
, void* new_proc
, void* curr_proc
);
27 } // namespace internal
29 // This structure represents information about one VTable method.
30 // We allocate an array of these structures per VTable that we patch to
31 // remember the original method. We also use this structure to actually
32 // describe the VTable patch functions
33 struct MethodPatchInfo
{
39 // Patches methods in the passed in COM interface. The indexes of the
40 // methods to patch and the actual patch functions are described in the
41 // array pointed to by patches.
42 // @param[in] unknown The pointer of the COM interface to patch
43 // @param[in] patches An array of MethodPatchInfo structures describing
44 // the methods to patch and the patch functions.
45 // The last entry of patches must have index_ set to -1.
46 HRESULT
PatchInterfaceMethods(void* unknown
, MethodPatchInfo
* patches
);
48 // Using the patch info provided in |patches| the function goes through the
49 // list of patched methods and modifies thunks so that they no longer point
50 // to a hook method but rather go straight through to the original target.
51 // The thunk itself is not destroyed to support chaining.
52 // @param[in] patches An array of MethodPatchInfo structures describing
53 // the methods to patch and the patch functions.
54 // The last entry of patches must have index_ set to -1.
55 HRESULT
UnpatchInterfaceMethods(MethodPatchInfo
* patches
);
57 // Disabled as we're not using it atm.
59 // Used when dynamically patching zero or more (usually more than 1)
60 // implementations of a particular interface.
61 class DynamicPatchManager
{
63 explicit DynamicPatchManager(const MethodPatchInfo
* patch_prototype
);
64 ~DynamicPatchManager();
66 // Returns S_OK if the object was successfully patched, S_FALSE if it was
67 // already patched or an error value if something bad happened.
68 HRESULT
PatchObject(void* unknown
);
73 struct PatchedObject
{
75 MethodPatchInfo patch_info_
[1];
77 // Used to match PatchedObject instances based on the vtable when
78 // searching through the patch list.
79 bool operator==(const PatchedObject
& that
) const {
80 return vtable_
== that
.vtable_
;
84 typedef std::list
<PatchedObject
*> PatchList
;
85 const MethodPatchInfo
* patch_prototype_
;
86 mutable base::Lock patch_list_lock_
;
87 PatchList patch_list_
;
89 #endif // disable DynamicPatchManager
91 } // namespace vtable_patch
93 // Begins the declaration of a VTable patch
94 // @param IFName The name of the interface to patch
95 #define BEGIN_VTABLE_PATCHES(IFName) \
96 vtable_patch::MethodPatchInfo IFName##_PatchInfo[] = {
97 // Defines a single method patch in a VTable
98 // @param index The index of the method to patch
99 // @param PatchFunction The patch function
100 #define VTABLE_PATCH_ENTRY(index, PatchFunction) {\
102 reinterpret_cast<PROC>(PatchFunction), \
106 #define DCHECK_IS_NOT_PATCHED(IFName) \
107 for (vtable_patch::MethodPatchInfo* it = IFName##_PatchInfo; \
108 it->index_ != -1; ++it) { \
109 DCHECK(it->stub_ == NULL); \
112 #define DCHECK_IS_PATCHED(IFName) \
113 for (vtable_patch::MethodPatchInfo* it = IFName##_PatchInfo; \
114 it->index_ != -1; ++it) { \
115 DCHECK(it->stub_ != NULL); \
118 // Checks if the interface is patched. Note that only the first method
119 // is checked and subsequent methods are assumed to have the same state.
120 #define IS_PATCHED(IFName) \
121 (IFName##_PatchInfo[0].stub_ != NULL)
123 // Ends the declaration of a VTable patch by adding an entry with
125 #define END_VTABLE_PATCHES() \
129 #endif // CHROME_FRAME_VTABLE_PATCH_MANAGER_H_