// DecalImpl.h // Declaration of default implementations for Decal interfaces #ifndef __DECALIMPL_H #define __DECALIMPL_H //C Library includes #include #include #include #import #include "../Include/Helpers.h" template< class ImplT > class ATL_NO_VTABLE IDecalServiceImpl : public IDecalService { public: CComPtr< IDecal > m_pDecal; HRESULT onInitialize() { return S_OK; } void onTerminate() { } STDMETHOD(Initialize)( IDecal *pDecal ) { m_pDecal = pDecal; HRESULT hRes = static_cast< ImplT * >( this )->onInitialize(); if( FAILED( hRes ) ) m_pDecal.Release(); return hRes; } STDMETHOD(Terminate)() { static_cast< ImplT * >( this )->onTerminate(); m_pDecal.Release(); return S_OK; } STDMETHOD(BeforePlugins)() { return S_OK; } STDMETHOD(AfterPlugins)() { return S_OK; } }; class IDecalRenderImpl : public IDecalRender { public: STDMETHOD(Render2D)() { return S_OK; } STDMETHOD(Render3D)() { return S_OK; } STDMETHOD(ChangeHWND)() { return S_OK; } STDMETHOD(ChangeDirectX)() { return S_OK; } }; template< class ImplT, const CLSID *pClsid > class IDecalFileSurrogateXMLImpl : public IDecalFileSurrogate { public: static LPCTSTR getConfigGroup() { // This function must be overridden _ASSERT( FALSE ); return _T( "Error: Bad config group" ); } STDMETHOD(Register)(BSTR strFilename) { USES_CONVERSION; MSXML::IXMLDOMDocumentPtr pDoc; pDoc.CreateInstance( __uuidof( MSXML::DOMDocument ), NULL, CLSCTX_INPROC_SERVER ); if( !pDoc->load( strFilename ) ) { _ASSERT( FALSE ); return E_FAIL; } MSXML::IXMLDOMElementPtr pRoot = pDoc->selectSingleNode( _T( "/*" ) ); _variant_t vCLSID = pRoot->getAttribute( _T( "clsid" ) ), vProgID = pRoot->getAttribute( _T( "progid" ) ), vName = pRoot->getAttribute( _T( "name" ) ); if( vCLSID.vt != VT_BSTR ) { _ASSERT( FALSE ); return E_FAIL; } // Convert the clsid CLSID clsid; HRESULT hRes = ::CLSIDFromString( vCLSID.bstrVal, &clsid ); if( FAILED( hRes ) ) { // Improperly formatted CLSID _ASSERT( FALSE ); return hRes; } // Everything we need now, make the registry entries LPOLESTR strKey, strSurrogate, strUninstall; ::StringFromCLSID( clsid, &strKey ); ::StringFromCLSID( *pClsid, &strSurrogate ); ::StringFromCLSID( __uuidof( SurrogateRemove ), &strUninstall ); LPTSTR szKey = OLE2T( strKey ); RegKey rk; TCHAR szPluginKey[ 255 ]; ::_stprintf( szPluginKey, _T( "Software\\Decal\\%s\\%s" ), static_cast< ImplT * >( this )->getConfigGroup(), szKey ); // Open it up rk.Create( HKEY_LOCAL_MACHINE, szPluginKey ); if( vName.vt == VT_BSTR ) rk.SetStringValue (NULL, OLE2T( vName.bstrVal )); LPTSTR szSurrogate = OLE2T( strSurrogate ); rk.SetDWORDValue (_T("Enabled"), 1); rk.SetStringValue (_T("Surrogate"), szSurrogate); rk.SetStringValue ( _T("Uninstall"), OLE2T( strUninstall )); rk.SetStringValue( _T("File"), OLE2T( strFilename ) ); if( vProgID.vt == VT_BSTR ) { LPTSTR szProgID = OLE2T( vProgID.bstrVal ); RegKey rkProgID; rkProgID.Create( HKEY_CLASSES_ROOT, szProgID ); rkProgID.SetKeyValue( _T( "CLSID" ), szKey ); rk.SetStringValue( _T("ProgID"), szProgID ); } ::CoTaskMemFree( strUninstall ); ::CoTaskMemFree( strSurrogate ); ::CoTaskMemFree( strKey ); return S_OK; } }; // Disp event dynamic is a hybrid that uses type info from a generated // typelib (at runtime) to dispatch messages. Unlike IDispEventImpl which // requires a registered typelib. Still, much code is copied from IDispEventImpl. template< UINT nID, class T > class ATL_NO_VTABLE IDispEventDynamicImpl : public IDispEventSimpleImpl< nID, T, &GUID_NULL > { public: typedef IDispEventSimpleImpl< nID, T, &GUID_NULL > _base; CComPtr< ITypeInfo2 > m_pTI; HRESULT GetSourceInterfaceInfo( IUnknown *pUnk, ITypeInfo **ppTI ) { // Get provide class info CComPtr< IProvideClassInfo > pPCI; HRESULT hRes = pUnk->QueryInterface( &pPCI ); if( FAILED( hRes ) ) // Does not support IProvideClassInfo, bad return hRes; CComPtr< ITypeInfo > pClassInfo; hRes = pPCI->GetClassInfo( &pClassInfo ); if( FAILED( hRes ) ) // Failed to return any class info return hRes; // Iterate through the Impl types to find the default source interface int nImplFlags; for( UINT i = 0; SUCCEEDED( pClassInfo->GetImplTypeFlags() ); ++ i ) { if( nImplFlags == ( IMPLTYPEFLAG_FSOURCE | IMPLTYPEFLAG_FDEFAULT ) ) { // Found it - locate our type info HREFTYPE href; hRes = pClassInfo->GetRefTypeOfImplType( i, &href ); if( FAILED( hRes ) ) // Could not access the ref type (referenced typelib not available?) return hRes; return pClassInfo->GetRefTypeInfo( href, ppTI ); } } // Did not find a suitable interface return E_FAIL; } HRESULT GetSourceIID( ITypeInfo *pTI, IID *piid ) { TYPEATTR *pTA; HRESULT hRes = pTI->GetTypeAttr( &pTA ); if( FAILED( hRes ) ) return hRes; *piid = pTA->guid; pTI->ReleaseTypeAttr( pTA ); return S_OK; } HRESULT DispEventAdvise( IUnknown *pUnk ) { CComPtr< ITypeInfo > pSourceInfo; HRESULT hRes = GetSourceInterfaceInfo( pUnk, &pSourceInfo ); if( FAILED( hRes ) ) return hRes; IID iid; hRes = GetSourceIID( pSourceInfo, &iid ); if( FAILED( hRes ) ) return hRes; hRes = _base::DispEventAdvise( pUnk, iid ); if( SUCCEEDED( hRes ) ) m_pTI = pSourceInfo; return hRes; } HRESULT DispEventUnadvise( IUnknown *pUnk ) { IID iid; HRESULT hRes = GetSourceIID( pSourceInfo, &iid ); _ASSERTE( SUCCEEDED( hRes ) ); _base::DispEventUnadvise( pUnk, iid ); m_pTI.Release(); return S_OK; } // Functions copied from IDispEventImpl 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 E_INVALIDARG; if( pptinfo == NULL ) return E_POINTER; return m_pTI->QueryIterface( pptinfo ); } STDMETHOD(GetIDsOfNames)(REFIID riid, LPOLESTR* rgszNames, UINT cNames, LCID, DISPID* rgdispid) { if( !::InlineIsEqualGUID( riid, IID_NULL ) ) // By spec return DISP_E_UNKNOWNINTERFACE; return m_pTI->GetIDsOfNames( rgszNames, cNames, rgdispid ); } // Helper for finding the function index for a DISPID HRESULT GetFuncInfoFromId(const IID& /*iid*/, DISPID dispidMember, LCID lcid, _ATL_FUNC_INFO& info) { FUNCDESC* pFuncDesc = NULL; UINT nIndex; HRESULT hr = m_pTI->GetFuncIndexOfMemId(dispidMember, INVOKE_FUNC, &nIndex); if (FAILED(hr)) return hr; hr = m_pTI->GetFuncDesc(nIndex, &pFuncDesc); if (FAILED(hr)) return hr; // If this assert occurs, then add a #define _ATL_MAX_VARTYPES nnnn // before including atlcom.h ATLASSERT(pFuncDesc->cParams <= _ATL_MAX_VARTYPES); if (pFuncDesc->cParams > _ATL_MAX_VARTYPES) return E_FAIL; for (int i=0; icParams; i++) { info.pVarTypes[i] = pFuncDesc->lprgelemdescParam[pFuncDesc->cParams - i - 1].tdesc.vt; if (info.pVarTypes[i] == VT_PTR) info.pVarTypes[i] = pFuncDesc->lprgelemdescParam[pFuncDesc->cParams - i - 1].tdesc.lptdesc->vt | VT_BYREF; if (info.pVarTypes[i] == VT_USERDEFINED) info.pVarTypes[i] = GetUserDefinedType(pFuncDesc->lprgelemdescParam[pFuncDesc->cParams-i-1].tdesc.hreftype); } VARTYPE vtReturn = pFuncDesc->elemdescFunc.tdesc.vt; switch(vtReturn) { case VT_INT: vtReturn = VT_I4; break; case VT_UINT: vtReturn = VT_UI4; break; case VT_VOID: vtReturn = VT_EMPTY; // this is how DispCallFunc() represents void break; case VT_HRESULT: vtReturn = VT_ERROR; break; } info.vtReturn = vtReturn; info.cc = pFuncDesc->callconv; info.nParams = pFuncDesc->cParams; m_pTI->ReleaseFuncDesc(pFuncDesc); return S_OK; } VARTYPE GetUserDefinedType(HREFTYPE hrt) { CComPtr spTypeInfo; VARTYPE vt = VT_USERDEFINED; HRESULT hr = E_FAIL; hr = m_pTI->GetRefTypeInfo(hrt, &spTypeInfo); if(FAILED(hr)) return vt; TYPEATTR *pta=NULL; m_pTI->GetTypeAttr(&pta); if(pta && pta->typekind == TKIND_ALIAS) { if (pta->tdescAlias.vt == VT_USERDEFINED) GetUserDefinedType(spTypeInfo,pta->tdescAlias.hreftype); else vt = pta->tdescAlias.vt; } if(pta) spTypeInfo->ReleaseTypeAttr(pta); return vt; } }; #endif