Index: chrome_frame/buggy_bho_handling.cc |
diff --git a/chrome_frame/buggy_bho_handling.cc b/chrome_frame/buggy_bho_handling.cc |
deleted file mode 100644 |
index 491bae5b408f5d53938d8e42cce9d339039a1421..0000000000000000000000000000000000000000 |
--- a/chrome_frame/buggy_bho_handling.cc |
+++ /dev/null |
@@ -1,237 +0,0 @@ |
-// Copyright (c) 2012 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/buggy_bho_handling.h" |
- |
-#include <algorithm> |
- |
-#include "base/logging.h" |
-#include "base/process/memory.h" |
-#include "base/win/scoped_comptr.h" |
-#include "chrome_frame/exception_barrier.h" |
-#include "chrome_frame/function_stub.h" |
-#include "chrome_frame/pin_module.h" |
-#include "chrome_frame/utils.h" |
-#include "chrome_frame/vtable_patch_manager.h" |
- |
-namespace buggy_bho { |
- |
-base::ThreadLocalPointer<BuggyBhoTls> BuggyBhoTls::s_bad_object_tls_; |
- |
-struct ModuleAndVersion { |
- const char* module_name_; |
- const uint32 major_version_; |
- const uint32 minor_version_; |
-}; |
- |
-const ModuleAndVersion kBuggyModules[] = { |
- { "askbar.dll", 4, 1 }, // troublemaker: 4.1.0.5. |
- { "gbieh.dll", 3, 8 }, // troublemaker: 3.8.14.12 |
- { "gbiehcef.dll", 3, 8 }, // troublemaker: 3.8.11.23 |
- { "alot.dll", 2, 5 }, // troublemaker: 2.5.12000.509 |
- { "ctbr.dll", 5, 1 }, // troublemaker: 5.1.0.95 |
- { "srchbxex.dll", 1, 2 }, // troublemaker: 1.2.123.0 |
- { "iedvtool32.dll", 8, 0 }, // troublemaker: 8.0.0.4 |
- { "mst164.dll", 9, 1 }, // troublemaker: 9.1.3700.1 |
- { "deposit_ie_com.dll", 0, 1 }, // troublemaker: 0.1.0.72 |
- { "rpshell32.dll", 6, 0 }, // troublemaker: 6.0.6000.1389 |
- { "msgsres.dll", 6, 0 }, // troublemaker: 6.0.6000.1389 |
- { "limewireinttb.dll", 4, 1 }, // troublemaker: 4.1.1.1000 |
- { "pxsecure.dll", 3, 0 }, // troublemaker: 3.0.5.220 |
- |
- // These BHOs seem to be out of the same buggy BHO factory |
- { "tbabso.dll", 4, 5 }, // troublemaker: 4.5.156.0 |
- { "tbabs0.dll.dll", 4, 5 }, // troublemaker: 4.5.156.0 |
- { "tbbes0.dll", 4, 5 }, // troublemaker: 4.5.153.0 |
- { "tbfre0.dll", 4, 5 }, // troublemaker: 4.5.181.1 |
- { "tbmypl.dll", 4, 5 }, // troublemaker: 4.5.181.3 |
- { "tbmul1.dll", 4, 5 }, // troublemaker: 4.5.181.1 |
- { "tbdow1.dll", 4, 5 }, // troublemaker: 4.5.167.0 |
- { "tbfree.dll", 4, 5 }, // troublemaker: 4.5.178.0 |
- |
- // Viruses? |
- { "msgsc2.dll", 0xffff, 0xffff }, // troublemaker: 1.2.3000.1 |
- { "essclis.dll", 0xffff, 0xffff }, // troublemaker: 4.3.1800.2 |
- { "snagwb.dll", 0xffff, 0xffff }, // troublemaker: 2.6.0.28 |
-}; |
- |
-bool IsBuggyBho(HMODULE mod) { |
- DCHECK(mod); |
- |
- char path[MAX_PATH * 2] = {0}; |
- ::GetModuleFileNameA(mod, path, arraysize(path)); |
- const char* file_name = ::PathFindFileNameA(path); |
- for (size_t i = 0; i < arraysize(kBuggyModules); ++i) { |
- if (lstrcmpiA(file_name, kBuggyModules[i].module_name_) == 0) { |
- uint32 version = 0; |
- GetModuleVersion(mod, &version, NULL); |
- const ModuleAndVersion& buggy = kBuggyModules[i]; |
- if (HIWORD(version) < buggy.major_version_ || |
- (HIWORD(version) == buggy.major_version_ && |
- LOWORD(version) <= buggy.minor_version_)) { |
- return true; |
- } |
- } |
- } |
- |
- return false; |
-} |
- |
-BuggyBhoTls::BuggyBhoTls() |
- : patched_(false) { |
- DCHECK(s_bad_object_tls_.Get() == NULL); |
- s_bad_object_tls_.Set(this); |
-} |
- |
-BuggyBhoTls::~BuggyBhoTls() { |
- DCHECK(BuggyBhoTls::GetInstance() == this); |
- s_bad_object_tls_.Set(NULL); |
-} |
- |
-void BuggyBhoTls::AddBuggyObject(IDispatch* obj) { |
- bad_objects_.push_back(obj); |
-} |
- |
-bool BuggyBhoTls::ShouldSkipInvoke(IDispatch* obj) const { |
- DCHECK(web_browser2_ != NULL); |
- if (IsChromeFrameDocument(web_browser2_)) { |
- return std::find(bad_objects_.begin(), bad_objects_.end(), obj) != |
- bad_objects_.end(); |
- } |
- return false; |
-} |
- |
-// static |
-BuggyBhoTls* BuggyBhoTls::GetInstance() { |
- BuggyBhoTls* tls_instance = s_bad_object_tls_.Get(); |
- if (!tls_instance) { |
- tls_instance = new BuggyBhoTls(); |
- DCHECK(s_bad_object_tls_.Get() != NULL); |
- } |
- return tls_instance; |
-} |
- |
-// static |
-void BuggyBhoTls::DestroyInstance() { |
- BuggyBhoTls* tls_instance = s_bad_object_tls_.Get(); |
- if (tls_instance) { |
- delete tls_instance; |
- DCHECK(s_bad_object_tls_.Get() == NULL); |
- } |
-} |
- |
-HRESULT BuggyBhoTls::PatchBuggyBHOs(IWebBrowser2* browser) { |
- if (patched_) |
- return S_FALSE; |
- |
- DCHECK(browser); |
- DCHECK(web_browser2_ == NULL); |
- |
- base::win::ScopedComPtr<IConnectionPointContainer> cpc; |
- HRESULT hr = cpc.QueryFrom(browser); |
- if (SUCCEEDED(hr)) { |
- const GUID sinks[] = { DIID_DWebBrowserEvents2, DIID_DWebBrowserEvents }; |
- for (size_t i = 0; i < arraysize(sinks); ++i) { |
- base::win::ScopedComPtr<IConnectionPoint> cp; |
- cpc->FindConnectionPoint(sinks[i], cp.Receive()); |
- if (cp) { |
- base::win::ScopedComPtr<IEnumConnections> connections; |
- cp->EnumConnections(connections.Receive()); |
- if (connections) { |
- CONNECTDATA cd = {0}; |
- DWORD fetched = 0; |
- while (connections->Next(1, &cd, &fetched) == S_OK && fetched) { |
- PatchIfBuggy(cd.pUnk, sinks[i]); |
- cd.pUnk->Release(); |
- fetched = 0; |
- } |
- } |
- } |
- } |
- } |
- patched_ = true; |
- web_browser2_ = browser; |
- return hr; |
-} |
- |
-bool BuggyBhoTls::PatchIfBuggy(IUnknown* unk, const IID& diid) { |
- DCHECK(unk); |
- PROC* methods = *reinterpret_cast<PROC**>(unk); |
- HMODULE mod = base::GetModuleFromAddress(methods[0]); |
- if (!IsBuggyBho(mod)) |
- return false; |
- |
- base::win::ScopedComPtr<IDispatch> disp; |
- HRESULT hr = unk->QueryInterface(diid, |
- reinterpret_cast<void**>(disp.Receive())); |
- if (FAILED(hr)) // Sometimes only IDispatch QI is supported |
- hr = disp.QueryFrom(unk); |
- DCHECK(SUCCEEDED(hr)); |
- |
- if (SUCCEEDED(hr)) { |
- const int kInvokeIndex = 6; |
- DCHECK(static_cast<IUnknown*>(disp) == unk); |
- if (SUCCEEDED(PatchInvokeMethod(&methods[kInvokeIndex]))) { |
- AddBuggyObject(disp); |
- } |
- } |
- return false; |
-} |
- |
-// static |
-STDMETHODIMP BuggyBhoTls::BuggyBhoInvoke(InvokeFunc original, IDispatch* me, |
- DISPID dispid, REFIID riid, LCID lcid, |
- WORD flags, DISPPARAMS* params, |
- VARIANT* result, EXCEPINFO* ei, |
- UINT* err) { |
- DVLOG(1) << __FUNCTION__; |
- |
- DCHECK(BuggyBhoTls::GetInstance()) |
- << "You must first have an instance of BuggyBhoTls on this thread"; |
- if (BuggyBhoTls::GetInstance() && |
- BuggyBhoTls::GetInstance()->ShouldSkipInvoke(me)) { |
- // Ignore this call and avoid the bug. |
- // TODO(tommi): Maybe we should check a specific list of DISPIDs too? |
- return S_OK; |
- } |
- |
- // No need to report crashes in those known-to-be-buggy DLLs. |
- ExceptionBarrierReportOnlyModule barrier; |
- return original(me, dispid, riid, lcid, flags, params, result, ei, err); |
-} |
- |
-// static |
-HRESULT BuggyBhoTls::PatchInvokeMethod(PROC* invoke) { |
- CCritSecLock lock(_pAtlModule->m_csStaticDataInitAndTypeInfo.m_sec, true); |
- |
- FunctionStub* stub = FunctionStub::FromCode(*invoke); |
- if (stub) |
- return S_FALSE; |
- |
- DWORD flags = 0; |
- if (!::VirtualProtect(invoke, sizeof(PROC), PAGE_EXECUTE_READWRITE, &flags)) |
- return AtlHresultFromLastError(); |
- |
- HRESULT hr = S_OK; |
- |
- stub = FunctionStub::Create(reinterpret_cast<uintptr_t>(*invoke), |
- BuggyBhoInvoke); |
- if (!stub) { |
- hr = E_OUTOFMEMORY; |
- } else { |
- if (!vtable_patch::internal::ReplaceFunctionPointer( |
- reinterpret_cast<void**>(invoke), stub->code(), |
- reinterpret_cast<void*>(stub->argument()))) { |
- hr = E_UNEXPECTED; |
- FunctionStub::Destroy(stub); |
- } else { |
- chrome_frame::PinModule(); // No backing out now. |
- ::FlushInstructionCache(::GetCurrentProcess(), invoke, sizeof(PROC)); |
- } |
- } |
- ::VirtualProtect(invoke, sizeof(PROC), flags, &flags); |
- return hr; |
-} |
- |
-} // end namespace buggy_bho |