| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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/dll_redirector.h" | 5 #include "chrome_frame/dll_redirector.h" |
| 6 | 6 |
| 7 #include <aclapi.h> | 7 #include <aclapi.h> |
| 8 #include <atlbase.h> | 8 #include <atlbase.h> |
| 9 #include <atlsecurity.h> | 9 #include <atlsecurity.h> |
| 10 #include <sddl.h> | 10 #include <sddl.h> |
| (...skipping 24 matching lines...) Expand all Loading... |
| 35 | 35 |
| 36 DllRedirector::DllRedirector(const char* shared_memory_name) | 36 DllRedirector::DllRedirector(const char* shared_memory_name) |
| 37 : shared_memory_name_(shared_memory_name), first_module_handle_(NULL) { | 37 : shared_memory_name_(shared_memory_name), first_module_handle_(NULL) { |
| 38 shared_memory_.reset(new base::SharedMemory(ASCIIToWide(shared_memory_name))); | 38 shared_memory_.reset(new base::SharedMemory(ASCIIToWide(shared_memory_name))); |
| 39 } | 39 } |
| 40 | 40 |
| 41 DllRedirector::~DllRedirector() { | 41 DllRedirector::~DllRedirector() { |
| 42 if (first_module_handle_) { | 42 if (first_module_handle_) { |
| 43 if (first_module_handle_ != reinterpret_cast<HMODULE>(&__ImageBase)) { | 43 if (first_module_handle_ != reinterpret_cast<HMODULE>(&__ImageBase)) { |
| 44 FreeLibrary(first_module_handle_); | 44 FreeLibrary(first_module_handle_); |
| 45 } else { |
| 46 NOTREACHED() << "Error, DllRedirector attempting to free self."; |
| 45 } | 47 } |
| 48 |
| 46 first_module_handle_ = NULL; | 49 first_module_handle_ = NULL; |
| 47 } | 50 } |
| 48 UnregisterAsFirstCFModule(); | 51 UnregisterAsFirstCFModule(); |
| 49 } | 52 } |
| 50 | 53 |
| 51 // static | 54 // static |
| 52 DllRedirector* DllRedirector::GetInstance() { | 55 DllRedirector* DllRedirector::GetInstance() { |
| 53 return Singleton<DllRedirector>::get(); | 56 return Singleton<DllRedirector>::get(); |
| 54 } | 57 } |
| 55 | 58 |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 135 lock_acquired = shared_memory_->Lock(kSharedMemoryLockTimeoutMs, &sec_attr); | 138 lock_acquired = shared_memory_->Lock(kSharedMemoryLockTimeoutMs, &sec_attr); |
| 136 } else { | 139 } else { |
| 137 lock_acquired = shared_memory_->Lock(kSharedMemoryLockTimeoutMs, NULL); | 140 lock_acquired = shared_memory_->Lock(kSharedMemoryLockTimeoutMs, NULL); |
| 138 } | 141 } |
| 139 | 142 |
| 140 if (!lock_acquired) { | 143 if (!lock_acquired) { |
| 141 // We couldn't get the lock in a reasonable amount of time, so fall | 144 // We couldn't get the lock in a reasonable amount of time, so fall |
| 142 // back to loading our current version. We return true to indicate that the | 145 // back to loading our current version. We return true to indicate that the |
| 143 // caller should not attempt to delegate to an already loaded version. | 146 // caller should not attempt to delegate to an already loaded version. |
| 144 dll_version_.swap(our_version); | 147 dll_version_.swap(our_version); |
| 145 first_module_handle_ = reinterpret_cast<HMODULE>(&__ImageBase); | |
| 146 return true; | 148 return true; |
| 147 } | 149 } |
| 148 | 150 |
| 149 bool created_beacon = true; | 151 bool created_beacon = true; |
| 150 bool result = shared_memory_->CreateNamed(shared_memory_name_.c_str(), | 152 bool result = shared_memory_->CreateNamed(shared_memory_name_.c_str(), |
| 151 false, // open_existing | 153 false, // open_existing |
| 152 kSharedMemorySize); | 154 kSharedMemorySize); |
| 153 | 155 |
| 154 if (result) { | 156 if (result) { |
| 155 // We created the beacon, now we need to mutate the security attributes | 157 // We created the beacon, now we need to mutate the security attributes |
| (...skipping 19 matching lines...) Expand all Loading... |
| 175 if (result) { | 177 if (result) { |
| 176 // Either write our own version number or read it in if it was already | 178 // Either write our own version number or read it in if it was already |
| 177 // present in the shared memory section. | 179 // present in the shared memory section. |
| 178 if (created_beacon) { | 180 if (created_beacon) { |
| 179 dll_version_.swap(our_version); | 181 dll_version_.swap(our_version); |
| 180 | 182 |
| 181 lstrcpynA(reinterpret_cast<char*>(shared_memory_->memory()), | 183 lstrcpynA(reinterpret_cast<char*>(shared_memory_->memory()), |
| 182 dll_version_->GetString().c_str(), | 184 dll_version_->GetString().c_str(), |
| 183 std::min(kSharedMemorySize, | 185 std::min(kSharedMemorySize, |
| 184 dll_version_->GetString().length() + 1)); | 186 dll_version_->GetString().length() + 1)); |
| 185 | |
| 186 // Mark ourself as the first module in. | |
| 187 first_module_handle_ = reinterpret_cast<HMODULE>(&__ImageBase); | |
| 188 } else { | 187 } else { |
| 189 char buffer[kSharedMemorySize] = {0}; | 188 char buffer[kSharedMemorySize] = {0}; |
| 190 memcpy(buffer, shared_memory_->memory(), kSharedMemorySize - 1); | 189 memcpy(buffer, shared_memory_->memory(), kSharedMemorySize - 1); |
| 191 dll_version_.reset(Version::GetVersionFromString(buffer)); | 190 dll_version_.reset(Version::GetVersionFromString(buffer)); |
| 192 | 191 |
| 193 if (!dll_version_.get() || dll_version_->Equals(*our_version.get())) { | 192 if (!dll_version_.get() || dll_version_->Equals(*our_version.get())) { |
| 194 // If we either couldn't parse a valid version out of the shared | 193 // If we either couldn't parse a valid version out of the shared |
| 195 // memory or we did parse a version and it is the same as our own, | 194 // memory or we did parse a version and it is the same as our own, |
| 196 // then pretend we're first in to avoid trying to load any other DLLs. | 195 // then pretend we're first in to avoid trying to load any other DLLs. |
| 197 dll_version_.reset(our_version.release()); | 196 dll_version_.reset(our_version.release()); |
| 198 first_module_handle_ = reinterpret_cast<HMODULE>(&__ImageBase); | |
| 199 created_beacon = true; | 197 created_beacon = true; |
| 200 } | 198 } |
| 201 } | 199 } |
| 202 } else { | 200 } else { |
| 203 NOTREACHED() << "Failed to map in version beacon."; | 201 NOTREACHED() << "Failed to map in version beacon."; |
| 204 } | 202 } |
| 205 } else { | 203 } else { |
| 206 NOTREACHED() << "Could not create file mapping for version beacon, gle: " | 204 NOTREACHED() << "Could not create file mapping for version beacon, gle: " |
| 207 << ::GetLastError(); | 205 << ::GetLastError(); |
| 208 } | 206 } |
| (...skipping 12 matching lines...) Expand all Loading... |
| 221 // deleted. | 219 // deleted. |
| 222 shared_memory_->Close(); | 220 shared_memory_->Close(); |
| 223 shared_memory_->Unlock(); | 221 shared_memory_->Unlock(); |
| 224 } | 222 } |
| 225 } | 223 } |
| 226 } | 224 } |
| 227 | 225 |
| 228 LPFNGETCLASSOBJECT DllRedirector::GetDllGetClassObjectPtr() { | 226 LPFNGETCLASSOBJECT DllRedirector::GetDllGetClassObjectPtr() { |
| 229 HMODULE first_module_handle = GetFirstModule(); | 227 HMODULE first_module_handle = GetFirstModule(); |
| 230 | 228 |
| 231 LPFNGETCLASSOBJECT proc_ptr = reinterpret_cast<LPFNGETCLASSOBJECT>( | 229 LPFNGETCLASSOBJECT proc_ptr = NULL; |
| 232 GetProcAddress(first_module_handle, "DllGetClassObject")); | 230 if (first_module_handle) { |
| 233 if (!proc_ptr) { | 231 proc_ptr = reinterpret_cast<LPFNGETCLASSOBJECT>( |
| 234 DPLOG(ERROR) << "DllRedirector: Could not get address of DllGetClassObject " | 232 GetProcAddress(first_module_handle, "DllGetClassObject")); |
| 235 "from first loaded module."; | 233 DPLOG_IF(ERROR, !proc_ptr) << "DllRedirector: Could not get address of " |
| 236 // Oh boink, the first module we loaded was somehow bogus, make ourselves | 234 "DllGetClassObject from first loaded module."; |
| 237 // the first module again. | |
| 238 first_module_handle = reinterpret_cast<HMODULE>(&__ImageBase); | |
| 239 } | 235 } |
| 236 |
| 240 return proc_ptr; | 237 return proc_ptr; |
| 241 } | 238 } |
| 242 | 239 |
| 243 Version* DllRedirector::GetCurrentModuleVersion() { | 240 Version* DllRedirector::GetCurrentModuleVersion() { |
| 244 scoped_ptr<FileVersionInfo> file_version_info( | 241 scoped_ptr<FileVersionInfo> file_version_info( |
| 245 FileVersionInfo::CreateFileVersionInfoForCurrentModule()); | 242 FileVersionInfo::CreateFileVersionInfoForCurrentModule()); |
| 246 DCHECK(file_version_info.get()); | 243 DCHECK(file_version_info.get()); |
| 247 | 244 |
| 248 Version* current_version = NULL; | 245 Version* current_version = NULL; |
| 249 if (file_version_info.get()) { | 246 if (file_version_info.get()) { |
| 250 current_version = Version::GetVersionFromString( | 247 current_version = Version::GetVersionFromString( |
| 251 WideToASCII(file_version_info->file_version())); | 248 WideToASCII(file_version_info->file_version())); |
| 252 DCHECK(current_version); | 249 DCHECK(current_version); |
| 253 } | 250 } |
| 254 | 251 |
| 255 return current_version; | 252 return current_version; |
| 256 } | 253 } |
| 257 | 254 |
| 258 HMODULE DllRedirector::GetFirstModule() { | 255 HMODULE DllRedirector::GetFirstModule() { |
| 259 DCHECK(dll_version_.get()) | 256 DCHECK(dll_version_.get()) |
| 260 << "Error: Did you call RegisterAsFirstCFModule() first?"; | 257 << "Error: Did you call RegisterAsFirstCFModule() first?"; |
| 261 | 258 |
| 262 if (first_module_handle_ == NULL) { | 259 if (first_module_handle_ == NULL) { |
| 263 first_module_handle_ = LoadVersionedModule(dll_version_.get()); | 260 first_module_handle_ = LoadVersionedModule(dll_version_.get()); |
| 264 if (!first_module_handle_) { | 261 } |
| 265 first_module_handle_ = reinterpret_cast<HMODULE>(&__ImageBase); | 262 |
| 266 } | 263 if (first_module_handle_ == reinterpret_cast<HMODULE>(&__ImageBase)) { |
| 264 NOTREACHED() << "Should not be loading own version."; |
| 265 first_module_handle_ = NULL; |
| 267 } | 266 } |
| 268 | 267 |
| 269 return first_module_handle_; | 268 return first_module_handle_; |
| 270 } | 269 } |
| 271 | 270 |
| 272 HMODULE DllRedirector::LoadVersionedModule(Version* version) { | 271 HMODULE DllRedirector::LoadVersionedModule(Version* version) { |
| 273 DCHECK(version); | 272 DCHECK(version); |
| 274 | 273 |
| 275 FilePath module_path; | 274 FilePath module_path; |
| 276 PathService::Get(base::FILE_MODULE, &module_path); | 275 PathService::Get(base::FILE_MODULE, &module_path); |
| 277 DCHECK(!module_path.empty()); | 276 DCHECK(!module_path.empty()); |
| 278 | 277 |
| 279 // For a module located in | 278 // For a module located in |
| 280 // Foo\XXXXXXXXX\<module>.dll, load | 279 // Foo\XXXXXXXXX\<module>.dll, load |
| 281 // Foo\<version>\<module>.dll: | 280 // Foo\<version>\<module>.dll: |
| 282 FilePath module_name = module_path.BaseName(); | 281 FilePath module_name = module_path.BaseName(); |
| 283 module_path = module_path.DirName() | 282 module_path = module_path.DirName() |
| 284 .DirName() | 283 .DirName() |
| 285 .Append(ASCIIToWide(version->GetString())) | 284 .Append(ASCIIToWide(version->GetString())) |
| 286 .Append(module_name); | 285 .Append(module_name); |
| 287 | 286 |
| 288 HMODULE hmodule = LoadLibrary(module_path.value().c_str()); | 287 HMODULE hmodule = LoadLibrary(module_path.value().c_str()); |
| 289 if (hmodule == NULL) { | 288 if (hmodule == NULL) { |
| 290 DPLOG(ERROR) << "Could not load reported module version " | 289 DPLOG(ERROR) << "Could not load reported module version " |
| 291 << version->GetString(); | 290 << version->GetString(); |
| 292 } | 291 } |
| 293 | 292 |
| 294 return hmodule; | 293 return hmodule; |
| 295 } | 294 } |
| OLD | NEW |