combase.cpp 7.8 KB

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