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.
 
 
 
 
 
 

891 lines
19 KiB

//////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 1999-2002 Microsoft Corporation
//
// Module Name:
// EnumCPINotifyUI.cpp
//
// Description:
// INotifyUI Connection Point Enumerator implementation.
//
// Maintained By:
// David Potter (DavidP) 14-JUN-2001
// Geoffrey Pease (GPease) 04-AUG-2000
//
//////////////////////////////////////////////////////////////////////////////
#include "Pch.h"
#include "EnumCPINotifyUI.h"
DEFINE_THISCLASS("CEnumCPINotifyUI")
#define PUNK_BUFFER_GROW_SIZE 10
//*************************************************************************//
/////////////////////////////////////////////////////////////////////////////
// CEnumCPINotifyUI class
/////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//++
//
// CEnumCPINotifyUI::S_HrCreateInstance
//
// Description:
// Create a CEnumCPINotifyUI instance.
//
// Arguments:
// None.
//
// Return Values:
// S_OK
// Success.
//
// E_POINTER
// The passed in ppunk is NULL.
//
// other HRESULTs
// Object creation failed.
//
//--
//////////////////////////////////////////////////////////////////////////////
HRESULT
CEnumCPINotifyUI::S_HrCreateInstance(
IUnknown ** ppunkOut
)
{
TraceFunc( "" );
HRESULT hr = S_OK;
CEnumCPINotifyUI * pecnui = NULL;
Assert( ppunkOut != NULL );
if ( ppunkOut == NULL )
{
hr = THR( E_POINTER );
goto Cleanup;
} // if:
pecnui = new CEnumCPINotifyUI();
if ( pecnui == NULL )
{
hr = THR( E_OUTOFMEMORY );
goto Cleanup;
} // if:
hr = THR( pecnui->HrInit() ); // fIsCloneIn = FALSE
if ( FAILED( hr ) )
{
goto Cleanup;
} // if:
hr = THR( pecnui->TypeSafeQI( IUnknown, ppunkOut ) );
if ( FAILED( hr ) )
{
goto Cleanup;
} // if:
Cleanup:
if ( pecnui != NULL )
{
pecnui->Release();
} // if:
HRETURN( hr );
} //*** CEnumCPINotifyUI::S_HrCreateInstance
//////////////////////////////////////////////////////////////////////////////
//++
//
// CEnumCPINotifyUI::CEnumCPINotifyUI
//
// Description:
// Default constructor.
//
// Arguments:
// None.
//
// Return Values:
// None.
//
//--
//////////////////////////////////////////////////////////////////////////////
CEnumCPINotifyUI::CEnumCPINotifyUI( void )
: m_cRef( 1 )
{
TraceFunc( "" );
InterlockedIncrement( &g_cObjects );
TraceFuncExit();
} //*** CEnumCPINotifyUI::CEnumCPINotifyUI
//////////////////////////////////////////////////////////////////////////////
//++
//
// CEnumCPINotifyUI::~CEnumCPINotifyUI
//
// Description:
// Destructor.
//
// Arguments:
// None.
//
// Return Values:
// None.
//
//--
//////////////////////////////////////////////////////////////////////////////
CEnumCPINotifyUI::~CEnumCPINotifyUI( 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();
} // if:
} // while: m_cAlloced
TraceFree( m_pList );
} // if:
InterlockedDecrement( &g_cObjects );
TraceFuncExit();
} //*** CEnumCPINotifyUI::~CEnumCPINotifyUI
//*************************************************************************//
/////////////////////////////////////////////////////////////////////////////
// CEnumCPINotifyUI -- IUnknown interface.
/////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//++
//
// CEnumCPINotifyUI::AddRef
//
// Description:
// Increment the reference count of this object by one.
//
// Arguments:
// None.
//
// Return Value:
// The new reference count.
//
// Remarks:
// None.
//
//--
//////////////////////////////////////////////////////////////////////////////
STDMETHODIMP_(ULONG)
CEnumCPINotifyUI::AddRef( void )
{
TraceFunc( "[IUnknown]" );
InterlockedIncrement( &m_cRef );
CRETURN( m_cRef );
} //*** CEnumCPINotifyUI::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)
CEnumCPINotifyUI::Release( void )
{
TraceFunc( "[IUnknown]" );
LONG cRef;
cRef = InterlockedDecrement( &m_cRef );
if ( cRef == 0 )
{
TraceDo( delete this );
} // if:
CRETURN( cRef );
} //*** CEnumCPINotifyUI::Release
//////////////////////////////////////////////////////////////////////////////
//++
//
// CEnumCPINotifyUI::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
CEnumCPINotifyUI::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;
} // if:
//
// 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 );
} //*** CEnumCPINotifyUI::QueryInterface
//*************************************************************************//
/////////////////////////////////////////////////////////////////////////////
// CEnumCPINotifyUI -- IEnumConnectionPoints interface.
/////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//++
//
// CEnumCPINotifyUI::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
CEnumCPINotifyUI::Next(
ULONG cConnectionsIn
, LPCONNECTDATA rgcdOut
, 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, &rgcdOut[ cIter ].pUnk ) );
if ( FAILED( hr ) )
{
goto Error;
} // if:
rgcdOut[ cIter ].pUnk = TraceInterface( L"EnumCPINotifyUI!IUnknown", IUnknown, rgcdOut[ cIter ].pUnk, 1 );
rgcdOut[ 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--;
rgcdOut[ cIter ].pUnk->Release();
} // while:
goto Cleanup;
} //*** CEnumCPINotifyUI::Next
//////////////////////////////////////////////////////////////////////////////
//++
//
// CEnumCPINotifyUI::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
CEnumCPINotifyUI::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 );
} //*** CEnumCPINotifyUI::Skip
//////////////////////////////////////////////////////////////////////////////
//++
//
// CEnumCPINotifyUI::Reset
//
// Description:
// Enumerator Reset method.
//
// Arguments:
// None.
//
// Return Values:
// S_OK
// Success.
//
//--
//////////////////////////////////////////////////////////////////////////////
STDMETHODIMP
CEnumCPINotifyUI::Reset( void )
{
TraceFunc( "[IEnumConnectionPoints]" );
HRESULT hr = S_OK;
m_cIter = 0;
HRETURN( hr );
} //*** CEnumCPINotifyUI::Reset
//////////////////////////////////////////////////////////////////////////////
//++
//
// CEnumCPINotifyUI::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
CEnumCPINotifyUI::Clone(
IEnumConnections ** ppEnumOut
)
{
TraceFunc( "[IEnumConnectionPoints]" );
HRESULT hr = S_OK;
CEnumCPINotifyUI * pecp = new CEnumCPINotifyUI();
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"EnumCPINotifyUI!IEnumConnections", IEnumConnections, *ppEnumOut, 1 );
pecp->Release();
pecp = NULL;
Cleanup:
if ( pecp != NULL )
{
delete pecp;
} // if:
HRETURN( hr );
} //*** CEnumCPINotifyUI::Clone
//*************************************************************************//
/////////////////////////////////////////////////////////////////////////////
// CEnumCPINotifyUI -- Public methods.
/////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//++
//
// CEnumCPINotifyUI::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
CEnumCPINotifyUI::HrAddConnection(
IUnknown * punkIn
, DWORD * pdwCookieOut
)
{
TraceFunc( "" );
HRESULT hr = S_FALSE;
ULONG cIter;
if ( pdwCookieOut == NULL )
{
hr = THR( E_POINTER );
goto Cleanup;
} // if:
//
// 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"CEnumCPINotifyUI!IUnknown", IUnknown, m_pList[ cIter ], 1 );
*pdwCookieOut = cIter + 1;
// Doesn't matter if it succeeded or fail, exit.
goto Cleanup;
} // if:
} // for:
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;
} // if:
//
// Add it to the list.
//
hr = THR( punkIn->TypeSafeQI( IUnknown, &m_pList[ m_cCurrent ] ) );
if ( FAILED( hr ) )
{
goto Cleanup;
} // if:
m_pList[ m_cCurrent ] = TraceInterface( L"CEnumCPINotifyUI!IUnknown", IUnknown, m_pList[ m_cCurrent ], 1 );
m_cCurrent ++;
*pdwCookieOut = m_cCurrent; // starts at ONE, not ZERO
Cleanup:
HRETURN( hr );
} //*** CEnumCPINotifyUI::HrAddConnection
//////////////////////////////////////////////////////////////////////////////
//++
//
// CEnumCPINotifyUI::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
CEnumCPINotifyUI::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 );
} //*** CEnumCPINotifyUI::HrRemoveConnection
//*************************************************************************//
/////////////////////////////////////////////////////////////////////////////
// CEnumCPINotifyUI -- Private methods.
/////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//++
//
// CEnumCPINotifyUI::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
CEnumCPINotifyUI::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 );
} //*** CEnumCPINotifyUI::HrInit
//////////////////////////////////////////////////////////////////////////////
//++
//
// CEnumCPINotifyUI::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
CEnumCPINotifyUI::HrCopy(
CEnumCPINotifyUI * pecpIn
)
{
TraceFunc( "" );
HRESULT hr = S_FALSE;
ULONG cIter;
Assert( m_cAlloced == 0 );
Assert( m_cCurrent == 0 );
Assert( m_pList == NULL );
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"EnumCPINotifyUI!IUnknown", IUnknown, m_pList[ cIter ], 1 );
} // if:
else
{
m_pList[ cIter ] = NULL;
} // else:
} // for:
hr = S_OK;
Cleanup:
HRETURN( hr );
} //*** CEnumCPINotifyUI::HrCopy