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.

260 lines
9.0 KiB

  1. #ifndef _NFFMSTM_HXX_
  2. #define _NFFMSTM_HXX_
  3. #include <propstm.hxx>
  4. class CNtfsStream;
  5. class CNtfsUpdateStreamForPropStg;
  6. //+----------------------------------------------------------------------------
  7. //
  8. // Class: CNFFMappedStream
  9. //
  10. // This class is used by CNtfsStream, and implements the IMappedStream
  11. // interface for use on NFF (NTFS Flat-File) files. The mapping
  12. // exposed by this implementation is robust, in that updates to the
  13. // underlying stream are atomic (though not durable until flushed).
  14. //
  15. // This atomicity is accomplished by using stream renaming (which is only
  16. // supported in NTFS5). When this mapping is written to the underlying
  17. // NTFS files, it is written to a second stream (the "update" stream),
  18. // rather than the original stream. When Flush is called,
  19. // the update stream is renamed over the original stream. In order to
  20. // make NTFS stream renaming atomic, the overwritten stream must be
  21. // truncated first to have zero length. The the overall flush operation
  22. // is: truncate the original stream, rename the update stream over
  23. // the original stream, and optionally create a new update stream to be
  24. // ready for the next write.
  25. //
  26. // When the original stream is truncated, the update stream is then
  27. // considered master. So if there is a crash before the truncate, then
  28. // the original stream, with the original data, is master. If there is
  29. // a crash after the truncate but before the rename, then the update stream
  30. // is considered master. In this case, on the next open, the update stream
  31. // is either renamed over the zero-length original (if opening for write),
  32. // or the update stream is simply used as is (if opening for read).
  33. //
  34. // If the file isn't on an NTFS5 volume, so stream renaming isn't supported,
  35. // we just use the original stream unconditionally and there is no robustness.
  36. //
  37. // To accomplish all of this, this class works with two stream handles,
  38. // the original and the update. The original is the stream handle held
  39. // by the parent CNtfsStream. The update stream handle must behave like all other
  40. // stream handles, wrt USN, oplock, timestamps, etc (see CNtfsStream).
  41. // So the update stream is wrapped in a CNtfsStream too, but a special
  42. // one - the CNtfsUpdateStreamForPropStg derivation. An instance of this
  43. // CNtfsUpdateStreamForPropStg class is maintained by here (by CNFFMappedStream).
  44. //
  45. //
  46. //
  47. // +-------------+ +------------------+
  48. // | |------->| |
  49. // | CNtfsStream | | CNFFMappedStream |
  50. // | |<-------| |
  51. // +-------------+ +------------------+
  52. // | | +------------------------------+
  53. // | | | |
  54. // | +----->| CNtfsUpdateStreamForPropStg |
  55. // V | : public CNtfsStream |
  56. // Original | |
  57. // NTFS +------------------------------+
  58. // Stream |
  59. // |
  60. // V
  61. // Updated
  62. // NTFS
  63. // Stream
  64. //
  65. //+----------------------------------------------------------------------------
  66. class CNFFMappedStream : public IMappedStream
  67. #if DBG
  68. , public IStorageTest // For testing only
  69. #endif
  70. {
  71. // Constructors
  72. public:
  73. CNFFMappedStream( CNtfsStream *pnffstm );
  74. ~CNFFMappedStream();
  75. // -------------
  76. // IMappedStream
  77. // -------------
  78. public:
  79. STDMETHODIMP QueryInterface(REFIID riid, void **ppvObject);
  80. STDMETHODIMP_(ULONG) AddRef(void);
  81. STDMETHODIMP_(ULONG) Release(void);
  82. STDMETHODIMP_(VOID) Open(IN NTPROP np, OUT LONG *phr);
  83. STDMETHODIMP_(VOID) Close(OUT LONG *phr);
  84. STDMETHODIMP_(VOID) ReOpen(IN OUT VOID **ppv, OUT LONG *phr);
  85. STDMETHODIMP_(VOID) Quiesce(VOID);
  86. STDMETHODIMP_(VOID) Map(IN BOOLEAN fCreate, OUT VOID **ppv);
  87. STDMETHODIMP_(VOID) Unmap(IN BOOLEAN fFlush, IN OUT VOID **ppv);
  88. STDMETHODIMP_(VOID) Flush(OUT LONG *phr);
  89. STDMETHODIMP_(ULONG) GetSize(OUT LONG *phr);
  90. STDMETHODIMP_(VOID) SetSize(IN ULONG cb, IN BOOLEAN fPersistent, IN OUT VOID **ppv, OUT LONG *phr);
  91. STDMETHODIMP_(NTSTATUS) Lock(IN BOOLEAN fExclusive);
  92. STDMETHODIMP_(NTSTATUS) Unlock(VOID);
  93. STDMETHODIMP_(VOID) QueryTimeStamps(OUT STATPROPSETSTG *pspss, BOOLEAN fNonSimple) const;
  94. STDMETHODIMP_(BOOLEAN) QueryModifyTime(OUT LONGLONG *pll) const;
  95. STDMETHODIMP_(BOOLEAN) QuerySecurity(OUT ULONG *pul) const;
  96. STDMETHODIMP_(BOOLEAN) IsWriteable(VOID) const;
  97. STDMETHODIMP_(BOOLEAN) IsModified(VOID) const;
  98. STDMETHODIMP_(VOID) SetModified(OUT LONG *phr);
  99. STDMETHODIMP_(HANDLE) GetHandle(VOID) const;
  100. #if DBG
  101. STDMETHODIMP_(BOOLEAN) SetChangePending(BOOLEAN fChangePending);
  102. STDMETHODIMP_(BOOLEAN) IsNtMappedStream(VOID) const;
  103. #endif
  104. // ------------
  105. // IStorageTest
  106. // ------------
  107. public:
  108. #if DBG
  109. STDMETHOD(UseNTFS4Streams)( BOOL fUseNTFS4Streams );
  110. STDMETHOD(GetFormatVersion)(WORD *pw);
  111. STDMETHOD(SimulateLowMemory)( BOOL fSimulate );
  112. STDMETHOD_(LONG, GetLockCount)();
  113. STDMETHOD(IsDirty)();
  114. #endif
  115. // -----------------------------
  116. // Public, non-interface methods
  117. // -----------------------------
  118. public:
  119. inline BOOL IsMapped();
  120. inline ULONG SizeOfMapping();
  121. void Read( void *pv, ULONG ulOffset, ULONG *pcbCopy );
  122. void Write( const void *pv, ULONG ulOffset, ULONG *pcbCopy );
  123. HRESULT Init( HANDLE hStream );
  124. HRESULT ShutDown();
  125. // ----------------
  126. // Internal Methods
  127. // ----------------
  128. private:
  129. void InitMappedStreamMembers();
  130. void BeginUsingUpdateStream();
  131. void EndUsingUpdateStream();
  132. void BeginUsingLatestStream();
  133. void EndUsingLatestStream();
  134. HRESULT WriteMappedStream();
  135. enum enumCREATE_NEW_UPDATE_STREAM
  136. {
  137. CREATE_NEW_UPDATE_STREAM = 1,
  138. DONT_CREATE_NEW_UPDATE_STREAM = 2
  139. };
  140. inline HRESULT CreateUpdateStreamIfNecessary();
  141. HRESULT ReplaceOriginalWithUpdate( enumCREATE_NEW_UPDATE_STREAM CreateNewUpdateStream );
  142. HRESULT OpenUpdateStream( BOOL fCreate );
  143. HRESULT RollForwardIfNecessary();
  144. // --------------
  145. // Internal state
  146. // --------------
  147. private:
  148. // Containing stream (i.e., we're an embedded object in this CNtfsStream)
  149. CNtfsStream *_pnffstm;
  150. // Are we using global reserved memory?
  151. BOOL _fLowMem:1;
  152. // Does the mapped stream have unflushed changes?
  153. BOOL _fMappedStreamDirty:1;
  154. #if DBG
  155. // Should we pretent that CoTaskMemAlloc fails?
  156. BOOL _fSimulateLowMem:1;
  157. #endif
  158. // Is the latest data in _pstmUpdate?
  159. BOOL _fUpdateStreamHasLatest:1;
  160. // Have we already called the RollForwardIfNecessary method?
  161. BOOL _fCheckedForRollForward:1;
  162. // Is this an NTFS5 volume?
  163. BOOL _fStreamRenameSupported:1;
  164. // The current mapping
  165. BYTE *_pbMappedStream;
  166. // The size of the buffer referred to by _pbMappedStream
  167. ULONG _cbMappedStream;
  168. // The size of the underlying stream that _pbMappedStream represents
  169. ULONG _cbMappedStreamActual;
  170. // Cookie used in PrOnMappedStreamEvent
  171. VOID *_pMappedStreamOwner;
  172. // Count of calls to BeginUsingUpdateStream unmatched by a call to
  173. // EndUsingUpdateStream
  174. USHORT _cUpdateStreamInUse;
  175. // Count of calls to BeginUsingLatestStream unmatched by a call to
  176. // EndUsingLatestStream
  177. USHORT _cLatestStreamInUse;
  178. // The Update stream.
  179. CNtfsUpdateStreamForPropStg
  180. *_pstmUpdate;
  181. }; // class CNFFMappedStream
  182. inline CNFFMappedStream::CNFFMappedStream( CNtfsStream *pnffstm )
  183. {
  184. _pnffstm = pnffstm;
  185. _pstmUpdate = NULL;
  186. _fUpdateStreamHasLatest = FALSE;
  187. IFDBG( _fSimulateLowMem = FALSE );
  188. InitMappedStreamMembers();
  189. }
  190. inline BOOL
  191. CNFFMappedStream::IsMapped()
  192. {
  193. return( NULL != _pbMappedStream );
  194. }
  195. inline ULONG
  196. CNFFMappedStream::SizeOfMapping()
  197. {
  198. return( _cbMappedStream );
  199. }
  200. #endif // #ifndef _NFFMSTM_HXX_