1 //------------------------------------------------------------------------------
4 // Desc: DirectShow base classes - implements class hierarchy for creating
7 // Copyright (c) 1992-2002 Microsoft Corporation. All rights reserved.
8 //------------------------------------------------------------------------------
12 #pragma warning( disable : 4514 ) // Disable warnings re unused inline functions
15 /* Define the static member variable */
17 LONG
CBaseObject::m_cObjects
= 0;
22 CBaseObject::CBaseObject(const TCHAR
*pName
)
24 /* Increment the number of active objects */
25 InterlockedIncrement(&m_cObjects
);
30 m_dwCookie
= DbgRegisterObjectCreation(0, pName
);
32 m_dwCookie
= DbgRegisterObjectCreation(pName
, 0);
39 CBaseObject::CBaseObject(const char *pName
)
41 /* Increment the number of active objects */
42 InterlockedIncrement(&m_cObjects
);
45 m_dwCookie
= DbgRegisterObjectCreation(pName
, 0);
50 HINSTANCE hlibOLEAut32
;
54 CBaseObject::~CBaseObject()
56 /* Decrement the number of objects active */
57 if (InterlockedDecrement(&m_cObjects
) == 0) {
59 FreeLibrary(hlibOLEAut32
);
67 DbgRegisterObjectDestruction(m_dwCookie
);
71 static const TCHAR szOle32Aut
[] = TEXT("OleAut32.dll");
73 HINSTANCE
LoadOLEAut32()
75 if (hlibOLEAut32
== 0) {
77 hlibOLEAut32
= LoadLibrary(szOle32Aut
);
86 // We know we use "this" in the initialization list, we also know we don't modify *phr.
87 #pragma warning( disable : 4355 4100 )
88 CUnknown::CUnknown(const TCHAR
*pName
, LPUNKNOWN pUnk
)
90 /* Start the object with a reference count of zero - when the */
91 /* object is queried for it's first interface this may be */
92 /* incremented depending on whether or not this object is */
93 /* currently being aggregated upon */
95 /* Set our pointer to our IUnknown interface. */
96 /* If we have an outer, use its, otherwise use ours. */
97 /* This pointer effectivly points to the owner of */
98 /* this object and can be accessed by the GetOwner() method. */
99 , m_pUnknown( pUnk
!= 0 ? pUnk
: reinterpret_cast<LPUNKNOWN
>( static_cast<PNDUNKNOWN
>(this) ) )
100 /* Why the double cast? Well, the inner cast is a type-safe cast */
101 /* to pointer to a type from which we inherit. The second is */
102 /* type-unsafe but works because INonDelegatingUnknown "behaves */
103 /* like" IUnknown. (Only the names on the methods change.) */
105 // Everything we need to do has been done in the initializer list
108 // This does the same as above except it has a useless HRESULT argument
109 // use the previous constructor, this is just left for compatibility...
110 CUnknown::CUnknown(TCHAR
*pName
, LPUNKNOWN pUnk
,HRESULT
*phr
) :
113 m_pUnknown( pUnk
!= 0 ? pUnk
: reinterpret_cast<LPUNKNOWN
>( static_cast<PNDUNKNOWN
>(this) ) )
118 CUnknown::CUnknown(const CHAR
*pName
, LPUNKNOWN pUnk
)
119 : CBaseObject(pName
), m_cRef(0),
120 m_pUnknown( pUnk
!= 0 ? pUnk
: reinterpret_cast<LPUNKNOWN
>( static_cast<PNDUNKNOWN
>(this) ) )
123 CUnknown::CUnknown(CHAR
*pName
, LPUNKNOWN pUnk
,HRESULT
*phr
) :
124 CBaseObject(pName
), m_cRef(0),
125 m_pUnknown( pUnk
!= 0 ? pUnk
: reinterpret_cast<LPUNKNOWN
>( static_cast<PNDUNKNOWN
>(this) ) )
130 #pragma warning( default : 4355 4100 )
135 STDMETHODIMP
CUnknown::NonDelegatingQueryInterface(REFIID riid
, void ** ppv
)
137 CheckPointer(ppv
,E_POINTER
);
138 ValidateReadWritePtr(ppv
,sizeof(PVOID
));
140 /* We know only about IUnknown */
142 if (riid
== IID_IUnknown
) {
143 GetInterface((LPUNKNOWN
) (PNDUNKNOWN
) this, ppv
);
147 return E_NOINTERFACE
;
151 /* We have to ensure that we DON'T use a max macro, since these will typically */
152 /* lead to one of the parameters being evaluated twice. Since we are worried */
153 /* about concurrency, we can't afford to access the m_cRef twice since we can't */
154 /* afford to run the risk that its value having changed between accesses. */
156 template<class T
> inline static T
ourmax( const T
& a
, const T
& b
)
158 return a
> b
? a
: b
;
163 STDMETHODIMP_(ULONG
) CUnknown::NonDelegatingAddRef()
165 LONG lRef
= InterlockedIncrement( &m_cRef
);
167 DbgLog((LOG_MEMORY
,3,TEXT(" Obj %d ref++ = %d"),
168 m_dwCookie
, m_cRef
));
169 return ourmax(ULONG(m_cRef
), 1ul);
175 STDMETHODIMP_(ULONG
) CUnknown::NonDelegatingRelease()
177 /* If the reference count drops to zero delete ourselves */
179 LONG lRef
= InterlockedDecrement( &m_cRef
);
182 DbgLog((LOG_MEMORY
,3,TEXT(" Object %d ref-- = %d"),
183 m_dwCookie
, m_cRef
));
186 // COM rules say we must protect against re-entrancy.
187 // If we are an aggregator and we hold our own interfaces
188 // on the aggregatee, the QI for these interfaces will
189 // addref ourselves. So after doing the QI we must release
190 // a ref count on ourselves. Then, before releasing the
191 // private interface, we must addref ourselves. When we do
192 // this from the destructor here it will result in the ref
193 // count going to 1 and then back to 0 causing us to
194 // re-enter the destructor. Hence we add an extra refcount here
195 // once we know we will delete the object.
196 // for an example aggregator see filgraph\distrib.cpp.
203 return ourmax(ULONG(m_cRef
), 1ul);
208 /* Return an interface pointer to a requesting client
209 performing a thread safe AddRef as necessary */
211 STDAPI
GetInterface(LPUNKNOWN pUnk
, void **ppv
)
213 CheckPointer(ppv
, E_POINTER
);
220 /* Compares two interfaces and returns TRUE if they are on the same object */
222 BOOL WINAPI
IsEqualObject(IUnknown
*pFirst
, IUnknown
*pSecond
)
224 /* Different objects can't have the same interface pointer for
227 if (pFirst
== pSecond
) {
230 /* OK - do it the hard way - check if they have the same
231 IUnknown pointers - a single object can only have one of these
233 LPUNKNOWN pUnknown1
; // Retrieve the IUnknown interface
234 LPUNKNOWN pUnknown2
; // Retrieve the other IUnknown interface
235 HRESULT hr
; // General OLE return code
240 /* See if the IUnknown pointers match */
242 hr
= pFirst
->QueryInterface(IID_IUnknown
,(void **) &pUnknown1
);
243 ASSERT(SUCCEEDED(hr
));
246 hr
= pSecond
->QueryInterface(IID_IUnknown
,(void **) &pUnknown2
);
247 ASSERT(SUCCEEDED(hr
));
250 /* Release the extra interfaces we hold */
252 pUnknown1
->Release();
253 pUnknown2
->Release();
254 return (pUnknown1
== pUnknown2
);