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.

356 lines
10 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) (void)(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. // This is assumed to lock the whole storage
  189. // (the open stream list code requires this)
  190. ULONG _sig; // Class signature
  191. LONG _cRefs; // Reference count
  192. CNtfsStorage * _pnffstg; // Not ref-counted, NULL-ed in ShutDown
  193. // This class maintains its own copy of the seek pointer, different from
  194. // the underlying file's. This is necessary so that the IStream methods mantain
  195. // a consistent seek location, even when methods on e.g. IMappedStream are called.
  196. CLargeInteger _liCurrentSeekPosition;
  197. CNtfsStream * _pnffstmPrev; // links for the list of open streams.
  198. CNtfsStream * _pnffstmNext;
  199. OVERLAPPED _ovlp; // structure used for Async IO.
  200. }; // class CNtfsStream
  201. inline HANDLE
  202. CNtfsStream::GetFileHandle()
  203. {
  204. return _hFile;
  205. }
  206. inline HRESULT
  207. CNtfsStream::CheckReverted()
  208. {
  209. if(INVALID_HANDLE_VALUE == _hFile)
  210. return STG_E_REVERTED;
  211. return S_OK;
  212. }
  213. inline const WCHAR*
  214. CNtfsStream::GetName() const
  215. {
  216. return _pwcsName;
  217. }
  218. inline HRESULT
  219. CNtfsStream::Lock( DWORD dwTimeout )
  220. {
  221. return( _pBlockingLock->Lock( dwTimeout ));
  222. }
  223. inline HRESULT
  224. CNtfsStream::Unlock()
  225. {
  226. return( _pBlockingLock->Unlock() );
  227. }
  228. inline BOOL
  229. CNtfsStream::IsWriteable()
  230. {
  231. return( GrfModeIsWriteable( _grfMode ));
  232. }
  233. //+----------------------------------------------------------------------------
  234. //
  235. // Class: CNtfsUpdateStreamForPropStg
  236. //
  237. // This class wraps the update stream handle, used by
  238. // CNFFMappedStream. See that class declaration for a description.
  239. //
  240. //+----------------------------------------------------------------------------
  241. class CNtfsUpdateStreamForPropStg : public CNtfsStream
  242. {
  243. public:
  244. CNtfsUpdateStreamForPropStg( CNtfsStorage *pnffstg, IBlockingLock *_pBlockingLock );
  245. ~CNtfsUpdateStreamForPropStg();
  246. protected:
  247. virtual HRESULT ShutDown();
  248. }; // class CNtfsStreamForPropStg
  249. inline
  250. CNtfsUpdateStreamForPropStg::CNtfsUpdateStreamForPropStg( CNtfsStorage *pnffstg, IBlockingLock *pBlockingLock )
  251. : CNtfsStream( pnffstg, pBlockingLock )
  252. {
  253. }
  254. inline
  255. CNtfsUpdateStreamForPropStg::~CNtfsUpdateStreamForPropStg()
  256. {
  257. // If the CNFFMappedStream was shutdown without flushing, and it couldn't
  258. // save and fix up the update stream, then there's nothing we can
  259. // do to recover and we should delete the stream.
  260. // In the normal path, CNFFMappedStream::~CNFFMappedStream calls
  261. // ReplaceOriginalWithUpdate(DONT_CREATE_NEW_UPDATE_STREAM),
  262. // and subsequently our handle is closed, and CheckReverted
  263. // returns STG_E_REVERTED.
  264. if( SUCCEEDED(CheckReverted()) )
  265. Delete();
  266. }