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