//==========================================================================;
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
// PURPOSE.
//
// Copyright (c) 1992 - 1997 Microsoft Corporation. All Rights Reserved.
//
//--------------------------------------------------------------------------;
//
// Ext_Enum.h
//
//
// Contents:
//
#ifndef _Ext_Enum_h
#define _Ext_Enum_h
#pragma warning( disable : 4514 )
// A helper template & macro so that we only release non-null interface
// pointers and we set the pointer to null afterwards so that we don't
// release it again.
template<class Interface> void SafeRelPtrIPtr( Interface * * ppIUnk )
{
if ( *ppIUnk )
{
(*ppIUnk)->Release();
(*ppIUnk) = 0;
}
}
#define SafeRelIPtr( pI ) SafeRelPtrIPtr( &(pI) )
// A template function for cloning. We always clone an Implementation, but
// supply a pointer to an Interface. We need both to parameterize this function.
template<class Implementation, class Interface>
static inline HRESULT CloneAny( const Implementation & _this, Interface ** ppI)
{
HRESULT hr;
if (ppI)
{
*ppI = 0;
// Relies on Implementation having defined this kind of "copy" constructor.
Implementation *const p = new Implementation( _this, &hr );
if (p)
{
if SUCCEEDED(hr) *ppI = p;
else delete p;
}
else hr = E_OUTOFMEMORY;
}
else hr = E_POINTER;
return hr;
}
// AnyEnum presents a simple concrete class that can cover any enumerator that conforms to
// the standard COM enumerator interface. You'll probably never instantiate one of these,
// but it gives us a good foundation from which to build derived enumerators with special
// behaviour.
template<class IEnum, class BaseType> class AnyEnum : public IEnum
{
protected:
long m_cRef; // Local ref count
IEnum * m_pIEnum; // Pointer to a "real" enumarator that will do most of the work
// Protected default constructor, derived classes relying on this must set m_pIEnum themselves.
AnyEnum() : m_cRef(1), m_pIEnum(0) {}
public:
virtual ~AnyEnum() { SafeRelIPtr( m_pIEnum ); }
AnyEnum( const AnyEnum & copy, HRESULT * phr );
// IUnknown interface
STDMETHODIMP QueryInterface( REFIID iid, void ** ppv );
STDMETHODIMP_(ULONG) AddRef();
STDMETHODIMP_(ULONG) Release();
// IEnum interface
STDMETHODIMP Next( ULONG cBase, BaseType ** ppBase, ULONG * pcFetched );
STDMETHODIMP Skip( ULONG cBase );
STDMETHODIMP Reset( void );
STDMETHODIMP Clone( IEnum ** ppEnum );
};
// ConstrictedEnum
//
// An abstract template class extending AnyEnum by adding a Select() method.
// Derived classes must implement this method. For each object that our inner
// enumerator passes back to us, we ask Select() if it meets its selection
// criteria, if it does, we pass the object back to our caller, otherwise we
// ask our inner enumerator for another candidate.
//
// Next() is enhanced to call Select() for each candidate. Skip() is re-implemented
// since its skip count must now be in terms of objects that meet Select()'s criteria.
// A new Skip() is implemented where we can explicity get a count of the number of
// candidates skipped.
template<class IEnum, class BaseType> class ConstrictedEnum : public AnyEnum<IEnum,BaseType>
{
protected:
ConstrictedEnum() {}
// Pure virtual Selector method.
virtual BOOL Select( BaseType ** ppBase ) =0;
public:
ConstrictedEnum( const ConstrictedEnum & copy, HRESULT * phr )
: AnyEnum<IEnum,BaseType>( copy, phr ) {}
STDMETHODIMP Next( ULONG cBase, BaseType ** ppBase, ULONG * pcFetched );
STDMETHODIMP Skip( ULONG cBase );
STDMETHODIMP Skip( ULONG cBase, ULONG * pcCount );
};
// CImpIEnumFilters
//
// This class not only restricts ennumeration to IBaseFilters that support a specific interface,
// it also returns pointers to THAT interface, rather than just IBaseFilter pointers.
class CImpIEnumFilters : public ConstrictedEnum<IEnumFilters, IBaseFilter>
{
private:
REFIIDm_iid;
protected:
CImpIEnumFilters( REFIID iid ) : m_iid(iid) {}
BOOLSelect( IBaseFilter ** ppIFilter );
public:
CImpIEnumFilters( const CImpIEnumFilters & copy, HRESULT * phr )
: ConstrictedEnum<IEnumFilters,IBaseFilter>( copy, phr ), m_iid( copy.m_iid ) {}
CImpIEnumFilters( IFilterGraph * pIFilterGraph, REFIID iid )
: m_iid(iid)
{
HRESULT hr = pIFilterGraph->EnumFilters( &m_pIEnum );
ASSERT( SUCCEEDED(hr) );
}
STDMETHODIMP Clone( IEnumFilters ** ppEnum );
};
// CImpIEnumUnconnectedFilters
//
// Enumerates filters over a filter graph, but only returns those who have none of their pins connected
class CImpIEnumUnconnectedFilters : public ConstrictedEnum<IEnumFilters, IBaseFilter>
{
protected:
BOOLSelect( IBaseFilter ** ppIFilter );
public:
CImpIEnumUnconnectedFilters( const CImpIEnumUnconnectedFilters & copy, HRESULT * phr )
: ConstrictedEnum<IEnumFilters,IBaseFilter>( copy, phr ) {}
CImpIEnumUnconnectedFilters( IFilterGraph * pIFilterGraph )
{
HRESULT hr = pIFilterGraph->EnumFilters( &m_pIEnum );
ASSERT( SUCCEEDED(hr) );
}
STDMETHODIMP Clone( IEnumFilters ** ppEnum );
};
template<PIN_DIRECTION DIR> class CImpIEnumPins : public ConstrictedEnum<IEnumPins, IPin>
{
protected:
CImpIEnumPins() {}
BOOLSelect( IPin ** ppIPin );
public:
CImpIEnumPins( const CImpIEnumPins & copy, HRESULT * phr )
: ConstrictedEnum<IEnumPins, IPin>( copy, phr ) {}
CImpIEnumPins( IBaseFilter * pIFilter )
{
HRESULT hr = pIFilter->EnumPins( &m_pIEnum );
ASSERT ( SUCCEEDED(hr) );
}
STDMETHODIMP Clone( IEnumPins ** ppEnum );
};
typedef CImpIEnumPins<PINDIR_INPUT> CImpIEnumPinsIn;
typedef CImpIEnumPins<PINDIR_OUTPUT> CImpIEnumPinsOut;
typedef AnyEnum<IEnumPins, IPin> CImpIEnumPinsBoth;
template<class EnumPinClass> class CImpIEnumOverGraph : public EnumPinClass
{
private:
CImpIEnumOverGraph() {}
protected:
HRESULT m_hr;
IEnumFilters* m_pIEnumFilters;
CCritSec m_crit_sec;
HRESULT NextFilter(); // Iterates us through the filters
public:
~CImpIEnumOverGraph() { SafeRelIPtr(m_pIEnumFilters); }
CImpIEnumOverGraph( const CImpIEnumOverGraph & copy, HRESULT * phr )
: EnumPinClass( copy, phr )
{
if SUCCEEDED(*phr)
{
*phr = copy.m_pIEnumFilters->Clone( &m_pIEnumFilters );
m_hr = SUCCEEDED(*phr) ? copy.m_hr : *phr;
}
else m_pIEnumFilters = 0;
}
CImpIEnumOverGraph( IFilterGraph * pIFilterGraph )
{
HRESULT hr;
hr = pIFilterGraph->EnumFilters( &m_pIEnumFilters );
ASSERT( SUCCEEDED(hr) );
hr = NextFilter();
ASSERT( SUCCEEDED(hr) );
}
STDMETHODIMP Next( ULONG cBase, IPin ** ppBase, ULONG * pcFetched );
STDMETHODIMP Reset( void );
STDMETHODIMP Clone( IEnumPins ** ppEnum );
};
typedef CImpIEnumOverGraph<CImpIEnumPinsIn> CImpIEnumPinsInOverGraph;
typedef CImpIEnumOverGraph<CImpIEnumPinsOut> CImpIEnumPinsOutOverGraph;
typedef CImpIEnumOverGraph<CImpIEnumPinsBoth> CImpIEnumPinsOverGraph;
#include "Ext_Enum.inl"
#endif