|
|
//+-------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1999
//
// File: scriptevents.cpp
//
// Contents: Implementation of script events thru connection points
//
// History: 11-Feb-99 AudriusZ Created
//
//--------------------------------------------------------------------------
#include "stdafx.h"
#include "scriptevents.h"
// Traces
#ifdef DBG
CTraceTag tagComEvents(_T("Events"), _T("COM events")); #endif
/***************************************************************************\
* * METHOD: CEventDispatcherBase::SetContainer * * PURPOSE: Accesory function. Sets Connection point container * to be used for getting the sinks * * PARAMETERS: * LPUNKNOWN pComObject - pointer to COM object - event source (NULL is OK) * * RETURNS: * SC - result code * \***************************************************************************/ void CEventDispatcherBase::SetContainer(LPUNKNOWN pComObject) { // It makes difference to us if the object pointer is NULL
// (that means there are no com object , and that's OK)
// Or QI for IConnectionPointContainer will fail
// (that means an error)
m_bEventSourceExists = !(pComObject == NULL); if (!m_bEventSourceExists) return;
// note it's not guaranteed here m_spContainer won't be NULL
m_spContainer = pComObject; }
/***************************************************************************\
* * METHOD: CEventDispatcherBase::ScInvokeOnConnections * * PURPOSE: This method will iterate thu sinks and invoke * same method on each ot them * * PARAMETERS: * REFIID riid - GUID of disp interface * DISPID dispid - disp id * CComVariant *pVar - array of parameters (may be NULL) * int count - count of items in pVar * * RETURNS: * SC - result code * \***************************************************************************/ SC CEventDispatcherBase::ScInvokeOnConnections(REFIID riid, DISPID dispid, CComVariant *pVar, int count, CEventBuffer& buffer) const { DECLARE_SC(sc, TEXT("CEventDispatcherBase::ScInvokeOnConnections"));
// the pointer to event source passed is NULL,
// that means there is no event source - and no event sinks connected
// thus we are done at this point
if (!m_bEventSourceExists) return sc;
// check if com object supports IConnectionPointContainer;
// Bad pointer ( or to bad object ) if it does not
sc = ScCheckPointers(m_spContainer, E_NOINTERFACE); if (sc) return sc;
// get connection point
IConnectionPointPtr spConnectionPoint; sc = m_spContainer->FindConnectionPoint(riid, &spConnectionPoint); if (sc) return sc;
// recheck the pointer
sc = ScCheckPointers(spConnectionPoint, E_UNEXPECTED); if (sc) return sc;
// get connections
IEnumConnectionsPtr spEnumConnections; sc = spConnectionPoint->EnumConnections(&spEnumConnections); if (sc) return sc;
// recheck the pointer
sc = ScCheckPointers(spEnumConnections, E_UNEXPECTED); if (sc) return sc;
// reset iterator
sc = spEnumConnections->Reset(); if (sc) return sc;
// iterate thru sinks until Next returns S_FALSE.
CONNECTDATA connectdata; SC sc_last_error; while (1) // will use <break> to exit
{ // get the next sink
ZeroMemory(&connectdata, sizeof(connectdata)); sc = spEnumConnections->Next( 1, &connectdata, NULL ); if (sc) return sc;
// done if no more sinks
if (sc == SC(S_FALSE)) break;
// recheck the pointer
sc = ScCheckPointers(connectdata.pUnk, E_UNEXPECTED); if (sc) return sc;
// QI for IDispatch
IDispatchPtr spDispatch = connectdata.pUnk; connectdata.pUnk->Release();
// recheck the pointer
sc = ScCheckPointers(spDispatch, E_UNEXPECTED); if (sc) return sc;
// if events are locked by now, we need to postpone the call
// else - emit it
sc = buffer.ScEmitOrPostpone(spDispatch, dispid, pVar, count); if (sc) { sc_last_error = sc; // continue even if some calls failed
sc.TraceAndClear(); } } // we succeeded, but sinks may not,
// report the error (if one happened)
return sc_last_error; }
/***************************************************************************\
* * METHOD: CEventDispatcherBase::ScHaveSinksRegisteredForInterface * * PURPOSE: Checks if there are any sinks registered with interface * Function allows perform early check to skip com object creation * fo event parameters if event will go nowere anyway * * PARAMETERS: * const REFIID riid - interface id * * RETURNS: * SC - result code * \***************************************************************************/ SC CEventDispatcherBase::ScHaveSinksRegisteredForInterface(const REFIID riid) { DECLARE_SC(sc, TEXT("CEventDispatcherBase::ScHaveSinksRegisteredForInterface"));
// the pointer to event source passed is NULL,
// that means there is no event source - and no event sinks connected
if (!m_bEventSourceExists) return sc = S_FALSE;
// check if com object supports IConnectionPointContainer;
// Bad pointer ( or to bad object ) if it does not
sc = ScCheckPointers(m_spContainer, E_NOINTERFACE); if (sc) return sc;
// get connection point
IConnectionPointPtr spConnectionPoint; sc = m_spContainer->FindConnectionPoint(riid, &spConnectionPoint); if (sc) return sc;
// recheck the pointer
sc = ScCheckPointers(spConnectionPoint, E_UNEXPECTED); if (sc) return sc;
// get connections
IEnumConnectionsPtr spEnumConnections; sc = spConnectionPoint->EnumConnections(&spEnumConnections); if (sc) return sc;
// recheck the pointer
sc = ScCheckPointers(spEnumConnections, E_UNEXPECTED); if (sc) return sc;
// reset iterator
sc = spEnumConnections->Reset(); if (sc) return sc;
// get first member. Will return S_FALSE if no items in collection
CONNECTDATA connectdata; ZeroMemory(&connectdata, sizeof(connectdata)); sc = spEnumConnections->Next( 1, &connectdata, NULL ); if (sc) return sc;
// release the data
if (connectdata.pUnk) connectdata.pUnk->Release();
return sc; }
|