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.

354 lines
9.5 KiB

  1. #pragma once
  2. //+============================================================================
  3. //
  4. // Microsoft Windows
  5. // Copyright (C) Microsoft Corporation, 1994 - 1998.
  6. //
  7. // File: hntfsstg.hxx
  8. //
  9. // This file provides the NFF (NTFS Flat File) IStream implementation.
  10. //
  11. // History:
  12. //
  13. //+============================================================================
  14. #include "reserved.hxx"
  15. #include "nffmstm.hxx"
  16. //
  17. // NTFS Stream and NTFS Storage are debugged together under the same
  18. // infolevel and debug sub-system. The Stream header is included first
  19. //
  20. DECLARE_DEBUG(nff);
  21. #ifdef DEB_INFO
  22. #undef DEB_INFO
  23. #endif
  24. #define DEB_INFO DEB_USER1
  25. #define DEB_REFCOUNT DEB_USER2
  26. #define DEB_READ DEB_USER3
  27. #define DEB_WRITE DEB_USER4
  28. #define DEB_OPENS DEB_USER5
  29. #define DEB_STATCTRL DEB_USER6
  30. #define DEB_OPLOCK DEB_USER7
  31. #if DBG == 1
  32. #define nffAssert(e) Win4Assert(e)
  33. #define nffVerify(e) Win4Assert(e)
  34. #define nffDebug(x) nffInlineDebugOut x
  35. #define nffXTrace(x) nffCDbgTrace dbg_( DEB_TRACE, x )
  36. #define nffITrace(x) nffCDbgTrace dbg_( DEB_ITRACE, x )
  37. // nffDebugOut is called from the Chk/Err macros
  38. #define nffDebugOut(x) nffInlineDebugOut x
  39. #else
  40. #define nffAssert(e)
  41. #define nffVerify(e) (e)
  42. #define nffDebug(x)
  43. #define nffXTrace(x)
  44. #define nffITrace(x)
  45. #endif
  46. #define nffErr(l, e) ErrJmp(nff, l, e, sc)
  47. #define nffChkTo(l, e) if (FAILED(sc = (e))) nffErr(l, sc) else 1
  48. #define nffChk(e) nffChkTo(EH_Err, e)
  49. #define nffHChkTo(l, e) if (FAILED(sc = DfGetScode(e))) nffErr(l, sc) else 1
  50. #define nffHChk(e) nffHChkTo(EH_Err, e)
  51. #define nffMemTo(l, e) \
  52. if ((e) == NULL) nffErr(l, STG_E_INSUFFICIENTMEMORY) else 1
  53. #define nffMem(e) nffMemTo(EH_Err, e)
  54. #define nffBoolTo(l, e) if (!(e)) nffErr(l, LAST_STG_SCODE) else 1
  55. #define nffBool(e) nffBoolTo(EH_Err, e)
  56. #define NFF_VALIDATE(x) EXP_VALIDATE(nff, x)
  57. #define NTFSSTREAM_SIG LONGSIG('N','T','S','T')
  58. #define NTFSSTREAM_SIGDEL LONGSIG('N','T','S','t')
  59. ////////////////////////////////////////////////////////////////
  60. // IStream for an NTFS file stream. Hungarian Prefix "nffstm"
  61. //
  62. class CNtfsStream : public IStream,
  63. public ILockBytes // For use in e.g. StgCreateStorageOnILockBytes
  64. #if DBG
  65. , public IStorageTest
  66. #endif
  67. {
  68. friend class CNtfsStorage;
  69. friend class CNFFMappedStream;
  70. // ------------
  71. // Construction
  72. // ------------
  73. public:
  74. CNtfsStream( CNtfsStorage *pnffstg, IBlockingLock *pBlockingLock );
  75. virtual ~CNtfsStream();
  76. virtual HRESULT Init( HANDLE hFile,
  77. DWORD grfMode,
  78. const OLECHAR *pwcsName,
  79. CNtfsStream *pnffstm );
  80. // --------
  81. // IUnknown
  82. // --------
  83. public:
  84. STDMETHODIMP QueryInterface(REFIID riid, void **ppvObject);
  85. STDMETHODIMP_(ULONG) AddRef(void);
  86. STDMETHODIMP_(ULONG) Release(void);
  87. // -------
  88. // IStream
  89. // -------
  90. public:
  91. HRESULT STDMETHODCALLTYPE Read(
  92. /* [length_is][size_is][out] */ void __RPC_FAR *pv,
  93. /* [in] */ ULONG cb,
  94. /* [out] */ ULONG __RPC_FAR *pcbRead);
  95. HRESULT STDMETHODCALLTYPE Write(
  96. /* [size_is][in] */ const void __RPC_FAR *pv,
  97. /* [in] */ ULONG cb,
  98. /* [out] */ ULONG __RPC_FAR *pcbWritten);
  99. HRESULT STDMETHODCALLTYPE Seek(
  100. /* [in] */ LARGE_INTEGER dlibMove,
  101. /* [in] */ DWORD dwOrigin,
  102. /* [out] */ ULARGE_INTEGER __RPC_FAR *plibNewPosition);
  103. HRESULT STDMETHODCALLTYPE SetSize(
  104. /* [in] */ ULARGE_INTEGER libNewSize);
  105. HRESULT STDMETHODCALLTYPE CopyTo(
  106. /* [unique][in] */ IStream __RPC_FAR *pstm,
  107. /* [in] */ ULARGE_INTEGER cb,
  108. /* [out] */ ULARGE_INTEGER __RPC_FAR *pcbRead,
  109. /* [out] */ ULARGE_INTEGER __RPC_FAR *pcbWritten);
  110. HRESULT STDMETHODCALLTYPE Commit(
  111. /* [in] */ DWORD grfCommitFlags);
  112. HRESULT STDMETHODCALLTYPE Revert(void);
  113. HRESULT STDMETHODCALLTYPE LockRegion(
  114. /* [in] */ ULARGE_INTEGER libOffset,
  115. /* [in] */ ULARGE_INTEGER cb,
  116. /* [in] */ DWORD dwLockType);
  117. HRESULT STDMETHODCALLTYPE UnlockRegion(
  118. /* [in] */ ULARGE_INTEGER libOffset,
  119. /* [in] */ ULARGE_INTEGER cb,
  120. /* [in] */ DWORD dwLockType);
  121. HRESULT STDMETHODCALLTYPE Stat(
  122. /* [out] */ STATSTG __RPC_FAR *pstatstg,
  123. /* [in] */ DWORD grfStatFlag);
  124. HRESULT STDMETHODCALLTYPE Clone(
  125. /* [out] */ IStream __RPC_FAR *__RPC_FAR *ppstm);
  126. // ----------
  127. // ILockBytes
  128. // ----------
  129. public:
  130. HRESULT STDMETHODCALLTYPE ReadAt(
  131. /* [in] */ ULARGE_INTEGER ulOffset,
  132. /* [length_is][size_is][out] */ void __RPC_FAR *pv,
  133. /* [in] */ ULONG cb,
  134. /* [out] */ ULONG __RPC_FAR *pcbRead);
  135. HRESULT STDMETHODCALLTYPE WriteAt(
  136. /* [in] */ ULARGE_INTEGER ulOffset,
  137. /* [size_is][in] */ const void __RPC_FAR *pv,
  138. /* [in] */ ULONG cb,
  139. /* [out] */ ULONG __RPC_FAR *pcbWritten);
  140. HRESULT STDMETHODCALLTYPE Flush(void);
  141. public:
  142. inline BOOL IsWriteable();
  143. HRESULT CheckReverted();
  144. // ------------
  145. // IStorageTest
  146. // ------------
  147. public:
  148. #if DBG
  149. STDMETHOD(UseNTFS4Streams)( BOOL fUseNTFS4Streams );
  150. STDMETHOD(GetFormatVersion)(WORD *pw);
  151. STDMETHOD(SimulateLowMemory)( BOOL fSimulate );
  152. STDMETHOD(GetLockCount)();
  153. STDMETHOD(IsDirty)();
  154. #endif
  155. // ----------------
  156. // Internal Methods
  157. // ----------------
  158. protected:
  159. virtual HRESULT ShutDown();
  160. void InsertSelfIntoList(CNtfsStream * pnffstmList);
  161. void RemoveSelfFromList();
  162. HRESULT Delete();
  163. private:
  164. HRESULT SetFileSize( const CULargeInteger &uliNewSize );
  165. HRESULT Rename( const WCHAR *pwcsName, BOOL fOverWrite );
  166. inline HRESULT Lock( DWORD dwTimeout );
  167. inline HRESULT Unlock();
  168. static HRESULT DeleteStream( HANDLE *phStream );
  169. HRESULT SyncReadAtFile( ULARGE_INTEGER ulOffset,
  170. PVOID pv, ULONG cb, PULONG pcbRead );
  171. HRESULT SyncWriteAtFile( ULARGE_INTEGER ulOffset,
  172. const void *pv, ULONG cb, PULONG pcbWritten );
  173. HANDLE GetFileHandle(); // Used by friend CNtfsStorage.
  174. HRESULT MarkStreamAux( const MARK_HANDLE_INFO& mhi );
  175. static HRESULT MarkFileHandleAux( HANDLE hFile, const MARK_HANDLE_INFO& mhi );
  176. HRESULT SetStreamTime( const FILETIME*, const FILETIME*, const FILETIME* );
  177. static HRESULT SetFileHandleTime( HANDLE hFile, const FILETIME*, const FILETIME*, const FILETIME* );
  178. const WCHAR* GetName() const;
  179. // --------------
  180. // Internal State
  181. // --------------
  182. private:
  183. WCHAR * _pwcsName;
  184. CNFFMappedStream _nffMappedStream;
  185. DWORD _grfMode; // The mode used to open the IStream
  186. HANDLE _hFile; // File represented by this stream
  187. IBlockingLock * _pBlockingLock; // The lock to use for mutual exclusion
  188. ULONG _sig; // Class signature
  189. LONG _cRefs; // Reference count
  190. CNtfsStorage * _pnffstg; // Not ref-counted, NULL-ed in ShutDown
  191. // This class maintains its own copy of the seek pointer, different from
  192. // the underlying file's. This is necessary so that the IStream methods mantain
  193. // a consistent seek location, even when methods on e.g. IMappedStream are called.
  194. CLargeInteger _liCurrentSeekPosition;
  195. CNtfsStream * _pnffstmPrev; // links for the list of open streams.
  196. CNtfsStream * _pnffstmNext;
  197. OVERLAPPED _ovlp; // structure used for Async IO.
  198. }; // class CNtfsStream
  199. inline HANDLE
  200. CNtfsStream::GetFileHandle()
  201. {
  202. return _hFile;
  203. }
  204. inline HRESULT
  205. CNtfsStream::CheckReverted()
  206. {
  207. if(INVALID_HANDLE_VALUE == _hFile)
  208. return STG_E_REVERTED;
  209. return S_OK;
  210. }
  211. inline const WCHAR*
  212. CNtfsStream::GetName() const
  213. {
  214. return _pwcsName;
  215. }
  216. inline HRESULT
  217. CNtfsStream::Lock( DWORD dwTimeout )
  218. {
  219. return( _pBlockingLock->Lock( dwTimeout ));
  220. }
  221. inline HRESULT
  222. CNtfsStream::Unlock()
  223. {
  224. return( _pBlockingLock->Unlock() );
  225. }
  226. inline BOOL
  227. CNtfsStream::IsWriteable()
  228. {
  229. return( GrfModeIsWriteable( _grfMode ));
  230. }
  231. //+----------------------------------------------------------------------------
  232. //
  233. // Class: CNtfsUpdateStreamForPropStg
  234. //
  235. // This class wraps the update stream handle, used by
  236. // CNFFMappedStream. See that class declaration for a description.
  237. //
  238. //+----------------------------------------------------------------------------
  239. class CNtfsUpdateStreamForPropStg : public CNtfsStream
  240. {
  241. public:
  242. CNtfsUpdateStreamForPropStg( CNtfsStorage *pnffstg, IBlockingLock *_pBlockingLock );
  243. ~CNtfsUpdateStreamForPropStg();
  244. protected:
  245. virtual HRESULT ShutDown();
  246. }; // class CNtfsStreamForPropStg
  247. inline
  248. CNtfsUpdateStreamForPropStg::CNtfsUpdateStreamForPropStg( CNtfsStorage *pnffstg, IBlockingLock *pBlockingLock )
  249. : CNtfsStream( pnffstg, pBlockingLock )
  250. {
  251. }
  252. inline
  253. CNtfsUpdateStreamForPropStg::~CNtfsUpdateStreamForPropStg()
  254. {
  255. // If the CNFFMappedStream was shutdown without flushing, and it couldn't
  256. // save and fix up the update stream, then there's nothing we can
  257. // do to recover and we should delete the stream.
  258. // In the normal path, CNFFMappedStream::~CNFFMappedStream calls
  259. // ReplaceOriginalWithUpdate(DONT_CREATE_NEW_UPDATE_STREAM),
  260. // and subsequently our handle is closed, and CheckReverted
  261. // returns STG_E_REVERTED.
  262. if( SUCCEEDED(CheckReverted()) )
  263. Delete();
  264. }