//+--------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1992 - 1995 // // File: evtsink.cxx // // Contents: Implementation of the CScriptEventSink class // //---------------------------------------------------------------------------- #include "headers.hxx" CScriptEventSink::CScriptEventSink(CScriptHost *pSH) { _pSH = pSH; _ulRefs = 1; Assert(_dwSinkCookie == 0); } CScriptEventSink::~CScriptEventSink() { Disconnect(); } //+--------------------------------------------------------------------------- // // Member: CScriptEventSink::Connect, public // // Synopsis: Connects to event interface on the source object // // Arguments: [pSource] -- Object to sink events from // // Returns: HRESULT // // TODO: This method should be more generic and walk through // the object's typeinfo looking for the default source // interface. // //---------------------------------------------------------------------------- HRESULT CScriptEventSink::Connect(IDispatch *pSource, BSTR bstrProgID) { HRESULT hr = S_OK; IConnectionPointContainer *pCPC; IConnectionPoint *pCP = 0; _pDispSource = pSource; pSource->AddRef(); hr = _pDispSource->QueryInterface(IID_IConnectionPointContainer, (LPVOID*)&pCPC); if (!hr) { if (bstrProgID && SysStringLen(bstrProgID) > 0) hr = CLSIDFromProgID(bstrProgID, &_clsidEvents); else _clsidEvents = DIID_DRemoteMTScriptEvents; if (hr == S_OK) hr = pCPC->FindConnectionPoint(_clsidEvents, &pCP); if (!hr) { hr = pCP->Advise(this, &_dwSinkCookie); ReleaseInterface(pCP); } ReleaseInterface(pCPC); #if DBG == 1 if (hr) TraceTag((tagError, "Hookup to event sink returned %x", hr)); #endif } return hr; } //+--------------------------------------------------------------------------- // // Member: CScriptEventSink::Disconnect, public // // Synopsis: Disconnects from a machine we connected to via Connect(). // // Arguments: (none) // //---------------------------------------------------------------------------- void CScriptEventSink::Disconnect() { HRESULT hr = S_OK; if (_dwSinkCookie && _pDispSource) { IConnectionPointContainer *pCPC; IConnectionPoint *pCP; hr = _pDispSource->QueryInterface(IID_IConnectionPointContainer, (LPVOID*)&pCPC); if (!hr) { hr = pCPC->FindConnectionPoint(DIID_DRemoteMTScriptEvents, &pCP); if (!hr) { pCP->Unadvise(_dwSinkCookie); ReleaseInterface(pCP); } ReleaseInterface(pCPC); #if DBG == 1 if (hr) TraceTag((tagError, "Unadvise from event sink returned %x", hr)); #endif } _dwSinkCookie = 0; } ClearInterface(&_pDispSource); _pSH = NULL; } // ************************************************************************* // // CScriptEventSink // // Class which implements the event sink for the remote object. We only pay // attention to Invoke calls. // // ************************************************************************* HRESULT CScriptEventSink::QueryInterface(REFIID iid, void **ppv) { if (iid == IID_IUnknown || iid == IID_IDispatch || iid == _clsidEvents) { *ppv = (IDispatch *)this; } else { *ppv = NULL; return E_NOINTERFACE; } ((IUnknown *)*ppv)->AddRef(); return S_OK; } //--------------------------------------------------------------------------- // // Member: CScriptEventSink::GetTypeInfo, IDispatch // //--------------------------------------------------------------------------- HRESULT CScriptEventSink::GetTypeInfo(UINT itinfo, ULONG lcid, ITypeInfo ** pptinfo) { return E_NOTIMPL; } //--------------------------------------------------------------------------- // // Member: CScriptEventSink::GetTypeInfoCount, IDispatch // //--------------------------------------------------------------------------- HRESULT CScriptEventSink::GetTypeInfoCount(UINT * pctinfo) { *pctinfo = 0; return S_OK; } //--------------------------------------------------------------------------- // // Member: CScriptEventSink::GetIDsOfNames, IDispatch // //--------------------------------------------------------------------------- HRESULT CScriptEventSink::GetIDsOfNames(REFIID riid, LPOLESTR * rgszNames, UINT cNames, LCID lcid, DISPID * rgdispid) { return E_NOTIMPL; } //--------------------------------------------------------------------------- // // Member: CScriptEventSink::Invoke, IDispatch // //--------------------------------------------------------------------------- HRESULT CScriptEventSink::Invoke(DISPID dispidMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS * pdispparams, VARIANT * pvarResult, EXCEPINFO * pexcepinfo, UINT * puArgErr) { if (_pSH && _pSH->GetSite() && _pSH->GetSite()->_pDispSink) { DISPPARAMS dp; VARIANTARG varg[20]; // We need to tack on 2 parameters to the call. First is the object // that is firing the event. Second is the dispatch ID. // We put them on the end of the list, which means they become // the first and second parameters to the event. if (pdispparams->cArgs > ARRAY_SIZE(varg) - 2) { AssertSz(FALSE, "NONFATAL: Too many parameters to event (max==18)!"); return E_FAIL; } dp.cArgs = pdispparams->cArgs + 2; dp.cNamedArgs = pdispparams->cNamedArgs; dp.rgdispidNamedArgs = pdispparams->rgdispidNamedArgs; memcpy(varg, pdispparams->rgvarg, pdispparams->cArgs * sizeof(VARIANTARG)); V_VT(&varg[dp.cArgs-1]) = VT_DISPATCH; V_DISPATCH(&varg[dp.cArgs-1]) = _pDispSource; V_VT(&varg[dp.cArgs-2]) = VT_I4; V_I4(&varg[dp.cArgs-2]) = dispidMember; dp.rgvarg = varg; return _pSH->GetSite()->_pDispSink->Invoke( DISPID_MTScript_OnEventSourceEvent, IID_NULL, lcid, DISPATCH_METHOD, &dp, pvarResult, pexcepinfo, puArgErr); } return S_OK; }