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

Side by Side Diff: chrome_frame/buggy_bho_handling.cc

Issue 3031009: A different approach to avoid crashes in buggy 3rd party BHOs. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 10 years, 5 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chrome_frame/buggy_bho_handling.h ('k') | chrome_frame/chrome_active_document.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Property Changes:
Added: svn:eol-style
+ LF
OLDNEW
(Empty)
1 // Copyright (c) 2010 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.
4
5 #include "chrome_frame/buggy_bho_handling.h"
6
7 #include "base/logging.h"
8 #include "base/scoped_comptr_win.h"
9
10 #include "chrome_frame/function_stub.h"
11 #include "chrome_frame/utils.h"
12 #include "chrome_frame/vtable_patch_manager.h"
13
14 namespace buggy_bho {
15
16 base::ThreadLocalPointer<BuggyBhoTls> BuggyBhoTls::s_bad_object_tls_;
17
18 struct ModuleAndVersion {
19 const char* module_name_;
20 const uint32 major_version_;
21 const uint32 minor_version_;
22 };
23
24 const ModuleAndVersion kBuggyModules[] = {
25 { "askbar.dll", 4, 1 }, // troublemaker: 4.1.0.5.
26 { "gbieh.dll", 3, 8 }, // troublemaker: 3.8.14.12
27 { "gbiehcef.dll", 3, 8 }, // troublemaker: 3.8.11.23
28 { "alot.dll", 2, 5 }, // troublemaker: 2.5.12000.509
29 { "srchbxex.dll", 1, 2 }, // troublemaker: 1.2.123.0
30 { "tbabso.dll", 4, 5 }, // troublemaker: 4.5.156.0
31 { "tbabs0.dll.dll", 4, 5 }, // troublemaker: 4.5.156.0
32 { "tbbes0.dll", 4, 5 }, // troublemaker: 4.5.153.0
33 { "ctbr.dll", 5, 1 }, // troublemaker: 5.1.0.95
34
35 // Viruses?
36 { "msgsc2.dll", 0xffff, 0xffff }, // troublemaker: 1.2.3000.1
37 { "essclis.dll", 0xffff, 0xffff }, // troublemaker: 4.3.1800.2
38 };
39
40 bool IsBuggyBho(HMODULE mod) {
41 DCHECK(mod);
42
43 char path[MAX_PATH * 2] = {0};
44 ::GetModuleFileNameA(mod, path, arraysize(path));
45 const char* file_name = ::PathFindFileNameA(path);
46 for (size_t i = 0; i < arraysize(kBuggyModules); ++i) {
47 if (lstrcmpiA(file_name, kBuggyModules[i].module_name_) == 0) {
48 uint32 version = 0;
49 GetModuleVersion(mod, &version, NULL);
50 const ModuleAndVersion& buggy = kBuggyModules[i];
51 if (HIWORD(version) < buggy.major_version_ ||
52 (HIWORD(version) == buggy.major_version_ &&
53 LOWORD(version) <= buggy.minor_version_)) {
54 return true;
55 }
56 }
57 }
58
59 return false;
60 }
61
62 BuggyBhoTls::BuggyBhoTls() : previous_instance_(s_bad_object_tls_.Get()) {
63 s_bad_object_tls_.Set(this);
64 }
65
66 BuggyBhoTls::~BuggyBhoTls() {
67 DCHECK(FromCurrentThread() == this);
68 s_bad_object_tls_.Set(previous_instance_);
69 }
70
71 void BuggyBhoTls::AddBuggyObject(IDispatch* obj) {
72 bad_objects_.push_back(obj);
73 }
74
75 bool BuggyBhoTls::IsBuggyObject(IDispatch* obj) const {
76 return std::find(bad_objects_.begin(), bad_objects_.end(), obj) !=
77 bad_objects_.end();
78 }
79
80 // static
81 BuggyBhoTls* BuggyBhoTls::FromCurrentThread() {
82 return s_bad_object_tls_.Get();
83 }
84
85 // static
86 STDMETHODIMP BuggyBhoTls::BuggyBhoInvoke(InvokeFunc original, IDispatch* me,
87 DISPID dispid, REFIID riid, LCID lcid,
88 WORD flags, DISPPARAMS* params,
89 VARIANT* result, EXCEPINFO* ei,
90 UINT* err) {
91 DLOG(INFO) << __FUNCTION__;
92
93 const BuggyBhoTls* tls = BuggyBhoTls::FromCurrentThread();
94 if (tls && tls->IsBuggyObject(me)) {
95 // Ignore this call and avoid the bug.
96 // TODO(tommi): Maybe we should check a specific list of DISPIDs too?
97 return S_OK;
98 }
99
100 return original(me, dispid, riid, lcid, flags, params, result, ei, err);
101 }
102
103 // static
104 HRESULT BuggyBhoTls::PatchInvokeMethod(PROC* invoke) {
105 CCritSecLock lock(_pAtlModule->m_csStaticDataInitAndTypeInfo, true);
106
107 FunctionStub* stub = FunctionStub::FromCode(*invoke);
108 if (stub)
109 return S_FALSE;
110
111 DWORD flags = 0;
112 if (!::VirtualProtect(invoke, sizeof(PROC), PAGE_EXECUTE_READWRITE, &flags))
113 return AtlHresultFromLastError();
114
115 HRESULT hr = S_OK;
116
117 stub = FunctionStub::Create(reinterpret_cast<uintptr_t>(*invoke),
118 BuggyBhoInvoke);
119 if (!stub) {
120 hr = E_OUTOFMEMORY;
121 } else {
122 if (!vtable_patch::internal::ReplaceFunctionPointer(
123 reinterpret_cast<void**>(invoke), stub->code(),
124 reinterpret_cast<void*>(stub->argument()))) {
125 hr = E_UNEXPECTED;
126 FunctionStub::Destroy(stub);
127 } else {
128 ::FlushInstructionCache(::GetCurrentProcess(), invoke, sizeof(PROC));
129 }
130 }
131
132 ::VirtualProtect(invoke, sizeof(PROC), flags, &flags);
133
134 return hr;
135 }
136
137 // static
138 bool BuggyBhoTls::PatchIfBuggy(CONNECTDATA* cd, const IID& diid) {
139 DCHECK(cd);
140 PROC* methods = *reinterpret_cast<PROC**>(cd->pUnk);
141 HMODULE mod = GetModuleFromAddress(methods[0]);
142 if (!IsBuggyBho(mod))
143 return false;
144
145 ScopedComPtr<IDispatch> disp;
146 HRESULT hr = cd->pUnk->QueryInterface(diid,
147 reinterpret_cast<void**>(disp.Receive()));
148 if (FAILED(hr)) // Sometimes only IDispatch QI is supported
149 hr = disp.QueryFrom(cd->pUnk);
150 DCHECK(SUCCEEDED(hr));
151
152 if (SUCCEEDED(hr)) {
153 const int kInvokeIndex = 6;
154 DCHECK(static_cast<IUnknown*>(disp) == cd->pUnk);
155 if (SUCCEEDED(PatchInvokeMethod(&methods[kInvokeIndex]))) {
156 BuggyBhoTls* tls = BuggyBhoTls::FromCurrentThread();
157 DCHECK(tls);
158 if (tls) {
159 tls->AddBuggyObject(disp);
160 }
161 }
162 }
163
164 return false;
165 }
166
167 // static
168 HRESULT BuggyBhoTls::PatchBuggyBHOs(IWebBrowser2* browser) {
169 DCHECK(browser);
170 DCHECK(BuggyBhoTls::FromCurrentThread())
171 << "You must first have an instance of BuggyBhoTls on this thread";
172
173 ScopedComPtr<IConnectionPointContainer> cpc;
174 HRESULT hr = cpc.QueryFrom(browser);
175 if (SUCCEEDED(hr)) {
176 const GUID sinks[] = { DIID_DWebBrowserEvents2, DIID_DWebBrowserEvents };
177 for (size_t i = 0; i < arraysize(sinks); ++i) {
178 ScopedComPtr<IConnectionPoint> cp;
179 cpc->FindConnectionPoint(sinks[i], cp.Receive());
180 if (cp) {
181 ScopedComPtr<IEnumConnections> connections;
182 cp->EnumConnections(connections.Receive());
183 if (connections) {
184 CONNECTDATA cd = {0};
185 DWORD fetched = 0;
186 while (connections->Next(1, &cd, &fetched) == S_OK && fetched) {
187 PatchIfBuggy(&cd, sinks[i]);
188 cd.pUnk->Release();
189 fetched = 0;
190 }
191 }
192 }
193 }
194 }
195
196 return hr;
197 }
198
199 } // end namespace buggy_bho
OLDNEW
« no previous file with comments | « chrome_frame/buggy_bho_handling.h ('k') | chrome_frame/chrome_active_document.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698