blob: bf7e351270114e68f70fd0983c83d33c973a7f20 [file] [log] [blame]
Sauw Ming93ba7fe2012-04-18 02:38:42 +00001//------------------------------------------------------------------------------
2// File: ComBase.cpp
3//
4// Desc: DirectShow base classes - implements class hierarchy for creating
5// COM objects.
6//
7// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
8//------------------------------------------------------------------------------
9
Nanang Izzuddinc46d1152012-04-24 07:07:39 +000010#include <pjmedia-videodev/config.h>
11
12#if defined(PJMEDIA_VIDEO_DEV_HAS_DSHOW) && PJMEDIA_VIDEO_DEV_HAS_DSHOW != 0
Sauw Ming93ba7fe2012-04-18 02:38:42 +000013
14#include <streams.h>
15#pragma warning( disable : 4514 ) // Disable warnings re unused inline functions
16
17
18/* Define the static member variable */
19
20LONG CBaseObject::m_cObjects = 0;
21
22
23/* Constructor */
24
25CBaseObject::CBaseObject(__in_opt LPCTSTR pName)
26{
27 /* Increment the number of active objects */
28 InterlockedIncrement(&m_cObjects);
29
30#ifdef DEBUG
31
32#ifdef UNICODE
33 m_dwCookie = DbgRegisterObjectCreation(0, pName);
34#else
35 m_dwCookie = DbgRegisterObjectCreation(pName, 0);
36#endif
37
38#endif
39}
40
41#ifdef UNICODE
42CBaseObject::CBaseObject(const char *pName)
43{
44 /* Increment the number of active objects */
45 InterlockedIncrement(&m_cObjects);
46
47#ifdef DEBUG
48 m_dwCookie = DbgRegisterObjectCreation(pName, 0);
49#endif
50}
51#endif
52
53HINSTANCE hlibOLEAut32;
54
55/* Destructor */
56
57CBaseObject::~CBaseObject()
58{
59 /* Decrement the number of objects active */
60 if (InterlockedDecrement(&m_cObjects) == 0) {
61 if (hlibOLEAut32) {
62 FreeLibrary(hlibOLEAut32);
63
64 hlibOLEAut32 = 0;
65 }
66 };
67
68
69#ifdef DEBUG
70 DbgRegisterObjectDestruction(m_dwCookie);
71#endif
72}
73
74static const TCHAR szOle32Aut[] = TEXT("OleAut32.dll");
75
76HINSTANCE LoadOLEAut32()
77{
78 if (hlibOLEAut32 == 0) {
79
80 hlibOLEAut32 = LoadLibrary(szOle32Aut);
81 }
82
83 return hlibOLEAut32;
84}
85
86
87/* Constructor */
88
89// We know we use "this" in the initialization list, we also know we don't modify *phr.
90#pragma warning( disable : 4355 4100 )
91CUnknown::CUnknown(__in_opt LPCTSTR pName, __in_opt LPUNKNOWN pUnk)
92: CBaseObject(pName)
93/* Start the object with a reference count of zero - when the */
94/* object is queried for it's first interface this may be */
95/* incremented depending on whether or not this object is */
96/* currently being aggregated upon */
97, m_cRef(0)
98/* Set our pointer to our IUnknown interface. */
99/* If we have an outer, use its, otherwise use ours. */
100/* This pointer effectivly points to the owner of */
101/* this object and can be accessed by the GetOwner() method. */
102, m_pUnknown( pUnk != 0 ? pUnk : reinterpret_cast<LPUNKNOWN>( static_cast<PNDUNKNOWN>(this) ) )
103 /* Why the double cast? Well, the inner cast is a type-safe cast */
104 /* to pointer to a type from which we inherit. The second is */
105 /* type-unsafe but works because INonDelegatingUnknown "behaves */
106 /* like" IUnknown. (Only the names on the methods change.) */
107{
108 // Everything we need to do has been done in the initializer list
109}
110
111// This does the same as above except it has a useless HRESULT argument
112// use the previous constructor, this is just left for compatibility...
113CUnknown::CUnknown(__in_opt LPCTSTR pName, __in_opt LPUNKNOWN pUnk, __inout_opt HRESULT *phr) :
114 CBaseObject(pName),
115 m_cRef(0),
116 m_pUnknown( pUnk != 0 ? pUnk : reinterpret_cast<LPUNKNOWN>( static_cast<PNDUNKNOWN>(this) ) )
117{
118}
119
120#ifdef UNICODE
121CUnknown::CUnknown(__in_opt LPCSTR pName, __in_opt LPUNKNOWN pUnk)
122: CBaseObject(pName), m_cRef(0),
123 m_pUnknown( pUnk != 0 ? pUnk : reinterpret_cast<LPUNKNOWN>( static_cast<PNDUNKNOWN>(this) ) )
124{ }
125
126CUnknown::CUnknown(__in_opt LPCSTR pName, __in_opt LPUNKNOWN pUnk, __inout_opt HRESULT *phr) :
127 CBaseObject(pName), m_cRef(0),
128 m_pUnknown( pUnk != 0 ? pUnk : reinterpret_cast<LPUNKNOWN>( static_cast<PNDUNKNOWN>(this) ) )
129{ }
130
131#endif
132
133#pragma warning( default : 4355 4100 )
134
135
136/* QueryInterface */
137
138STDMETHODIMP CUnknown::NonDelegatingQueryInterface(REFIID riid, __deref_out void ** ppv)
139{
140 CheckPointer(ppv,E_POINTER);
141 ValidateReadWritePtr(ppv,sizeof(PVOID));
142
143 /* We know only about IUnknown */
144
145 if (riid == IID_IUnknown) {
146 GetInterface((LPUNKNOWN) (PNDUNKNOWN) this, ppv);
147 return NOERROR;
148 } else {
149 *ppv = NULL;
150 return E_NOINTERFACE;
151 }
152}
153
154/* We have to ensure that we DON'T use a max macro, since these will typically */
155/* lead to one of the parameters being evaluated twice. Since we are worried */
156/* about concurrency, we can't afford to access the m_cRef twice since we can't */
157/* afford to run the risk that its value having changed between accesses. */
158
159template<class T> inline static T ourmax( const T & a, const T & b )
160{
161 return a > b ? a : b;
162}
163
164/* AddRef */
165
166STDMETHODIMP_(ULONG) CUnknown::NonDelegatingAddRef()
167{
168 LONG lRef = InterlockedIncrement( &m_cRef );
169 ASSERT(lRef > 0);
170 DbgLog((LOG_MEMORY,3,TEXT(" Obj %d ref++ = %d"),
171 m_dwCookie, m_cRef));
172 return ourmax(ULONG(m_cRef), 1ul);
173}
174
175
176/* Release */
177
178STDMETHODIMP_(ULONG) CUnknown::NonDelegatingRelease()
179{
180 /* If the reference count drops to zero delete ourselves */
181
182 LONG lRef = InterlockedDecrement( &m_cRef );
183 ASSERT(lRef >= 0);
184
185 DbgLog((LOG_MEMORY,3,TEXT(" Object %d ref-- = %d"),
186 m_dwCookie, m_cRef));
187 if (lRef == 0) {
188
189 // COM rules say we must protect against re-entrancy.
190 // If we are an aggregator and we hold our own interfaces
191 // on the aggregatee, the QI for these interfaces will
192 // addref ourselves. So after doing the QI we must release
193 // a ref count on ourselves. Then, before releasing the
194 // private interface, we must addref ourselves. When we do
195 // this from the destructor here it will result in the ref
196 // count going to 1 and then back to 0 causing us to
197 // re-enter the destructor. Hence we add an extra refcount here
198 // once we know we will delete the object.
199 // for an example aggregator see filgraph\distrib.cpp.
200
201 m_cRef++;
202
203 delete this;
204 return ULONG(0);
205 } else {
206 // Don't touch m_cRef again even in this leg as the object
207 // may have just been released on another thread too
208 return ourmax(ULONG(lRef), 1ul);
209 }
210}
211
212
213/* Return an interface pointer to a requesting client
214 performing a thread safe AddRef as necessary */
215
216STDAPI GetInterface(LPUNKNOWN pUnk, __out void **ppv)
217{
218 CheckPointer(ppv, E_POINTER);
219 *ppv = pUnk;
220 pUnk->AddRef();
221 return NOERROR;
222}
223
224
225/* Compares two interfaces and returns TRUE if they are on the same object */
226
227BOOL WINAPI IsEqualObject(IUnknown *pFirst, IUnknown *pSecond)
228{
229 /* Different objects can't have the same interface pointer for
230 any interface
231 */
232 if (pFirst == pSecond) {
233 return TRUE;
234 }
235 /* OK - do it the hard way - check if they have the same
236 IUnknown pointers - a single object can only have one of these
237 */
238 LPUNKNOWN pUnknown1; // Retrieve the IUnknown interface
239 LPUNKNOWN pUnknown2; // Retrieve the other IUnknown interface
240 HRESULT hr; // General OLE return code
241
242 ASSERT(pFirst);
243 ASSERT(pSecond);
244
245 /* See if the IUnknown pointers match */
246
247 hr = pFirst->QueryInterface(IID_IUnknown,(void **) &pUnknown1);
248 if (FAILED(hr)) {
249 return FALSE;
250 }
251 ASSERT(pUnknown1);
252
253 /* Release the extra interface we hold */
254
255 pUnknown1->Release();
256
257 hr = pSecond->QueryInterface(IID_IUnknown,(void **) &pUnknown2);
258 if (FAILED(hr)) {
259 return FALSE;
260 }
261 ASSERT(pUnknown2);
262
263 /* Release the extra interface we hold */
264
265 pUnknown2->Release();
266 return (pUnknown1 == pUnknown2);
267}
268
Nanang Izzuddinc46d1152012-04-24 07:07:39 +0000269#endif /* PJMEDIA_VIDEO_DEV_HAS_DSHOW */