// MarshalableTI.h : Declaration of the CMarshalableTI #ifndef __MARSHALABLETI_H_ #define __MARSHALABLETI_H_ #include "mslablti.h" #include "resource.h" // main symbols // ATL doesn't support multiple LCID's at the same time // Whatever LCID is queried for first is the one that is used. class CComTypeInfoHolder2 { // Should be 'protected' but can cause compiler to generate fat code. public: const GUID* m_pguid; const GUID* m_plibid; WORD m_wMajor; WORD m_wMinor; ITypeInfo* m_pInfo; long m_dwRef; struct stringdispid { CComBSTR bstr; int nLen; DISPID id; }; stringdispid* m_pMap; int m_nCount; CComTypeInfoHolder2() { m_pInfo = NULL; m_pMap = NULL; } ~CComTypeInfoHolder2() { if (m_pInfo != NULL) { m_pInfo->Release(); } m_pInfo = NULL; if(m_pMap!= NULL) { delete [] m_pMap; } m_pMap = NULL; } public: HRESULT GetTI(LCID lcid, ITypeInfo** ppInfo) { HRESULT hr = S_OK; if (m_pInfo == NULL) hr = GetTI(lcid); *ppInfo = m_pInfo; if (m_pInfo != NULL) { m_pInfo->AddRef(); hr = S_OK; } return hr; } HRESULT GetTI(LCID lcid); HRESULT EnsureTI(LCID lcid) { HRESULT hr = S_OK; if (m_pInfo == NULL) hr = GetTI(lcid); return hr; } HRESULT GetTypeInfo(UINT /* itinfo */, LCID lcid, ITypeInfo** pptinfo) { HRESULT hRes = E_POINTER; if (pptinfo != NULL) hRes = GetTI(lcid, pptinfo); return hRes; } HRESULT GetIDsOfNames(REFIID /* riid */, LPOLESTR* rgszNames, UINT cNames, LCID lcid, DISPID* rgdispid) { HRESULT hRes = EnsureTI(lcid); if (m_pInfo != NULL) { for (int i=0; i<(int)cNames; i++) { int n = ocslen(rgszNames[i]); for (int j=m_nCount-1; j>=0; j--) { if ((n == m_pMap[j].nLen) && (memcmp(m_pMap[j].bstr, rgszNames[i], m_pMap[j].nLen * sizeof(OLECHAR)) == 0)) { rgdispid[i] = m_pMap[j].id; break; } } if (j < 0) { hRes = m_pInfo->GetIDsOfNames(rgszNames + i, 1, &rgdispid[i]); if (FAILED(hRes)) break; } } } return hRes; } HRESULT Invoke(IDispatch* p, DISPID dispidMember, REFIID /* riid */, LCID lcid, WORD wFlags, DISPPARAMS* pdispparams, VARIANT* pvarResult, EXCEPINFO* pexcepinfo, UINT* puArgErr) { HRESULT hRes = EnsureTI(lcid); if (m_pInfo != NULL) hRes = m_pInfo->Invoke(p, dispidMember, wFlags, pdispparams, pvarResult, pexcepinfo, puArgErr); return hRes; } HRESULT LoadNameCache(ITypeInfo* pTypeInfo) { TYPEATTR* pta; HRESULT hr = pTypeInfo->GetTypeAttr(&pta); if (SUCCEEDED(hr)) { m_nCount = pta->cFuncs; m_pMap = m_nCount == 0 ? 0 : new stringdispid[m_nCount]; for (int i=0; iGetFuncDesc(i, &pfd))) { CComBSTR bstrName; if (SUCCEEDED(pTypeInfo->GetDocumentation(pfd->memid, &bstrName, NULL, NULL, NULL))) { m_pMap[i].bstr.Attach(bstrName.Detach()); m_pMap[i].nLen = SysStringLen(m_pMap[i].bstr); m_pMap[i].id = pfd->memid; } pTypeInfo->ReleaseFuncDesc(pfd); } } pTypeInfo->ReleaseTypeAttr(pta); } return S_OK; } }; inline HRESULT CComTypeInfoHolder2::GetTI(LCID lcid) { //If this assert occurs then most likely didn't initialize properly ATLASSERT(m_plibid != NULL && m_pguid != NULL); ATLASSERT(!InlineIsEqualGUID(*m_plibid, GUID_NULL) && "Did you forget to pass the LIBID to CComModule::Init?"); if (m_pInfo != NULL) return S_OK; HRESULT hRes = E_FAIL; EnterCriticalSection(&_Module.m_csTypeInfoHolder); if (m_pInfo == NULL) { ITypeLib* pTypeLib; hRes = LoadRegTypeLib(*m_plibid, m_wMajor, m_wMinor, lcid, &pTypeLib); if (SUCCEEDED(hRes)) { CComPtr spTypeInfo; hRes = pTypeLib->GetTypeInfoOfGuid(*m_pguid, &spTypeInfo); if (SUCCEEDED(hRes)) { CComPtr spInfo(spTypeInfo); CComPtr spTypeInfo2; if (SUCCEEDED(spTypeInfo->QueryInterface(IID_ITypeInfo2, reinterpret_cast(&spTypeInfo2)))) spInfo = spTypeInfo2; LoadNameCache(spInfo); m_pInfo = spInfo.Detach(); } pTypeLib->Release(); } } LeaveCriticalSection(&_Module.m_csTypeInfoHolder); return hRes; } ///////////////////////////////////////////////////////////////////////////// // CMarshalableTI class ATL_NO_VTABLE CMarshalableTI : public CComObjectRootEx, public CComCoClass, public IMarshalableTI, public IMarshal, public ITypeInfo { private: CComTypeInfoHolder2 m_TIHolder; GUID m_guid; GUID m_libid; LCID m_lcid; bool m_bCreated; public: DECLARE_REGISTRY_RESOURCEID(IDR_MSLABLTI) DECLARE_NOT_AGGREGATABLE(CMarshalableTI) DECLARE_PROTECT_FINAL_CONSTRUCT() BEGIN_COM_MAP(CMarshalableTI) COM_INTERFACE_ENTRY(IMarshalableTI) COM_INTERFACE_ENTRY(IMarshal) COM_INTERFACE_ENTRY(ITypeInfo) END_COM_MAP() HRESULT FinalConstruct(); ///////////////////////////////////////////////////////////////////////////////// // IMarshalableTI methods STDMETHOD(Create)(/*[in]*/ REFIID clsid, /*[in]*/ REFIID iidLib, /*[in]*/ LCID lcid, /*[in]*/ WORD dwMajorVer, /*[in]*/ WORD dwMinorVer); ///////////////////////////////////////////////////////////////////////////////// // IMarshal methods STDMETHOD(GetUnmarshalClass)( /* [in] */ REFIID riid, /* [unique][in] */ void *pv, /* [in] */ DWORD dwDestContext, /* [unique][in] */ void *pvDestContext, /* [in] */ DWORD mshlflags, /* [out] */ CLSID *pCid); STDMETHOD(GetMarshalSizeMax)( /* [in] */ REFIID riid, /* [unique][in] */ void *pv, /* [in] */ DWORD dwDestContext, /* [unique][in] */ void *pvDestContext, /* [in] */ DWORD mshlflags, /* [out] */ DWORD *pSize); STDMETHOD(MarshalInterface)( /* [unique][in] */ IStream *pStm, /* [in] */ REFIID riid, /* [unique][in] */ void *pv, /* [in] */ DWORD dwDestContext, /* [unique][in] */ void *pvDestContext, /* [in] */ DWORD mshlflags); STDMETHOD(UnmarshalInterface)( /* [unique][in] */ IStream *pStm, /* [in] */ REFIID riid, /* [out] */ void **ppv); STDMETHOD(ReleaseMarshalData)( /* [unique][in] */ IStream *pStm); STDMETHOD(DisconnectObject)( /* [in] */ DWORD dwReserved); ///////////////////////////////////////////////////////////////////////////////// // ITypeInfo methods STDMETHOD(GetTypeAttr)( TYPEATTR ** ppTypeAttr); STDMETHOD(GetTypeComp)( ITypeComp ** ppTComp); STDMETHOD(GetFuncDesc)( UINT index, FUNCDESC ** ppFuncDesc); STDMETHOD(GetVarDesc)( UINT index, VARDESC ** ppVarDesc); STDMETHOD(GetNames)( MEMBERID memid, BSTR * rgBstrNames, UINT cMaxNames, UINT * pcNames); STDMETHOD(GetRefTypeOfImplType)( UINT index, HREFTYPE * pRefType); STDMETHOD(GetImplTypeFlags)( UINT index, INT * pImplTypeFlags); STDMETHOD(GetIDsOfNames)( LPOLESTR * rgszNames, UINT cNames, MEMBERID * pMemId); STDMETHOD(Invoke)( PVOID pvInstance, MEMBERID memid, WORD wFlags, DISPPARAMS * pDispParams, VARIANT * pVarResult, EXCEPINFO * pExcepInfo, UINT * puArgErr); STDMETHOD(GetDocumentation)( MEMBERID memid, BSTR * pBstrName, BSTR * pBstrDocString, DWORD * pdwHelpContext, BSTR * pBstrHelpFile); STDMETHOD(GetDllEntry)( MEMBERID memid, INVOKEKIND invKind, BSTR * pBstrDllName, BSTR * pBstrName, WORD * pwOrdinal); STDMETHOD(GetRefTypeInfo)( HREFTYPE hRefType, ITypeInfo ** ppTInfo); STDMETHOD(AddressOfMember)( MEMBERID memid, INVOKEKIND invKind, PVOID * ppv); STDMETHOD(CreateInstance)( IUnknown * pUnkOuter, REFIID riid, PVOID * ppvObj); STDMETHOD(GetMops)( MEMBERID memid, BSTR * pBstrMops); STDMETHOD(GetContainingTypeLib)( ITypeLib ** ppTLib, UINT * pIndex); STDMETHOD_(void, ReleaseTypeAttr)( TYPEATTR * pTypeAttr); STDMETHOD_(void, ReleaseFuncDesc)( FUNCDESC * pFuncDesc); STDMETHOD_(void, ReleaseVarDesc)( VARDESC * pVarDesc); private: HRESULT _GetClassInfo(ITypeInfo** ppTI); }; #endif //__MARSHALABLETI_H_