combase.cpp 7.4 KB

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