15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2011 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef CHROME_FRAME_COM_TYPE_INFO_HOLDER_H_ 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define CHROME_FRAME_COM_TYPE_INFO_HOLDER_H_ 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <map> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <ocidl.h> // IProvideClassInfo2 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/synchronization/lock.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/scoped_comptr.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define NO_VTABLE __declspec(novtable) 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace com_util { 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A map from a name hash (32 bit value) to a DISPID. 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Used as a caching layer before looking the name up in a type lib. 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class NameToDispIdCache { 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef uint32 HashType; 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool Lookup(HashType hash, DISPID* dispid) const; 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void Add(HashType hash, DISPID dispid); 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Hashes the name by calling LHashValOfName. 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The returned hash value is independent of the case of the characters 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // in |name|. 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static HashType Hash(const wchar_t* name); 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected: 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef std::map<HashType, DISPID> DispidMap; 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DispidMap map_; 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mutable base::Lock lock_; 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Wraps an instance of ITypeInfo and builds+maintains a cache of names 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to dispids. Also offers an Invoke method that simply forwards the call 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to ITypeInfo::Invoke. 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class TypeInfoNameCache { 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Loads the module's type library and fetches the ITypeInfo object for 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the specified interface ID. 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HRESULT Initialize(const IID& iid); 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Fetches the id's of the given names. If there's a cache miss, the results 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // are fetched from the underlying ITypeInfo and then cached. 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HRESULT GetIDsOfNames(OLECHAR** names, uint32 count, DISPID* dispids); 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Calls ITypeInfo::Invoke. 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HRESULT Invoke(IDispatch* p, DISPID dispid, WORD flags, DISPPARAMS* params, 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VARIANT* result, EXCEPINFO* excepinfo, UINT* arg_err); 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inline ITypeInfo* CopyTypeInfo() { 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ITypeInfo* ti = type_info_.get(); 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ti) 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ti->AddRef(); 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ti; 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected: 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::win::ScopedComPtr<ITypeInfo> type_info_; 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NameToDispIdCache cache_; 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The root class for type lib access. 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This class has only one instance that should be accessed via the 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Singleton method. 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class TypeInfoCache { 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TypeInfoCache() { 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ~TypeInfoCache(); 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Looks up a previously cached TypeInfoNameCache instance or creates and 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // caches a new one. 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TypeInfoNameCache* Lookup(const IID* iid); 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Call to get access to the singleton instance of TypeInfoCache. 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static TypeInfoCache* Singleton(); 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected: 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef std::map<const IID*, TypeInfoNameCache*> CacheMap; 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Lock lock_; 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CacheMap cache_; 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Holds a pointer to the type info of a given COM interface. 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The type info is loaded once on demand and after that cached. 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// NOTE: This class only supports loading the first typelib from the 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// current module. 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <const IID& iid> 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class TypeInfoHolder { 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TypeInfoHolder() : type_info_(NULL) { 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool EnsureTI() { 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!type_info_) 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) type_info_ = TypeInfoCache::Singleton()->Lookup(&iid); 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return type_info_ != NULL; 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HRESULT GetTypeInfo(UINT itinfo, LCID lcid, ITypeInfo** info) { 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (EnsureTI()) { 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *info = type_info_->CopyTypeInfo(); 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return S_OK; 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return E_UNEXPECTED; 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HRESULT GetIDsOfNames(REFIID riid, OLECHAR** names, UINT count, LCID lcid, 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISPID* dispids) { 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!EnsureTI()) 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return E_UNEXPECTED; 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return type_info_->GetIDsOfNames(names, count, dispids); 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HRESULT Invoke(IDispatch* p, DISPID dispid, REFIID riid, LCID lcid, 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WORD flags, DISPPARAMS* params, VARIANT* result, 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXCEPINFO* excepinfo, UINT* arg_err) { 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!EnsureTI()) 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return E_UNEXPECTED; 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return type_info_->Invoke(p, dispid, flags, params, result, excepinfo, 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) arg_err); 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected: 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TypeInfoNameCache* type_info_; 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Implements IDispatch part of T (where T is an IDispatch derived interface). 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The class assumes that the type info of T is available in a typelib of the 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// current module. 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <class T, const IID& iid = __uuidof(T)> 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class NO_VTABLE IDispatchImpl : public T { 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) STDMETHOD(GetTypeInfoCount)(UINT* count) { 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (count == NULL) 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return E_POINTER; 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *count = 1; 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return S_OK; 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) STDMETHOD(GetTypeInfo)(UINT itinfo, LCID lcid, ITypeInfo** pptinfo) { 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return type_info_.GetTypeInfo(itinfo, lcid, pptinfo); 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) STDMETHOD(GetIDsOfNames)(REFIID riid, LPOLESTR* names, UINT count, 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LCID lcid, DISPID* dispids) { 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return type_info_.GetIDsOfNames(riid, names, count, lcid, dispids); 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) STDMETHOD(Invoke)(DISPID dispid, REFIID riid, LCID lcid, WORD flags, 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISPPARAMS* params, VARIANT* result, EXCEPINFO* excepinfo, 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UINT* arg_err) { 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return type_info_.Invoke(static_cast<IDispatch*>(this), dispid, riid, lcid, 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) flags, params, result, excepinfo, arg_err); 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected: 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TypeInfoHolder<iid> type_info_; 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Simple implementation of IProvideClassInfo[2]. 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <const CLSID& class_id, const IID& source_iid> 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class NO_VTABLE IProvideClassInfo2Impl : public IProvideClassInfo2 { 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) STDMETHOD(GetClassInfo)(ITypeInfo** pptinfo) { 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return type_info_.GetTypeInfo(0, LANG_NEUTRAL, pptinfo); 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) STDMETHOD(GetGUID)(DWORD guid_kind, GUID* guid) { 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (guid == NULL || guid_kind != GUIDKIND_DEFAULT_SOURCE_DISP_IID) 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return E_INVALIDARG; 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *guid = source_iid; 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return S_OK; 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected: 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TypeInfoHolder<class_id> type_info_; 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace com_util 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // CHROME_FRAME_COM_TYPE_INFO_HOLDER_H_ 192