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.

240 lines
6.6 KiB

  1. #ifndef _REFHANDLE_H_
  2. #define _REFHANDLE_H_
  3. // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  4. //
  5. // REFHANDLE.H
  6. //
  7. // Copyright 1999 Microsoft Corporation, All Rights Reserved
  8. //
  9. #include <ex\refcnt.h>
  10. #include <ex\autoptr.h>
  11. // ========================================================================
  12. //
  13. // CLASS IRefHandle
  14. //
  15. // Implements a refcounted handle. AddRef() and Release() replace the
  16. // much slower in-process DuplicateHandle() calls.
  17. //
  18. // The reason for the interface is that handles may come from many sources
  19. // and it is not always clear what we should do once we are done with one
  20. // when the last ref goes away. In the most common case (where we own the
  21. // raw handle) we just want to call CloseHandle(). But we don't always own
  22. // the raw handle. When someone else owns the raw handle, we must use
  23. // their mechanisms to indicate when we are done using it. CIFSHandle in
  24. // davex\exifs.cpp is one such instance.
  25. //
  26. class IRefHandle : public CRefCountedObject
  27. {
  28. // NOT IMPLEMENTED
  29. //
  30. IRefHandle( const IRefHandle& );
  31. IRefHandle& operator=( const IRefHandle& );
  32. protected:
  33. // CREATORS
  34. // Only create this object through it's descendents!
  35. //
  36. IRefHandle()
  37. {
  38. //
  39. // Start the ref count at 1. The expectation is that we will
  40. // typically use constructs like this
  41. //
  42. // auto_ref_handle hf;
  43. // hf.take_ownership(new CFooRefHandle());
  44. //
  45. // or this
  46. //
  47. // auto_ref_ptr<IRefHandle> pRefHandle;
  48. // pRefHandle.take_ownership(new CFooRefHandle());
  49. //
  50. // when creating these objects.
  51. //
  52. m_cRef = 1;
  53. }
  54. public:
  55. // CREATORS
  56. //
  57. virtual ~IRefHandle() = 0 {}
  58. // ACCESSORS
  59. //
  60. virtual HANDLE Handle() const = 0;
  61. };
  62. // ========================================================================
  63. //
  64. // CLASS CRefHandle
  65. //
  66. // By far the most common form of a refcounted handle -- the one where we
  67. // own the raw HANDLE and must call CloseHandle() on it when we are done.
  68. //
  69. // This is implemented as a simple refcounted auto_handle.
  70. //
  71. class CRefHandle : public IRefHandle
  72. {
  73. //
  74. // The handle
  75. //
  76. auto_handle<HANDLE> m_h;
  77. // NOT IMPLEMENTED
  78. //
  79. CRefHandle( const CRefHandle& );
  80. CRefHandle& operator=( const CRefHandle& );
  81. public:
  82. // CREATORS
  83. //
  84. CRefHandle(auto_handle<HANDLE>& h)
  85. {
  86. // Take ownership of the passed-in auto_handle
  87. //
  88. *m_h.load() = h.relinquish();
  89. }
  90. // ACCESSORS
  91. //
  92. HANDLE Handle() const
  93. {
  94. return m_h;
  95. }
  96. };
  97. // ========================================================================
  98. //
  99. // CLASS auto_ref_handle
  100. //
  101. // Implements automatic refcounting on IRefHandle objects. The idea is
  102. // that an auto_ref_handle can be used in most cases to replace a raw
  103. // HANDLE. The main difference is that copying a raw HANDLE introduces
  104. // an issue of ownership, but copying an auto_ref_handle does not.
  105. // Typically, a raw handle is copied with an expensive DuplicateHandle()
  106. // call. Copying an auto_ref_handle just does a cheap AddRef().
  107. //
  108. class auto_ref_handle
  109. {
  110. auto_ref_ptr<IRefHandle> m_pRefHandle;
  111. public:
  112. // CREATORS
  113. //
  114. auto_ref_handle() {}
  115. auto_ref_handle(const auto_ref_handle& rhs)
  116. {
  117. m_pRefHandle = rhs.m_pRefHandle;
  118. }
  119. // ACCESSORS
  120. //
  121. HANDLE get() const
  122. {
  123. return m_pRefHandle.get() ? m_pRefHandle->Handle() : NULL;
  124. }
  125. // MANIPULATORS
  126. //
  127. auto_ref_handle& operator=(const auto_ref_handle& rhs)
  128. {
  129. if ( m_pRefHandle.get() != rhs.m_pRefHandle.get() )
  130. m_pRefHandle = rhs.m_pRefHandle;
  131. return *this;
  132. }
  133. VOID take_ownership(IRefHandle * pRefHandle)
  134. {
  135. Assert( !m_pRefHandle.get() );
  136. m_pRefHandle.take_ownership(pRefHandle);
  137. }
  138. // ------------------------------------------------------------------------
  139. //
  140. // auto_ref_handle::FCreate()
  141. //
  142. // This function serves to simplify the very specific -- but very common --
  143. // case of having an auto_ref_handle take ownership of a raw HANDLE.
  144. // Without this function, callers would essentially need to go through all
  145. // of the same steps that we do here. The number of different objects
  146. // required to get to the final auto_ref_handle (a temporary auto_handle,
  147. // a CRefHandle, and an auto_ref_ptr to hold it) and how to assemble them
  148. // correctly would be confusing enough to be bug prone. It is far better
  149. // to keep things simple from the caller's perspective.
  150. //
  151. // Returns:
  152. // TRUE if the auto_ref_handle successfully takes ownership of the
  153. // specified valid handle.
  154. // FALSE if the specified handle is NULL or invalid or if there is
  155. // some other failure in the function. In the latter case
  156. // the function also CLOSES THE RAW HANDLE.
  157. //
  158. // !!! IMPORTANT !!!
  159. // This function is designed to be called with the direct return value
  160. // from any API that creates a raw HANDLE. If this call fails
  161. // (i.e. returns FALSE) then it will close the raw HANDLE passed in!
  162. // The whole point of the auto_ref_handle class is to replace usage of
  163. // the raw HANDLE.
  164. //
  165. BOOL FCreate(HANDLE h)
  166. {
  167. Assert( !m_pRefHandle.get() );
  168. // Don't even bother with NULL or invalid handles.
  169. //
  170. if (NULL == h || INVALID_HANDLE_VALUE == h)
  171. return FALSE;
  172. // Put the raw handle into an auto_handle so that we clean up properly
  173. // (i.e. close the handle) if instantiating the CRefHandle below fails
  174. // by throwing an exception (as it would with a throwing allocator).
  175. //
  176. auto_handle<HANDLE> hTemp(h);
  177. // Preserve the last error from our caller. Our caller could have passed
  178. // in a raw HANDLE from a CreateFile() call and may need to check the last
  179. // error even in the success case -- to determine whether the file already
  180. // existed, for example.
  181. //
  182. DWORD dw = GetLastError();
  183. // Create a new refcounted handle object to control the lifetime
  184. // of the handle that we are taking ownership of.
  185. //
  186. // Note: the reason we preserved the last error above is that the
  187. // allocator clears the last error when we create the CRefHandle
  188. // here if the allocation succeeds.
  189. //
  190. m_pRefHandle.take_ownership(new CRefHandle(hTemp));
  191. if (!m_pRefHandle.get())
  192. {
  193. // Return a failure. Note that we don't restore the last
  194. // error here -- callers should expect the last error to
  195. // be set to a value appropriate for the last call that
  196. // failed which is us.
  197. //
  198. return FALSE;
  199. }
  200. // Restore our caller's last error before returning.
  201. //
  202. SetLastError(dw);
  203. // We now own the handle.
  204. //
  205. return TRUE;
  206. }
  207. VOID clear()
  208. {
  209. m_pRefHandle = NULL;
  210. }
  211. };
  212. #endif // !defined(_REFHANDLE_H_)