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_