diff options
Diffstat (limited to 'chrome_frame/buggy_bho_handling.cc')
-rw-r--r-- | chrome_frame/buggy_bho_handling.cc | 199 |
1 files changed, 0 insertions, 199 deletions
diff --git a/chrome_frame/buggy_bho_handling.cc b/chrome_frame/buggy_bho_handling.cc deleted file mode 100644 index 1c6df94..0000000 --- a/chrome_frame/buggy_bho_handling.cc +++ /dev/null @@ -1,199 +0,0 @@ -// Copyright (c) 2010 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 "base/logging.h" -#include "base/scoped_comptr_win.h" - -#include "chrome_frame/function_stub.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 - { "srchbxex.dll", 1, 2 }, // troublemaker: 1.2.123.0 - { "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 - { "ctbr.dll", 5, 1 }, // troublemaker: 5.1.0.95 - - // Viruses? - { "msgsc2.dll", 0xffff, 0xffff }, // troublemaker: 1.2.3000.1 - { "essclis.dll", 0xffff, 0xffff }, // troublemaker: 4.3.1800.2 -}; - -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() : previous_instance_(s_bad_object_tls_.Get()) { - s_bad_object_tls_.Set(this); -} - -BuggyBhoTls::~BuggyBhoTls() { - DCHECK(FromCurrentThread() == this); - s_bad_object_tls_.Set(previous_instance_); -} - -void BuggyBhoTls::AddBuggyObject(IDispatch* obj) { - bad_objects_.push_back(obj); -} - -bool BuggyBhoTls::IsBuggyObject(IDispatch* obj) const { - return std::find(bad_objects_.begin(), bad_objects_.end(), obj) != - bad_objects_.end(); -} - -// static -BuggyBhoTls* BuggyBhoTls::FromCurrentThread() { - return s_bad_object_tls_.Get(); -} - -// static -STDMETHODIMP BuggyBhoTls::BuggyBhoInvoke(InvokeFunc original, IDispatch* me, - DISPID dispid, REFIID riid, LCID lcid, - WORD flags, DISPPARAMS* params, - VARIANT* result, EXCEPINFO* ei, - UINT* err) { - DLOG(INFO) << __FUNCTION__; - - const BuggyBhoTls* tls = BuggyBhoTls::FromCurrentThread(); - if (tls && tls->IsBuggyObject(me)) { - // Ignore this call and avoid the bug. - // TODO(tommi): Maybe we should check a specific list of DISPIDs too? - return S_OK; - } - - return original(me, dispid, riid, lcid, flags, params, result, ei, err); -} - -// static -HRESULT BuggyBhoTls::PatchInvokeMethod(PROC* invoke) { - CCritSecLock lock(_pAtlModule->m_csStaticDataInitAndTypeInfo, 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 { - ::FlushInstructionCache(::GetCurrentProcess(), invoke, sizeof(PROC)); - } - } - - ::VirtualProtect(invoke, sizeof(PROC), flags, &flags); - - return hr; -} - -// static -bool BuggyBhoTls::PatchIfBuggy(CONNECTDATA* cd, const IID& diid) { - DCHECK(cd); - PROC* methods = *reinterpret_cast<PROC**>(cd->pUnk); - HMODULE mod = GetModuleFromAddress(methods[0]); - if (!IsBuggyBho(mod)) - return false; - - ScopedComPtr<IDispatch> disp; - HRESULT hr = cd->pUnk->QueryInterface(diid, - reinterpret_cast<void**>(disp.Receive())); - if (FAILED(hr)) // Sometimes only IDispatch QI is supported - hr = disp.QueryFrom(cd->pUnk); - DCHECK(SUCCEEDED(hr)); - - if (SUCCEEDED(hr)) { - const int kInvokeIndex = 6; - DCHECK(static_cast<IUnknown*>(disp) == cd->pUnk); - if (SUCCEEDED(PatchInvokeMethod(&methods[kInvokeIndex]))) { - BuggyBhoTls* tls = BuggyBhoTls::FromCurrentThread(); - DCHECK(tls); - if (tls) { - tls->AddBuggyObject(disp); - } - } - } - - return false; -} - -// static -HRESULT BuggyBhoTls::PatchBuggyBHOs(IWebBrowser2* browser) { - DCHECK(browser); - DCHECK(BuggyBhoTls::FromCurrentThread()) - << "You must first have an instance of BuggyBhoTls on this thread"; - - 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) { - ScopedComPtr<IConnectionPoint> cp; - cpc->FindConnectionPoint(sinks[i], cp.Receive()); - if (cp) { - 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, sinks[i]); - cd.pUnk->Release(); - fetched = 0; - } - } - } - } - } - - return hr; -} - -} // end namespace buggy_bho |