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.

319 lines
5.8 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. //
  58. // This is used to take over ownership from a dumb pointer so that you
  59. // don't have to remember to call Release on the dumb pointer.
  60. //
  61. // Example:
  62. //
  63. // SmartInterface<IFoo> smart(0);
  64. // IFoo* dumb = 0;
  65. //
  66. // HRESULT hr =
  67. // ::YourGetDumbPointerCall(
  68. // __uuidof(IFoo),
  69. // reinterpret_cast<void**>(&dumb));
  70. // BREAK_ON_FAILED_HRESULT(hr);
  71. //
  72. // smart.Acquire(dumb);
  73. //
  74. // Don't call dumb->Release(), when smart dies it will release the
  75. // pointer.
  76. void
  77. Acquire(T* p)
  78. {
  79. ASSERT(!ptr);
  80. ptr = p;
  81. }
  82. HRESULT
  83. AcquireViaQueryInterface(IUnknown& i)
  84. {
  85. return AcquireViaQueryInterface(i, __uuidof(T));
  86. }
  87. // fallback for those interfaces that are not
  88. // declared w/ __declspec(uuid())
  89. HRESULT
  90. AcquireViaQueryInterface(IUnknown& i, const IID& interfaceDesired)
  91. {
  92. ASSERT(!ptr);
  93. HRESULT hr =
  94. i.QueryInterface(interfaceDesired, reinterpret_cast<void**>(&ptr));
  95. // don't assert success, since we might just be testing to see
  96. // if an interface is available.
  97. return hr;
  98. }
  99. HRESULT
  100. AcquireViaCreateInstance(
  101. const CLSID& classID,
  102. IUnknown* unknownOuter,
  103. DWORD classExecutionContext)
  104. {
  105. return
  106. AcquireViaCreateInstance(
  107. classID,
  108. unknownOuter,
  109. classExecutionContext,
  110. __uuidof(T));
  111. }
  112. // fallback for those interfaces that are not
  113. // declared w/ __declspec(uuid())
  114. HRESULT
  115. AcquireViaCreateInstance(
  116. const CLSID& classID,
  117. IUnknown* unknownOuter,
  118. DWORD classExecutionContext,
  119. const IID& interfaceDesired)
  120. {
  121. ASSERT(!ptr);
  122. HRESULT hr =
  123. // REVIEWED-2002/02/18-sburns
  124. // Callers of this function should make sure the flags do not allow for
  125. // an out-of-proc create if the class only supports in-proc.
  126. ::CoCreateInstance(
  127. classID,
  128. unknownOuter,
  129. classExecutionContext,
  130. interfaceDesired,
  131. reinterpret_cast<void**>(&ptr));
  132. return hr;
  133. }
  134. void
  135. Relinquish()
  136. {
  137. if (ptr)
  138. {
  139. ptr->Release();
  140. ptr = 0;
  141. }
  142. }
  143. operator T*() const
  144. {
  145. return ptr;
  146. }
  147. // this allows SmartInterface instances to be passed as the first
  148. // parameter to AquireViaQueryInterface. Note that this is a conversion
  149. // to IUnknown&, not IUnknown*. An operator IUnknown* would be ambiguous
  150. // with respect to operator T*.
  151. //
  152. // (does not return a const IUnknown&, as COM interfaces are not const
  153. // aware.)
  154. operator IUnknown&() const
  155. {
  156. ASSERT(ptr);
  157. return *(static_cast<IUnknown*>(ptr));
  158. }
  159. // don't appear to need this: less is better.
  160. // T&
  161. // operator*()
  162. // {
  163. // ASSERT(ptr);
  164. // return *ptr;
  165. // }
  166. T*
  167. operator->() const
  168. {
  169. ASSERT(ptr);
  170. return ptr;
  171. }
  172. T*
  173. operator=(T* rhs)
  174. {
  175. ASSERT(rhs);
  176. if (ptr != rhs)
  177. {
  178. Relinquish();
  179. ptr = rhs;
  180. if (ptr)
  181. {
  182. ptr->AddRef();
  183. }
  184. }
  185. return ptr;
  186. }
  187. // This is required by some STL container classes.
  188. const SmartInterface<T>&
  189. operator=(const SmartInterface<T>& rhs)
  190. {
  191. this->operator=(rhs.ptr);
  192. return *this;
  193. }
  194. // // This might be a good idea, but std::list.erase chokes on it.
  195. // ISSUE-2002/03/26-sburns maybe that's fixed w/ VS 7?
  196. //
  197. // T**
  198. // operator& ()
  199. // {
  200. // ASSERT(!ptr);
  201. //
  202. // if (ptr)
  203. // {
  204. // return &ptr;
  205. // }
  206. // else
  207. // {
  208. // return 0;
  209. // }
  210. // }
  211. private:
  212. #ifdef DBG
  213. // Some code that takes the address of an instance of this class is working
  214. // by happy coincidence: that taking the address of an instance yields the
  215. // same address as the ptr member. For chk builds, I am deliberately
  216. // breaking that code by inserting a dummy guard value, so that &i != i.ptr
  217. //
  218. // You should not try to take the address of a SmartInterface in order to
  219. // access the internal pointer. You should instead use one of the Acquire
  220. // methods, or use a dumb pointer and then acquire it. Under no
  221. // circumstances will we allow access to our internal state!
  222. int ptrGuard;
  223. #endif
  224. T* ptr;
  225. };
  226. } // namespace Burnslib
  227. #endif // SMARTPTR_HPP_INCLUDED