Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

261 lines
7.2 KiB

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