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 #ifndef CHROME_FRAME_COM_TYPE_INFO_HOLDER_H_
6 #define CHROME_FRAME_COM_TYPE_INFO_HOLDER_H_
9 #include <ocidl.h> // IProvideClassInfo2
11 #include "base/synchronization/lock.h"
12 #include "base/win/scoped_comptr.h"
14 #define NO_VTABLE __declspec(novtable)
18 // A map from a name hash (32 bit value) to a DISPID.
19 // Used as a caching layer before looking the name up in a type lib.
20 class NameToDispIdCache
{
22 typedef uint32 HashType
;
24 bool Lookup(HashType hash
, DISPID
* dispid
) const;
25 void Add(HashType hash
, DISPID dispid
);
27 // Hashes the name by calling LHashValOfName.
28 // The returned hash value is independent of the case of the characters
30 static HashType
Hash(const wchar_t* name
);
33 typedef std::map
<HashType
, DISPID
> DispidMap
;
35 mutable base::Lock lock_
;
38 // Wraps an instance of ITypeInfo and builds+maintains a cache of names
39 // to dispids. Also offers an Invoke method that simply forwards the call
40 // to ITypeInfo::Invoke.
41 class TypeInfoNameCache
{
43 // Loads the module's type library and fetches the ITypeInfo object for
44 // the specified interface ID.
45 HRESULT
Initialize(const IID
& iid
);
47 // Fetches the id's of the given names. If there's a cache miss, the results
48 // are fetched from the underlying ITypeInfo and then cached.
49 HRESULT
GetIDsOfNames(OLECHAR
** names
, uint32 count
, DISPID
* dispids
);
51 // Calls ITypeInfo::Invoke.
52 HRESULT
Invoke(IDispatch
* p
, DISPID dispid
, WORD flags
, DISPPARAMS
* params
,
53 VARIANT
* result
, EXCEPINFO
* excepinfo
, UINT
* arg_err
);
55 inline ITypeInfo
* CopyTypeInfo() {
56 ITypeInfo
* ti
= type_info_
.get();
63 base::win::ScopedComPtr
<ITypeInfo
> type_info_
;
64 NameToDispIdCache cache_
;
67 // The root class for type lib access.
68 // This class has only one instance that should be accessed via the
77 // Looks up a previously cached TypeInfoNameCache instance or creates and
79 TypeInfoNameCache
* Lookup(const IID
* iid
);
81 // Call to get access to the singleton instance of TypeInfoCache.
82 static TypeInfoCache
* Singleton();
85 typedef std::map
<const IID
*, TypeInfoNameCache
*> CacheMap
;
90 // Holds a pointer to the type info of a given COM interface.
91 // The type info is loaded once on demand and after that cached.
92 // NOTE: This class only supports loading the first typelib from the
94 template <const IID
& iid
>
95 class TypeInfoHolder
{
97 TypeInfoHolder() : type_info_(NULL
) {
102 type_info_
= TypeInfoCache::Singleton()->Lookup(&iid
);
103 return type_info_
!= NULL
;
106 HRESULT
GetTypeInfo(UINT itinfo
, LCID lcid
, ITypeInfo
** info
) {
108 *info
= type_info_
->CopyTypeInfo();
115 HRESULT
GetIDsOfNames(REFIID riid
, OLECHAR
** names
, UINT count
, LCID lcid
,
119 return type_info_
->GetIDsOfNames(names
, count
, dispids
);
122 HRESULT
Invoke(IDispatch
* p
, DISPID dispid
, REFIID riid
, LCID lcid
,
123 WORD flags
, DISPPARAMS
* params
, VARIANT
* result
,
124 EXCEPINFO
* excepinfo
, UINT
* arg_err
) {
128 return type_info_
->Invoke(p
, dispid
, flags
, params
, result
, excepinfo
,
133 TypeInfoNameCache
* type_info_
;
136 // Implements IDispatch part of T (where T is an IDispatch derived interface).
137 // The class assumes that the type info of T is available in a typelib of the
139 template <class T
, const IID
& iid
= __uuidof(T
)>
140 class NO_VTABLE IDispatchImpl
: public T
{
142 STDMETHOD(GetTypeInfoCount
)(UINT
* count
) {
149 STDMETHOD(GetTypeInfo
)(UINT itinfo
, LCID lcid
, ITypeInfo
** pptinfo
) {
150 return type_info_
.GetTypeInfo(itinfo
, lcid
, pptinfo
);
153 STDMETHOD(GetIDsOfNames
)(REFIID riid
, LPOLESTR
* names
, UINT count
,
154 LCID lcid
, DISPID
* dispids
) {
155 return type_info_
.GetIDsOfNames(riid
, names
, count
, lcid
, dispids
);
157 STDMETHOD(Invoke
)(DISPID dispid
, REFIID riid
, LCID lcid
, WORD flags
,
158 DISPPARAMS
* params
, VARIANT
* result
, EXCEPINFO
* excepinfo
,
160 return type_info_
.Invoke(static_cast<IDispatch
*>(this), dispid
, riid
, lcid
,
161 flags
, params
, result
, excepinfo
, arg_err
);
165 TypeInfoHolder
<iid
> type_info_
;
168 // Simple implementation of IProvideClassInfo[2].
169 template <const CLSID
& class_id
, const IID
& source_iid
>
170 class NO_VTABLE IProvideClassInfo2Impl
: public IProvideClassInfo2
{
172 STDMETHOD(GetClassInfo
)(ITypeInfo
** pptinfo
) {
173 return type_info_
.GetTypeInfo(0, LANG_NEUTRAL
, pptinfo
);
176 STDMETHOD(GetGUID
)(DWORD guid_kind
, GUID
* guid
) {
177 if (guid
== NULL
|| guid_kind
!= GUIDKIND_DEFAULT_SOURCE_DISP_IID
)
186 TypeInfoHolder
<class_id
> type_info_
;
189 } // namespace com_util
191 #endif // CHROME_FRAME_COM_TYPE_INFO_HOLDER_H_