594 lines
12 KiB
C++
594 lines
12 KiB
C++
|
//////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Copyright (c) 1999-2000 Microsoft Corporation
|
||
|
//
|
||
|
// Module Name:
|
||
|
// EnumCPINotifyUI.cpp
|
||
|
//
|
||
|
// Description:
|
||
|
// INotifyUI Connection Point Enumerator implementation.
|
||
|
//
|
||
|
// Maintained By:
|
||
|
// Geoffrey Pease (GPease) 04-AUG-2000
|
||
|
//
|
||
|
//////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
#include "pch.h"
|
||
|
#include "EnumCPINotifyUI.h"
|
||
|
|
||
|
DEFINE_THISCLASS("CEnumCPINotifyUI")
|
||
|
|
||
|
#define PUNK_BUFFER_GROW_SIZE 10
|
||
|
|
||
|
// ************************************************************************
|
||
|
//
|
||
|
// Constructor / Destructor
|
||
|
//
|
||
|
// ************************************************************************
|
||
|
|
||
|
|
||
|
//////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// HRESULT
|
||
|
// CEnumCPINotifyUI::S_HrCreateInstance(
|
||
|
// IUnknown ** ppunkOut
|
||
|
// )
|
||
|
//
|
||
|
//////////////////////////////////////////////////////////////////////////////
|
||
|
HRESULT
|
||
|
CEnumCPINotifyUI::S_HrCreateInstance(
|
||
|
IUnknown ** ppunkOut
|
||
|
)
|
||
|
{
|
||
|
TraceFunc( "" );
|
||
|
|
||
|
Assert( ppunkOut != NULL );
|
||
|
|
||
|
HRESULT hr;
|
||
|
|
||
|
CEnumCPINotifyUI * lpcc = new CEnumCPINotifyUI( );
|
||
|
if ( lpcc != NULL )
|
||
|
{
|
||
|
hr = THR( lpcc->Init( ) );
|
||
|
if ( SUCCEEDED( hr ) )
|
||
|
{
|
||
|
hr = THR( lpcc->TypeSafeQI( IUnknown, ppunkOut ) );
|
||
|
} // if: success
|
||
|
|
||
|
lpcc->Release( );
|
||
|
|
||
|
} // if: got object
|
||
|
else
|
||
|
{
|
||
|
hr = E_OUTOFMEMORY;
|
||
|
} // else: out of memory
|
||
|
|
||
|
HRETURN( hr );
|
||
|
|
||
|
} // S_HrCreateInstance( )
|
||
|
|
||
|
//
|
||
|
// Constructor
|
||
|
//
|
||
|
CEnumCPINotifyUI::CEnumCPINotifyUI( void )
|
||
|
{
|
||
|
TraceFunc( "" );
|
||
|
|
||
|
InterlockedIncrement( &g_cObjects );
|
||
|
|
||
|
TraceFuncExit();
|
||
|
|
||
|
} // CEnumCPINotifyUI( )
|
||
|
|
||
|
//////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// STDMETHODIMP
|
||
|
// CEnumCPINotifyUI::Init( )
|
||
|
//
|
||
|
//////////////////////////////////////////////////////////////////////////////
|
||
|
STDMETHODIMP
|
||
|
CEnumCPINotifyUI::Init( )
|
||
|
{
|
||
|
TraceFunc( "" );
|
||
|
|
||
|
// IUnknown stuff
|
||
|
Assert( m_cRef == 0 );
|
||
|
AddRef( ); // Add one count
|
||
|
|
||
|
// IEnumConnectionPoints
|
||
|
Assert( m_cAlloced == 0 );
|
||
|
Assert( m_cCurrent == 0 );
|
||
|
Assert( m_cIter == 0 );
|
||
|
Assert( m_pList == NULL );
|
||
|
|
||
|
// INotifyUI
|
||
|
|
||
|
HRETURN( S_OK );
|
||
|
|
||
|
} // Init( )
|
||
|
|
||
|
//////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// CEnumCPINotifyUI::~CEnumCPINotifyUI( )
|
||
|
//
|
||
|
//////////////////////////////////////////////////////////////////////////////
|
||
|
CEnumCPINotifyUI::~CEnumCPINotifyUI( )
|
||
|
{
|
||
|
TraceFunc( "" );
|
||
|
|
||
|
if ( m_pList != NULL )
|
||
|
{
|
||
|
while( m_cAlloced != 0 )
|
||
|
{
|
||
|
IUnknown * punk;
|
||
|
|
||
|
m_cAlloced --;
|
||
|
|
||
|
punk = m_pList[ m_cAlloced ];
|
||
|
|
||
|
AssertMsg( punk == NULL, "Someone didn't Unadvise before releasing the last Ref" );
|
||
|
if ( punk != NULL )
|
||
|
{
|
||
|
punk->Release( );
|
||
|
}
|
||
|
|
||
|
} // while: m_cAlloced
|
||
|
|
||
|
TraceFree( m_pList );
|
||
|
}
|
||
|
|
||
|
InterlockedDecrement( &g_cObjects );
|
||
|
|
||
|
TraceFuncExit();
|
||
|
|
||
|
} // ~CEnumCPINotifyUI( )
|
||
|
|
||
|
|
||
|
// ************************************************************************
|
||
|
//
|
||
|
// IUnknown
|
||
|
//
|
||
|
// ************************************************************************
|
||
|
|
||
|
|
||
|
//////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// STDMETHODIMP
|
||
|
// CEnumCPINotifyUI::QueryInterface(
|
||
|
// REFIID riid,
|
||
|
// LPVOID *ppv
|
||
|
// )
|
||
|
//
|
||
|
//////////////////////////////////////////////////////////////////////////////
|
||
|
STDMETHODIMP
|
||
|
CEnumCPINotifyUI::QueryInterface(
|
||
|
REFIID riid,
|
||
|
LPVOID *ppv
|
||
|
)
|
||
|
{
|
||
|
TraceQIFunc( riid, ppv );
|
||
|
|
||
|
HRESULT hr = E_NOINTERFACE;
|
||
|
|
||
|
if ( IsEqualIID( riid, IID_IUnknown ) )
|
||
|
{
|
||
|
*ppv = static_cast< IEnumConnections * >( this );
|
||
|
hr = S_OK;
|
||
|
} // if: IUnknown
|
||
|
else if ( IsEqualIID( riid, IID_IEnumConnections ) )
|
||
|
{
|
||
|
*ppv = TraceInterface( __THISCLASS__, IEnumConnections, this, 0 );
|
||
|
hr = S_OK;
|
||
|
} // else if: IEnumConnections
|
||
|
|
||
|
if ( SUCCEEDED( hr ) )
|
||
|
{
|
||
|
((IUnknown*) *ppv)->AddRef( );
|
||
|
} // if: success
|
||
|
|
||
|
QIRETURN_IGNORESTDMARSHALLING( hr, riid );
|
||
|
|
||
|
} // QueryInterface( )
|
||
|
|
||
|
//////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// STDMETHODIMP_(ULONG)
|
||
|
// CEnumCPINotifyUI::AddRef( void )
|
||
|
//
|
||
|
//////////////////////////////////////////////////////////////////////////////
|
||
|
STDMETHODIMP_(ULONG)
|
||
|
CEnumCPINotifyUI::AddRef( void )
|
||
|
{
|
||
|
TraceFunc( "[IUnknown]" );
|
||
|
|
||
|
InterlockedIncrement( &m_cRef );
|
||
|
|
||
|
RETURN( m_cRef );
|
||
|
|
||
|
} // AddRef( )
|
||
|
|
||
|
//////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// STDMETHODIMP_(ULONG)
|
||
|
// CEnumCPINotifyUI::Release( void )
|
||
|
//
|
||
|
//////////////////////////////////////////////////////////////////////////////
|
||
|
STDMETHODIMP_(ULONG)
|
||
|
CEnumCPINotifyUI::Release( void )
|
||
|
{
|
||
|
TraceFunc( "[IUnknown]" );
|
||
|
|
||
|
InterlockedDecrement( &m_cRef );
|
||
|
|
||
|
if ( m_cRef )
|
||
|
RETURN( m_cRef );
|
||
|
|
||
|
TraceDo( delete this );
|
||
|
|
||
|
RETURN(0);
|
||
|
|
||
|
} // Release( )
|
||
|
|
||
|
|
||
|
// ************************************************************************
|
||
|
//
|
||
|
// IEnumConnectionPoints
|
||
|
//
|
||
|
// ************************************************************************
|
||
|
|
||
|
|
||
|
//////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// STDMETHODIMP
|
||
|
// CEnumCPINotifyUI::Next(
|
||
|
// ULONG cConnectionsIn,
|
||
|
// LPCONNECTIONPOINT *ppCPOut,
|
||
|
// ULONG *pcFetchedOut
|
||
|
// )
|
||
|
//
|
||
|
//////////////////////////////////////////////////////////////////////////////
|
||
|
STDMETHODIMP
|
||
|
CEnumCPINotifyUI::Next(
|
||
|
ULONG cConnectionsIn,
|
||
|
LPCONNECTDATA rgcd,
|
||
|
ULONG *pcFetchedOut
|
||
|
)
|
||
|
{
|
||
|
TraceFunc( "[IEnumConnectionPoints]" );
|
||
|
|
||
|
ULONG cIter;
|
||
|
|
||
|
HRESULT hr = E_UNEXPECTED;
|
||
|
|
||
|
if ( pcFetchedOut != NULL )
|
||
|
{
|
||
|
*pcFetchedOut = 0;
|
||
|
}
|
||
|
|
||
|
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"EnumCPINotifyUI!IUnknown", IUnknown, rgcd[ cIter ].pUnk, 1 );
|
||
|
|
||
|
rgcd[ cIter ].dwCookie = m_cIter + 1;
|
||
|
|
||
|
cIter ++;
|
||
|
}
|
||
|
|
||
|
} // for: cIter
|
||
|
|
||
|
if ( cIter != cConnectionsIn )
|
||
|
{
|
||
|
hr = S_FALSE;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hr = S_OK;
|
||
|
}
|
||
|
|
||
|
if ( pcFetchedOut != NULL )
|
||
|
{
|
||
|
*pcFetchedOut = cIter;
|
||
|
}
|
||
|
|
||
|
Cleanup:
|
||
|
HRETURN( hr );
|
||
|
|
||
|
Error:
|
||
|
while( cIter != 0 )
|
||
|
{
|
||
|
cIter --;
|
||
|
rgcd[ cIter ].pUnk->Release( );
|
||
|
}
|
||
|
goto Cleanup;
|
||
|
|
||
|
} // Next( )
|
||
|
|
||
|
//////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// STDMETHODIMP
|
||
|
// CEnumCPINotifyUI::Skip(
|
||
|
// ULONG cConnectionsIn
|
||
|
// )
|
||
|
//
|
||
|
//////////////////////////////////////////////////////////////////////////////
|
||
|
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;
|
||
|
}
|
||
|
|
||
|
HRETURN( hr );
|
||
|
|
||
|
} // Skip( )
|
||
|
|
||
|
//////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// STDMETHODIMP
|
||
|
// CEnumCPINotifyUI::Reset( void )
|
||
|
//
|
||
|
//////////////////////////////////////////////////////////////////////////////
|
||
|
STDMETHODIMP
|
||
|
CEnumCPINotifyUI::Reset( void )
|
||
|
{
|
||
|
TraceFunc( "[IEnumConnectionPoints]" );
|
||
|
|
||
|
HRESULT hr = S_OK;
|
||
|
|
||
|
m_cIter = 0;
|
||
|
|
||
|
HRETURN( hr );
|
||
|
|
||
|
} // Reset( )
|
||
|
|
||
|
//////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// STDMETHODIMP
|
||
|
// CEnumCPINotifyUI::Clone(
|
||
|
// IEnumConnectionPoints **ppEnumOut
|
||
|
// )
|
||
|
//
|
||
|
//////////////////////////////////////////////////////////////////////////////
|
||
|
STDMETHODIMP
|
||
|
CEnumCPINotifyUI::Clone(
|
||
|
IEnumConnections **ppEnumOut
|
||
|
)
|
||
|
{
|
||
|
TraceFunc( "[IEnumConnectionPoints]" );
|
||
|
|
||
|
HRESULT hr;
|
||
|
|
||
|
CEnumCPINotifyUI * pecp = new CEnumCPINotifyUI( );
|
||
|
if ( pecp == NULL )
|
||
|
goto OutOfMemory;
|
||
|
|
||
|
hr = THR( pecp->Init( ) );
|
||
|
if ( FAILED( hr ) )
|
||
|
goto Cleanup;
|
||
|
|
||
|
hr = THR( pecp->HrCopy( this ) );
|
||
|
if ( FAILED( hr ) )
|
||
|
goto Cleanup;
|
||
|
|
||
|
hr = THR( pecp->TypeSafeQI( IEnumConnections, ppEnumOut ) );
|
||
|
if ( FAILED( hr ) )
|
||
|
goto Cleanup;
|
||
|
|
||
|
*ppEnumOut = TraceInterface( L"EnumCPINotifyUI!IEnumConnections", IEnumConnections, *ppEnumOut, 1 );
|
||
|
|
||
|
pecp->Release( );
|
||
|
pecp = NULL;
|
||
|
|
||
|
Cleanup:
|
||
|
if ( pecp != NULL )
|
||
|
{
|
||
|
delete pecp;
|
||
|
}
|
||
|
|
||
|
HRETURN( hr );
|
||
|
|
||
|
OutOfMemory:
|
||
|
hr = E_OUTOFMEMORY;
|
||
|
goto Cleanup;
|
||
|
|
||
|
} // Clone( )
|
||
|
|
||
|
//////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// HRESULT
|
||
|
// CEnumCPINotifyUI::HrCopy(
|
||
|
// CEnumCPINotifyUI * pecpIn
|
||
|
// )
|
||
|
//
|
||
|
//////////////////////////////////////////////////////////////////////////////
|
||
|
HRESULT
|
||
|
CEnumCPINotifyUI::HrCopy(
|
||
|
CEnumCPINotifyUI * pecpIn
|
||
|
)
|
||
|
{
|
||
|
TraceFunc( "" );
|
||
|
|
||
|
HRESULT hr = E_UNEXPECTED;
|
||
|
|
||
|
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 )
|
||
|
goto OutOfMemory;
|
||
|
|
||
|
m_cCurrent = m_cAlloced = pecpIn->m_cCurrent;
|
||
|
m_cIter = 0;
|
||
|
|
||
|
for( cIter = 0; cIter < pecpIn->m_cCurrent; cIter ++ )
|
||
|
{
|
||
|
hr = THR( pecpIn->m_pList[ cIter ]->TypeSafeQI( IUnknown, &m_pList[ cIter ] ) );
|
||
|
if ( FAILED( hr ) )
|
||
|
goto Cleanup;
|
||
|
|
||
|
m_pList[ cIter ] = TraceInterface( L"EnumCPINotifyUI!IUnknown", IUnknown, m_pList[ cIter ], 1 );
|
||
|
}
|
||
|
|
||
|
hr = S_OK;
|
||
|
|
||
|
Cleanup:
|
||
|
HRETURN( hr );
|
||
|
|
||
|
OutOfMemory:
|
||
|
hr = E_OUTOFMEMORY;
|
||
|
goto Cleanup;
|
||
|
|
||
|
} // HrCopy( )
|
||
|
|
||
|
//////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// HRESULT
|
||
|
// CEnumCPINotifyUI::HrAddConnection(
|
||
|
// INotifyUI * punkIn,
|
||
|
// DWORD * pdwCookieOut
|
||
|
// )
|
||
|
//
|
||
|
//////////////////////////////////////////////////////////////////////////////
|
||
|
HRESULT
|
||
|
CEnumCPINotifyUI::HrAddConnection(
|
||
|
IUnknown * punkIn,
|
||
|
DWORD * pdwCookieOut
|
||
|
)
|
||
|
{
|
||
|
TraceFunc( "" );
|
||
|
|
||
|
HRESULT hr = E_UNEXPECTED;
|
||
|
|
||
|
ULONG cIter;
|
||
|
|
||
|
if ( pdwCookieOut == NULL )
|
||
|
goto InvalidPointer;
|
||
|
|
||
|
//
|
||
|
// 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 ( 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 )
|
||
|
goto OutOfMemory;
|
||
|
|
||
|
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"CEnumCPINotifyUI!IUnknown", IUnknown, m_pList[ m_cCurrent ], 1 );
|
||
|
|
||
|
m_cCurrent ++;
|
||
|
*pdwCookieOut = m_cCurrent; // starts at ONE, not ZERO
|
||
|
|
||
|
Cleanup:
|
||
|
HRETURN( hr );
|
||
|
|
||
|
OutOfMemory:
|
||
|
hr = E_OUTOFMEMORY;
|
||
|
goto Cleanup;
|
||
|
|
||
|
InvalidPointer:
|
||
|
hr = THR( E_POINTER );
|
||
|
goto Cleanup;
|
||
|
|
||
|
} // HrAddConnection( )
|
||
|
|
||
|
//////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// HRESULT
|
||
|
// CEnumCPINotifyUI::HrRemoveConnection(
|
||
|
// DWORD dwCookieIn
|
||
|
// )
|
||
|
//
|
||
|
//////////////////////////////////////////////////////////////////////////////
|
||
|
HRESULT
|
||
|
CEnumCPINotifyUI::HrRemoveConnection(
|
||
|
DWORD dwCookieIn
|
||
|
)
|
||
|
{
|
||
|
TraceFunc( "" );
|
||
|
|
||
|
HRESULT hr;
|
||
|
|
||
|
if ( dwCookieIn == 0 || dwCookieIn > m_cCurrent )
|
||
|
goto InvalidArg;
|
||
|
|
||
|
if ( m_pList[ dwCookieIn - 1 ] == NULL )
|
||
|
goto InvalidArg;
|
||
|
|
||
|
m_pList[ dwCookieIn - 1 ]->Release( );
|
||
|
m_pList[ dwCookieIn - 1 ] = NULL;
|
||
|
|
||
|
hr = S_OK;
|
||
|
|
||
|
Cleanup:
|
||
|
HRETURN( hr );
|
||
|
|
||
|
InvalidArg:
|
||
|
hr = THR( E_INVALIDARG );
|
||
|
goto Cleanup;
|
||
|
|
||
|
} // HrRemoveConnection( )
|
||
|
|