|
|
//////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 1999-2002 Microsoft Corporation
//
// Module Name:
// EnumCPICCCB.cpp
//
// Description:
// IClusCfgCallback Connection Point Enumerator implementation.
//
// Maintained By:
// David Potter (DavidP) 14-JUN-2001
// Geoffrey Pease (GPease) 10-NOV-2000
//
//////////////////////////////////////////////////////////////////////////////
#include "Pch.h"
#include "EnumCPICCCB.h"
DEFINE_THISCLASS("CEnumCPICCCB")
#define PUNK_BUFFER_GROW_SIZE 10
//*************************************************************************//
/////////////////////////////////////////////////////////////////////////////
// CEnumCPICCCB class
/////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//++
//
// CEnumCPICCCB::S_HrCreateInstance
//
// Description:
// Create a CEnumCPICCCB instance.
//
// Arguments:
// None.
//
// Return Values:
// S_OK
// Success.
//
// E_POINTER
// The passed in ppunk is NULL.
//
// other HRESULTs
// Object creation failed.
//
//--
//////////////////////////////////////////////////////////////////////////////
HRESULT CEnumCPICCCB::S_HrCreateInstance( IUnknown ** ppunkOut ) { TraceFunc( "" );
HRESULT hr = S_OK; CEnumCPICCCB * pcc = NULL;
Assert( ppunkOut != NULL ); if ( ppunkOut == NULL ) { hr = THR( E_POINTER ); goto Cleanup; } // if:
pcc = new CEnumCPICCCB(); if ( pcc == NULL ) { hr = THR( E_OUTOFMEMORY ); goto Cleanup; } // if:
hr = THR( pcc->HrInit() ); // fIsCloneIn = FALSE
if ( FAILED( hr ) ) { goto Cleanup; } // if:
hr = THR( pcc->TypeSafeQI( IUnknown, ppunkOut ) ); if ( FAILED( hr ) ) { goto Cleanup; } // if:
Cleanup:
if ( pcc != NULL ) { pcc->Release(); } // if:
HRETURN( hr );
} //*** CEnumCPICCCB::S_HrCreateInstance
//////////////////////////////////////////////////////////////////////////////
//++
//
// CEnumCPICCCB::CEnumCPICCCB
//
// Description:
// Default constructor.
//
// Arguments:
// None.
//
// Return Values:
// None.
//
//--
//////////////////////////////////////////////////////////////////////////////
CEnumCPICCCB::CEnumCPICCCB( void ) : m_cRef( 1 ) { TraceFunc( "" );
InterlockedIncrement( &g_cObjects );
TraceFuncExit();
} //*** CEnumCPICCCB::CEnumCPICCCB
//////////////////////////////////////////////////////////////////////////////
//++
//
// CEnumCPICCCB::~CEnumCPICCCB
//
// Description:
// Default destructor.
//
// Arguments:
// None.
//
// Return Values:
// None.
//
//--
//////////////////////////////////////////////////////////////////////////////
CEnumCPICCCB::~CEnumCPICCCB( void ) { TraceFunc( "" );
IUnknown * punk = NULL;
if ( m_pList != NULL ) { while ( m_cAlloced != 0 ) { m_cAlloced --;
punk = m_pList[ m_cAlloced ];
AssertMsg( m_fIsClone || punk == NULL, "Someone didn't Unadvise before releasing the last Reference." ); if ( punk != NULL ) { punk->Release(); }
} // while: m_cAlloced
TraceFree( m_pList ); } // while:
InterlockedDecrement( &g_cObjects );
TraceFuncExit();
} //*** CEnumCPICCCB::~CEnumCPICCCB
//*************************************************************************//
/////////////////////////////////////////////////////////////////////////////
// CEnumCPICCCB -- IUnknown interface.
/////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//++
//
// CEnumCPICCCB::AddRef
//
// Description:
// Increment the reference count of this object by one.
//
// Arguments:
// None.
//
// Return Value:
// The new reference count.
//
// Remarks:
// None.
//
//--
//////////////////////////////////////////////////////////////////////////////
STDMETHODIMP_(ULONG) CEnumCPICCCB::AddRef( void ) { TraceFunc( "[IUnknown]" );
InterlockedIncrement( &m_cRef );
CRETURN( m_cRef );
} //*** CEnumCPICCCB::AddRef
//////////////////////////////////////////////////////////////////////////////
//++
//
// CTaskCancelCleanup::Release
//
// Description:
// Decrement the reference count of this object by one.
//
// Arguments:
// None.
//
// Return Value:
// The new reference count.
//
// Remarks:
// None.
//
//--
//////////////////////////////////////////////////////////////////////////////
STDMETHODIMP_(ULONG) CEnumCPICCCB::Release( void ) { TraceFunc( "[IUnknown]" );
LONG cRef;
cRef = InterlockedDecrement( &m_cRef );
if ( cRef == 0 ) { TraceDo( delete this ); }
CRETURN( cRef );
} //*** CEnumCPICCCB::Release
//////////////////////////////////////////////////////////////////////////////
//++
//
// CEnumCPICCCB::QueryInterface
//
// Description:
// Query this object for the passed in interface.
//
// Arguments:
// riidIn
// Id of interface requested.
//
// ppvOut
// Pointer to the requested interface.
//
// Return Value:
// S_OK
// If the interface is available on this object.
//
// E_NOINTERFACE
// If the interface is not available.
//
// E_POINTER
// ppvOut was NULL.
//
// Remarks:
// None.
//
//--
//////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CEnumCPICCCB::QueryInterface( REFIID riidIn , LPVOID * ppvOut ) { TraceQIFunc( riidIn, ppvOut );
HRESULT hr = S_OK;
//
// Validate arguments.
//
Assert( ppvOut != NULL ); if ( ppvOut == NULL ) { hr = THR( E_POINTER ); goto Cleanup; }
//
// Handle known interfaces.
//
if ( IsEqualIID( riidIn, IID_IUnknown ) ) { *ppvOut = static_cast< IEnumConnections * >( this ); } // if: IUnknown
else if ( IsEqualIID( riidIn, IID_IEnumConnections ) ) { *ppvOut = TraceInterface( __THISCLASS__, IEnumConnections, this, 0 ); } // else if: IEnumConnections
else { *ppvOut = NULL; hr = E_NOINTERFACE; } // else
//
// Add a reference to the interface if successful.
//
if ( SUCCEEDED( hr ) ) { ((IUnknown *) *ppvOut)->AddRef(); } // if: success
Cleanup:
QIRETURN_IGNORESTDMARSHALLING( hr, riidIn );
} //*** CEnumCPICCCB::QueryInterface
//*************************************************************************//
/////////////////////////////////////////////////////////////////////////////
// CEnumCPICCCB -- IEnumConnectionPoints interface.
/////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//++
//
// CEnumCPICCCB::Next
//
// Description:
// Enumerator Next method.
//
// Arguments:
// cConnectionsIn
// How many items requested. Also tells us how bing rgcd.
//
// rgcdOut
// Array that gets the data.
//
// pcFetchedOut
// How many did we place in the array.
//
// Return Values:
// S_OK
// Success.
//
// S_FALSE
// cConnectionsIn > *pcFetchedOut. Did not return as many items
// as the caller asked for.
//
// Other HRESULT errors.
//
//--
//////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CEnumCPICCCB::Next( ULONG cConnectionsIn, LPCONNECTDATA rgcd, ULONG *pcFetchedOut ) { TraceFunc( "[IEnumConnectionPoints]" );
ULONG cIter; HRESULT hr = S_FALSE;
if ( pcFetchedOut != NULL ) { *pcFetchedOut = 0; } // if:
for( cIter = 0 ; ( cIter < cConnectionsIn ) && ( m_cIter < m_cCurrent ) ; m_cIter++ ) { IUnknown * punk = m_pList[ m_cIter ]; if ( punk != NULL ) { hr = THR( punk->TypeSafeQI( IUnknown, &rgcd[ cIter ].pUnk ) ); if ( FAILED( hr ) ) goto Error;
rgcd[ cIter ].pUnk = TraceInterface( L"EnumCPICCCB!IUnknown", IUnknown, rgcd[ cIter ].pUnk, 1 );
rgcd[ cIter ].dwCookie = m_cIter + 1;
cIter ++; } // if:
} // for: cIter
if ( cIter != cConnectionsIn ) { hr = S_FALSE; } // if:
else { hr = S_OK; } // else:
if ( pcFetchedOut != NULL ) { *pcFetchedOut = cIter; } // if:
Cleanup:
HRETURN( hr );
Error: while ( cIter != 0 ) { cIter --; rgcd[ cIter ].pUnk->Release(); } // while:
goto Cleanup;
} //*** CEnumCPICCCB::Next
//////////////////////////////////////////////////////////////////////////////
//++
//
// CEnumCPICCCB::Skip
//
// Description:
// Enumerator Skip method.
//
// Arguments:
// cConnectionsIn
// Number of items to skip.
//
// Return Values:
// S_OK
// Success.
//
// S_FALSE
// The number to skip put us at the end of the list.
//
// Other HRESULT errors.
//
//--
//////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CEnumCPICCCB::Skip( ULONG cConnectionsIn ) { TraceFunc( "[IEnumConnectionPoints]" );
HRESULT hr = S_OK;
m_cIter += cConnectionsIn; if ( m_cIter >= m_cCurrent ) { m_cIter = m_cCurrent; hr = S_FALSE; } // if:
HRETURN( hr );
} //*** CEnumCPICCCB::Skip
//////////////////////////////////////////////////////////////////////////////
//++
//
// CEnumCPICCCB::Reset
//
// Description:
// Enumerator Reset method.
//
// Arguments:
// None.
//
// Return Values:
// S_OK
// Success.
//
//--
//////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CEnumCPICCCB::Reset( void ) { TraceFunc( "[IEnumConnectionPoints]" );
HRESULT hr = S_OK;
m_cIter = 0;
HRETURN( hr );
} //*** CEnumCPICCCB::Reset
//////////////////////////////////////////////////////////////////////////////
//++
//
// CEnumCPICCCB::Clone
//
// Description:
// Enumerator Clone method.
//
// Arguments:
// ppEnumOut
// The new enumerator that we are cloning ourselves into.
//
// Return Values:
// S_OK
// Success.
//
// Other HRESULT errors.
//
//--
//////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CEnumCPICCCB::Clone( IEnumConnections **ppEnumOut ) { TraceFunc( "[IEnumConnectionPoints]" );
HRESULT hr;
CEnumCPICCCB * pecp = new CEnumCPICCCB(); if ( pecp == NULL ) { hr = THR( E_OUTOFMEMORY ); goto Cleanup; } // if:
hr = THR( pecp->HrInit( TRUE ) ); // fIsCloneIn = TRUE
if ( FAILED( hr ) ) { goto Cleanup; } // if:
hr = THR( pecp->HrCopy( this ) ); if ( FAILED( hr ) ) { goto Cleanup; } // if:
hr = THR( pecp->TypeSafeQI( IEnumConnections, ppEnumOut ) ); if ( FAILED( hr ) ) { goto Cleanup; } // if:
*ppEnumOut = TraceInterface( L"EnumCPICCCB!IEnumConnections", IEnumConnections, *ppEnumOut, 1 );
pecp->Release(); pecp = NULL;
Cleanup:
if ( pecp != NULL ) { delete pecp; } // if:
HRETURN( hr );
} //*** CEnumCPICCCB::Clone
//*************************************************************************//
/////////////////////////////////////////////////////////////////////////////
// CEnumCPINotifyUI -- Public methods.
/////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//++
//
// CEnumCPICCCB::HrAddConnection
//
// Description:
// Add a connection point container to our list of clients.
//
// Arguments:
// punkIn
// The new client object.
//
// pdwCookieOut
// Cookie used to find this client object in our list.
//
// Return Values:
// S_OK
// Success.
//
// Other HRESULT errors.
//
//--
//////////////////////////////////////////////////////////////////////////////
HRESULT CEnumCPICCCB::HrAddConnection( IUnknown * punkIn, DWORD * pdwCookieOut ) { TraceFunc( "" );
HRESULT hr = S_FALSE;
ULONG cIter;
if ( pdwCookieOut == NULL ) { hr = THR( E_POINTER ); goto Cleanup; }
//
// See if there is an openning in the currently allocated list.
//
for ( cIter = 0; cIter < m_cCurrent; cIter ++ ) { if ( m_pList[ cIter ] == NULL ) { //
// Found an openning... try to use it.
//
hr = THR( punkIn->TypeSafeQI( IUnknown, &m_pList[ cIter ] ) );
m_pList[ cIter ] = TraceInterface( L"CEnumCPICCCB!IUnknown", IUnknown, m_pList[ cIter ], 1 );
*pdwCookieOut = cIter + 1;
// Doesn't matter if it succeeded or fail, exit.
goto Cleanup; } }
if ( m_cCurrent == m_cAlloced ) { IUnknown ** pNewList;
//
// Try making some more space.
//
pNewList = (IUnknown **) TraceAlloc( HEAP_ZERO_MEMORY, ( m_cAlloced + PUNK_BUFFER_GROW_SIZE ) * sizeof( IUnknown * ) ); if ( pNewList == NULL ) { hr = THR( E_OUTOFMEMORY ); goto Cleanup; }
CopyMemory( pNewList, m_pList, m_cCurrent * sizeof( IUnknown * ) ); TraceFree( m_pList );
m_pList = pNewList; m_cAlloced += PUNK_BUFFER_GROW_SIZE; }
//
// Add it to the list.
//
hr = THR( punkIn->TypeSafeQI( IUnknown, &m_pList[ m_cCurrent ] ) ); if ( FAILED( hr ) ) { goto Cleanup; }
m_pList[ m_cCurrent ] = TraceInterface( L"CEnumCPICCCB!IUnknown", IUnknown, m_pList[ m_cCurrent ], 1 );
m_cCurrent ++; *pdwCookieOut = m_cCurrent; // starts at ONE, not ZERO
Cleanup:
HRETURN( hr );
} //*** CEnumCPICCCB::HrAddConnection
//////////////////////////////////////////////////////////////////////////////
//++
//
// CEnumCPICCCB::HrRemoveConnection
//
// Description:
// Remove the client identified by the passed in cookie from the list.
//
// Arguments:
// dwCookieIn
// The cookie of the client that is to be removed from the list.
//
// Return Values:
// S_OK
// Success.
//
// Other HRESULT errors.
//
//--
//////////////////////////////////////////////////////////////////////////////
HRESULT CEnumCPICCCB::HrRemoveConnection( DWORD dwCookieIn ) { TraceFunc( "" );
HRESULT hr;
if ( dwCookieIn == 0 || dwCookieIn > m_cCurrent ) { hr = THR( E_INVALIDARG ); goto Cleanup; } // if:
if ( m_pList[ dwCookieIn - 1 ] == NULL ) { hr = THR( E_INVALIDARG ); goto Cleanup; } // if:
m_pList[ dwCookieIn - 1 ]->Release(); m_pList[ dwCookieIn - 1 ] = NULL;
hr = S_OK;
Cleanup:
HRETURN( hr );
} //*** CEnumCPICCCB::HrRemoveConnection
//*************************************************************************//
/////////////////////////////////////////////////////////////////////////////
// CEnumCPICCCB -- Private methods.
/////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//++
//
// CEnumCPICCCB::HrInt
//
// Description:
// Do any initialization that may fail here.
//
// Arguments:
// fIsCloneIn
// Is this instance a clone?
//
// Return Values:
// S_OK
// Success.
//
// Other HRESULT errors.
//
//--
//////////////////////////////////////////////////////////////////////////////
HRESULT CEnumCPICCCB::HrInit( BOOL fIsCloneIn // = FALSE
) { TraceFunc( "" );
// IUnknown stuff
Assert( m_cRef == 1 );
// IEnumConnectionPoints
Assert( m_cAlloced == 0 ); Assert( m_cCurrent == 0 ); Assert( m_cIter == 0 ); Assert( m_pList == NULL ); Assert( m_fIsClone == FALSE );
m_fIsClone = fIsCloneIn;
// INotifyUI
HRETURN( S_OK );
} //*** CEnumCPICCCB::HrInit
//////////////////////////////////////////////////////////////////////////////
//++
//
// CEnumCPICCCB::HrCopy
//
// Description:
// Copy from the passed in enumerator.
//
// Arguments:
// pecpIn
// The source that we are to copy from.
//
// Return Values:
// S_OK
// Success.
//
// Other HRESULT errors.
//
//--
//////////////////////////////////////////////////////////////////////////////
HRESULT CEnumCPICCCB::HrCopy( CEnumCPICCCB * pecpIn ) { TraceFunc( "" );
HRESULT hr = S_FALSE;
ULONG cIter;
Assert( m_cAlloced == 0 ); Assert( m_cCurrent == 0 ); Assert( m_pList == 0 );
m_pList = (IUnknown**) TraceAlloc( HEAP_ZERO_MEMORY, pecpIn->m_cCurrent * sizeof( IUnknown * ) ); if ( m_pList == NULL ) { hr = THR( E_OUTOFMEMORY ); goto Cleanup; } // if:
m_cCurrent = m_cAlloced = pecpIn->m_cCurrent; m_cIter = 0;
for ( cIter = 0; cIter < pecpIn->m_cCurrent; cIter ++ ) { //
// Does the source have a pointer at the current index? If it does then "copy" it,
// otherwise NULL out that index in our copy...
//
if ( pecpIn->m_pList[ cIter ] != NULL ) { hr = THR( pecpIn->m_pList[ cIter ]->TypeSafeQI( IUnknown, &m_pList[ cIter ] ) ); if ( FAILED( hr ) ) { goto Cleanup; } // if:
m_pList[ cIter ] = TraceInterface( L"EnumCPICCCB!IUnknown", IUnknown, m_pList[ cIter ], 1 ); } // if:
else { m_pList[ cIter ] = NULL; } // else:
} // for:
hr = S_OK;
Cleanup:
HRETURN( hr );
} //*** CEnumCPICCCB::HrCopy
|