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

Side by Side Diff: chrome_frame/module_utils.cc

Issue 2038007: Merge 46738 - Change to a simpler upgrade scheme for Chrome Frame whereby we ... (Closed) Base URL: svn://svn.chromium.org/chrome/branches/375/src/
Patch Set: Created 10 years, 7 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/module_utils.h ('k') | chrome_frame/test/module_utils_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome_frame/module_utils.h" 5 #include "chrome_frame/module_utils.h"
6 6
7 #include <atlbase.h> 7 #include <atlbase.h>
8 #include <TlHelp32.h> 8 #include "base/logging.h"
9 9
10 #include "base/scoped_ptr.h" 10 const wchar_t kBeaconWindowClassName[] =
11 #include "base/file_version_info.h" 11 L"ChromeFrameBeaconWindowClass826C5D01-E355-4b23-8AC2-40650E0B7843";
12 #include "base/logging.h"
13 #include "base/scoped_handle.h"
14 #include "base/string_util.h"
15 #include "base/version.h"
16 #include "chrome_frame/exception_barrier.h"
17 12
18 DllRedirector::DllRedirector() : dcgo_ptr_(NULL), initialized_(false), 13 // static
19 module_handle_(NULL) {} 14 ATOM DllRedirector::atom_ = 0;
20 15
21 DllRedirector::~DllRedirector() { 16 bool DllRedirector::RegisterAsFirstCFModule() {
22 if (module_handle_) { 17 // This would imply that this module had already registered a window class
23 FreeLibrary(module_handle_); 18 // which should never happen.
24 module_handle_ = NULL; 19 if (atom_) {
25 } 20 NOTREACHED();
26 } 21 return true;
27
28 void DllRedirector::EnsureInitialized(const wchar_t* module_name,
29 REFCLSID clsid) {
30 if (!initialized_) {
31 initialized_ = true;
32 // Also sets module_handle_.
33 dcgo_ptr_ = GetDllGetClassObjectFromModuleName(module_name, clsid);
34 }
35 }
36
37 LPFNGETCLASSOBJECT DllRedirector::get_dll_get_class_object_ptr() const {
38 DCHECK(initialized_);
39 return dcgo_ptr_;
40 }
41
42 LPFNGETCLASSOBJECT DllRedirector::GetDllGetClassObjectFromModuleName(
43 const wchar_t* module_name, REFCLSID clsid) {
44 module_handle_ = NULL;
45 LPFNGETCLASSOBJECT proc_ptr = NULL;
46 HMODULE module_handle;
47 if (GetOldestNamedModuleHandle(module_name, clsid, &module_handle)) {
48 HMODULE this_module = reinterpret_cast<HMODULE>(&__ImageBase);
49 if (module_handle != this_module) {
50 proc_ptr = GetDllGetClassObjectPtr(module_handle);
51 if (proc_ptr) {
52 // Stash away the module handle in module_handle_ so that it will be
53 // automatically closed when we get destroyed. GetDllGetClassObjectPtr
54 // above will have incremented the module's ref count.
55 module_handle_ = module_handle;
56 }
57 } else {
58 LOG(INFO) << "Module Scan: DllGetClassObject found in current module.";
59 }
60 } 22 }
61 23
62 return proc_ptr; 24 WNDCLASSEX wnd_class = {0};
63 } 25 wnd_class.cbSize = sizeof(WNDCLASSEX);
26 wnd_class.style = CS_GLOBALCLASS;
27 wnd_class.lpfnWndProc = &DefWindowProc;
28 wnd_class.cbClsExtra = sizeof(HMODULE);
29 wnd_class.cbWndExtra = 0;
30 wnd_class.hInstance = NULL;
31 wnd_class.hIcon = NULL;
64 32
65 bool DllRedirector::GetOldestNamedModuleHandle(const std::wstring& module_name, 33 wnd_class.hCursor = LoadCursor(NULL, IDC_ARROW);
66 REFCLSID clsid, 34 wnd_class.hbrBackground = NULL;
67 HMODULE* oldest_module_handle) { 35 wnd_class.lpszMenuName = NULL;
68 DCHECK(oldest_module_handle); 36 wnd_class.lpszClassName = kBeaconWindowClassName;
37 wnd_class.hIconSm = wnd_class.hIcon;
69 38
70 ScopedHandle snapshot(CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, 0)); 39 ATOM atom = RegisterClassEx(&wnd_class);
71 if (snapshot == INVALID_HANDLE_VALUE) {
72 LOG(ERROR) << "Could not create module snapshot!";
73 return false;
74 }
75
76 40
77 bool success = false; 41 bool success = false;
78 PathToHModuleMap map; 42 if (atom != 0) {
79 43 HWND hwnd = CreateWindow(MAKEINTATOM(atom), L"temp_window", WS_POPUP,
80 { 44 0, 0, 0, 0, NULL, NULL, NULL, NULL);
81 // Here we add an SEH to the chain to prevent our VEH from picking up on any 45 DCHECK(IsWindow(hwnd));
82 // exceptions thrown in DLLs who hook some of the below api calls. We will 46 if (hwnd) {
83 // still report the exceptions if they make our way back to us, the hope is 47 HMODULE this_module = reinterpret_cast<HMODULE>(&__ImageBase);
84 // that they will not. 48 LONG_PTR lp = reinterpret_cast<LONG_PTR>(this_module);
85 ExceptionBarrier exception_barrier; 49 SetClassLongPtr(hwnd, 0, lp);
86 50 // We need to check the GLE value since SetClassLongPtr returns 0 on
87 // First get the list of module paths, and save the full path to base 51 // failure as well as on the first call.
88 // address mapping. 52 if (GetLastError() == ERROR_SUCCESS) {
89 MODULEENTRY32W module_entry = {0}; 53 atom_ = atom;
90 module_entry.dwSize = sizeof(module_entry); 54 success = true;
91 BOOL cont = Module32FirstW(snapshot, &module_entry);
92 while (cont) {
93 if (!lstrcmpi(module_entry.szModule, module_name.c_str())) {
94 std::wstring full_path(module_entry.szExePath);
95 map[full_path] = module_entry.hModule;
96 } 55 }
97 SecureZeroMemory(&module_entry, sizeof(MODULEENTRY32W)); 56 DestroyWindow(hwnd);
98 module_entry.dwSize = sizeof(module_entry);
99 cont = Module32NextW(snapshot, &module_entry);
100 } 57 }
101 } 58 }
102 59
103 // Next, enumerate the map and find the oldest version of the module.
104 // (check if the map is of size 1 first)
105 if (!map.empty()) {
106 if (map.size() == 1) {
107 *oldest_module_handle = map.begin()->second;
108 } else {
109 *oldest_module_handle = GetHandleOfOldestModule(map, clsid);
110 }
111
112 if (*oldest_module_handle != NULL) {
113 success = true;
114 }
115 } else {
116 LOG(INFO) << "Module Scan: No modules named " << module_name
117 << " were found.";
118 }
119
120 return success; 60 return success;
121 } 61 }
122 62
123 HMODULE DllRedirector::GetHandleOfOldestModule(const PathToHModuleMap& map, 63 void DllRedirector::UnregisterAsFirstCFModule() {
124 REFCLSID clsid) { 64 if (atom_) {
65 UnregisterClass(MAKEINTATOM(atom_), NULL);
66 }
67 }
68
69 HMODULE DllRedirector::GetFirstCFModule() {
70 WNDCLASSEX wnd_class = {0};
125 HMODULE oldest_module = NULL; 71 HMODULE oldest_module = NULL;
126 scoped_ptr<Version> min_version( 72 HWND hwnd = CreateWindow(kBeaconWindowClassName, L"temp_window", WS_POPUP, 0,
127 Version::GetVersionFromString("999.999.999.999")); 73 0, 0, 0, NULL, NULL, NULL, NULL);
128 74 DCHECK(IsWindow(hwnd));
129 PathToHModuleMap::const_iterator map_iter(map.begin()); 75 if (hwnd) {
130 for (; map_iter != map.end(); ++map_iter) { 76 oldest_module = reinterpret_cast<HMODULE>(GetClassLongPtr(hwnd, 0));
131 // First check that either we are in the current module or that the DLL 77 DestroyWindow(hwnd);
132 // returns a class factory for our clsid.
133 bool current_module =
134 (map_iter->second == reinterpret_cast<HMODULE>(&__ImageBase));
135 bool gco_succeeded = false;
136 if (!current_module) {
137 LPFNGETCLASSOBJECT dgco_ptr = GetDllGetClassObjectPtr(map_iter->second);
138 if (dgco_ptr) {
139 {
140 CComPtr<IClassFactory> class_factory;
141 HRESULT hr = dgco_ptr(clsid, IID_IClassFactory,
142 reinterpret_cast<void**>(&class_factory));
143 gco_succeeded = SUCCEEDED(hr) && class_factory != NULL;
144 }
145 // Release the module ref count we picked up in GetDllGetClassObjectPtr.
146 FreeLibrary(map_iter->second);
147 }
148 }
149
150 if (current_module || gco_succeeded) {
151 // Then check that the version is less than we've already found:
152 scoped_ptr<FileVersionInfo> version_info(
153 FileVersionInfo::CreateFileVersionInfo(map_iter->first));
154 scoped_ptr<Version> version(
155 Version::GetVersionFromString(version_info->file_version()));
156 if (version->CompareTo(*min_version.get()) < 0) {
157 oldest_module = map_iter->second;
158 min_version.reset(version.release());
159 }
160 }
161 } 78 }
162
163 return oldest_module; 79 return oldest_module;
164 } 80 }
165 81
166 LPFNGETCLASSOBJECT DllRedirector::GetDllGetClassObjectPtr(HMODULE module) { 82 LPFNGETCLASSOBJECT DllRedirector::GetDllGetClassObjectPtr(HMODULE module) {
167 LPFNGETCLASSOBJECT proc_ptr = NULL; 83 LPFNGETCLASSOBJECT proc_ptr = NULL;
168 HMODULE temp_handle = 0; 84 HMODULE temp_handle = 0;
169 // Increment the module ref count while we have an pointer to its 85 // Increment the module ref count while we have an pointer to its
170 // DllGetClassObject function. 86 // DllGetClassObject function.
171 if (GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, 87 if (GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
172 reinterpret_cast<LPCTSTR>(module), 88 reinterpret_cast<LPCTSTR>(module),
173 &temp_handle)) { 89 &temp_handle)) {
174 proc_ptr = reinterpret_cast<LPFNGETCLASSOBJECT>( 90 proc_ptr = reinterpret_cast<LPFNGETCLASSOBJECT>(
175 GetProcAddress(temp_handle, "DllGetClassObject")); 91 GetProcAddress(temp_handle, "DllGetClassObject"));
176 if (!proc_ptr) { 92 if (!proc_ptr) {
177 FreeLibrary(temp_handle); 93 FreeLibrary(temp_handle);
178 LOG(ERROR) << "Module Scan: Couldn't get address of " 94 LOG(ERROR) << "Module Scan: Couldn't get address of "
179 << "DllGetClassObject: " 95 << "DllGetClassObject: "
180 << GetLastError(); 96 << GetLastError();
181 } 97 }
182 } else { 98 } else {
183 LOG(ERROR) << "Module Scan: Could not increment module count: " 99 LOG(ERROR) << "Module Scan: Could not increment module count: "
184 << GetLastError(); 100 << GetLastError();
185 } 101 }
186 return proc_ptr; 102 return proc_ptr;
187 } 103 }
OLDNEW
« no previous file with comments | « chrome_frame/module_utils.h ('k') | chrome_frame/test/module_utils_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698