home *** CD-ROM | disk | FTP | other *** search
/ The Net: Ultimate Internet Guide / WWLCD1.ISO / mac / SiteBldr / AMOVIE / SDK / _SETUP / COMMON.Z / ext_enum.inl < prev    next >
Encoding:
Text File  |  1996-04-29  |  8.0 KB  |  308 lines

  1. //==========================================================================;
  2. //
  3. //  THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
  4. //  KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  5. //  IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
  6. //  PURPOSE.
  7. //
  8. //  Copyright (c) 1992 - 1996  Microsoft Corporation.  All Rights Reserved.
  9. //
  10. //--------------------------------------------------------------------------;
  11.  
  12. // AnyEnum
  13.  
  14. // Copy(ish) constructor
  15. // For reasons of performance, we tend to pass a HRESULT *  and set this if anything
  16. // goes wrong, rather than resort to C++ exception handling.  The instantiator is
  17. // responsible for checking the HRESULT and deleting us if we're deemed worthless.
  18. template<class IEnum, class BaseType>
  19. AnyEnum<IEnum, BaseType>::AnyEnum( const AnyEnum & copy, HRESULT * phr )
  20. : m_cRef(1)
  21. {
  22.     *phr = copy.m_pIEnum->Clone( &m_pIEnum );
  23. }
  24.  
  25. // Our QueryInterface is a little degenerate.  We will give back an IUnknown,
  26. // but we can't actually tell the IID of the IEnum we are covering, so we can't
  27. // (easily) check that say, IID_IEnumPins, is realy us.  If you try and get
  28. // anything other than an IUnknown, we'll tell you to E_NOINTERFACE.
  29. template<class IEnum, class BaseType>
  30. STDMETHODIMP AnyEnum<IEnum, BaseType>::QueryInterface( REFIID iid, void ** ppv )
  31. {
  32.     HRESULT hr = S_OK;
  33.     if (ppv)
  34.     {
  35.         *ppv = 0;
  36.         if ( iid == IID_IUnknown )          *ppv = static_cast<IUnknown *>(this);
  37.         else                                hr = E_NOINTERFACE;
  38.         if ( *ppv )                         AddRef();
  39.     }
  40.     else hr = E_POINTER;
  41.     return E_UNEXPECTED;
  42. }
  43.  
  44. template<class IEnum, class BaseType>
  45. STDMETHODIMP_(ULONG) AnyEnum<IEnum, BaseType>::AddRef()
  46. {
  47.     return InterlockedIncrement(&m_cRef);
  48. }
  49.  
  50. template<class IEnum, class BaseType>
  51. STDMETHODIMP_(ULONG) AnyEnum<IEnum, BaseType>::Release()
  52. {
  53.     const ULONG count = InterlockedDecrement(&m_cRef);
  54.     if (count==0) delete this;
  55.     return count;
  56. }
  57.  
  58. // Delagate Next() to our inner IEnum
  59. template<class IEnum, class BaseType>
  60. STDMETHODIMP AnyEnum<IEnum, BaseType>::Next( ULONG cBase, BaseType ** ppBase, ULONG * pcFetched )
  61. {
  62.     return m_pIEnum->Next( cBase, ppBase, pcFetched );
  63. }
  64.  
  65. // Delagate Skip() to our inner IEnum
  66. template<class IEnum, class BaseType>
  67. STDMETHODIMP AnyEnum<IEnum, BaseType>::Skip( ULONG cBase )
  68. {
  69.     return m_pIEnum->Skip(cBase);
  70. }
  71.  
  72. // Delagate Reset() to our inner IEnum
  73. template<class IEnum, class BaseType>
  74. STDMETHODIMP AnyEnum<IEnum, BaseType>::Reset( void )
  75. {
  76.     return m_pIEnum->Reset();
  77. }
  78.  
  79. // Our Clone() method clones the outer, then clones the inner.
  80. // This method will have to be overriden in derived classes
  81. // that introduce new attributes.
  82. template<class IEnum, class BaseType>
  83. STDMETHODIMP AnyEnum<IEnum, BaseType>::Clone( IEnum ** ppEnum )
  84. {
  85.     return CloneAny( *this, ppEnum );
  86. }
  87.  
  88.  
  89.  
  90. // ConstrictedEnum
  91.  
  92. // This is the meat.  We must retrieve BaseObjects individually and only pass them back to
  93. // our caller if they meet Select's criteria (whatever that might be).  pcFetched must be a
  94. // pointer to a ULONG.  ppBase may be null, in which case we don't pass back any objects, we
  95. // merely count them (this is mainly for the benefit of Skip()).
  96. template<class IEnum, class BaseType>
  97. STDMETHODIMP ConstrictedEnum<IEnum, BaseType>::Next( ULONG cBase, BaseType ** ppBase, ULONG * pcFetched )
  98. {
  99.     HRESULT hr = S_OK;
  100.         
  101.     BaseType * lcl_pBase;
  102.     ULONG lcl_fetched;
  103.  
  104.     if ( pcFetched )
  105.     {
  106.         *pcFetched = 0;
  107.  
  108.         while ( cBase > *pcFetched )
  109.         {
  110.             hr = m_pIEnum->Next( 1, &lcl_pBase, &lcl_fetched );
  111.             if (FAILED(hr)) break;
  112.             if (lcl_fetched == 0) break;
  113.  
  114.             if ( Select( &lcl_pBase ) )
  115.             {
  116.                 // Yes, client wants it counted
  117.                 ++*pcFetched;
  118.                 // Does client want the pointers?
  119.                 if ( ppBase )
  120.                 {
  121.                     // yes
  122.                     *ppBase = lcl_pBase;
  123.                     ++ppBase;
  124.                 }
  125.                 else lcl_pBase->Release();
  126.             }
  127.             else
  128.             {
  129.                 // Select doesn't want it, throw it away!
  130.                 lcl_pBase->Release();
  131.             }
  132.         }
  133.     }
  134.     else hr = E_POINTER;
  135.  
  136.     return hr;
  137. }
  138.  
  139. // We can't use our inherited or inner Skip(), since these won't honour
  140. // Select()'s selection criteria.
  141. template<class IEnum, class BaseType>
  142. STDMETHODIMP ConstrictedEnum<IEnum, BaseType>::Skip( ULONG cBase )
  143. {
  144.     ULONG cFetched;
  145.     return Next( cBase, 0, &cFetched );
  146. }
  147.  
  148. template<class IEnum, class BaseType>
  149. STDMETHODIMP ConstrictedEnum<IEnum, BaseType>::Skip( ULONG cBase, ULONG * pcCount )
  150. {
  151.     return Next( cBase, 0, pcCount );
  152. }
  153.  
  154.  
  155.  
  156. // CImpIEnumFilters
  157.  
  158. BOOL CImpIEnumFilters::Select( IFilter ** ppIFilter )
  159. {
  160.     ASSERT( ppIFilter );
  161.        void * this_interface;
  162.     const BOOL result = SUCCEEDED((*ppIFilter)->QueryInterface( m_iid, &this_interface ));
  163.     if ( result )
  164.     {
  165.         (*ppIFilter)->Release();
  166.         (*ppIFilter) = reinterpret_cast<IFilter*>(this_interface);
  167.     }
  168.     return result;
  169. }
  170.  
  171. STDMETHODIMP CImpIEnumFilters::Clone( IEnumFilters  ** ppEnum )
  172. {
  173.     return CloneAny( *this, ppEnum );
  174. }
  175.  
  176.  
  177.  
  178. // CImpIEnumUnconnectedFilters
  179.  
  180. BOOL CImpIEnumUnconnectedFilters::Select( IFilter ** ppIFilter )
  181. {
  182.     HRESULT hr;
  183.     BOOL connected = FALSE;
  184.     IFilter & iFilter = **ppIFilter;
  185.     IEnumPins * pIEnumPins = 0;
  186.     hr = iFilter.EnumPins( &pIEnumPins );
  187.     do
  188.     {
  189.         IPin *pIPin, *pConnectedToPin;
  190.         ULONG fetched;
  191.         hr = pIEnumPins->Next( 1, &pIPin, &fetched );
  192.         if FAILED(hr) break;
  193.         if ( fetched != 1 ) break;
  194.         pIPin->ConnectedTo( &pConnectedToPin );
  195.         if (pConnectedToPin)
  196.         {
  197.             connected = TRUE;
  198.             pConnectedToPin->Release();
  199.         }
  200.         pIPin->Release();
  201.     } while (!connected);
  202.     pIEnumPins->Release();
  203.     return !connected;
  204. }
  205.  
  206. STDMETHODIMP CImpIEnumUnconnectedFilters::Clone( IEnumFilters  ** ppEnum )
  207. {
  208.     return CloneAny( *this, ppEnum );
  209. }
  210.  
  211.  
  212.  
  213. // CImpIEnumPins
  214.  
  215. template<PIN_DIRECTION DIR>
  216. BOOL CImpIEnumPins<DIR>::Select( IPin ** ppIPin )
  217. {
  218.     HRESULT hr;
  219.     PIN_INFO PinInfo;
  220.     hr = (*ppIPin)->QueryPinInfo( &PinInfo );
  221.     ASSERT( SUCCEEDED(hr) );
  222.     return PinInfo.dir == DIR;
  223. }
  224.  
  225. template<PIN_DIRECTION DIR>
  226. STDMETHODIMP CImpIEnumPins<DIR>::Clone( IEnumPins  ** ppEnum )
  227. {
  228.     return CloneAny( *this, ppEnum );
  229. }
  230.  
  231.  
  232.  
  233. // CImpIEnumOverGraph
  234.  
  235. // This is the meat.  We must retrieve BaseObjects individually and only pass them back to
  236. // our caller if the meet Select's criteria (whatever that might be).  When we've exhausted
  237. // one filter, we call NextFilter() to go to the next one.
  238. template<class EnumPinClass>
  239. STDMETHODIMP CImpIEnumOverGraph<EnumPinClass>::Next( ULONG cBase, IPin ** ppBase, ULONG  *pcFetched )
  240. {
  241.     HRESULT hr;
  242.             
  243.     ULONG lcl_fetched;
  244.     *pcFetched = 0;
  245.  
  246.     if (m_pIEnum)
  247.     {
  248.         m_crit_sec.Lock();
  249.         while ( cBase > 0 )
  250.         {
  251.             hr = EnumPinClass::Next( cBase, ppBase, &lcl_fetched );
  252.             if (FAILED(hr)) break;
  253.             cBase -= lcl_fetched;
  254.             *pcFetched += lcl_fetched;
  255.             ppBase += lcl_fetched;
  256.             if ( hr==S_FALSE )
  257.             {
  258.                 hr = NextFilter();
  259.                 if ( hr != NOERROR ) break;
  260.             }
  261.         }
  262.         m_crit_sec.Unlock();
  263.     }
  264.     else hr = m_hr;
  265.     
  266.     return hr;
  267. }
  268.  
  269. // This method jumps us between filters
  270. template<class EnumPinClass>
  271. HRESULT CImpIEnumOverGraph<EnumPinClass>::NextFilter()
  272. {
  273.     if (m_pIEnum)
  274.     {
  275.         HRESULT hr;
  276.         hr = m_pIEnum->Release();
  277.         ASSERT( SUCCEEDED(hr) );
  278.         m_pIEnum = 0;
  279.     }
  280.  
  281.     IFilter * pIFilter;
  282.     ULONG lcl_count;
  283.     m_hr = m_pIEnumFilters->Next( 1, &pIFilter, &lcl_count );
  284.     ASSERT( SUCCEEDED(m_hr) );
  285.     if ( m_hr == NOERROR )
  286.     {
  287.         ASSERT( lcl_count == 1 );
  288.         m_hr = pIFilter->EnumPins( &m_pIEnum );
  289.         ASSERT( SUCCEEDED(m_hr) );
  290.         pIFilter->Release();
  291.     }
  292.     return m_hr;
  293. }
  294.  
  295. template<class EnumPinClass>
  296. STDMETHODIMP CImpIEnumOverGraph<EnumPinClass>::Reset( void )
  297. {
  298.     m_hr = m_pIEnumFilters->Reset();
  299.     if SUCCEEDED(m_hr) NextFilter();
  300.     return m_hr;
  301. }
  302.  
  303. template<class EnumPinClass>
  304. STDMETHODIMP CImpIEnumOverGraph<EnumPinClass>::Clone( IEnumPins ** ppEnum )
  305. {
  306.     return CloneAny( *this, ppEnum );
  307. }
  308.