forked from LeenkxTeam/LNXSDK
		
	
		
			
	
	
		
			266 lines
		
	
	
		
			7.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
		
		
			
		
	
	
			266 lines
		
	
	
		
			7.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
|  | //------------------------------------------------------------------------------
 | ||
|  | // File: ComBase.cpp
 | ||
|  | //
 | ||
|  | // Desc: DirectShow base classes - implements class hierarchy for creating
 | ||
|  | //       COM objects.
 | ||
|  | //
 | ||
|  | // Copyright (c) 1992-2001 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(__in_opt LPCTSTR 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(__in_opt LPCTSTR pName, __in_opt 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(__in_opt LPCTSTR pName, __in_opt LPUNKNOWN pUnk, __inout_opt HRESULT *phr) : | ||
|  |     CBaseObject(pName), | ||
|  |     m_cRef(0), | ||
|  |     m_pUnknown( pUnk != 0 ? pUnk : reinterpret_cast<LPUNKNOWN>( static_cast<PNDUNKNOWN>(this) ) ) | ||
|  | { | ||
|  | } | ||
|  | 
 | ||
|  | #ifdef UNICODE
 | ||
|  | CUnknown::CUnknown(__in_opt LPCSTR pName, __in_opt LPUNKNOWN pUnk) | ||
|  | : CBaseObject(pName), m_cRef(0), | ||
|  |     m_pUnknown( pUnk != 0 ? pUnk : reinterpret_cast<LPUNKNOWN>( static_cast<PNDUNKNOWN>(this) ) ) | ||
|  | { } | ||
|  | 
 | ||
|  | CUnknown::CUnknown(__in_opt LPCSTR pName, __in_opt LPUNKNOWN pUnk, __inout_opt 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, __deref_out 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 { | ||
|  |         //  Don't touch m_cRef again even in this leg as the object
 | ||
|  |         //  may have just been released on another thread too
 | ||
|  |         return ourmax(ULONG(lRef), 1ul); | ||
|  |     } | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | /* Return an interface pointer to a requesting client
 | ||
|  |    performing a thread safe AddRef as necessary */ | ||
|  | 
 | ||
|  | STDAPI GetInterface(LPUNKNOWN pUnk, __out 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); | ||
|  |     if (FAILED(hr)) { | ||
|  |         return FALSE; | ||
|  |     } | ||
|  |     ASSERT(pUnknown1); | ||
|  | 
 | ||
|  |     /* Release the extra interface we hold */ | ||
|  | 
 | ||
|  |     pUnknown1->Release(); | ||
|  | 
 | ||
|  |     hr = pSecond->QueryInterface(IID_IUnknown,(void **) &pUnknown2); | ||
|  |     if (FAILED(hr)) { | ||
|  |         return FALSE; | ||
|  |     } | ||
|  |     ASSERT(pUnknown2); | ||
|  | 
 | ||
|  |     /* Release the extra interface we hold */ | ||
|  | 
 | ||
|  |     pUnknown2->Release(); | ||
|  |     return (pUnknown1 == pUnknown2); | ||
|  | } | ||
|  | 
 |