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.

277 lines
4.5 KiB

  1. // Copyright (c) 1997-1999 Microsoft Corporation
  2. //
  3. // Smart (Interface) pointer class
  4. //
  5. // 9-25-97 sburns
  6. #ifndef SMARTPTR_HPP_INCLUDED
  7. #define SMARTPTR_HPP_INCLUDED
  8. namespace Burnslib
  9. {
  10. // Requires that T derive from IUnknown
  11. template <class T>
  12. class SmartInterface
  13. {
  14. public:
  15. // need default ctor if we are to use STL containers to hold SmartInterfaces
  16. SmartInterface()
  17. :
  18. #ifdef DBG
  19. ptrGuard(0xDDDDDDDD),
  20. #endif
  21. ptr(0)
  22. {
  23. }
  24. explicit
  25. SmartInterface(T* p)
  26. #ifdef DBG
  27. :
  28. ptrGuard(0xDDDDDDDD)
  29. #endif
  30. {
  31. // don't assert(p), since construction w/ 0 is legal.
  32. ptr = p;
  33. if (ptr)
  34. {
  35. ptr->AddRef();
  36. }
  37. }
  38. SmartInterface(const SmartInterface<T>& s)
  39. #ifdef DBG
  40. :
  41. ptrGuard(0xDDDDDDDD)
  42. #endif
  43. {
  44. // makes no sense to pass null pointers
  45. ASSERT(s.ptr);
  46. ptr = s.ptr;
  47. if (ptr)
  48. {
  49. ptr->AddRef();
  50. }
  51. }
  52. ~SmartInterface()
  53. {
  54. Relinquish();
  55. }
  56. // Aquire means "take over from a dumb pointer, but don't AddRef it."
  57. void
  58. Acquire(T* p)
  59. {
  60. ASSERT(!ptr);
  61. ptr = p;
  62. }
  63. HRESULT
  64. AcquireViaQueryInterface(IUnknown& i)
  65. {
  66. return AcquireViaQueryInterface(i, __uuidof(T));
  67. }
  68. // fallback for those interfaces that are not
  69. // declared w/ __declspec(uuid())
  70. HRESULT
  71. AcquireViaQueryInterface(IUnknown& i, const IID& interfaceDesired)
  72. {
  73. ASSERT(!ptr);
  74. HRESULT hr =
  75. i.QueryInterface(interfaceDesired, reinterpret_cast<void**>(&ptr));
  76. // don't assert success, since we might just be testing to see
  77. // if an interface is available.
  78. return hr;
  79. }
  80. HRESULT
  81. AcquireViaCreateInstance(
  82. const CLSID& classID,
  83. IUnknown* unknownOuter,
  84. DWORD classExecutionContext)
  85. {
  86. return
  87. AcquireViaCreateInstance(
  88. classID,
  89. unknownOuter,
  90. classExecutionContext,
  91. __uuidof(T));
  92. }
  93. // fallback for those interfaces that are not
  94. // declared w/ __declspec(uuid())
  95. HRESULT
  96. AcquireViaCreateInstance(
  97. const CLSID& classID,
  98. IUnknown* unknownOuter,
  99. DWORD classExecutionContext,
  100. const IID& interfaceDesired)
  101. {
  102. ASSERT(!ptr);
  103. HRESULT hr =
  104. ::CoCreateInstance(
  105. classID,
  106. unknownOuter,
  107. classExecutionContext,
  108. interfaceDesired,
  109. reinterpret_cast<void**>(&ptr));
  110. ASSERT(SUCCEEDED(hr));
  111. return hr;
  112. }
  113. void
  114. Relinquish()
  115. {
  116. if (ptr)
  117. {
  118. ptr->Release();
  119. ptr = 0;
  120. }
  121. }
  122. operator T*() const
  123. {
  124. return ptr;
  125. }
  126. // this allows SmartInterface instances to be passed as the first
  127. // parameter to AquireViaQueryInterface. Note that this is a conversion
  128. // to IUnknown&, not IUnknown*. An operator IUnknown* would be ambiguous
  129. // with respect to operator T*.
  130. //
  131. // (does not return a const IUnknown&, as COM interfaces are not const
  132. // aware.)
  133. operator IUnknown&() const
  134. {
  135. ASSERT(ptr);
  136. return *(static_cast<IUnknown*>(ptr));
  137. }
  138. // don't appear to need this: less is better.
  139. // T&
  140. // operator*()
  141. // {
  142. // ASSERT(ptr);
  143. // return *ptr;
  144. // }
  145. T*
  146. operator->() const
  147. {
  148. ASSERT(ptr);
  149. return ptr;
  150. }
  151. T*
  152. operator=(T* rhs)
  153. {
  154. ASSERT(rhs);
  155. if (ptr != rhs)
  156. {
  157. Relinquish();
  158. ptr = rhs;
  159. if (ptr)
  160. {
  161. ptr->AddRef();
  162. }
  163. }
  164. return ptr;
  165. }
  166. // This is required by some STL container classes.
  167. const SmartInterface<T>&
  168. operator=(const SmartInterface<T>& rhs)
  169. {
  170. this->operator=(rhs.ptr);
  171. return *this;
  172. }
  173. private:
  174. #ifdef DBG
  175. // Some code that takes the address of an instance of this class is working
  176. // by happy coincidence: that taking the address of an instance yields the
  177. // same address as the ptr member. For chk builds, I am deliberately
  178. // breaking that code by inserting a dummy guard value, so that &i != i.ptr
  179. //
  180. // You should not try to take the address of a SmartInterface in order to
  181. // access the internal pointer. You should instead use one of the Acquire
  182. // methods, or use a dumb pointer and then acquire it. Under no
  183. // circumstances will we allow access to our internal state!
  184. int ptrGuard;
  185. #endif
  186. T* ptr;
  187. };
  188. } // namespace Burnslib
  189. #endif // SMARTPTR_HPP_INCLUDED