topical media & game development

talk show tell print

hush-src-multi-BaseClasses-combase.cpp / cpp



  //------------------------------------------------------------------------------
  // File: ComBase.cpp
  //
  // Desc: DirectShow base classes - implements class hierarchy for creating
  //       COM objects.
  //
  // Copyright (c) Microsoft Corporation.  All rights reserved.
  //------------------------------------------------------------------------------
  
  include <streams.h>
  #pragma warning( disable : 4514 )   // Disable warnings re unused inline functions
  
  /* Define the static member variable */
  
  LONG CBaseObject::m_cObjects = 0;
  
  /* Constructor */
  
  CBaseObject::CBaseObject(const TCHAR *pName)
  {
      /* Increment the number of active objects */
      InterlockedIncrement(&m_cObjects);
  
  ifdef DEBUG
  
  ifdef UNICODE
      m_dwCookie = DbgRegisterObjectCreation(0, pName);
  else
      m_dwCookie = DbgRegisterObjectCreation(pName, 0);
  endif
  
  endif
  }
  
  ifdef UNICODE
  CBaseObject::CBaseObject(const char *pName)
  {
      /* Increment the number of active objects */
      InterlockedIncrement(&m_cObjects);
  
  ifdef DEBUG
      m_dwCookie = DbgRegisterObjectCreation(pName, 0);
  endif
  }
  endif
  
  HINSTANCE        hlibOLEAut32;
  
  /* Destructor */
  
  CBaseObject::~CBaseObject()
  {
      /* Decrement the number of objects active */
      if (InterlockedDecrement(&m_cObjects) == 0) {
          if (hlibOLEAut32) {
              FreeLibrary(hlibOLEAut32);
  
              hlibOLEAut32 = 0;
          }
      };
  
  ifdef DEBUG
      DbgRegisterObjectDestruction(m_dwCookie);
  endif
  }
  
  static const TCHAR szOle32Aut[]   = TEXT(<OleAut32.dll>);
  
  HINSTANCE LoadOLEAut32()
  {
      if (hlibOLEAut32 == 0) {
  
          hlibOLEAut32 = LoadLibrary(szOle32Aut);
      }
  
      return hlibOLEAut32;
  }
  
  /* Constructor */
  
  // We know we use "this" in the initialization list, we also know we don't modify *phr.
  #pragma warning( disable : 4355 4100 )
  CUnknown::CUnknown(const TCHAR *pName, LPUNKNOWN pUnk)
  : CBaseObject(pName)
  /* Start the object with a reference count of zero - when the      */
  /* object is queried for it's first interface this may be          */
  /* incremented depending on whether or not this object is          */
  /* currently being aggregated upon                                 */
  , m_cRef(0)
  /* Set our pointer to our IUnknown interface.                      */
  /* If we have an outer, use its, otherwise use ours.               */
  /* This pointer effectivly points to the owner of                  */
  /* this object and can be accessed by the GetOwner() method.       */
  , m_pUnknown( pUnk != 0 ? pUnk : reinterpret_cast<LPUNKNOWN>( static_cast<PNDUNKNOWN>(this) ) )
   /* Why the double cast?  Well, the inner cast is a type-safe cast */
   /* to pointer to a type from which we inherit.  The second is     */
   /* type-unsafe but works because INonDelegatingUnknown "behaves   */
   /* like" IUnknown. (Only the names on the methods change.)        */
  {
      // Everything we need to do has been done in the initializer list
  }
  
  // This does the same as above except it has a useless HRESULT argument
  // use the previous constructor, this is just left for compatibility...
  CUnknown::CUnknown(TCHAR *pName, LPUNKNOWN pUnk,HRESULT *phr) :
      CBaseObject(pName),
      m_cRef(0),
      m_pUnknown( pUnk != 0 ? pUnk : reinterpret_cast<LPUNKNOWN>( static_cast<PNDUNKNOWN>(this) ) )
  {
  }
  
  ifdef UNICODE
  CUnknown::CUnknown(const CHAR *pName, LPUNKNOWN pUnk)
  : CBaseObject(pName), m_cRef(0),
      m_pUnknown( pUnk != 0 ? pUnk : reinterpret_cast<LPUNKNOWN>( static_cast<PNDUNKNOWN>(this) ) )
  { }
  
  CUnknown::CUnknown(CHAR *pName, LPUNKNOWN pUnk,HRESULT *phr) :
      CBaseObject(pName), m_cRef(0),
      m_pUnknown( pUnk != 0 ? pUnk : reinterpret_cast<LPUNKNOWN>( static_cast<PNDUNKNOWN>(this) ) )
  { }
  
  endif
  
  #pragma warning( default : 4355 4100 )
  
  /* QueryInterface */
  
  STDMETHODIMP CUnknown::NonDelegatingQueryInterface(REFIID riid, void ** ppv)
  {
      CheckPointer(ppv,E_POINTER);
      ValidateReadWritePtr(ppv,sizeof(PVOID));
  
      /* We know only about IUnknown */
  
      if (riid == IID_IUnknown) {
          GetInterface((LPUNKNOWN) (PNDUNKNOWN) this, ppv);
          return NOERROR;
      } else {
          *ppv = NULL;
          return E_NOINTERFACE;
      }
  }
  
  /* We have to ensure that we DON'T use a max macro, since these will typically   */
  /* lead to one of the parameters being evaluated twice.  Since we are worried    */
  /* about concurrency, we can't afford to access the m_cRef twice since we can't  */
  /* afford to run the risk that its value having changed between accesses.        */
  
  template<class T> inline static T ourmax( const T & a, const T & b )
  {
      return a > b ? a : b;
  }
  
  /* AddRef */
  
  STDMETHODIMP_(ULONG) CUnknown::NonDelegatingAddRef()
  {
      LONG lRef = InterlockedIncrement( &m_cRef );
      ASSERT(lRef > 0);
      DbgLog((LOG_MEMORY,3,TEXT("    Obj \%d ref++ = \%d"),
             m_dwCookie, m_cRef));
      return ourmax(ULONG(m_cRef), 1ul);
  }
  
  /* Release */
  
  STDMETHODIMP_(ULONG) CUnknown::NonDelegatingRelease()
  {
      /* If the reference count drops to zero delete ourselves */
  
      LONG lRef = InterlockedDecrement( &m_cRef );
      ASSERT(lRef >= 0);
  
      DbgLog((LOG_MEMORY,3,TEXT("    Object \%d ref-- = \%d"),
              m_dwCookie, m_cRef));
      if (lRef == 0) {
  
          // COM rules say we must protect against re-entrancy.
          // If we are an aggregator and we hold our own interfaces
          // on the aggregatee, the QI for these interfaces will
          // addref ourselves. So after doing the QI we must release
          // a ref count on ourselves. Then, before releasing the
          // private interface, we must addref ourselves. When we do
          // this from the destructor here it will result in the ref
          // count going to 1 and then back to 0 causing us to
          // re-enter the destructor. Hence we add an extra refcount here
          // once we know we will delete the object.
          // for an example aggregator see filgraph\distrib.cpp.
  
          m_cRef++;
  
          delete this;
          return ULONG(0);
      } else {
          return ourmax(ULONG(m_cRef), 1ul);
      }
  }
  
  /* Return an interface pointer to a requesting client
     performing a thread safe AddRef as necessary */
  
  STDAPI GetInterface(LPUNKNOWN pUnk, void **ppv)
  {
      CheckPointer(ppv, E_POINTER);
      *ppv = pUnk;
      pUnk->AddRef();
      return NOERROR;
  }
  
  /* Compares two interfaces and returns TRUE if they are on the same object */
  
  BOOL WINAPI IsEqualObject(IUnknown *pFirst, IUnknown *pSecond)
  {
      /*  Different objects can't have the same interface pointer for
          any interface
      */
      if (pFirst == pSecond) {
          return TRUE;
      }
      /*  OK - do it the hard way - check if they have the same
          IUnknown pointers - a single object can only have one of these
      */
      LPUNKNOWN pUnknown1;     // Retrieve the IUnknown interface
      LPUNKNOWN pUnknown2;     // Retrieve the other IUnknown interface
      HRESULT hr;              // General OLE return code
  
      ASSERT(pFirst);
      ASSERT(pSecond);
  
      /* See if the IUnknown pointers match */
  
      hr = pFirst->QueryInterface(IID_IUnknown,(void **) &pUnknown1);
      ASSERT(SUCCEEDED(hr));
      ASSERT(pUnknown1);
  
      hr = pSecond->QueryInterface(IID_IUnknown,(void **) &pUnknown2);
      ASSERT(SUCCEEDED(hr));
      ASSERT(pUnknown2);
  
      /* Release the extra interfaces we hold */
  
      pUnknown1->Release();
      pUnknown2->Release();
      return (pUnknown1 == pUnknown2);
  }
  
  


(C) Æliens 20/2/2008

You may not copy or print any of this material without explicit permission of the author or the publisher. In case of other copyright issues, contact the author.