chromeos: dbus: add Bluetooth properties support
[chromium-blink-merge.git] / chrome_frame / com_type_info_holder.h
bloba777d7ce4e52d6c4f4fdc77dc7bd2ffb71a9e450
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_
8 #include <map>
9 #include <ocidl.h> // IProvideClassInfo2
11 #include "base/synchronization/lock.h"
12 #include "base/win/scoped_comptr.h"
14 #define NO_VTABLE __declspec(novtable)
16 namespace com_util {
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 {
21 public:
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
29 // in |name|.
30 static HashType Hash(const wchar_t* name);
32 protected:
33 typedef std::map<HashType, DISPID> DispidMap;
34 DispidMap map_;
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 {
42 public:
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();
57 if (ti)
58 ti->AddRef();
59 return ti;
62 protected:
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
69 // Singleton method.
70 class TypeInfoCache {
71 public:
72 TypeInfoCache() {
75 ~TypeInfoCache();
77 // Looks up a previously cached TypeInfoNameCache instance or creates and
78 // caches a new one.
79 TypeInfoNameCache* Lookup(const IID* iid);
81 // Call to get access to the singleton instance of TypeInfoCache.
82 static TypeInfoCache* Singleton();
84 protected:
85 typedef std::map<const IID*, TypeInfoNameCache*> CacheMap;
86 base::Lock lock_;
87 CacheMap cache_;
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
93 // current module.
94 template <const IID& iid>
95 class TypeInfoHolder {
96 public:
97 TypeInfoHolder() : type_info_(NULL) {
100 bool EnsureTI() {
101 if (!type_info_)
102 type_info_ = TypeInfoCache::Singleton()->Lookup(&iid);
103 return type_info_ != NULL;
106 HRESULT GetTypeInfo(UINT itinfo, LCID lcid, ITypeInfo** info) {
107 if (EnsureTI()) {
108 *info = type_info_->CopyTypeInfo();
109 return S_OK;
112 return E_UNEXPECTED;
115 HRESULT GetIDsOfNames(REFIID riid, OLECHAR** names, UINT count, LCID lcid,
116 DISPID* dispids) {
117 if (!EnsureTI())
118 return E_UNEXPECTED;
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) {
125 if (!EnsureTI())
126 return E_UNEXPECTED;
128 return type_info_->Invoke(p, dispid, flags, params, result, excepinfo,
129 arg_err);
132 protected:
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
138 // current module.
139 template <class T, const IID& iid = __uuidof(T)>
140 class NO_VTABLE IDispatchImpl : public T {
141 public:
142 STDMETHOD(GetTypeInfoCount)(UINT* count) {
143 if (count == NULL)
144 return E_POINTER;
145 *count = 1;
146 return S_OK;
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,
159 UINT* arg_err) {
160 return type_info_.Invoke(static_cast<IDispatch*>(this), dispid, riid, lcid,
161 flags, params, result, excepinfo, arg_err);
164 protected:
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 {
171 public:
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)
178 return E_INVALIDARG;
180 *guid = source_iid;
182 return S_OK;
185 protected:
186 TypeInfoHolder<class_id> type_info_;
189 } // namespace com_util
191 #endif // CHROME_FRAME_COM_TYPE_INFO_HOLDER_H_