1635 lines
47 KiB
C++
1635 lines
47 KiB
C++
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
/* File: connect.cpp
|
||
|
|
||
|
Description: Contains class definitions for classes associated with
|
||
|
OLE connection points. These are:
|
||
|
|
||
|
ConnectionPoint ( IConnectionPoint )
|
||
|
ConnectionPointEnum ( IEnumConnectionPoints )
|
||
|
ConnectionEnum ( IEnumConnections )
|
||
|
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
Date Description Programmer
|
||
|
-------- --------------------------------------------------- ----------
|
||
|
06/19/96 Initial creation. BrianAu
|
||
|
*/
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
#include "pch.h" // PCH
|
||
|
#pragma hdrstop
|
||
|
|
||
|
#include "connect.h"
|
||
|
#include "guidsp.h"
|
||
|
|
||
|
//
|
||
|
// Constants for connection point-related objects.
|
||
|
//
|
||
|
const UINT CONNECTION_FIRST_COOKIE = 100; // 1st cookie value given out.
|
||
|
|
||
|
//
|
||
|
// Verify that build is UNICODE.
|
||
|
//
|
||
|
#if !defined(UNICODE)
|
||
|
# error This module must be compiled UNICODE.
|
||
|
#endif
|
||
|
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
/* Function: ConnectionPoint::ConnectionPoint
|
||
|
|
||
|
Description: Constructor,
|
||
|
|
||
|
Arguments:
|
||
|
pUnkContainer - Pointer to containing DiskQuotaController object.
|
||
|
|
||
|
riid - Reference to IID that this connection point object supports.
|
||
|
|
||
|
Returns: Nothing.
|
||
|
|
||
|
Exceptions: CAllocException, CSyncException
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
Date Description Programmer
|
||
|
-------- --------------------------------------------------- ----------
|
||
|
06/19/96 Initial creation. BrianAu
|
||
|
09/06/96 Added exception handling. BrianAu
|
||
|
*/
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
ConnectionPoint::ConnectionPoint(
|
||
|
LPUNKNOWN pUnkContainer,
|
||
|
REFIID riid
|
||
|
) : m_cRef(0),
|
||
|
m_cConnections(0),
|
||
|
m_dwCookieNext(CONNECTION_FIRST_COOKIE),
|
||
|
m_pUnkContainer(pUnkContainer),
|
||
|
m_riid(riid),
|
||
|
m_hMutex(NULL)
|
||
|
{
|
||
|
DBGTRACE((DM_CONNPT, DL_MID, TEXT("ConnectionPoint::ConnectionPoint")));
|
||
|
DBGASSERT((NULL != pUnkContainer));
|
||
|
|
||
|
if (NULL == (m_hMutex = CreateMutex(NULL, FALSE, NULL)))
|
||
|
throw CSyncException(CSyncException::mutex, CSyncException::create);
|
||
|
|
||
|
m_Dispatch.Initialize(static_cast<IDispatch *>(this),
|
||
|
LIBID_DiskQuotaTypeLibrary,
|
||
|
IID_DIDiskQuotaControlEvents,
|
||
|
L"DSKQUOTA.DLL");
|
||
|
}
|
||
|
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
/* Function: ConnectionPoint::~ConnectionPoint
|
||
|
|
||
|
Description: Destructor.
|
||
|
|
||
|
Arguments: None.
|
||
|
|
||
|
Returns: Nothing.
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
Date Description Programmer
|
||
|
-------- --------------------------------------------------- ----------
|
||
|
06/19/96 Initial creation. BrianAu
|
||
|
*/
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
ConnectionPoint::~ConnectionPoint(
|
||
|
VOID
|
||
|
)
|
||
|
{
|
||
|
DBGTRACE((DM_CONNPT, DL_MID, TEXT("ConnectionPoint::~ConnectionPoint")));
|
||
|
|
||
|
Lock();
|
||
|
UINT cConnections = m_ConnectionList.Count();
|
||
|
for (UINT i = 0; i < cConnections; i++)
|
||
|
{
|
||
|
if (NULL != m_ConnectionList[i].pUnk)
|
||
|
{
|
||
|
m_ConnectionList[i].pUnk->Release();
|
||
|
}
|
||
|
}
|
||
|
ReleaseLock();
|
||
|
|
||
|
if (NULL != m_hMutex)
|
||
|
CloseHandle(m_hMutex);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
/* Function: ConnectionPoint::QueryInterface
|
||
|
|
||
|
Description: Returns an interface pointer to the object's IUnknown or
|
||
|
IConnectionPoint interface. Only IID_IUnknown and
|
||
|
IID_IConnectionPoint are recognized. The object referenced by the
|
||
|
returned interface pointer is uninitialized. The recipient of the
|
||
|
pointer must call Initialize() before the object is usable.
|
||
|
|
||
|
Arguments:
|
||
|
riid - Reference to requested interface ID.
|
||
|
|
||
|
ppvOut - Address of interface pointer variable to accept interface ptr.
|
||
|
|
||
|
Returns:
|
||
|
NOERROR - Success.
|
||
|
E_NOINTERFACE - Requested interface not supported.
|
||
|
E_INVALIDARG - ppvOut argument was NULL.
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
Date Description Programmer
|
||
|
-------- --------------------------------------------------- ----------
|
||
|
06/18/96 Initial creation. BrianAu
|
||
|
*/
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
STDMETHODIMP
|
||
|
ConnectionPoint::QueryInterface(
|
||
|
REFIID riid,
|
||
|
LPVOID *ppvOut
|
||
|
)
|
||
|
{
|
||
|
DBGTRACE((DM_CONNPT, DL_MID, TEXT("ConnectionPoint::QueryInterface")));
|
||
|
DBGPRINTIID(DM_CONNPT, DL_MID, riid);
|
||
|
|
||
|
HRESULT hr = E_NOINTERFACE;
|
||
|
|
||
|
if (NULL == ppvOut)
|
||
|
return E_INVALIDARG;
|
||
|
|
||
|
*ppvOut = NULL;
|
||
|
|
||
|
if (IID_IUnknown == riid || IID_IConnectionPoint == riid)
|
||
|
{
|
||
|
*ppvOut = static_cast<IConnectionPoint *>(this);
|
||
|
}
|
||
|
else if (IID_IDispatch == riid)
|
||
|
{
|
||
|
*ppvOut = static_cast<IDispatch *>(this);
|
||
|
}
|
||
|
if (NULL != *ppvOut)
|
||
|
{
|
||
|
((LPUNKNOWN)*ppvOut)->AddRef();
|
||
|
hr = NOERROR;
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
/* Function: ConnectionPoint::AddRef
|
||
|
|
||
|
Description: Increments object reference count.
|
||
|
|
||
|
Arguments: None.
|
||
|
|
||
|
Returns: New reference count value.
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
Date Description Programmer
|
||
|
-------- --------------------------------------------------- ----------
|
||
|
06/18/96 Initial creation. BrianAu
|
||
|
*/
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
STDMETHODIMP_(ULONG)
|
||
|
ConnectionPoint::AddRef(
|
||
|
VOID
|
||
|
)
|
||
|
{
|
||
|
DBGTRACE((DM_CONNPT, DL_LOW, TEXT("ConnectionPoint::AddRef")));
|
||
|
DBGPRINT((DM_CONNPT, DL_LOW, TEXT("\t0x%08X %d -> %d\n"),
|
||
|
this, m_cRef, m_cRef + 1));
|
||
|
|
||
|
ULONG ulReturn = m_cRef + 1;
|
||
|
InterlockedIncrement(&m_cRef);
|
||
|
|
||
|
//
|
||
|
// NOTE: We maintain a pointer to the quota controller (m_pUnkContainer) but
|
||
|
// we DO NOT AddRef it. The controller calls AddRef for connection
|
||
|
// point objects so this would create a circular reference.
|
||
|
//
|
||
|
|
||
|
return ulReturn;
|
||
|
}
|
||
|
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
/* Function: ConnectionPoint::Release
|
||
|
|
||
|
Description: Decrements object reference count. If count drops to 0,
|
||
|
object is deleted.
|
||
|
|
||
|
Arguments: None.
|
||
|
|
||
|
Returns: New reference count value.
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
Date Description Programmer
|
||
|
-------- --------------------------------------------------- ----------
|
||
|
06/18/96 Initial creation. BrianAu
|
||
|
*/
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
STDMETHODIMP_(ULONG)
|
||
|
ConnectionPoint::Release(
|
||
|
VOID
|
||
|
)
|
||
|
{
|
||
|
DBGTRACE((DM_CONNPT, DL_LOW, TEXT("ConnectionPoint::Release")));
|
||
|
DBGPRINT((DM_COM, DL_HIGH, TEXT("\t0x%08X %d -> %d\n"),
|
||
|
this, m_cRef, m_cRef - 1));
|
||
|
|
||
|
ULONG ulReturn = m_cRef - 1;
|
||
|
if (InterlockedDecrement(&m_cRef) == 0)
|
||
|
{
|
||
|
delete this;
|
||
|
ulReturn = 0;
|
||
|
}
|
||
|
return ulReturn;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
/* Function: ConnectionPoint::GetConnectionInterface
|
||
|
|
||
|
Description: Retrieves a connection point's interface ID.
|
||
|
|
||
|
Arguments:
|
||
|
pIID - Address of IID variable to receive the IID.
|
||
|
|
||
|
Returns:
|
||
|
NOERROR - Success.
|
||
|
E_INVALIDARG - pIID is NULL.
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
Date Description Programmer
|
||
|
-------- --------------------------------------------------- ----------
|
||
|
06/18/96 Initial creation. BrianAu
|
||
|
*/
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
STDMETHODIMP
|
||
|
ConnectionPoint::GetConnectionInterface(
|
||
|
LPIID pIID
|
||
|
)
|
||
|
{
|
||
|
DBGTRACE((DM_CONNPT, DL_HIGH, TEXT("ConnectionPoint::GetConnectionInterface")));
|
||
|
HRESULT hr = E_INVALIDARG;
|
||
|
|
||
|
if (NULL != pIID)
|
||
|
{
|
||
|
*pIID = m_riid;
|
||
|
hr = NOERROR;
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
/* Function: ConnectionPoint::GetConnectionPointContainer
|
||
|
|
||
|
Description: Retrieves an interface pointer for the point's parent
|
||
|
container.
|
||
|
|
||
|
Arguments:
|
||
|
ppCPC - Address of variable to receive container's interface pointer
|
||
|
value.
|
||
|
|
||
|
Returns:
|
||
|
NOERROR - Success.
|
||
|
E_INVALIDARG - ppCPC argument was NULL.
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
Date Description Programmer
|
||
|
-------- --------------------------------------------------- ----------
|
||
|
06/18/96 Initial creation. BrianAu
|
||
|
*/
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
STDMETHODIMP
|
||
|
ConnectionPoint::GetConnectionPointContainer(
|
||
|
PCONNECTIONPOINTCONTAINER *ppCPC
|
||
|
)
|
||
|
{
|
||
|
DBGTRACE((DM_CONNPT, DL_HIGH, TEXT("ConnectionPoint::GetConnectionPointContainer")));
|
||
|
return m_pUnkContainer->QueryInterface(IID_IConnectionPointContainer,
|
||
|
(LPVOID *)ppCPC);
|
||
|
}
|
||
|
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
/* Function: ConnectionPoint::Advise
|
||
|
|
||
|
Description: Notifies the connection point of an outgoing interface.
|
||
|
|
||
|
Arguments:
|
||
|
pUnkSink - Pointer to outgoing interface provided by Sink.
|
||
|
|
||
|
pdwCookie - Address of variable to receive the "cookie" returned
|
||
|
for this connection. The client uses this "cookie" value to
|
||
|
refer to the connection.
|
||
|
|
||
|
Returns:
|
||
|
NOERROR - Success.
|
||
|
E_INVALIDARG - pUnkSink or pdwCookie were NULL.
|
||
|
CONNECT_E_CANNOTCONNECT - Sink doesn't support our event interface.
|
||
|
E_UNEXPECTED - Exception caught while calling client code.
|
||
|
E_OUTOFMEMORY - Insufficient memory.
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
Date Description Programmer
|
||
|
-------- --------------------------------------------------- ----------
|
||
|
07/21/96 Initial creation. BrianAu
|
||
|
09/06/96 Added exception handling. BrianAu
|
||
|
*/
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
STDMETHODIMP
|
||
|
ConnectionPoint::Advise(
|
||
|
LPUNKNOWN pUnkSink,
|
||
|
LPDWORD pdwCookie
|
||
|
)
|
||
|
{
|
||
|
DBGTRACE((DM_CONNPT, DL_HIGH, TEXT("ConnectionPoint::Advise")));
|
||
|
DBGPRINT((DM_CONNPT, DL_MID, TEXT("\tAdvising connpt 0x%08X of sink 0x%08X"),
|
||
|
this, pUnkSink));
|
||
|
|
||
|
HRESULT hr = NOERROR;
|
||
|
if (NULL == pUnkSink || NULL == pdwCookie)
|
||
|
return E_INVALIDARG;
|
||
|
|
||
|
LPUNKNOWN pSink = NULL;
|
||
|
AutoLockMutex lock(m_hMutex);
|
||
|
|
||
|
//
|
||
|
// Does the sink support our conn pt interface?
|
||
|
//
|
||
|
try
|
||
|
{
|
||
|
//
|
||
|
// QueryInterface() is client code. Must handle exceptions.
|
||
|
//
|
||
|
hr = pUnkSink->QueryInterface(m_riid, (LPVOID *)&pSink);
|
||
|
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
CONNECTDATA cd;
|
||
|
|
||
|
//
|
||
|
// See if there is an unused entry in the list.
|
||
|
// If not, we'll have to extend the list.
|
||
|
//
|
||
|
UINT index = m_cConnections;
|
||
|
for (UINT i = 0; i < m_cConnections; i++)
|
||
|
{
|
||
|
if (NULL == m_ConnectionList[i].pUnk)
|
||
|
{
|
||
|
index = i;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Fill in the connection info and add to connection list.
|
||
|
//
|
||
|
cd.pUnk = pSink;
|
||
|
*pdwCookie = cd.dwCookie = m_dwCookieNext++;
|
||
|
|
||
|
if (index < m_cConnections)
|
||
|
m_ConnectionList[index] = cd;
|
||
|
else
|
||
|
m_ConnectionList.Append(cd); // This can throw OutOfMemory.
|
||
|
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
m_cConnections++; // Another connection.
|
||
|
DBGPRINT((DM_CONNPT, DL_HIGH,
|
||
|
TEXT("CONNPT - Connection complete. Cookie = %d. %d total connections."),
|
||
|
*pdwCookie, m_cConnections));
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
DBGERROR((TEXT("ConnPt connection failed with error 0x%08X."), hr));
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
hr = CONNECT_E_CANNOTCONNECT; // Interface not supported.
|
||
|
}
|
||
|
catch(CAllocException& e)
|
||
|
{
|
||
|
DBGERROR((TEXT("Insufficient memory exception")));
|
||
|
hr = E_OUTOFMEMORY;
|
||
|
}
|
||
|
|
||
|
if (FAILED(hr) && NULL != pSink)
|
||
|
{
|
||
|
//
|
||
|
// Something failed after QueryInterface. Release sink pointer.
|
||
|
//
|
||
|
pSink->Release();
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
/* Function: ConnectionPoint::Unadvise
|
||
|
|
||
|
Description: Disconntinues an outgoing communication channel with the
|
||
|
connection point object.
|
||
|
|
||
|
Arguments:
|
||
|
dwCookie - The "channel" identifier returned from Advise().
|
||
|
|
||
|
Returns:
|
||
|
NOERROR - Success.
|
||
|
CONNECT_E_NOCONNECTION - No connection found for this cookie.
|
||
|
E_UNEXPECTED - Exception caught while calling client code.
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
Date Description Programmer
|
||
|
-------- --------------------------------------------------- ----------
|
||
|
07/21/96 Initial creation. BrianAu
|
||
|
*/
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
STDMETHODIMP
|
||
|
ConnectionPoint::Unadvise(
|
||
|
DWORD dwCookie
|
||
|
)
|
||
|
{
|
||
|
DBGTRACE((DM_CONNPT, DL_HIGH, TEXT("ConnectionPoint::Unadvise")));
|
||
|
DBGPRINT((DM_CONNPT, DL_MID, TEXT("\tUnadvising connpt 0x%08X of cookie %d"),
|
||
|
this, dwCookie));
|
||
|
|
||
|
HRESULT hr = CONNECT_E_NOCONNECTION;
|
||
|
|
||
|
if (0 != dwCookie)
|
||
|
{
|
||
|
AutoLockMutex lock(m_hMutex);
|
||
|
for (UINT i = 0; i < m_cConnections; i++)
|
||
|
{
|
||
|
if (m_ConnectionList[i].dwCookie == dwCookie)
|
||
|
{
|
||
|
//
|
||
|
// Matching cookie found. Release interface, mark connection
|
||
|
// list entry as unused.
|
||
|
//
|
||
|
hr = NOERROR;
|
||
|
m_ConnectionList[i].pUnk->Release();
|
||
|
m_ConnectionList[i].pUnk = NULL;
|
||
|
m_ConnectionList[i].dwCookie = 0;
|
||
|
m_cConnections--;
|
||
|
DBGPRINT((DM_CONNPT, DL_HIGH, TEXT("CONNPT - Connection terminated for cookie %d. %d total connections"),
|
||
|
dwCookie, m_cConnections));
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
/* Function: ConnectionPoint::EnumConnections
|
||
|
|
||
|
Description: Retrieves in interface pointer to a connection enumerator
|
||
|
which enumerates all connections associated with this connection
|
||
|
point.
|
||
|
|
||
|
Arguments:
|
||
|
ppEnum - Address of interface pointer variable to received address of
|
||
|
the enumerator's IEnumConnection interface.
|
||
|
|
||
|
Returns:
|
||
|
NOERROR - Success.
|
||
|
E_INVALIDARG - ppEnum was NULL.
|
||
|
E_OUTOFMEMORY - Insufficient memory to create enumerator.
|
||
|
E_UNEXPECTED - Unexpected exception.
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
Date Description Programmer
|
||
|
-------- --------------------------------------------------- ----------
|
||
|
07/21/96 Initial creation. BrianAu
|
||
|
09/06/96 Added exception handling. BrianAu
|
||
|
*/
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
STDMETHODIMP
|
||
|
ConnectionPoint::EnumConnections(
|
||
|
PENUMCONNECTIONS *ppEnum
|
||
|
)
|
||
|
{
|
||
|
DBGTRACE((DM_CONNPT, DL_HIGH, TEXT("ConnectionPoint::EnumConnections")));
|
||
|
|
||
|
HRESULT hr = NOERROR;
|
||
|
|
||
|
if (NULL == ppEnum)
|
||
|
return E_INVALIDARG;
|
||
|
|
||
|
ConnectionEnum *pEnum = NULL;
|
||
|
AutoLockMutex lock(m_hMutex);
|
||
|
|
||
|
try
|
||
|
{
|
||
|
array_autoptr<CONNECTDATA> ptrCD;
|
||
|
PCONNECTDATA pcd = NULL;
|
||
|
//
|
||
|
// Build temp array of connection data to initialize enumerator.
|
||
|
// Note: If m_cConnections == 0, we still return an enumerator
|
||
|
// but it's uninitialized. Calls to Next and Skip will always
|
||
|
// return S_FALSE so the enumerator is just viewed as "empty".
|
||
|
//
|
||
|
if (0 != m_cConnections)
|
||
|
{
|
||
|
ptrCD = new CONNECTDATA[m_cConnections];
|
||
|
pcd = ptrCD.get();
|
||
|
|
||
|
//
|
||
|
// Transfer connection info to temp array for initializting
|
||
|
// the enumerator object.
|
||
|
// Remember, the connection list can have unused entries so
|
||
|
// cConnListEntries can be greater than m_cConnections.
|
||
|
//
|
||
|
UINT cConnListEntries = m_ConnectionList.Count();
|
||
|
for (UINT i = 0, j = 0; i < cConnListEntries; i++)
|
||
|
{
|
||
|
DBGASSERT((j < m_cConnections));
|
||
|
*(pcd + j) = m_ConnectionList[i];
|
||
|
if (NULL != pcd[j].pUnk)
|
||
|
j++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Create the enumerator object.
|
||
|
// The enumerator keeps a copy of the connection's
|
||
|
// IUnknown pointer. Note that we still create an
|
||
|
// enumerator even if m_cConnections is 0. It's just an
|
||
|
// empty enumerator. If m_cConnections is 0, pcd can be NULL.
|
||
|
//
|
||
|
DBGASSERT((m_cConnections ? NULL != pcd : TRUE));
|
||
|
pEnum = new ConnectionEnum(static_cast<IConnectionPoint *>(this), m_cConnections, pcd);
|
||
|
|
||
|
hr = pEnum->QueryInterface(IID_IEnumConnections,
|
||
|
(LPVOID *)ppEnum);
|
||
|
}
|
||
|
catch(CAllocException& e)
|
||
|
{
|
||
|
DBGERROR((TEXT("Insufficient memory exception")));
|
||
|
delete pEnum;
|
||
|
hr = E_OUTOFMEMORY;
|
||
|
}
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// IDispatch::GetIDsOfNames
|
||
|
//
|
||
|
STDMETHODIMP
|
||
|
ConnectionPoint::GetIDsOfNames(
|
||
|
REFIID riid,
|
||
|
OLECHAR **rgszNames,
|
||
|
UINT cNames,
|
||
|
LCID lcid,
|
||
|
DISPID *rgDispId
|
||
|
)
|
||
|
{
|
||
|
DBGTRACE((DM_CONNPT, DL_HIGH, TEXT("ConnectionPoint::GetIDsOfNames")));
|
||
|
//
|
||
|
// Let our dispatch object handle this.
|
||
|
//
|
||
|
return m_Dispatch.GetIDsOfNames(riid,
|
||
|
rgszNames,
|
||
|
cNames,
|
||
|
lcid,
|
||
|
rgDispId);
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// IDispatch::GetTypeInfo
|
||
|
//
|
||
|
STDMETHODIMP
|
||
|
ConnectionPoint::GetTypeInfo(
|
||
|
UINT iTInfo,
|
||
|
LCID lcid,
|
||
|
ITypeInfo **ppTypeInfo
|
||
|
)
|
||
|
{
|
||
|
DBGTRACE((DM_CONNPT, DL_HIGH, TEXT("ConnectionPoint::GetTypeInfo")));
|
||
|
//
|
||
|
// Let our dispatch object handle this.
|
||
|
//
|
||
|
return m_Dispatch.GetTypeInfo(iTInfo, lcid, ppTypeInfo);
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// IDispatch::GetTypeInfoCount
|
||
|
//
|
||
|
STDMETHODIMP
|
||
|
ConnectionPoint::GetTypeInfoCount(
|
||
|
UINT *pctinfo
|
||
|
)
|
||
|
{
|
||
|
DBGTRACE((DM_CONNPT, DL_HIGH, TEXT("ConnectionPoint::GetTypeInfoCount")));
|
||
|
//
|
||
|
// Let our dispatch object handle this.
|
||
|
//
|
||
|
return m_Dispatch.GetTypeInfoCount(pctinfo);
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// IDispatch::Invoke
|
||
|
//
|
||
|
STDMETHODIMP
|
||
|
ConnectionPoint::Invoke(
|
||
|
DISPID dispIdMember,
|
||
|
REFIID riid,
|
||
|
LCID lcid,
|
||
|
WORD wFlags,
|
||
|
DISPPARAMS *pDispParams,
|
||
|
VARIANT *pVarResult,
|
||
|
EXCEPINFO *pExcepInfo,
|
||
|
UINT *puArgErr
|
||
|
)
|
||
|
{
|
||
|
DBGTRACE((DM_CONNPT, DL_HIGH, TEXT("ConnectionPoint::Invoke")));
|
||
|
//
|
||
|
// Let our dispatch object handle this.
|
||
|
//
|
||
|
return m_Dispatch.Invoke(dispIdMember,
|
||
|
riid,
|
||
|
lcid,
|
||
|
wFlags,
|
||
|
pDispParams,
|
||
|
pVarResult,
|
||
|
pExcepInfo,
|
||
|
puArgErr);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
/* Function: ConnectionEnum::ConnectionEnum
|
||
|
|
||
|
Description: Constructor,
|
||
|
|
||
|
Arguments:
|
||
|
pUnkContainer - Pointer to the IUnknown interface of the containing
|
||
|
object.
|
||
|
|
||
|
cConnections - Number of connections in array pointed to by rgConnections.
|
||
|
|
||
|
rgConnections - Array of connection information used to
|
||
|
initialize the enumerator.
|
||
|
|
||
|
Returns: Nothing.
|
||
|
|
||
|
Exceptions: CAllocException.
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
Date Description Programmer
|
||
|
-------- --------------------------------------------------- ----------
|
||
|
06/19/96 Initial creation. BrianAu
|
||
|
09/06/06 Added copy constructor. BrianAu
|
||
|
*/
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
ConnectionEnum::ConnectionEnum(
|
||
|
LPUNKNOWN pUnkContainer,
|
||
|
UINT cConnections,
|
||
|
PCONNECTDATA rgConnections
|
||
|
) : m_cRef(0),
|
||
|
m_iCurrent(0),
|
||
|
m_cConnections(0),
|
||
|
m_rgConnections(NULL),
|
||
|
m_pUnkContainer(pUnkContainer)
|
||
|
{
|
||
|
DBGTRACE((DM_CONNPT, DL_MID, TEXT("ConnectionEnum::ConnectionEnum")));
|
||
|
DBGASSERT((NULL != pUnkContainer));
|
||
|
|
||
|
if (0 != cConnections)
|
||
|
{
|
||
|
m_rgConnections = new CONNECTDATA[cConnections];
|
||
|
|
||
|
DBGASSERT((NULL != rgConnections));
|
||
|
|
||
|
for (UINT i = 0; i < cConnections; i++)
|
||
|
{
|
||
|
//
|
||
|
// IUnknown::AddRef() is client code. It can generate an exception.
|
||
|
// Caller must catch and handle it.
|
||
|
//
|
||
|
rgConnections[i].pUnk->AddRef();
|
||
|
m_rgConnections[i].pUnk = rgConnections[i].pUnk;
|
||
|
m_rgConnections[i].dwCookie = rgConnections[i].dwCookie;
|
||
|
m_cConnections++;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
ConnectionEnum::ConnectionEnum(const ConnectionEnum& refEnum)
|
||
|
: m_cRef(0),
|
||
|
m_iCurrent(0),
|
||
|
m_cConnections(0),
|
||
|
m_rgConnections(NULL),
|
||
|
m_pUnkContainer(m_pUnkContainer)
|
||
|
{
|
||
|
DBGTRACE((DM_CONNPT, DL_MID, TEXT("ConnectionEnum::ConnectionEnum [copy]")));
|
||
|
|
||
|
if (0 != m_cConnections)
|
||
|
{
|
||
|
m_rgConnections = new CONNECTDATA[m_cConnections];
|
||
|
|
||
|
DBGASSERT((NULL != refEnum.m_rgConnections));
|
||
|
for (UINT i = 0; i < m_cConnections; i++)
|
||
|
{
|
||
|
//
|
||
|
// IUnknown::AddRef() is client code. It can generate an exception.
|
||
|
// Caller must catch and handle it.
|
||
|
//
|
||
|
refEnum.m_rgConnections[i].pUnk->AddRef();
|
||
|
m_rgConnections[i].pUnk = refEnum.m_rgConnections[i].pUnk;
|
||
|
m_rgConnections[i].dwCookie = refEnum.m_rgConnections[i].dwCookie;
|
||
|
m_cConnections++;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
/* Function: ConnectionEnum::~ConnectionEnum
|
||
|
|
||
|
Description: Destructor. Releases all connection sink interface pointers
|
||
|
held in enumerator's array.
|
||
|
|
||
|
Arguments: None.
|
||
|
|
||
|
Returns: Nothing.
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
Date Description Programmer
|
||
|
-------- --------------------------------------------------- ----------
|
||
|
06/19/96 Initial creation. BrianAu
|
||
|
*/
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
ConnectionEnum::~ConnectionEnum(
|
||
|
VOID
|
||
|
)
|
||
|
{
|
||
|
DBGTRACE((DM_CONNPT, DL_MID, TEXT("ConnectionEnum::~ConnectionEnum")));
|
||
|
|
||
|
if (NULL != m_rgConnections)
|
||
|
{
|
||
|
for (UINT i = 0; i < m_cConnections; i++)
|
||
|
{
|
||
|
if (NULL != m_rgConnections[i].pUnk)
|
||
|
{
|
||
|
m_rgConnections[i].pUnk->Release();
|
||
|
m_rgConnections[i].pUnk = NULL;
|
||
|
}
|
||
|
}
|
||
|
delete[] m_rgConnections;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
/* Function: ConnectionEnum::QueryInterface
|
||
|
|
||
|
Description: Returns an interface pointer to the object's IUnknown or
|
||
|
IEnumConnections interface. Only IID_IUnknown and
|
||
|
IID_IEnumConnections are recognized. The object referenced by the
|
||
|
returned interface pointer is uninitialized. The recipient of the
|
||
|
pointer must call Initialize() before the object is usable.
|
||
|
|
||
|
Arguments:
|
||
|
riid - Reference to requested interface ID.
|
||
|
|
||
|
ppvOut - Address of interface pointer variable to accept interface ptr.
|
||
|
|
||
|
Returns:
|
||
|
NOERROR - Success.
|
||
|
E_NOINTERFACE - Requested interface not supported.
|
||
|
E_INVALIDARG - ppvOut arg is NULL.
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
Date Description Programmer
|
||
|
-------- --------------------------------------------------- ----------
|
||
|
06/18/96 Initial creation. BrianAu
|
||
|
*/
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
STDMETHODIMP
|
||
|
ConnectionEnum::QueryInterface(
|
||
|
REFIID riid,
|
||
|
LPVOID *ppvOut
|
||
|
)
|
||
|
{
|
||
|
DBGTRACE((DM_CONNPT, DL_MID, TEXT("ConnectionEnum::QueryInterface")));
|
||
|
DBGPRINTIID(DM_CONNPT, DL_MID, riid);
|
||
|
|
||
|
HRESULT hr = E_NOINTERFACE;
|
||
|
|
||
|
if (NULL == ppvOut)
|
||
|
return E_INVALIDARG;
|
||
|
|
||
|
*ppvOut = NULL;
|
||
|
|
||
|
if (IID_IUnknown == riid || IID_IEnumConnections == riid)
|
||
|
{
|
||
|
*ppvOut = this;
|
||
|
((LPUNKNOWN)*ppvOut)->AddRef();
|
||
|
hr = NOERROR;
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
/* Function: ConnectionEnum::AddRef
|
||
|
|
||
|
Description: Increments object reference count.
|
||
|
|
||
|
Arguments: None.
|
||
|
|
||
|
Returns: New reference count value.
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
Date Description Programmer
|
||
|
-------- --------------------------------------------------- ----------
|
||
|
06/18/96 Initial creation. BrianAu
|
||
|
*/
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
STDMETHODIMP_(ULONG)
|
||
|
ConnectionEnum::AddRef(
|
||
|
VOID
|
||
|
)
|
||
|
{
|
||
|
DBGTRACE((DM_CONNPT, DL_LOW, TEXT("ConnectionEnum::AddRef")));
|
||
|
DBGPRINT((DM_CONNPT, DL_LOW, TEXT("\t0x%08X %d -> %d\n"),
|
||
|
this, m_cRef, m_cRef + 1));
|
||
|
|
||
|
ULONG ulReturn = m_cRef + 1;
|
||
|
|
||
|
|
||
|
InterlockedIncrement(&m_cRef);
|
||
|
|
||
|
//
|
||
|
// Increment ref count of connection point so that it stays around
|
||
|
// while the connection enumerator is alive.
|
||
|
//
|
||
|
m_pUnkContainer->AddRef();
|
||
|
|
||
|
return ulReturn;
|
||
|
}
|
||
|
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
/* Function: ConnectionEnum::Release
|
||
|
|
||
|
Description: Decrements object reference count. If count drops to 0,
|
||
|
object is deleted.
|
||
|
|
||
|
Arguments: None.
|
||
|
|
||
|
Returns: New reference count value.
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
Date Description Programmer
|
||
|
-------- --------------------------------------------------- ----------
|
||
|
06/18/96 Initial creation. BrianAu
|
||
|
*/
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
STDMETHODIMP_(ULONG)
|
||
|
ConnectionEnum::Release(
|
||
|
VOID
|
||
|
)
|
||
|
{
|
||
|
DBGTRACE((DM_CONNPT, DL_LOW, TEXT("ConnectionEnum::Release")));
|
||
|
DBGPRINT((DM_CONNPT, DL_LOW, TEXT("\t0x%08X %d -> %d\n"),
|
||
|
this, m_cRef, m_cRef - 1));
|
||
|
|
||
|
ULONG ulReturn = m_cRef - 1;
|
||
|
|
||
|
//
|
||
|
// Decrement ref count of connection point. We AddRef'd it
|
||
|
// above.
|
||
|
//
|
||
|
m_pUnkContainer->Release();
|
||
|
|
||
|
if (InterlockedDecrement(&m_cRef) == 0)
|
||
|
{
|
||
|
delete this;
|
||
|
ulReturn = 0;
|
||
|
}
|
||
|
|
||
|
return ulReturn;
|
||
|
}
|
||
|
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
/* Function: ConnectionEnum::Next
|
||
|
|
||
|
Description: Retrieve the next cConnections connections supported by
|
||
|
the enumerator.
|
||
|
|
||
|
Arguments:
|
||
|
cConnections - Number of elements in pConnections array.
|
||
|
|
||
|
pConnections - Array to receive CONNECTDATA data records.
|
||
|
|
||
|
pcCreated [optional] - Address of DWORD to accept the count of records
|
||
|
returned in pConnections. Note that any array locations equal to
|
||
|
or beyond the value returned in pcCreated are invalid and set to
|
||
|
NULL.
|
||
|
|
||
|
Returns:
|
||
|
S_OK - Success. Enumerated number of requested connections.
|
||
|
S_FALSE - End of enumeration encountered. Returning less than
|
||
|
cConnections records.
|
||
|
E_INVALIDARG - pConnections arg is NULL.
|
||
|
E_UNEXPECTED - Exception caught.
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
Date Description Programmer
|
||
|
-------- --------------------------------------------------- ----------
|
||
|
06/19/96 Initial creation. BrianAu
|
||
|
*/
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
HRESULT
|
||
|
ConnectionEnum::Next(
|
||
|
DWORD cConnections, // Number of elements in array.
|
||
|
PCONNECTDATA pConnections, // Dest array for connection info.
|
||
|
DWORD *pcCreated // Return number created.
|
||
|
)
|
||
|
{
|
||
|
DBGTRACE((DM_CONNPT, DL_HIGH, TEXT("ConnectionEnum::Next")));
|
||
|
|
||
|
if (NULL == pConnections)
|
||
|
return E_INVALIDARG;
|
||
|
|
||
|
HRESULT hr = S_OK;
|
||
|
DWORD cCreated = 0;
|
||
|
|
||
|
//
|
||
|
// Transfer data to caller's array.
|
||
|
// Stop when at the end of the enumeration or we've
|
||
|
// returned all that the caller asked for.
|
||
|
//
|
||
|
while(m_iCurrent < m_cConnections && cConnections > 0)
|
||
|
{
|
||
|
DBGASSERT((NULL != m_rgConnections));
|
||
|
*pConnections = m_rgConnections[m_iCurrent++];
|
||
|
if (NULL != pConnections->pUnk)
|
||
|
{
|
||
|
pConnections->pUnk->AddRef();
|
||
|
pConnections++;
|
||
|
cCreated++;
|
||
|
cConnections--;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// If requested, return the count of items enumerated.
|
||
|
//
|
||
|
if (NULL != pcCreated)
|
||
|
*pcCreated = cCreated;
|
||
|
|
||
|
if (cConnections > 0)
|
||
|
{
|
||
|
//
|
||
|
// Less than requested number of connections were retrieved.
|
||
|
//
|
||
|
hr = S_FALSE;
|
||
|
while(cConnections > 0)
|
||
|
{
|
||
|
//
|
||
|
// Set any un-filled array elements to NULL.
|
||
|
//
|
||
|
pConnections->pUnk = NULL;
|
||
|
pConnections->dwCookie = 0;
|
||
|
pConnections++;
|
||
|
cConnections--;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
/* Function: ConnectionEnum::Skip
|
||
|
|
||
|
Description: Skips a specified number of connections in the enumeration.
|
||
|
|
||
|
Arguments:
|
||
|
cConnections - Number of connections to skip.
|
||
|
|
||
|
Returns:
|
||
|
S_OK - Success. Skipped number of requested items.
|
||
|
S_FALSE - End of enumeration encountered. Skipped less than
|
||
|
cConnections items.
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
Date Description Programmer
|
||
|
-------- --------------------------------------------------- ----------
|
||
|
06/19/96 Initial creation. BrianAu
|
||
|
*/
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
STDMETHODIMP
|
||
|
ConnectionEnum::Skip(
|
||
|
DWORD cConnections
|
||
|
)
|
||
|
{
|
||
|
DBGTRACE((DM_CONNPT, DL_HIGH, TEXT("ConnectionEnum::Skip")));
|
||
|
|
||
|
while(m_iCurrent < m_cConnections && cConnections > 0)
|
||
|
{
|
||
|
m_iCurrent++;
|
||
|
cConnections--;
|
||
|
}
|
||
|
|
||
|
return cConnections == 0 ? S_OK : S_FALSE;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
/* Function: ConnectionEnum::Reset
|
||
|
|
||
|
Description: Resets the enumerator object so that the next call to Next()
|
||
|
starts enumerating at the beginning of the enumeration.
|
||
|
|
||
|
Arguments: None.
|
||
|
|
||
|
Returns:
|
||
|
S_OK - Success.
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
Date Description Programmer
|
||
|
-------- --------------------------------------------------- ----------
|
||
|
06/19/96 Initial creation. BrianAu
|
||
|
*/
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
STDMETHODIMP
|
||
|
ConnectionEnum::Reset(
|
||
|
VOID
|
||
|
)
|
||
|
{
|
||
|
DBGTRACE((DM_CONNPT, DL_HIGH, TEXT("ConnectionEnum::Reset")));
|
||
|
|
||
|
m_iCurrent = 0;
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
/* Function: ConnectionEnum::Clone
|
||
|
|
||
|
Description: Creates a duplicate of the enumerator object and returns
|
||
|
a pointer to the new object's IEnumConnections interface.
|
||
|
|
||
|
Arguments:
|
||
|
ppEnum - Address of interface pointer variable to accept the pointer
|
||
|
to the new object's IEnumConnections interface.
|
||
|
|
||
|
Returns:
|
||
|
NOERROR - Success.
|
||
|
E_OUTOFMEMORY - Insufficient memory to create new enumerator.
|
||
|
E_INVALIDARG - ppEnum arg was NULL.
|
||
|
E_UNEXPECTED - Exception caught while calling client code.
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
Date Description Programmer
|
||
|
-------- --------------------------------------------------- ----------
|
||
|
06/19/96 Initial creation. BrianAu
|
||
|
*/
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
STDMETHODIMP
|
||
|
ConnectionEnum::Clone(
|
||
|
PENUMCONNECTIONS *ppEnum
|
||
|
)
|
||
|
{
|
||
|
DBGTRACE((DM_CONNPT, DL_HIGH, TEXT("ConnectionEnum::Clone")));
|
||
|
|
||
|
if (NULL == ppEnum)
|
||
|
return E_INVALIDARG;
|
||
|
|
||
|
HRESULT hr = NOERROR;
|
||
|
ConnectionEnum *pEnum = NULL;
|
||
|
|
||
|
*ppEnum = NULL;
|
||
|
|
||
|
try
|
||
|
{
|
||
|
pEnum = new ConnectionEnum((const ConnectionEnum&)*this);
|
||
|
|
||
|
hr = pEnum->QueryInterface(IID_IEnumConnections, (LPVOID *)ppEnum);
|
||
|
}
|
||
|
catch(CAllocException& e)
|
||
|
{
|
||
|
DBGERROR((TEXT("Insufficient memory exception")));
|
||
|
hr = E_OUTOFMEMORY;
|
||
|
}
|
||
|
|
||
|
if (FAILED(hr) && NULL != pEnum)
|
||
|
{
|
||
|
delete pEnum;
|
||
|
*ppEnum = NULL;
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
/* Function: ConnectionPointEnum::ConnectionPointEnum
|
||
|
|
||
|
Description: Constructor,
|
||
|
|
||
|
Arguments:
|
||
|
pUnkContainer - Pointer to IUnknown of containing object.
|
||
|
|
||
|
cConnPts - Number of connection points in array pointed to by rgConnPts.
|
||
|
|
||
|
rgConnPts - Array of connection point object pointers used to
|
||
|
initialize the enumerator.
|
||
|
|
||
|
Returns: Nothing.
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
Date Description Programmer
|
||
|
-------- --------------------------------------------------- ----------
|
||
|
06/19/96 Initial creation. BrianAu
|
||
|
09/06/96 Added copy constructor. BrianAu
|
||
|
*/
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
ConnectionPointEnum::ConnectionPointEnum(
|
||
|
LPUNKNOWN pUnkContainer,
|
||
|
UINT cConnPts,
|
||
|
PCONNECTIONPOINT *rgConnPts
|
||
|
) : m_cRef(0),
|
||
|
m_iCurrent(0),
|
||
|
m_cConnPts(0),
|
||
|
m_rgConnPts(NULL),
|
||
|
m_pUnkContainer(pUnkContainer)
|
||
|
{
|
||
|
DBGTRACE((DM_CONNPT, DL_MID, TEXT("ConnectionPointEnum::ConnectionPointEnum")));
|
||
|
DBGASSERT((NULL != pUnkContainer));
|
||
|
|
||
|
if (0 != cConnPts)
|
||
|
{
|
||
|
m_rgConnPts = new PCONNECTIONPOINT[cConnPts];
|
||
|
|
||
|
m_cConnPts = cConnPts;
|
||
|
for (UINT i = 0; i < m_cConnPts; i++)
|
||
|
{
|
||
|
m_rgConnPts[i] = rgConnPts[i];
|
||
|
m_rgConnPts[i]->AddRef();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
ConnectionPointEnum::ConnectionPointEnum(
|
||
|
const ConnectionPointEnum& refEnum
|
||
|
) : m_cRef(0),
|
||
|
m_iCurrent(0),
|
||
|
m_cConnPts(0),
|
||
|
m_rgConnPts(NULL),
|
||
|
m_pUnkContainer(refEnum.m_pUnkContainer)
|
||
|
{
|
||
|
DBGTRACE((DM_CONNPT, DL_MID, TEXT("ConnectionPointEnum::ConnectionPointEnum [copy]")));
|
||
|
|
||
|
if (0 != refEnum.m_cConnPts)
|
||
|
{
|
||
|
m_rgConnPts = new PCONNECTIONPOINT[refEnum.m_cConnPts];
|
||
|
|
||
|
m_cConnPts = refEnum.m_cConnPts;
|
||
|
for (UINT i = 0; i < m_cConnPts; i++)
|
||
|
{
|
||
|
m_rgConnPts[i] = refEnum.m_rgConnPts[i];
|
||
|
m_rgConnPts[i]->AddRef();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
/* Function: ConnectionPointEnum::~ConnectionPointEnum
|
||
|
|
||
|
Description: Destructor. Releases all connection point object pointers
|
||
|
held in enumerator's array.
|
||
|
|
||
|
Arguments: None.
|
||
|
|
||
|
Returns: Nothing.
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
Date Description Programmer
|
||
|
-------- --------------------------------------------------- ----------
|
||
|
06/19/96 Initial creation. BrianAu
|
||
|
*/
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
ConnectionPointEnum::~ConnectionPointEnum(
|
||
|
VOID
|
||
|
)
|
||
|
{
|
||
|
DBGTRACE((DM_CONNPT, DL_MID, TEXT("ConnectionPointEnum::~ConnectionPointEnum")));
|
||
|
|
||
|
if (NULL != m_rgConnPts)
|
||
|
{
|
||
|
for (UINT i = 0; i < m_cConnPts; i++)
|
||
|
{
|
||
|
if (NULL != m_rgConnPts[i])
|
||
|
{
|
||
|
m_rgConnPts[i]->Release();
|
||
|
m_rgConnPts[i] = NULL;
|
||
|
}
|
||
|
}
|
||
|
delete[] m_rgConnPts;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
/* Function: ConnectionPointEnum::QueryInterface
|
||
|
|
||
|
Description: Returns an interface pointer to the object's IUnknown or
|
||
|
IEnumConnectionPoints interface. Only IID_IUnknown and
|
||
|
IID_IEnumConnectionPoints are recognized. The object referenced by the
|
||
|
returned interface pointer is uninitialized. The recipient of the
|
||
|
pointer must call Initialize() before the object is usable.
|
||
|
|
||
|
Arguments:
|
||
|
riid - Reference to requested interface ID.
|
||
|
|
||
|
ppvOut - Address of interface pointer variable to accept interface ptr.
|
||
|
|
||
|
Returns:
|
||
|
NOERROR - Success.
|
||
|
E_NOINTERFACE - Requested interface not supported.
|
||
|
E_INVALIDARG - ppvOut argument was NULL.
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
Date Description Programmer
|
||
|
-------- --------------------------------------------------- ----------
|
||
|
06/18/96 Initial creation. BrianAu
|
||
|
*/
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
STDMETHODIMP
|
||
|
ConnectionPointEnum::QueryInterface(
|
||
|
REFIID riid,
|
||
|
LPVOID *ppvOut
|
||
|
)
|
||
|
{
|
||
|
DBGTRACE((DM_CONNPT, DL_MID, TEXT("ConnectionPointEnum::QueryInterface")));
|
||
|
DBGPRINTIID(DM_CONNPT, DL_MID, riid);
|
||
|
|
||
|
HRESULT hr = E_NOINTERFACE;
|
||
|
|
||
|
if (NULL == ppvOut)
|
||
|
return E_INVALIDARG;
|
||
|
|
||
|
*ppvOut = NULL;
|
||
|
|
||
|
if (IID_IUnknown == riid || IID_IEnumConnectionPoints == riid)
|
||
|
{
|
||
|
*ppvOut = this;
|
||
|
((LPUNKNOWN)*ppvOut)->AddRef();
|
||
|
hr = NOERROR;
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
/* Function: ConnectionPointEnum::AddRef
|
||
|
|
||
|
Description: Increments object reference count.
|
||
|
|
||
|
Arguments: None.
|
||
|
|
||
|
Returns: New reference count value.
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
Date Description Programmer
|
||
|
-------- --------------------------------------------------- ----------
|
||
|
06/18/96 Initial creation. BrianAu
|
||
|
*/
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
STDMETHODIMP_(ULONG)
|
||
|
ConnectionPointEnum::AddRef(
|
||
|
VOID
|
||
|
)
|
||
|
{
|
||
|
DBGTRACE((DM_CONNPT, DL_LOW, TEXT("ConnectionPointEnum::AddRef")));
|
||
|
DBGPRINT((DM_CONNPT, DL_LOW, TEXT("\t0x%08X %d -> %d\n"),
|
||
|
this, m_cRef, m_cRef + 1));
|
||
|
|
||
|
ULONG ulReturn = m_cRef + 1;
|
||
|
|
||
|
|
||
|
//
|
||
|
// Increment ref count of QuotaController so that it stays around
|
||
|
// while the enumerator is alive.
|
||
|
//
|
||
|
m_pUnkContainer->AddRef();
|
||
|
|
||
|
InterlockedIncrement(&m_cRef);
|
||
|
|
||
|
return ulReturn;
|
||
|
}
|
||
|
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
/* Function: ConnectionPointEnum::Release
|
||
|
|
||
|
Description: Decrements object reference count. If count drops to 0,
|
||
|
object is deleted.
|
||
|
|
||
|
Arguments: None.
|
||
|
|
||
|
Returns: New reference count value.
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
Date Description Programmer
|
||
|
-------- --------------------------------------------------- ----------
|
||
|
06/18/96 Initial creation. BrianAu
|
||
|
*/
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
STDMETHODIMP_(ULONG)
|
||
|
ConnectionPointEnum::Release(
|
||
|
VOID
|
||
|
)
|
||
|
{
|
||
|
DBGTRACE((DM_CONNPT, DL_LOW, TEXT("ConnectionPointEnum::Release")));
|
||
|
DBGPRINT((DM_COM, DL_HIGH, TEXT("\t0x%08X %d -> %d\n"),
|
||
|
this, m_cRef, m_cRef - 1));
|
||
|
|
||
|
ULONG ulReturn = m_cRef - 1;
|
||
|
|
||
|
//
|
||
|
// Decrement ref count of QuotaController. We AddRef'd it above.
|
||
|
//
|
||
|
m_pUnkContainer->Release();
|
||
|
|
||
|
if (InterlockedDecrement(&m_cRef) == 0)
|
||
|
{
|
||
|
delete this;
|
||
|
ulReturn = 0;
|
||
|
}
|
||
|
|
||
|
return ulReturn;
|
||
|
}
|
||
|
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
/* Function: ConnectionPointEnum::Next
|
||
|
|
||
|
Description: Retrieve the next cConnPts connections supported by
|
||
|
the enumerator.
|
||
|
|
||
|
Arguments:
|
||
|
cConnPts - Number of elements in pConnPts array.
|
||
|
|
||
|
pConnPts - Array to receive PCONNECTIONPOINT pointers.
|
||
|
|
||
|
pcCreated [optional] - Address of DWORD to accept the count of records
|
||
|
returned in pConnPts. Note that any array locations equal to or
|
||
|
beyond the value returned in pcCreated are invalid and set to NULL.
|
||
|
|
||
|
Returns:
|
||
|
S_OK - Success. Enumerated number of requested connection pts.
|
||
|
S_FALSE - End of enumeration encountered. Returning less than
|
||
|
cConnPts records.
|
||
|
E_INVALIDARG - pConnPts arg is NULL.
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
Date Description Programmer
|
||
|
-------- --------------------------------------------------- ----------
|
||
|
06/19/96 Initial creation. BrianAu
|
||
|
*/
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
HRESULT
|
||
|
ConnectionPointEnum::Next(
|
||
|
DWORD cConnPts, // Number of elements in array.
|
||
|
PCONNECTIONPOINT *rgpConnPts, // Dest array for connection point ptrs.
|
||
|
DWORD *pcCreated // Return number created.
|
||
|
)
|
||
|
{
|
||
|
DBGTRACE((DM_CONNPT, DL_LOW, TEXT("ConnectionPointEnum::Next")));
|
||
|
|
||
|
if (NULL == rgpConnPts)
|
||
|
return E_INVALIDARG;
|
||
|
|
||
|
HRESULT hr = S_OK;
|
||
|
DWORD cCreated = 0;
|
||
|
|
||
|
//
|
||
|
// Transfer data to caller's array.
|
||
|
// Stop when at the end of the enumeration or we've
|
||
|
// returned all that the caller asked for.
|
||
|
//
|
||
|
while(m_iCurrent < m_cConnPts && cConnPts > 0)
|
||
|
{
|
||
|
*rgpConnPts = m_rgConnPts[m_iCurrent++];
|
||
|
if (NULL != *rgpConnPts)
|
||
|
{
|
||
|
(*rgpConnPts)->AddRef();
|
||
|
rgpConnPts++;
|
||
|
cCreated++;
|
||
|
cConnPts--;
|
||
|
}
|
||
|
else
|
||
|
DBGASSERT((FALSE)); // Shouldn't hit this.
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// If requested, return the count of items enumerated.
|
||
|
//
|
||
|
if (NULL != pcCreated)
|
||
|
*pcCreated = cCreated;
|
||
|
|
||
|
if (cConnPts > 0)
|
||
|
{
|
||
|
//
|
||
|
// Less than requested number of connections were retrieved.
|
||
|
//
|
||
|
hr = S_FALSE;
|
||
|
while(cConnPts > 0)
|
||
|
{
|
||
|
//
|
||
|
// Set any un-filled array elements to NULL.
|
||
|
//
|
||
|
*rgpConnPts = NULL;
|
||
|
rgpConnPts++;
|
||
|
cConnPts--;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
/* Function: ConnectionPointEnum::Skip
|
||
|
|
||
|
Description: Skips a specified number of connection pts in the enumeration.
|
||
|
|
||
|
Arguments:
|
||
|
cConnPts - Number of connection points to skip.
|
||
|
|
||
|
Returns:
|
||
|
S_OK - Success. Skipped number of requested items.
|
||
|
S_FALSE - End of enumeration encountered. Skipped less than
|
||
|
cConnPts items.
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
Date Description Programmer
|
||
|
-------- --------------------------------------------------- ----------
|
||
|
06/19/96 Initial creation. BrianAu
|
||
|
*/
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
STDMETHODIMP
|
||
|
ConnectionPointEnum::Skip(
|
||
|
DWORD cConnPts
|
||
|
)
|
||
|
{
|
||
|
DBGTRACE((DM_CONNPT, DL_LOW, TEXT("ConnectionPointEnum::Skip")));
|
||
|
|
||
|
while(m_iCurrent < m_cConnPts && cConnPts > 0)
|
||
|
{
|
||
|
m_iCurrent++;
|
||
|
cConnPts--;
|
||
|
}
|
||
|
|
||
|
return cConnPts == 0 ? S_OK : S_FALSE;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
/* Function: ConnectionPointEnum::Reset
|
||
|
|
||
|
Description: Resets the enumerator object so that the next call to Next()
|
||
|
starts enumerating at the start of the enumeration.
|
||
|
|
||
|
Arguments: None.
|
||
|
|
||
|
Returns:
|
||
|
S_OK - Success.
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
Date Description Programmer
|
||
|
-------- --------------------------------------------------- ----------
|
||
|
06/19/96 Initial creation. BrianAu
|
||
|
*/
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
STDMETHODIMP
|
||
|
ConnectionPointEnum::Reset(
|
||
|
VOID
|
||
|
)
|
||
|
{
|
||
|
DBGTRACE((DM_CONNPT, DL_LOW, TEXT("ConnectionPointEnum::Reset")));
|
||
|
|
||
|
m_iCurrent = 0;
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
/* Function: ConnectionPointEnum::Clone
|
||
|
|
||
|
Description: Creates a duplicate of the enumerator object and returns
|
||
|
a pointer to the new object's IEnumConnectionPoints interface.
|
||
|
|
||
|
Arguments:
|
||
|
ppEnum - Address of interface pointer variable to accept the pointer
|
||
|
to the new object's IEnumConnectionPoints interface.
|
||
|
|
||
|
Returns:
|
||
|
NOERROR - Success.
|
||
|
E_OUTOFMEMORY - Insufficient memory to create new enumerator.
|
||
|
E_INVALIDARG - ppEnum arg was NULL.
|
||
|
E_UNEXPECTED - Unexpected exception.
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
Date Description Programmer
|
||
|
-------- --------------------------------------------------- ----------
|
||
|
06/19/96 Initial creation. BrianAu
|
||
|
*/
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
STDMETHODIMP
|
||
|
ConnectionPointEnum::Clone(
|
||
|
PENUMCONNECTIONPOINTS *ppEnum
|
||
|
)
|
||
|
{
|
||
|
DBGTRACE((DM_CONNPT, DL_LOW, TEXT("ConnectionPointEnum::Clone")));
|
||
|
|
||
|
if (NULL == ppEnum)
|
||
|
return E_INVALIDARG;
|
||
|
|
||
|
HRESULT hr = NOERROR;
|
||
|
ConnectionPointEnum *pEnum = NULL;
|
||
|
|
||
|
try
|
||
|
{
|
||
|
*ppEnum = NULL;
|
||
|
pEnum = new ConnectionPointEnum((const ConnectionPointEnum&)*this);
|
||
|
|
||
|
hr = pEnum->QueryInterface(IID_IEnumConnectionPoints, (LPVOID *)ppEnum);
|
||
|
}
|
||
|
catch(CAllocException& e)
|
||
|
{
|
||
|
DBGERROR((TEXT("Insufficient memory exception")));
|
||
|
hr = E_OUTOFMEMORY;
|
||
|
}
|
||
|
|
||
|
if (FAILED(hr) && NULL != pEnum)
|
||
|
{
|
||
|
delete pEnum;
|
||
|
*ppEnum = NULL;
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
|