com_type_info_holder.cc revision 5821806d5e7f356e8fa4b058a389a808ea183019
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 3// found in the LICENSE file. 4 5#include "chrome_frame/com_type_info_holder.h" 6 7#include "base/lazy_instance.h" 8#include "base/logging.h" 9 10extern "C" IMAGE_DOS_HEADER __ImageBase; 11 12namespace com_util { 13 14base::LazyInstance<TypeInfoCache> type_info_cache = LAZY_INSTANCE_INITIALIZER; 15 16// TypeInfoCache 17 18TypeInfoCache::~TypeInfoCache() { 19 CacheMap::iterator it = cache_.begin(); 20 while (it != cache_.end()) { 21 delete it->second; 22 it++; 23 } 24} 25 26TypeInfoNameCache* TypeInfoCache::Lookup(const IID* iid) { 27 DCHECK(Singleton() == this); 28 29 TypeInfoNameCache* tih = NULL; 30 31 base::AutoLock lock(lock_); 32 CacheMap::iterator it = cache_.find(iid); 33 if (it == cache_.end()) { 34 tih = new TypeInfoNameCache(); 35 HRESULT hr = tih ? tih->Initialize(*iid) : E_OUTOFMEMORY; 36 if (SUCCEEDED(hr)) { 37 cache_[iid] = tih; 38 } else { 39 NOTREACHED(); 40 delete tih; 41 tih = NULL; 42 } 43 } else { 44 tih = it->second; 45 } 46 47 return tih; 48} 49 50TypeInfoCache* TypeInfoCache::Singleton() { 51 return type_info_cache.Pointer(); 52} 53 54HRESULT TypeInfoNameCache::Initialize(const IID& iid) { 55 DCHECK(type_info_ == NULL); 56 57 wchar_t file_path[MAX_PATH]; 58 DWORD path_len = ::GetModuleFileNameW(reinterpret_cast<HMODULE>(&__ImageBase), 59 file_path, arraysize(file_path)); 60 if (path_len == 0 || path_len == MAX_PATH) { 61 NOTREACHED(); 62 return E_UNEXPECTED; 63 } 64 65 base::win::ScopedComPtr<ITypeLib> type_lib; 66 HRESULT hr = LoadTypeLib(file_path, type_lib.Receive()); 67 if (SUCCEEDED(hr)) { 68 hr = type_lib->GetTypeInfoOfGuid(iid, type_info_.Receive()); 69 } 70 71 return hr; 72} 73 74// TypeInfoNameCache 75 76HRESULT TypeInfoNameCache::GetIDsOfNames(OLECHAR** names, uint32 count, 77 DISPID* dispids) { 78 DCHECK(type_info_ != NULL); 79 80 HRESULT hr = S_OK; 81 for (uint32 i = 0; i < count && SUCCEEDED(hr); ++i) { 82 NameToDispIdCache::HashType hash = NameToDispIdCache::Hash(names[i]); 83 if (!cache_.Lookup(hash, &dispids[i])) { 84 hr = type_info_->GetIDsOfNames(&names[i], 1, &dispids[i]); 85 if (SUCCEEDED(hr)) { 86 cache_.Add(hash, dispids[i]); 87 } 88 } 89 } 90 91 return hr; 92} 93 94HRESULT TypeInfoNameCache::Invoke(IDispatch* p, DISPID dispid, WORD flags, 95 DISPPARAMS* params, VARIANT* result, 96 EXCEPINFO* excepinfo, UINT* arg_err) { 97 DCHECK(type_info_); 98 HRESULT hr = type_info_->Invoke(p, dispid, flags, params, result, excepinfo, 99 arg_err); 100 DCHECK(hr != RPC_E_WRONG_THREAD); 101 return hr; 102} 103 104// NameToDispIdCache 105 106bool NameToDispIdCache::Lookup(HashType hash, DISPID* dispid) const { 107 base::AutoLock lock(lock_); 108 const DispidMap::const_iterator it = map_.find(hash); 109 bool found = (it != map_.end()); 110 if (found) 111 *dispid = it->second; 112 return found; 113} 114 115void NameToDispIdCache::Add(HashType hash, DISPID dispid) { 116 base::AutoLock lock(lock_); 117 map_[hash] = dispid; 118} 119 120NameToDispIdCache::HashType NameToDispIdCache::Hash(const wchar_t* name) { 121 return LHashValOfName(LANG_NEUTRAL, name); 122} 123 124} // namespace com_util 125