| //------------------------------------------------------------------------------ | |
| // 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); | |
| } | |