Leaked source code of windows server 2003
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.

186 lines
5.9 KiB

  1. //==========================================================================;
  2. //
  3. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
  4. // KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  5. // IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
  6. // PURPOSE.
  7. //
  8. // Copyright (c) 1992 - 1998 Microsoft Corporation. All Rights Reserved.
  9. //
  10. //--------------------------------------------------------------------------;
  11. // Base class hierachy for creating COM objects, December 1994
  12. #include "dmocom.h"
  13. #include <crtdbg.h>
  14. #pragma warning( disable : 4514 ) // Disable warnings re unused inline functions
  15. /* Constructor */
  16. // We know we use "this" in the initialization list, we also know we don't modify *phr.
  17. #pragma warning( disable : 4355 4100 )
  18. CComBase::CComBase(IUnknown* pUnk)
  19. :
  20. /* Start the object with a reference count of zero - when the */
  21. /* object is queried for it's first interface this may be */
  22. /* incremented depending on whether or not this object is */
  23. /* currently being aggregated upon */
  24. m_cRef(0)
  25. /* Set our pointer to our IUnknown interface. */
  26. /* If we have an outer, use its, otherwise use ours. */
  27. /* This pointer effectivly points to the owner of */
  28. /* this object and can be accessed by the GetOwner() method. */
  29. , m_pUnknown( pUnk != 0 ? pUnk : reinterpret_cast<IUnknown*>( static_cast<INDUnknown*>(this) ) )
  30. /* Why the double cast? Well, the inner cast is a type-safe cast */
  31. /* to pointer to a type from which we inherit. The second is */
  32. /* type-unsafe but works because INDUnknown "behaves */
  33. /* like" IUnknown. (Only the names on the methods change.) */
  34. {
  35. // Everything we need to do has been done in the initializer list
  36. }
  37. // This does the same as above except it has a useless HRESULT argument
  38. // use the previous constructor, this is just left for compatibility...
  39. CComBase::CComBase(IUnknown* pUnk,HRESULT *phr) :
  40. m_cRef(0),
  41. m_pUnknown( pUnk != 0 ? pUnk : reinterpret_cast<IUnknown*>( static_cast<INDUnknown*>(this) ) )
  42. {
  43. }
  44. #pragma warning( default : 4355 4100 )
  45. /* QueryInterface */
  46. STDMETHODIMP CComBase::NDQueryInterface(REFIID riid, void ** ppv)
  47. {
  48. CheckPointer(ppv,E_POINTER);
  49. //ValidateReadWritePtr(ppv,sizeof(PVOID));
  50. /* We know only about IUnknown */
  51. if (riid == IID_IUnknown) {
  52. GetInterface((IUnknown*) (INDUnknown*) this, ppv);
  53. return NOERROR;
  54. } else {
  55. *ppv = NULL;
  56. return E_NOINTERFACE;
  57. }
  58. }
  59. /* We have to ensure that we DON'T use a max macro, since these will typically */
  60. /* lead to one of the parameters being evaluated twice. Since we are worried */
  61. /* about concurrency, we can't afford to access the m_cRef twice since we can't */
  62. /* afford to run the risk that its value having changed between accesses. */
  63. #ifdef max
  64. #undef max
  65. #endif
  66. template<class T> inline static T max( const T & a, const T & b )
  67. {
  68. return a > b ? a : b;
  69. }
  70. /* AddRef */
  71. STDMETHODIMP_(ULONG) CComBase::NDAddRef()
  72. {
  73. LONG lRef = InterlockedIncrement( &m_cRef );
  74. _ASSERTE(lRef > 0);
  75. /*
  76. DbgLog((LOG_MEMORY,3,TEXT(" Obj %d ref++ = %d"),
  77. m_dwCookie, m_cRef));
  78. */
  79. return max(ULONG(m_cRef), 1ul);
  80. }
  81. /* Release */
  82. STDMETHODIMP_(ULONG) CComBase::NDRelease()
  83. {
  84. /* If the reference count drops to zero delete ourselves */
  85. LONG lRef = InterlockedDecrement( &m_cRef );
  86. _ASSERTE(lRef >= 0);
  87. /*
  88. DbgLog((LOG_MEMORY,3,TEXT(" Object %d ref-- = %d"),
  89. m_dwCookie, m_cRef));
  90. */
  91. if (lRef == 0) {
  92. // COM rules say we must protect against re-entrancy.
  93. // If we are an aggregator and we hold our own interfaces
  94. // on the aggregatee, the QI for these interfaces will
  95. // addref ourselves. So after doing the QI we must release
  96. // a ref count on ourselves. Then, before releasing the
  97. // private interface, we must addref ourselves. When we do
  98. // this from the destructor here it will result in the ref
  99. // count going to 1 and then back to 0 causing us to
  100. // re-enter the destructor. Hence we add an extra refcount here
  101. // once we know we will delete the object.
  102. // for an example aggregator see filgraph\distrib.cpp.
  103. m_cRef++;
  104. delete this;
  105. return ULONG(0);
  106. } else {
  107. return max(ULONG(m_cRef), 1ul);
  108. }
  109. }
  110. /* Return an interface pointer to a requesting client
  111. performing a thread safe AddRef as necessary */
  112. STDAPI GetInterface(IUnknown* pUnk, void **ppv)
  113. {
  114. CheckPointer(ppv, E_POINTER);
  115. *ppv = pUnk;
  116. pUnk->AddRef();
  117. return NOERROR;
  118. }
  119. /* Compares two interfaces and returns TRUE if they are on the same object */
  120. BOOL WINAPI IsEqualObject(IUnknown *pFirst, IUnknown *pSecond)
  121. {
  122. /* Different objects can't have the same interface pointer for
  123. any interface
  124. */
  125. if (pFirst == pSecond) {
  126. return TRUE;
  127. }
  128. /* OK - do it the hard way - check if they have the same
  129. IUnknown pointers - a single object can only have one of these
  130. */
  131. IUnknown* pUnknown1; // Retrieve the IUnknown interface
  132. IUnknown* pUnknown2; // Retrieve the other IUnknown interface
  133. HRESULT hr; // General OLE return code
  134. _ASSERTE(pFirst);
  135. _ASSERTE(pSecond);
  136. /* See if the IUnknown pointers match */
  137. hr = pFirst->QueryInterface(IID_IUnknown,(void **) &pUnknown1);
  138. _ASSERTE(SUCCEEDED(hr));
  139. _ASSERTE(pUnknown1);
  140. hr = pSecond->QueryInterface(IID_IUnknown,(void **) &pUnknown2);
  141. _ASSERTE(SUCCEEDED(hr));
  142. _ASSERTE(pUnknown2);
  143. /* Release the extra interfaces we hold */
  144. pUnknown1->Release();
  145. pUnknown2->Release();
  146. return (pUnknown1 == pUnknown2);
  147. }