combase.cpp
上传用户:liguizhu
上传日期:2015-11-01
资源大小:2422k
文件大小:7k
源码类别:

P2P编程

开发平台:

Visual C++

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