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.

233 lines
3.6 KiB

  1. // Copyright (c) 1997-1999 Microsoft Corporation
  2. //
  3. // Smart (Interface) pointer class
  4. //
  5. // copied from admin\burnslib\inc\smartptr.hpp
  6. #ifndef SMARTPTR_HPP_INCLUDED
  7. #define SMARTPTR_HPP_INCLUDED
  8. // Requires that T derive from IUnknown
  9. template <class T>
  10. class SmartInterface
  11. {
  12. public:
  13. // need default ctor if we are to use STL containers to hold SmartInterfaces
  14. SmartInterface() : ptr(0)
  15. {
  16. }
  17. explicit
  18. SmartInterface(T* p)
  19. {
  20. // don't assert(p), since construction w/ 0 is legal.
  21. ptr = p;
  22. if (ptr)
  23. {
  24. ptr->AddRef();
  25. }
  26. }
  27. SmartInterface(const SmartInterface<T>& s)
  28. {
  29. // makes no sense to pass null pointers
  30. ASSERT(s.ptr);
  31. ptr = s.ptr;
  32. if (ptr)
  33. {
  34. ptr->AddRef();
  35. }
  36. }
  37. ~SmartInterface()
  38. {
  39. Relinquish();
  40. }
  41. // Aquire means "take over from a dumb pointer, but don't AddRef it."
  42. void
  43. Acquire(T* p)
  44. {
  45. ASSERT(!ptr);
  46. ptr = p;
  47. }
  48. HRESULT
  49. AcquireViaQueryInterface(IUnknown& i)
  50. {
  51. return AcquireViaQueryInterface(i, __uuidof(T));
  52. }
  53. // fallback for those interfaces that are not
  54. // declared w/ __declspec(uuid())
  55. HRESULT
  56. AcquireViaQueryInterface(IUnknown& i, const IID& interfaceDesired)
  57. {
  58. ASSERT(!ptr);
  59. HRESULT hr =
  60. i.QueryInterface(interfaceDesired, reinterpret_cast<void**>(&ptr));
  61. // don't assert success, since we might just be testing to see
  62. // if an interface is available.
  63. return hr;
  64. }
  65. HRESULT
  66. AcquireViaCreateInstance(
  67. const CLSID& classID,
  68. IUnknown* unknownOuter,
  69. DWORD classExecutionContext)
  70. {
  71. return
  72. AcquireViaCreateInstance(
  73. classID,
  74. unknownOuter,
  75. classExecutionContext,
  76. __uuidof(T));
  77. }
  78. // fallback for those interfaces that are not
  79. // declared w/ __declspec(uuid())
  80. HRESULT
  81. AcquireViaCreateInstance(
  82. const CLSID& classID,
  83. IUnknown* unknownOuter,
  84. DWORD classExecutionContext,
  85. const IID& interfaceDesired)
  86. {
  87. ASSERT(!ptr);
  88. HRESULT hr =
  89. ::CoCreateInstance(
  90. classID,
  91. unknownOuter,
  92. classExecutionContext,
  93. interfaceDesired,
  94. reinterpret_cast<void**>(&ptr));
  95. ASSERT(SUCCEEDED(hr));
  96. return hr;
  97. }
  98. void
  99. Relinquish()
  100. {
  101. if (ptr)
  102. {
  103. ptr->Release();
  104. ptr = 0;
  105. }
  106. }
  107. operator T*() const
  108. {
  109. return ptr;
  110. }
  111. // this allows SmartInterface instances to be passed as the first
  112. // parameter to AquireViaQueryInterface. Note that this is a conversion
  113. // to IUnknown&, not IUnknown*. An operator IUnknown* would be ambiguous
  114. // with respect to operator T*.
  115. operator IUnknown&() const
  116. {
  117. ASSERT(ptr);
  118. return *(static_cast<IUnknown*>(ptr));
  119. }
  120. // don't appear to need this: less is better.
  121. // T&
  122. // operator*()
  123. // {
  124. // ASSERT(ptr);
  125. // return *ptr;
  126. // }
  127. T*
  128. operator->() const
  129. {
  130. ASSERT(ptr);
  131. return ptr;
  132. }
  133. T*
  134. operator=(T* rhs)
  135. {
  136. ASSERT(rhs);
  137. if (ptr != rhs)
  138. {
  139. Relinquish();
  140. ptr = rhs;
  141. if (ptr)
  142. {
  143. ptr->AddRef();
  144. }
  145. }
  146. return ptr;
  147. }
  148. // This is required by some STL container classes.
  149. const SmartInterface<T>&
  150. operator=(const SmartInterface<T>& rhs)
  151. {
  152. this->operator=(rhs.ptr);
  153. return *this;
  154. }
  155. private:
  156. T* ptr;
  157. };
  158. #endif // SMARTPTR_HPP_INCLUDED