263 lines
7.1 KiB
C++
263 lines
7.1 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;
|
||
|
}
|
||
|
|