Roll leveldb to r76.
[chromium-blink-merge.git] / chrome_frame / vtable_patch_manager.h
blob3e9e65b209b1ab3c02b055ac507a87485d45ad05
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_
8 #include <windows.h>
10 #include <list>
12 #include "base/synchronization/lock.h"
14 struct FunctionStub;
16 // This namespace provides methods to patch VTable methods of COM interfaces.
17 namespace vtable_patch {
19 // Internal implementation, exposed only for testing.
20 namespace internal {
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 {
34 int index_;
35 PROC method_;
36 FunctionStub* stub_;
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.
58 #if 0
59 // Used when dynamically patching zero or more (usually more than 1)
60 // implementations of a particular interface.
61 class DynamicPatchManager {
62 public:
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);
70 bool UnpatchAll();
72 protected:
73 struct PatchedObject {
74 void* vtable_;
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) {\
101 index, \
102 reinterpret_cast<PROC>(PatchFunction), \
103 NULL, \
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
124 // index set to -1.
125 #define END_VTABLE_PATCHES() \
126 -1, NULL, NULL \
129 #endif // CHROME_FRAME_VTABLE_PATCH_MANAGER_H_