windows-nt/Source/XPSP1/NT/sdktools/mtscript/scrhost/evtsink.cxx
2020-09-26 16:20:57 +08:00

263 lines
6.8 KiB
C++

//+---------------------------------------------------------------------------
//
// 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;
}