summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrobertshield@chromium.org <robertshield@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-05-07 21:34:41 +0000
committerrobertshield@chromium.org <robertshield@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-05-07 21:34:41 +0000
commit527498450ae8b478b6719d4603be03dfcdc8d812 (patch)
tree2541c8d121be167019726fefbab7dbad9f4887a6
parent1ee1f5b477243b2ab53cc31dc979e510b5d0aac9 (diff)
downloadchromium_src-527498450ae8b478b6719d4603be03dfcdc8d812.zip
chromium_src-527498450ae8b478b6719d4603be03dfcdc8d812.tar.gz
chromium_src-527498450ae8b478b6719d4603be03dfcdc8d812.tar.bz2
Change to a simpler upgrade scheme for Chrome Frame whereby we register a window class in DllMain on attach and tag it with our module handle, then unregister said window class on detach.
BUG=43343 Review URL: http://codereview.chromium.org/1994007 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@46738 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome_frame/chrome_frame.gyp1
-rw-r--r--chrome_frame/chrome_tab.cc40
-rw-r--r--chrome_frame/module_utils.cc186
-rw-r--r--chrome_frame/module_utils.h72
-rw-r--r--chrome_frame/test/module_utils_unittest.cc196
5 files changed, 90 insertions, 405 deletions
diff --git a/chrome_frame/chrome_frame.gyp b/chrome_frame/chrome_frame.gyp
index b3cafe3..d47348a 100644
--- a/chrome_frame/chrome_frame.gyp
+++ b/chrome_frame/chrome_frame.gyp
@@ -227,7 +227,6 @@
'test/chrome_frame_automation_mock.h',
'test/http_server.cc',
'test/http_server.h',
- 'test/module_utils_unittest.cc',
'test/proxy_factory_mock.cc',
'test/proxy_factory_mock.h',
'test/run_all_unittests.cc',
diff --git a/chrome_frame/chrome_tab.cc b/chrome_frame/chrome_tab.cc
index a00f814f..d7ca25d 100644
--- a/chrome_frame/chrome_tab.cc
+++ b/chrome_frame/chrome_tab.cc
@@ -75,8 +75,7 @@ OBJECT_ENTRY_AUTO(__uuidof(ChromeProtocol), ChromeProtocol)
// See comments in DllGetClassObject.
-DllRedirector g_dll_redirector;
-Lock g_redirector_lock;
+LPFNGETCLASSOBJECT g_dll_get_class_object_redir_ptr = NULL;
class ChromeTabModule
: public AtlPerUserModule<CAtlDllModuleT<ChromeTabModule> > {
@@ -173,9 +172,27 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE instance,
InitializeCrashReporting();
logging::InitLogging(NULL, logging::LOG_ONLY_TO_SYSTEM_DEBUG_LOG,
logging::LOCK_LOG_FILE, logging::DELETE_OLD_LOG_FILE);
+
+ if (!DllRedirector::RegisterAsFirstCFModule()) {
+ // We are not the first ones in, get the module who registered first.
+ HMODULE original_module = DllRedirector::GetFirstCFModule();
+ DCHECK(original_module != NULL)
+ << "Could not get first CF module handle.";
+ HMODULE this_module = reinterpret_cast<HMODULE>(&__ImageBase);
+ if (original_module != this_module) {
+ // Someone else was here first, try and get a pointer to their
+ // DllGetClassObject export:
+ g_dll_get_class_object_redir_ptr =
+ DllRedirector::GetDllGetClassObjectPtr(original_module);
+ DCHECK(g_dll_get_class_object_redir_ptr != NULL)
+ << "Found CF module with no DllGetClassObject export.";
+ }
+ }
+
// Enable ETW logging.
logging::LogEventProvider::Initialize(kChromeFrameProvider);
} else if (reason == DLL_PROCESS_DETACH) {
+ DllRedirector::UnregisterAsFirstCFModule();
g_patch_helper.UnpatchIfNeeded();
delete g_exit_manager;
g_exit_manager = NULL;
@@ -322,21 +339,10 @@ STDAPI DllCanUnloadNow() {
// Returns a class factory to create an object of the requested type
STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv) {
- // On first call, we scan the loaded module list to see if an older version
- // of Chrome Frame is already loaded. If it is, then we delegate all calls
- // to DllGetClassObject to it. This is to avoid having instances of
- // different versions of e.g. the BHO through an upgrade. It also prevents
- // us from repeatedly patching.
- LPFNGETCLASSOBJECT redir_ptr = NULL;
- {
- AutoLock lock(g_redirector_lock);
- g_dll_redirector.EnsureInitialized(L"npchrome_frame.dll",
- CLSID_ChromeActiveDocument);
- redir_ptr = g_dll_redirector.get_dll_get_class_object_ptr();
- }
-
- if (redir_ptr) {
- return redir_ptr(rclsid, riid, ppv);
+ // If we found another module present when we were loaded, then delegate to
+ // that:
+ if (g_dll_get_class_object_redir_ptr) {
+ return g_dll_get_class_object_redir_ptr(rclsid, riid, ppv);
} else {
g_patch_helper.InitializeAndPatchProtocolsIfNeeded();
return _AtlModule.DllGetClassObject(rclsid, riid, ppv);
diff --git a/chrome_frame/module_utils.cc b/chrome_frame/module_utils.cc
index f0e0e3f..df0ea68 100644
--- a/chrome_frame/module_utils.cc
+++ b/chrome_frame/module_utils.cc
@@ -5,161 +5,77 @@
#include "chrome_frame/module_utils.h"
#include <atlbase.h>
-#include <TlHelp32.h>
-
-#include "base/scoped_ptr.h"
-#include "base/file_version_info.h"
#include "base/logging.h"
-#include "base/scoped_handle.h"
-#include "base/string_util.h"
-#include "base/version.h"
-#include "chrome_frame/exception_barrier.h"
-
-DllRedirector::DllRedirector() : dcgo_ptr_(NULL), initialized_(false),
- module_handle_(NULL) {}
-
-DllRedirector::~DllRedirector() {
- if (module_handle_) {
- FreeLibrary(module_handle_);
- module_handle_ = NULL;
- }
-}
-void DllRedirector::EnsureInitialized(const wchar_t* module_name,
- REFCLSID clsid) {
- if (!initialized_) {
- initialized_ = true;
- // Also sets module_handle_.
- dcgo_ptr_ = GetDllGetClassObjectFromModuleName(module_name, clsid);
- }
-}
+const wchar_t kBeaconWindowClassName[] =
+ L"ChromeFrameBeaconWindowClass826C5D01-E355-4b23-8AC2-40650E0B7843";
-LPFNGETCLASSOBJECT DllRedirector::get_dll_get_class_object_ptr() const {
- DCHECK(initialized_);
- return dcgo_ptr_;
-}
+// static
+ATOM DllRedirector::atom_ = 0;
-LPFNGETCLASSOBJECT DllRedirector::GetDllGetClassObjectFromModuleName(
- const wchar_t* module_name, REFCLSID clsid) {
- module_handle_ = NULL;
- LPFNGETCLASSOBJECT proc_ptr = NULL;
- HMODULE module_handle;
- if (GetOldestNamedModuleHandle(module_name, clsid, &module_handle)) {
- HMODULE this_module = reinterpret_cast<HMODULE>(&__ImageBase);
- if (module_handle != this_module) {
- proc_ptr = GetDllGetClassObjectPtr(module_handle);
- if (proc_ptr) {
- // Stash away the module handle in module_handle_ so that it will be
- // automatically closed when we get destroyed. GetDllGetClassObjectPtr
- // above will have incremented the module's ref count.
- module_handle_ = module_handle;
- }
- } else {
- LOG(INFO) << "Module Scan: DllGetClassObject found in current module.";
- }
+bool DllRedirector::RegisterAsFirstCFModule() {
+ // This would imply that this module had already registered a window class
+ // which should never happen.
+ if (atom_) {
+ NOTREACHED();
+ return true;
}
- return proc_ptr;
-}
-
-bool DllRedirector::GetOldestNamedModuleHandle(const std::wstring& module_name,
- REFCLSID clsid,
- HMODULE* oldest_module_handle) {
- DCHECK(oldest_module_handle);
+ WNDCLASSEX wnd_class = {0};
+ wnd_class.cbSize = sizeof(WNDCLASSEX);
+ wnd_class.style = CS_GLOBALCLASS;
+ wnd_class.lpfnWndProc = &DefWindowProc;
+ wnd_class.cbClsExtra = sizeof(HMODULE);
+ wnd_class.cbWndExtra = 0;
+ wnd_class.hInstance = NULL;
+ wnd_class.hIcon = NULL;
- ScopedHandle snapshot(CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, 0));
- if (snapshot == INVALID_HANDLE_VALUE) {
- LOG(ERROR) << "Could not create module snapshot!";
- return false;
- }
+ wnd_class.hCursor = LoadCursor(NULL, IDC_ARROW);
+ wnd_class.hbrBackground = NULL;
+ wnd_class.lpszMenuName = NULL;
+ wnd_class.lpszClassName = kBeaconWindowClassName;
+ wnd_class.hIconSm = wnd_class.hIcon;
+ ATOM atom = RegisterClassEx(&wnd_class);
bool success = false;
- PathToHModuleMap map;
-
- {
- // Here we add an SEH to the chain to prevent our VEH from picking up on any
- // exceptions thrown in DLLs who hook some of the below api calls. We will
- // still report the exceptions if they make our way back to us, the hope is
- // that they will not.
- ExceptionBarrier exception_barrier;
-
- // First get the list of module paths, and save the full path to base
- // address mapping.
- MODULEENTRY32W module_entry = {0};
- module_entry.dwSize = sizeof(module_entry);
- BOOL cont = Module32FirstW(snapshot, &module_entry);
- while (cont) {
- if (!lstrcmpi(module_entry.szModule, module_name.c_str())) {
- std::wstring full_path(module_entry.szExePath);
- map[full_path] = module_entry.hModule;
+ if (atom != 0) {
+ HWND hwnd = CreateWindow(MAKEINTATOM(atom), L"temp_window", WS_POPUP,
+ 0, 0, 0, 0, NULL, NULL, NULL, NULL);
+ DCHECK(IsWindow(hwnd));
+ if (hwnd) {
+ HMODULE this_module = reinterpret_cast<HMODULE>(&__ImageBase);
+ LONG_PTR lp = reinterpret_cast<LONG_PTR>(this_module);
+ SetClassLongPtr(hwnd, 0, lp);
+ // We need to check the GLE value since SetClassLongPtr returns 0 on
+ // failure as well as on the first call.
+ if (GetLastError() == ERROR_SUCCESS) {
+ atom_ = atom;
+ success = true;
}
- SecureZeroMemory(&module_entry, sizeof(MODULEENTRY32W));
- module_entry.dwSize = sizeof(module_entry);
- cont = Module32NextW(snapshot, &module_entry);
+ DestroyWindow(hwnd);
}
}
- // Next, enumerate the map and find the oldest version of the module.
- // (check if the map is of size 1 first)
- if (!map.empty()) {
- if (map.size() == 1) {
- *oldest_module_handle = map.begin()->second;
- } else {
- *oldest_module_handle = GetHandleOfOldestModule(map, clsid);
- }
+ return success;
+}
- if (*oldest_module_handle != NULL) {
- success = true;
- }
- } else {
- LOG(INFO) << "Module Scan: No modules named " << module_name
- << " were found.";
+void DllRedirector::UnregisterAsFirstCFModule() {
+ if (atom_) {
+ UnregisterClass(MAKEINTATOM(atom_), NULL);
}
-
- return success;
}
-HMODULE DllRedirector::GetHandleOfOldestModule(const PathToHModuleMap& map,
- REFCLSID clsid) {
+HMODULE DllRedirector::GetFirstCFModule() {
+ WNDCLASSEX wnd_class = {0};
HMODULE oldest_module = NULL;
- scoped_ptr<Version> min_version(
- Version::GetVersionFromString("999.999.999.999"));
-
- PathToHModuleMap::const_iterator map_iter(map.begin());
- for (; map_iter != map.end(); ++map_iter) {
- // First check that either we are in the current module or that the DLL
- // returns a class factory for our clsid.
- bool current_module =
- (map_iter->second == reinterpret_cast<HMODULE>(&__ImageBase));
- bool gco_succeeded = false;
- if (!current_module) {
- LPFNGETCLASSOBJECT dgco_ptr = GetDllGetClassObjectPtr(map_iter->second);
- if (dgco_ptr) {
- {
- CComPtr<IClassFactory> class_factory;
- HRESULT hr = dgco_ptr(clsid, IID_IClassFactory,
- reinterpret_cast<void**>(&class_factory));
- gco_succeeded = SUCCEEDED(hr) && class_factory != NULL;
- }
- // Release the module ref count we picked up in GetDllGetClassObjectPtr.
- FreeLibrary(map_iter->second);
- }
- }
-
- if (current_module || gco_succeeded) {
- // Then check that the version is less than we've already found:
- scoped_ptr<FileVersionInfo> version_info(
- FileVersionInfo::CreateFileVersionInfo(map_iter->first));
- scoped_ptr<Version> version(
- Version::GetVersionFromString(version_info->file_version()));
- if (version->CompareTo(*min_version.get()) < 0) {
- oldest_module = map_iter->second;
- min_version.reset(version.release());
- }
- }
+ HWND hwnd = CreateWindow(kBeaconWindowClassName, L"temp_window", WS_POPUP, 0,
+ 0, 0, 0, NULL, NULL, NULL, NULL);
+ DCHECK(IsWindow(hwnd));
+ if (hwnd) {
+ oldest_module = reinterpret_cast<HMODULE>(GetClassLongPtr(hwnd, 0));
+ DestroyWindow(hwnd);
}
-
return oldest_module;
}
diff --git a/chrome_frame/module_utils.h b/chrome_frame/module_utils.h
index e5d8a68..4cdf4b8 100644
--- a/chrome_frame/module_utils.h
+++ b/chrome_frame/module_utils.h
@@ -8,71 +8,31 @@
#include <ObjBase.h>
#include <windows.h>
-#include <map>
-
-// A helper class that will find the named loaded module in the current
-// process with the lowest version, increment its ref count and return
-// a pointer to its DllGetClassObject() function if it exports one. If
-// the oldest named module is the current module, then this class does nothing
-// (does not muck with module ref count) and calls to
-// get_dll_get_class_object_ptr() will return NULL.
class DllRedirector {
public:
- typedef std::map<std::wstring, HMODULE> PathToHModuleMap;
-
- DllRedirector();
- ~DllRedirector();
-
- // Must call this before calling get_dll_get_class_object_ptr(). On first call
- // this performs the work of scanning the loaded modules for an old version
- // to delegate to. Not thread safe.
- void EnsureInitialized(const wchar_t* module_name, REFCLSID clsid);
+ // Attempts to register a window class under a well known name and appends to
+ // its extra data a handle to the current module. Will fail if the window
+ // class is already registered. This is intended to be called from DllMain
+ // under PROCESS_ATTACH.
+ static bool DllRedirector::RegisterAsFirstCFModule();
- LPFNGETCLASSOBJECT get_dll_get_class_object_ptr() const;
-
- private:
+ // Unregisters the well known window class if we registered it earlier.
+ // This is intended to be called from DllMain under PROCESS_DETACH.
+ static void DllRedirector::UnregisterAsFirstCFModule();
- // Returns the pointer to the named loaded module's DllGetClassObject export
- // or NULL if either the pointer could not be found or if the pointer would
- // point into the current module.
- // Sets module_handle_ and increments the modules reference count.
- //
- // For sanity's sake, the module must return a non-null class factory for
- // the given class id.
- LPFNGETCLASSOBJECT GetDllGetClassObjectFromModuleName(
- const wchar_t* module_name, REFCLSID clsid);
+ // Helper function that extracts the HMODULE parameter from our well known
+ // window class.
+ static HMODULE GetFirstCFModule();
- // Returns a handle in |module_handle| to the loaded module called
- // |module_name| in the current process. If there are multiple modules with
- // the same name, it returns the module with the oldest version number in its
- // VERSIONINFO block. The version string is expected to be of a form that
- // base::Version can parse.
- //
- // For sanity's sake, when there are multiple instances of the module,
- // |product_short_name|, if non-NULL, must match the module's
- // ProductShortName value
- //
- // Returns true if a named module with the given ProductShortName can be
- // found, returns false otherwise. Can return the current module handle.
- bool GetOldestNamedModuleHandle(const std::wstring& module_name,
- REFCLSID clsid,
- HMODULE* module_handle);
-
- // Given a PathToBaseAddressMap, iterates over the module images whose paths
- // are the keys and returns the handle to the module with the lowest
- // version number in its VERSIONINFO block whose DllGetClassObject returns a
- // class factory for the given CLSID.
- HMODULE GetHandleOfOldestModule(const PathToHModuleMap& map, REFCLSID clsid);
-
- private:
// Helper function to return the DllGetClassObject function pointer from
// the given module. On success, the return value is non-null and module
// will have had its reference count incremented.
- LPFNGETCLASSOBJECT GetDllGetClassObjectPtr(HMODULE module);
+ static LPFNGETCLASSOBJECT GetDllGetClassObjectPtr(HMODULE module);
- HMODULE module_handle_;
- LPFNGETCLASSOBJECT dcgo_ptr_;
- bool initialized_;
+ private:
+ // Use this to keep track of whether or not we have registered the window
+ // class in this module.
+ static ATOM atom_;
friend class ModuleUtilsTest;
};
diff --git a/chrome_frame/test/module_utils_unittest.cc b/chrome_frame/test/module_utils_unittest.cc
deleted file mode 100644
index 88d52f7..0000000
--- a/chrome_frame/test/module_utils_unittest.cc
+++ /dev/null
@@ -1,196 +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.
-
-// This test requires loading a set of DLLs from the chrome_frame\test\data
-// directory into the process and then inspecting them. As such, it is
-// part of chrome_frame_tests.exe and not chrome_frame_unittests.exe which
-// needs to run as a standalone test. No test is an island except for
-// chrome_frame_unittests.exe.
-
-#include "chrome_frame/module_utils.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-#include "base/logging.h"
-#include "base/file_path.h"
-#include "base/path_service.h"
-#include "chrome_frame/test_utils.h"
-
-#include "chrome_tab.h" // NOLINT
-
-class ModuleUtilsTest : public testing::Test {
- protected:
- // Constructor
- ModuleUtilsTest() {}
-
- // Returns the full path to the test DLL given a name.
- virtual bool GetDllPath(const std::wstring& dll_name, std::wstring* path) {
- if (!path) {
- return false;
- }
-
- FilePath test_path;
- if (!PathService::Get(base::DIR_SOURCE_ROOT, &test_path)) {
- return false;
- }
-
- test_path = test_path.Append(L"chrome_frame")
- .Append(L"test")
- .Append(L"data")
- .Append(L"test_dlls")
- .Append(FilePath(dll_name));
-
- *path = test_path.value();
- return true;
- }
-
- // Loads the CF Dll and returns its path in |cf_dll_path|.
- virtual bool LoadChromeFrameDll(std::wstring* cf_dll_path) {
- DCHECK(cf_dll_path);
- // Look for the CF dll in both the current directory and in servers.
- FilePath dll_path = ScopedChromeFrameRegistrar::GetChromeFrameBuildPath();
-
- bool success = false;
- if (!dll_path.empty()) {
- cf_dll_path_ = dll_path.value();
- HMODULE handle = LoadLibrary(cf_dll_path_.c_str());
- if (handle) {
- hmodule_map_[cf_dll_path_] = handle;
- *cf_dll_path = cf_dll_path_;
- success = true;
- } else {
- LOG(ERROR) << "Failed to load test dll: " << dll_path.value();
- }
- }
-
- return success;
- }
-
- virtual bool LoadTestDll(const std::wstring& dll_name) {
- bool success = false;
- std::wstring dll_path;
- if (GetDllPath(dll_name, &dll_path)) {
- HMODULE handle = LoadLibrary(dll_path.c_str());
- if (handle) {
- hmodule_map_[dll_name] = handle;
- success = true;
- } else {
- LOG(ERROR) << "Failed to load test dll: " << dll_name;
- }
- } else {
- LOG(ERROR) << "Failed to get dll path for " << dll_name;
- }
- return success;
- }
-
- // Unload any DLLs we have loaded and make sure they stay unloaded.
- virtual void TearDown() {
- DllRedirector::PathToHModuleMap::const_iterator iter(hmodule_map_.begin());
- for (; iter != hmodule_map_.end(); ++iter) {
- FreeLibrary(iter->second);
- }
-
- // Check that the modules were actually unloaded (i.e. we had no dangling
- // references). Do this after freeing all modules since they can have
- // references to each other.
- for (iter = hmodule_map_.begin(); iter != hmodule_map_.end(); ++iter) {
- // The CF module gets pinned, so don't check that that is unloaded.
- if (iter->first != cf_dll_path_) {
- HMODULE temp_handle;
- ASSERT_FALSE(GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
- reinterpret_cast<LPCTSTR>(iter->second),
- &temp_handle));
- }
- }
-
- hmodule_map_.clear();
- }
-
- DllRedirector::PathToHModuleMap hmodule_map_;
- std::wstring cf_dll_path_;
-};
-
-// Tests that if we load a few versions of the same module that all export
-// DllGetClassObject, that we correctly a) find a DllGetClassObject function
-// pointer and b) find it in the right module.
-TEST_F(ModuleUtilsTest, BasicTest) {
- ASSERT_TRUE(LoadTestDll(L"3\\TestDll.dll"));
- ASSERT_TRUE(LoadTestDll(L"2\\TestDll.dll"));
- ASSERT_TRUE(LoadTestDll(L"1\\TestDll.dll"));
-
- DllRedirector redir;
- redir.EnsureInitialized(L"TestDll.dll", CLSID_ChromeActiveDocument);
-
- LPFNGETCLASSOBJECT found_ptr = redir.get_dll_get_class_object_ptr();
- EXPECT_TRUE(found_ptr != NULL);
-
- LPFNGETCLASSOBJECT direct_ptr = reinterpret_cast<LPFNGETCLASSOBJECT>(
- GetProcAddress(hmodule_map_[L"1\\TestDll.dll"],
- "DllGetClassObject"));
- EXPECT_TRUE(direct_ptr != NULL);
-
- EXPECT_EQ(found_ptr, direct_ptr);
-}
-
-// Tests that a DLL that does not return a class factory for a Chrome Frame
-// guid even though it has a lower version string.
-TEST_F(ModuleUtilsTest, NoCFDllTest) {
- ASSERT_TRUE(LoadTestDll(L"1\\TestDll.dll"));
- ASSERT_TRUE(LoadTestDll(L"TestDllNoCF\\TestDll.dll"));
-
- DllRedirector redir;
- redir.EnsureInitialized(L"TestDll.dll", CLSID_ChromeActiveDocument);
-
- LPFNGETCLASSOBJECT found_ptr = redir.get_dll_get_class_object_ptr();
- EXPECT_TRUE(found_ptr != NULL);
-
- LPFNGETCLASSOBJECT direct_ptr =
- reinterpret_cast<LPFNGETCLASSOBJECT>(
- GetProcAddress(hmodule_map_[L"1\\TestDll.dll"],
- "DllGetClassObject"));
- EXPECT_TRUE(direct_ptr != NULL);
-
- EXPECT_EQ(found_ptr, direct_ptr);
-}
-
-// Tests that this works with the actual CF dll.
-TEST_F(ModuleUtilsTest, ChromeFrameDllTest) {
- ASSERT_TRUE(LoadTestDll(L"DummyCF\\npchrome_frame.dll"));
- std::wstring cf_dll_path;
- ASSERT_TRUE(LoadChromeFrameDll(&cf_dll_path));
- ASSERT_TRUE(!cf_dll_path.empty());
-
- DllRedirector redir;
- redir.EnsureInitialized(L"npchrome_frame.dll", CLSID_ChromeActiveDocument);
-
- LPFNGETCLASSOBJECT found_ptr = redir.get_dll_get_class_object_ptr();
- EXPECT_TRUE(found_ptr != NULL);
-
- LPFNGETCLASSOBJECT direct_ptr = reinterpret_cast<LPFNGETCLASSOBJECT>(
- GetProcAddress(hmodule_map_[L"DummyCF\\npchrome_frame.dll"],
- "DllGetClassObject"));
- EXPECT_TRUE(direct_ptr != NULL);
-
- EXPECT_EQ(found_ptr, direct_ptr);
-
- // Now try asking for a ChromeActiveDocument using the non-dummy CF DLL
- // handle and make sure that the delegation to the dummy module happens
- // correctly. Use the bare guid to keep dependencies simple
- const wchar_t kClsidChromeActiveDocument[] =
- L"{3e1d0e7f-f5e3-44cc-aa6a-c0a637619ab8}";
-
- LPFNGETCLASSOBJECT cf_ptr = reinterpret_cast<LPFNGETCLASSOBJECT>(
- GetProcAddress(hmodule_map_[cf_dll_path],
- "DllGetClassObject"));
- EXPECT_TRUE(cf_ptr != NULL);
-
- CLSID cf_clsid;
- HRESULT hr = CLSIDFromString(kClsidChromeActiveDocument, &cf_clsid);
- EXPECT_HRESULT_SUCCEEDED(hr);
-
- CComPtr<IClassFactory> class_factory;
- DWORD result = cf_ptr(cf_clsid, IID_IClassFactory,
- reinterpret_cast<void**>(&class_factory));
-
- EXPECT_EQ(S_OK, result);
-}