Index: lib/atl/atlbase.h =================================================================== --- lib/atl/atlbase.h (revision 71084) +++ lib/atl/atlbase.h (working copy) @@ -395,9 +395,9 @@ class CAtlModule : public _ATL_MODULE { -protected: +public: static GUID m_libid; -public: + CAtlModule() { ATLASSERT(_pAtlModule == NULL); Index: lib/atl/atlcom.h =================================================================== --- lib/atl/atlcom.h (revision 71084) +++ lib/atl/atlcom.h (working copy) @@ -1434,4 +1434,91 @@ {offsetofclass(ATL::_ICPLocator<&iid>, _atl_conn_classtype) - \ offsetofclass(ATL::IConnectionPointContainerImpl<_atl_conn_classtype>, _atl_conn_classtype)}, + + +/* TODO: + - IDispatchImpl contains a static member of type CComTypeInfoHolder that manages the type information for the dual interface. + If you have multiple objects that implement the same dual interface, only one instance of CComTypeInfoHolder is used. + - By default, the IDispatchImpl class looks up the type information for T in the registry. + To implement an unregistered interface, you can use the IDispatchImpl class without accessing the registry by using a predefined version number. + If you create an IDispatchImpl object that has 0xFFFF as the value for wMajor and 0xFFFF as the value for wMinor, + the IDispatchImpl class retrieves the type library from the .dll file instead of the registry. +*/ +template +class IDispatchImpl : + public T +{ +private: + CComPtr m_pTypeInfo; + + STDMETHOD(EnsureTILoaded)(LCID lcid) + { + HRESULT hr = S_OK; + if (m_pTypeInfo != NULL) + return hr; + + if (IsEqualCLSID(CLSID_NULL, *plibid)) + OutputDebugStringA("IDispatchImpl: plibid is CLSID_NULL!\r\n"); + + // Should we assert here? + if (wMajor == 0xffff && wMinor == 0xffff) + OutputDebugStringA("IDispatchImpl: not fully implemented, missing functionality to load TLB from file!\r\n"); + + CComPtr spTypeLib; + hr = LoadRegTypeLib(*plibid, wMajor, wMinor, lcid, &spTypeLib); + if (SUCCEEDED(hr)) + { + hr = spTypeLib->GetTypeInfoOfGuid(*piid, &m_pTypeInfo); + } + return hr; + } + +public: + IDispatchImpl() + { + } + + + // *** IDispatch methods *** + STDMETHOD(GetTypeInfoCount)(UINT *pctinfo) + { + if (pctinfo == NULL) + return E_POINTER; + + *pctinfo = 1; + return S_OK; + } + + STDMETHOD(GetTypeInfo)(UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo) + { + if (iTInfo != 0) + return DISP_E_BADINDEX; + if (ppTInfo == NULL) + return E_POINTER; + + HRESULT hr = EnsureTILoaded(lcid); + *ppTInfo = m_pTypeInfo; + if (*ppTInfo) + (*ppTInfo)->AddRef(); + + return hr; + } + + STDMETHOD(GetIDsOfNames)(REFIID /*riid*/, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId) + { + HRESULT hr = EnsureTILoaded(lcid); + if (SUCCEEDED(hr)) + hr = m_pTypeInfo->GetIDsOfNames(rgszNames, cNames, rgDispId); + return hr; + } + + STDMETHOD(Invoke)(DISPID dispIdMember, REFIID /*riid*/, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr) + { + HRESULT hr = EnsureTILoaded(lcid); + if (SUCCEEDED(hr)) + hr = m_pTypeInfo->Invoke(this, dispIdMember, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr); + return hr; + } +}; + }; // namespace ATL