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.

124 lines
3.4 KiB

  1. #include "stock.h"
  2. #pragma hdrstop
  3. #include "caggunk.h"
  4. ULONG CAggregatedUnknown::AddRef()
  5. {
  6. return _punkAgg->AddRef();
  7. }
  8. ULONG CAggregatedUnknown::Release()
  9. {
  10. return _punkAgg->Release();
  11. }
  12. HRESULT CAggregatedUnknown::QueryInterface(REFIID riid, void **ppvObj)
  13. {
  14. return _punkAgg->QueryInterface(riid, ppvObj);
  15. }
  16. HRESULT CAggregatedUnknown::CUnkInner::QueryInterface(REFIID riid, void **ppvObj)
  17. {
  18. if (IsEqualIID(riid, IID_IUnknown))
  19. {
  20. *ppvObj = SAFECAST(this, IUnknown*);
  21. InterlockedIncrement(&_cRef);
  22. return S_OK;
  23. }
  24. CAggregatedUnknown* pparent = IToClass(CAggregatedUnknown, _unkInner, this);
  25. return pparent->v_InternalQueryInterface(riid, ppvObj);
  26. }
  27. ULONG CAggregatedUnknown::CUnkInner::AddRef(void)
  28. {
  29. return InterlockedIncrement(&_cRef);
  30. }
  31. ULONG CAggregatedUnknown::CUnkInner::Release(void)
  32. {
  33. ASSERT( 0 != _cRef );
  34. ULONG cRef = InterlockedDecrement(&_cRef);
  35. if ( 0 == cRef )
  36. {
  37. CAggregatedUnknown* pparent = IToClass(CAggregatedUnknown, _unkInner, this);
  38. if (!pparent->v_HandleDelete(&_cRef))
  39. {
  40. _cRef = 1000; // protect against cached pointers bumping us up then down
  41. delete pparent;
  42. }
  43. }
  44. return cRef;
  45. }
  46. CAggregatedUnknown::CAggregatedUnknown(IUnknown* punkAgg)
  47. {
  48. _punkAgg = punkAgg ? punkAgg : &_unkInner;
  49. }
  50. CAggregatedUnknown::~CAggregatedUnknown()
  51. {
  52. }
  53. //
  54. // Convert our controlling unknown to its canonical IUnknown *without*
  55. // altering the reference count on the outer object.
  56. //
  57. // This is critical in order for QueryOuterInterface to work properly.
  58. //
  59. // Returns NULL if something horrible went wrong.
  60. //
  61. // OLE Magic: Since objects are required also to return the canonical
  62. // IUnknown in response to any QI(IUnknown), it follows that the canonical
  63. // IUnknown remains valid so long as there are any outstanding references
  64. // to the object. In other words, you can Release() the canonical IUnknown
  65. // and the pointer remains valid so long as you keep the object alive by
  66. // other means.
  67. //
  68. // Believe it or not, this is a feature. It's in the book!
  69. //
  70. IUnknown *CAggregatedUnknown::_GetCanonicalOuter(void)
  71. {
  72. IUnknown *punkAggCanon;
  73. HRESULT hres = _punkAgg->QueryInterface(IID_IUnknown, (void **)&punkAggCanon);
  74. if (SUCCEEDED(hres))
  75. {
  76. punkAggCanon->Release(); // see "OLE Magic" comment above
  77. return punkAggCanon;
  78. }
  79. else
  80. {
  81. // The outer object is most likely some other shell component,
  82. // so let's ASSERT so whoever owns the outer component will fix it.
  83. ASSERT(!"The outer object's implementation of QI(IUnknown) is broken.");
  84. return NULL;
  85. }
  86. }
  87. void CAggregatedUnknown::_ReleaseOuterInterface(IUnknown** ppunk)
  88. {
  89. ASSERT(IS_VALID_CODE_PTR(_punkAgg, IUnknown));
  90. IUnknown *punkAggCanon = _GetCanonicalOuter(); // non-refcounted pointer
  91. //
  92. // SHReleaseOuterInterface can handle punkAggCanon == NULL
  93. //
  94. SHReleaseOuterInterface(punkAggCanon, ppunk);
  95. }
  96. HRESULT CAggregatedUnknown::_QueryOuterInterface(REFIID riid, void ** ppvOut)
  97. {
  98. IUnknown *punkAggCanon = _GetCanonicalOuter(); // non-refcounted pointer
  99. //
  100. // SHQueryOuterInterface can handle punkAggCanon == NULL.
  101. //
  102. return SHQueryOuterInterface(punkAggCanon, riid, ppvOut);
  103. }