home *** CD-ROM | disk | FTP | other *** search
/ Isometric Game Programming with DirectX 7.0 / Isometric Game Programming.iso / directx / dxf / samples / multimedia / directshow / baseclasses / combase.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2000-11-04  |  7.4 KB  |  257 lines

  1. //------------------------------------------------------------------------------
  2. // File: ComBase.cpp
  3. //
  4. // Desc: DirectShow base classes - implements class hierarchy for creating
  5. //       COM objects.
  6. //
  7. // Copyright (c) 1992 - 2000, Microsoft Corporation.  All rights reserved.
  8. //------------------------------------------------------------------------------
  9.  
  10.  
  11. #include <streams.h>
  12. #pragma warning( disable : 4514 )   // Disable warnings re unused inline functions
  13.  
  14.  
  15. /* Define the static member variable */
  16.  
  17. LONG CBaseObject::m_cObjects = 0;
  18.  
  19.  
  20. /* Constructor */
  21.  
  22. CBaseObject::CBaseObject(const TCHAR *pName)
  23. {
  24.     /* Increment the number of active objects */
  25.     InterlockedIncrement(&m_cObjects);
  26.  
  27. #ifdef DEBUG
  28.  
  29. #ifdef UNICODE
  30.     m_dwCookie = DbgRegisterObjectCreation(0, pName);
  31. #else
  32.     m_dwCookie = DbgRegisterObjectCreation(pName, 0);
  33. #endif
  34.  
  35. #endif
  36. }
  37.  
  38. #ifdef UNICODE
  39. CBaseObject::CBaseObject(const char *pName)
  40. {
  41.     /* Increment the number of active objects */
  42.     InterlockedIncrement(&m_cObjects);
  43.  
  44. #ifdef DEBUG
  45.     m_dwCookie = DbgRegisterObjectCreation(pName, 0);
  46. #endif
  47. }
  48. #endif
  49.  
  50. HINSTANCE    hlibOLEAut32;
  51.  
  52. /* Destructor */
  53.  
  54. CBaseObject::~CBaseObject()
  55. {
  56.     /* Decrement the number of objects active */
  57.     if (InterlockedDecrement(&m_cObjects) == 0) {
  58.     if (hlibOLEAut32) {
  59.         FreeLibrary(hlibOLEAut32);
  60.  
  61.         hlibOLEAut32 = 0;
  62.     }
  63.     };
  64.  
  65.  
  66. #ifdef DEBUG
  67.     DbgRegisterObjectDestruction(m_dwCookie);
  68. #endif
  69. }
  70.  
  71. static const TCHAR szOle32Aut[]   = TEXT("OleAut32.dll");
  72.  
  73. HINSTANCE LoadOLEAut32()
  74. {
  75.     if (hlibOLEAut32 == 0) {
  76.  
  77.     hlibOLEAut32 = LoadLibrary(szOle32Aut);
  78.     }
  79.  
  80.     return hlibOLEAut32;
  81. }
  82.  
  83.  
  84. /* Constructor */
  85.  
  86. // We know we use "this" in the initialization list, we also know we don't modify *phr.
  87. #pragma warning( disable : 4355 4100 )
  88. CUnknown::CUnknown(const TCHAR *pName, LPUNKNOWN pUnk)
  89. : CBaseObject(pName)
  90. /* Start the object with a reference count of zero - when the      */
  91. /* object is queried for it's first interface this may be          */
  92. /* incremented depending on whether or not this object is          */
  93. /* currently being aggregated upon                                 */
  94. , m_cRef(0)
  95. /* Set our pointer to our IUnknown interface.                      */
  96. /* If we have an outer, use its, otherwise use ours.               */
  97. /* This pointer effectivly points to the owner of                  */
  98. /* this object and can be accessed by the GetOwner() method.       */
  99. , m_pUnknown( pUnk != 0 ? pUnk : reinterpret_cast<LPUNKNOWN>( static_cast<PNDUNKNOWN>(this) ) )
  100.  /* Why the double cast?  Well, the inner cast is a type-safe cast */
  101.  /* to pointer to a type from which we inherit.  The second is     */
  102.  /* type-unsafe but works because INonDelegatingUnknown "behaves   */
  103.  /* like" IUnknown. (Only the names on the methods change.)        */
  104. {
  105.     // Everything we need to do has been done in the initializer list
  106. }
  107.  
  108. // This does the same as above except it has a useless HRESULT argument
  109. // use the previous constructor, this is just left for compatibility...
  110. CUnknown::CUnknown(TCHAR *pName, LPUNKNOWN pUnk,HRESULT *phr) :
  111.     CBaseObject(pName),
  112.     m_cRef(0),
  113.     m_pUnknown( pUnk != 0 ? pUnk : reinterpret_cast<LPUNKNOWN>( static_cast<PNDUNKNOWN>(this) ) )
  114. {
  115. }
  116.  
  117. #ifdef UNICODE
  118. CUnknown::CUnknown(const CHAR *pName, LPUNKNOWN pUnk)
  119. : CBaseObject(pName), m_cRef(0),
  120.     m_pUnknown( pUnk != 0 ? pUnk : reinterpret_cast<LPUNKNOWN>( static_cast<PNDUNKNOWN>(this) ) )
  121. { }
  122.  
  123. CUnknown::CUnknown(CHAR *pName, LPUNKNOWN pUnk,HRESULT *phr) :
  124.     CBaseObject(pName), m_cRef(0),
  125.     m_pUnknown( pUnk != 0 ? pUnk : reinterpret_cast<LPUNKNOWN>( static_cast<PNDUNKNOWN>(this) ) )
  126. { }
  127.  
  128. #endif
  129.  
  130. #pragma warning( default : 4355 4100 )
  131.  
  132.  
  133. /* QueryInterface */
  134.  
  135. STDMETHODIMP CUnknown::NonDelegatingQueryInterface(REFIID riid, void ** ppv)
  136. {
  137.     CheckPointer(ppv,E_POINTER);
  138.     ValidateReadWritePtr(ppv,sizeof(PVOID));
  139.  
  140.     /* We know only about IUnknown */
  141.  
  142.     if (riid == IID_IUnknown) {
  143.         GetInterface((LPUNKNOWN) (PNDUNKNOWN) this, ppv);
  144.         return NOERROR;
  145.     } else {
  146.         *ppv = NULL;
  147.         return E_NOINTERFACE;
  148.     }
  149. }
  150.  
  151. /* We have to ensure that we DON'T use a max macro, since these will typically   */
  152. /* lead to one of the parameters being evaluated twice.  Since we are worried    */
  153. /* about concurrency, we can't afford to access the m_cRef twice since we can't  */
  154. /* afford to run the risk that its value having changed between accesses.        */
  155.  
  156. template<class T> inline static T ourmax( const T & a, const T & b )
  157. {
  158.     return a > b ? a : b;
  159. }
  160.  
  161. /* AddRef */
  162.  
  163. STDMETHODIMP_(ULONG) CUnknown::NonDelegatingAddRef()
  164. {
  165.     LONG lRef = InterlockedIncrement( &m_cRef );
  166.     ASSERT(lRef > 0);
  167.     DbgLog((LOG_MEMORY,3,TEXT("    Obj %d ref++ = %d"),
  168.            m_dwCookie, m_cRef));
  169.     return ourmax(ULONG(m_cRef), 1ul);
  170. }
  171.  
  172.  
  173. /* Release */
  174.  
  175. STDMETHODIMP_(ULONG) CUnknown::NonDelegatingRelease()
  176. {
  177.     /* If the reference count drops to zero delete ourselves */
  178.  
  179.     LONG lRef = InterlockedDecrement( &m_cRef );
  180.     ASSERT(lRef >= 0);
  181.  
  182.     DbgLog((LOG_MEMORY,3,TEXT("    Object %d ref-- = %d"),
  183.         m_dwCookie, m_cRef));
  184.     if (lRef == 0) {
  185.  
  186.         // COM rules say we must protect against re-entrancy.
  187.         // If we are an aggregator and we hold our own interfaces
  188.         // on the aggregatee, the QI for these interfaces will
  189.         // addref ourselves. So after doing the QI we must release
  190.         // a ref count on ourselves. Then, before releasing the
  191.         // private interface, we must addref ourselves. When we do
  192.         // this from the destructor here it will result in the ref
  193.         // count going to 1 and then back to 0 causing us to
  194.         // re-enter the destructor. Hence we add an extra refcount here
  195.         // once we know we will delete the object.
  196.         // for an example aggregator see filgraph\distrib.cpp.
  197.  
  198.         m_cRef++;
  199.  
  200.         delete this;
  201.         return ULONG(0);
  202.     } else {
  203.         return ourmax(ULONG(m_cRef), 1ul);
  204.     }
  205. }
  206.  
  207.  
  208. /* Return an interface pointer to a requesting client
  209.    performing a thread safe AddRef as necessary */
  210.  
  211. STDAPI GetInterface(LPUNKNOWN pUnk, void **ppv)
  212. {
  213.     CheckPointer(ppv, E_POINTER);
  214.     *ppv = pUnk;
  215.     pUnk->AddRef();
  216.     return NOERROR;
  217. }
  218.  
  219.  
  220. /* Compares two interfaces and returns TRUE if they are on the same object */
  221.  
  222. BOOL WINAPI IsEqualObject(IUnknown *pFirst, IUnknown *pSecond)
  223. {
  224.     /*  Different objects can't have the same interface pointer for
  225.         any interface
  226.     */
  227.     if (pFirst == pSecond) {
  228.         return TRUE;
  229.     }
  230.     /*  OK - do it the hard way - check if they have the same
  231.         IUnknown pointers - a single object can only have one of these
  232.     */
  233.     LPUNKNOWN pUnknown1;     // Retrieve the IUnknown interface
  234.     LPUNKNOWN pUnknown2;     // Retrieve the other IUnknown interface
  235.     HRESULT hr;              // General OLE return code
  236.  
  237.     ASSERT(pFirst);
  238.     ASSERT(pSecond);
  239.  
  240.     /* See if the IUnknown pointers match */
  241.  
  242.     hr = pFirst->QueryInterface(IID_IUnknown,(void **) &pUnknown1);
  243.     ASSERT(SUCCEEDED(hr));
  244.     ASSERT(pUnknown1);
  245.  
  246.     hr = pSecond->QueryInterface(IID_IUnknown,(void **) &pUnknown2);
  247.     ASSERT(SUCCEEDED(hr));
  248.     ASSERT(pUnknown2);
  249.  
  250.     /* Release the extra interfaces we hold */
  251.  
  252.     pUnknown1->Release();
  253.     pUnknown2->Release();
  254.     return (pUnknown1 == pUnknown2);
  255. }
  256.  
  257.