| Index: chrome_frame/dll_redirector.cc
|
| diff --git a/chrome_frame/dll_redirector.cc b/chrome_frame/dll_redirector.cc
|
| deleted file mode 100644
|
| index b21b368567697ec15a9672dda84def82764182e1..0000000000000000000000000000000000000000
|
| --- a/chrome_frame/dll_redirector.cc
|
| +++ /dev/null
|
| @@ -1,302 +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/dll_redirector.h"
|
| -
|
| -#include <aclapi.h>
|
| -#include <atlbase.h>
|
| -#include <atlsecurity.h>
|
| -#include <sddl.h>
|
| -
|
| -#include "base/file_version_info.h"
|
| -#include "base/files/file_path.h"
|
| -#include "base/logging.h"
|
| -#include "base/memory/shared_memory.h"
|
| -#include "base/path_service.h"
|
| -#include "base/strings/string_util.h"
|
| -#include "base/strings/utf_string_conversions.h"
|
| -#include "base/version.h"
|
| -#include "base/win/windows_version.h"
|
| -#include "chrome_frame/utils.h"
|
| -
|
| -const wchar_t kSharedMemoryName[] = L"ChromeFrameVersionBeacon_";
|
| -const uint32 kSharedMemorySize = 128;
|
| -const uint32 kSharedMemoryLockTimeoutMs = 1000;
|
| -
|
| -// static
|
| -DllRedirector::DllRedirector() : first_module_handle_(NULL) {
|
| - // TODO(robertshield): Allow for overrides to be taken from the environment.
|
| - std::wstring beacon_name(kSharedMemoryName);
|
| - beacon_name += GetHostProcessName(false);
|
| - shared_memory_.reset(new base::SharedMemory(beacon_name));
|
| - shared_memory_name_ = base::WideToUTF8(beacon_name);
|
| -}
|
| -
|
| -DllRedirector::DllRedirector(const char* shared_memory_name)
|
| - : shared_memory_name_(shared_memory_name), first_module_handle_(NULL) {
|
| - shared_memory_.reset(
|
| - new base::SharedMemory(base::ASCIIToWide(shared_memory_name)));
|
| -}
|
| -
|
| -DllRedirector::~DllRedirector() {
|
| - if (first_module_handle_) {
|
| - if (first_module_handle_ != reinterpret_cast<HMODULE>(&__ImageBase)) {
|
| - FreeLibrary(first_module_handle_);
|
| - } else {
|
| - NOTREACHED() << "Error, DllRedirector attempting to free self.";
|
| - }
|
| -
|
| - first_module_handle_ = NULL;
|
| - }
|
| - UnregisterAsFirstCFModule();
|
| -}
|
| -
|
| -// static
|
| -DllRedirector* DllRedirector::GetInstance() {
|
| - return Singleton<DllRedirector>::get();
|
| -}
|
| -
|
| -bool DllRedirector::BuildSecurityAttributesForLock(
|
| - CSecurityAttributes* sec_attr) {
|
| - DCHECK(sec_attr);
|
| - if (base::win::GetVersion() < base::win::VERSION_VISTA) {
|
| - // Don't bother with changing ACLs on pre-vista.
|
| - return false;
|
| - }
|
| -
|
| - bool success = false;
|
| -
|
| - // Fill out the rest of the security descriptor from the process token.
|
| - CAccessToken token;
|
| - if (token.GetProcessToken(TOKEN_QUERY)) {
|
| - CSecurityDesc security_desc;
|
| - // Set the SACL from an SDDL string that allows access to low-integrity
|
| - // processes. See http://msdn.microsoft.com/en-us/library/bb625958.aspx.
|
| - if (security_desc.FromString(L"S:(ML;;NW;;;LW)")) {
|
| - CSid sid_owner;
|
| - if (token.GetOwner(&sid_owner)) {
|
| - security_desc.SetOwner(sid_owner);
|
| - } else {
|
| - NOTREACHED() << "Could not get owner.";
|
| - }
|
| - CSid sid_group;
|
| - if (token.GetPrimaryGroup(&sid_group)) {
|
| - security_desc.SetGroup(sid_group);
|
| - } else {
|
| - NOTREACHED() << "Could not get group.";
|
| - }
|
| - CDacl dacl;
|
| - if (token.GetDefaultDacl(&dacl)) {
|
| - // Add an access control entry mask for the current user.
|
| - // This is what grants this user access from lower integrity levels.
|
| - CSid sid_user;
|
| - if (token.GetUser(&sid_user)) {
|
| - success = dacl.AddAllowedAce(sid_user, MUTEX_ALL_ACCESS);
|
| - security_desc.SetDacl(dacl);
|
| - sec_attr->Set(security_desc);
|
| - }
|
| - }
|
| - }
|
| - }
|
| -
|
| - return success;
|
| -}
|
| -
|
| -bool DllRedirector::SetFileMappingToReadOnly(base::SharedMemoryHandle mapping) {
|
| - bool success = false;
|
| -
|
| - CAccessToken token;
|
| - if (token.GetProcessToken(TOKEN_QUERY)) {
|
| - CSid sid_user;
|
| - if (token.GetUser(&sid_user)) {
|
| - CDacl dacl;
|
| - dacl.AddAllowedAce(sid_user, STANDARD_RIGHTS_READ | FILE_MAP_READ);
|
| - success = AtlSetDacl(mapping, SE_KERNEL_OBJECT, dacl);
|
| - }
|
| - }
|
| -
|
| - return success;
|
| -}
|
| -
|
| -
|
| -bool DllRedirector::RegisterAsFirstCFModule() {
|
| - DCHECK(first_module_handle_ == NULL);
|
| -
|
| - // Build our own file version outside of the lock:
|
| - scoped_ptr<Version> our_version(GetCurrentModuleVersion());
|
| -
|
| - // We sadly can't use the autolock here since we want to have a timeout.
|
| - // Be careful not to return while holding the lock. Also, attempt to do as
|
| - // little as possible while under this lock.
|
| -
|
| - bool lock_acquired = false;
|
| - CSecurityAttributes sec_attr;
|
| - if (base::win::GetVersion() >= base::win::VERSION_VISTA &&
|
| - BuildSecurityAttributesForLock(&sec_attr)) {
|
| - // On vista and above, we need to explicitly allow low integrity access
|
| - // to our objects. On XP, we don't bother.
|
| - lock_acquired = shared_memory_->Lock(kSharedMemoryLockTimeoutMs, &sec_attr);
|
| - } else {
|
| - lock_acquired = shared_memory_->Lock(kSharedMemoryLockTimeoutMs, NULL);
|
| - }
|
| -
|
| - if (!lock_acquired) {
|
| - // We couldn't get the lock in a reasonable amount of time, so fall
|
| - // back to loading our current version. We return true to indicate that the
|
| - // caller should not attempt to delegate to an already loaded version.
|
| - dll_version_.swap(our_version);
|
| - return true;
|
| - }
|
| -
|
| - bool created_beacon = true;
|
| - bool result = shared_memory_->CreateNamed(shared_memory_name_.c_str(),
|
| - false, // open_existing
|
| - kSharedMemorySize);
|
| -
|
| - if (result) {
|
| - // We created the beacon, now we need to mutate the security attributes
|
| - // on the shared memory to allow read-only access and let low-integrity
|
| - // processes open it. This will fail on FAT32 file systems.
|
| - if (!SetFileMappingToReadOnly(shared_memory_->handle())) {
|
| - DLOG(ERROR) << "Failed to set file mapping permissions.";
|
| - }
|
| - } else {
|
| - created_beacon = false;
|
| -
|
| - // We failed to create the shared memory segment, suggesting it may already
|
| - // exist: try to create it read-only.
|
| - result = shared_memory_->Open(shared_memory_name_.c_str(),
|
| - true /* read_only */);
|
| - }
|
| -
|
| - if (result) {
|
| - // Map in the whole thing.
|
| - result = shared_memory_->Map(0);
|
| - DCHECK(shared_memory_->memory());
|
| -
|
| - if (result) {
|
| - // Either write our own version number or read it in if it was already
|
| - // present in the shared memory section.
|
| - if (created_beacon) {
|
| - dll_version_.swap(our_version);
|
| -
|
| - lstrcpynA(reinterpret_cast<char*>(shared_memory_->memory()),
|
| - dll_version_->GetString().c_str(),
|
| - std::min(kSharedMemorySize,
|
| - dll_version_->GetString().length() + 1));
|
| - } else {
|
| - char buffer[kSharedMemorySize] = {0};
|
| - memcpy(buffer, shared_memory_->memory(), kSharedMemorySize - 1);
|
| - dll_version_.reset(new Version(buffer));
|
| -
|
| - if (!dll_version_->IsValid() ||
|
| - dll_version_->Equals(*our_version.get())) {
|
| - // If we either couldn't parse a valid version out of the shared
|
| - // memory or we did parse a version and it is the same as our own,
|
| - // then pretend we're first in to avoid trying to load any other DLLs.
|
| - dll_version_.reset(our_version.release());
|
| - created_beacon = true;
|
| - }
|
| - }
|
| - } else {
|
| - NOTREACHED() << "Failed to map in version beacon.";
|
| - }
|
| - } else {
|
| - NOTREACHED() << "Could not create file mapping for version beacon, gle: "
|
| - << ::GetLastError();
|
| - }
|
| -
|
| - // Matching Unlock.
|
| - shared_memory_->Unlock();
|
| -
|
| - return created_beacon;
|
| -}
|
| -
|
| -void DllRedirector::UnregisterAsFirstCFModule() {
|
| - if (base::SharedMemory::IsHandleValid(shared_memory_->handle())) {
|
| - bool lock_acquired = shared_memory_->Lock(kSharedMemoryLockTimeoutMs, NULL);
|
| - if (lock_acquired) {
|
| - // Free our handles. The last closed handle SHOULD result in it being
|
| - // deleted.
|
| - shared_memory_->Close();
|
| - shared_memory_->Unlock();
|
| - }
|
| - }
|
| -}
|
| -
|
| -LPFNGETCLASSOBJECT DllRedirector::GetDllGetClassObjectPtr() {
|
| - HMODULE first_module_handle = GetFirstModule();
|
| -
|
| - LPFNGETCLASSOBJECT proc_ptr = NULL;
|
| - if (first_module_handle) {
|
| - proc_ptr = reinterpret_cast<LPFNGETCLASSOBJECT>(
|
| - GetProcAddress(first_module_handle, "DllGetClassObject"));
|
| - DPLOG_IF(ERROR, !proc_ptr) << "DllRedirector: Could not get address of "
|
| - "DllGetClassObject from first loaded module.";
|
| - }
|
| -
|
| - return proc_ptr;
|
| -}
|
| -
|
| -Version* DllRedirector::GetCurrentModuleVersion() {
|
| - scoped_ptr<FileVersionInfo> file_version_info(
|
| - FileVersionInfo::CreateFileVersionInfoForCurrentModule());
|
| - DCHECK(file_version_info.get());
|
| -
|
| - scoped_ptr<Version> current_version;
|
| - if (file_version_info.get()) {
|
| - current_version.reset(
|
| - new Version(WideToASCII(file_version_info->file_version())));
|
| - DCHECK(current_version->IsValid());
|
| - }
|
| -
|
| - return current_version.release();
|
| -}
|
| -
|
| -HMODULE DllRedirector::GetFirstModule() {
|
| - DCHECK(dll_version_.get())
|
| - << "Error: Did you call RegisterAsFirstCFModule() first?";
|
| -
|
| - if (first_module_handle_ == NULL) {
|
| - first_module_handle_ = LoadVersionedModule(dll_version_.get());
|
| - }
|
| -
|
| - if (first_module_handle_ == reinterpret_cast<HMODULE>(&__ImageBase)) {
|
| - NOTREACHED() << "Should not be loading own version.";
|
| - first_module_handle_ = NULL;
|
| - }
|
| -
|
| - return first_module_handle_;
|
| -}
|
| -
|
| -HMODULE DllRedirector::LoadVersionedModule(Version* version) {
|
| - DCHECK(version);
|
| -
|
| - HMODULE hmodule = NULL;
|
| - wchar_t system_buffer[MAX_PATH];
|
| - HMODULE this_module = reinterpret_cast<HMODULE>(&__ImageBase);
|
| - system_buffer[0] = 0;
|
| - if (GetModuleFileName(this_module, system_buffer,
|
| - arraysize(system_buffer)) != 0) {
|
| - base::FilePath module_path(system_buffer);
|
| -
|
| - // For a module located in
|
| - // Foo\XXXXXXXXX\<module>.dll, load
|
| - // Foo\<version>\<module>.dll:
|
| - base::FilePath module_name = module_path.BaseName();
|
| - module_path = module_path.DirName()
|
| - .DirName()
|
| - .Append(base::ASCIIToWide(version->GetString()))
|
| - .Append(module_name);
|
| -
|
| - hmodule = LoadLibrary(module_path.value().c_str());
|
| - if (hmodule == NULL) {
|
| - DPLOG(ERROR) << "Could not load reported module version "
|
| - << version->GetString();
|
| - }
|
| - } else {
|
| - DPLOG(FATAL) << "Failed to get module file name";
|
| - }
|
| - return hmodule;
|
| -}
|
|
|