Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

890 lines
19 KiB

//////////////////////////////////////////////////////////////////////////////
//
// 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