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.
5 #include "chrome_frame/com_type_info_holder.h"
7 #include "base/lazy_instance.h"
8 #include "base/logging.h"
10 extern "C" IMAGE_DOS_HEADER __ImageBase
;
14 base::LazyInstance
<TypeInfoCache
> type_info_cache
= LAZY_INSTANCE_INITIALIZER
;
18 TypeInfoCache::~TypeInfoCache() {
19 CacheMap::iterator it
= cache_
.begin();
20 while (it
!= cache_
.end()) {
26 TypeInfoNameCache
* TypeInfoCache::Lookup(const IID
* iid
) {
27 DCHECK(Singleton() == this);
29 TypeInfoNameCache
* tih
= NULL
;
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
;
50 TypeInfoCache
* TypeInfoCache::Singleton() {
51 return type_info_cache
.Pointer();
54 HRESULT
TypeInfoNameCache::Initialize(const IID
& iid
) {
55 DCHECK(type_info_
== NULL
);
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
) {
65 base::win::ScopedComPtr
<ITypeLib
> type_lib
;
66 HRESULT hr
= LoadTypeLib(file_path
, type_lib
.Receive());
68 hr
= type_lib
->GetTypeInfoOfGuid(iid
, type_info_
.Receive());
76 HRESULT
TypeInfoNameCache::GetIDsOfNames(OLECHAR
** names
, uint32 count
,
78 DCHECK(type_info_
!= NULL
);
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
]);
86 cache_
.Add(hash
, dispids
[i
]);
94 HRESULT
TypeInfoNameCache::Invoke(IDispatch
* p
, DISPID dispid
, WORD flags
,
95 DISPPARAMS
* params
, VARIANT
* result
,
96 EXCEPINFO
* excepinfo
, UINT
* arg_err
) {
98 HRESULT hr
= type_info_
->Invoke(p
, dispid
, flags
, params
, result
, excepinfo
,
100 DCHECK(hr
!= RPC_E_WRONG_THREAD
);
106 bool 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());
111 *dispid
= it
->second
;
115 void NameToDispIdCache::Add(HashType hash
, DISPID dispid
) {
116 base::AutoLock
lock(lock_
);
120 NameToDispIdCache::HashType
NameToDispIdCache::Hash(const wchar_t* name
) {
121 return LHashValOfName(LANG_NEUTRAL
, name
);
124 } // namespace com_util