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.

909 lines
26 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) IStorage declaration.
  10. //
  11. // History:
  12. // 5/6/98 MikeHill
  13. // - Split the Init method into two methods, one which is
  14. // file name based and the other which is handle based.
  15. // 5/18/98 MikeHill
  16. // - Simplified constructur and added Init method.
  17. //
  18. //+============================================================================
  19. #include "prophdr.hxx"
  20. #include "stgprops.hxx"
  21. #include <new.h>
  22. #include "psetstg.hxx"
  23. #include "cli.hxx" // CLargeInteger/CULargeInteger
  24. #include "hntfsstm.hxx"
  25. #include "bag.hxx" // CPropertyBagEx
  26. #include "names.hxx"
  27. #ifndef ELEMENTS
  28. #define ELEMENTS(x) (sizeof(x)/sizeof(x[0]))
  29. #endif
  30. //+============================================================================
  31. //
  32. // Class CNtfsSTATSTGArray
  33. //
  34. // This class maintains an array of STATSTG structures. It's used by
  35. // CNtfsEnumSTATSTG. We separate this out from that class so that if you
  36. // clone a CNtfsEnumSTATSTG enumerator, the data can be shared, but the
  37. // clone can maintain its own seek pointer.
  38. //
  39. //+============================================================================
  40. class CNtfsSTATSTGArray
  41. {
  42. public:
  43. CNtfsSTATSTGArray( IBlockingLock *pBlockingLock );
  44. ~CNtfsSTATSTGArray();
  45. HRESULT Init( HANDLE hFile );
  46. public:
  47. HRESULT NextAt( ULONG iNext, STATSTG *prgstatstg, ULONG *pcFetched );
  48. inline VOID AddRef();
  49. inline VOID Release();
  50. inline ULONG GetCount();
  51. private:
  52. HRESULT ReadFileStreamInfo( HANDLE hFile );
  53. private:
  54. LONG _cRefs;
  55. IBlockingLock *_pBlockingLock;
  56. // A cache of the FileStreamInformation. To refresh this cache, the
  57. // caller must release the IEnum and re-create it.
  58. PFILE_STREAM_INFORMATION _pFileStreamInformation;
  59. ULONG _cFileStreamInformation;
  60. }; // class CNtfsSTATSTGArray
  61. inline
  62. CNtfsSTATSTGArray::CNtfsSTATSTGArray( IBlockingLock *pBlockingLock )
  63. {
  64. nffXTrace( "CNtfsSTATSTGArray::CNtfsSTATSTGArray" );
  65. _cFileStreamInformation = 0;
  66. _cRefs = 1;
  67. _pFileStreamInformation = NULL;
  68. _pBlockingLock = pBlockingLock;
  69. _pBlockingLock->AddRef();
  70. }
  71. inline
  72. CNtfsSTATSTGArray::~CNtfsSTATSTGArray()
  73. {
  74. nffXTrace( "CNtfsSTATSTGArray::~CNtfsSTATSTGArray" );
  75. if( NULL != _pFileStreamInformation )
  76. {
  77. CoTaskMemFree( _pFileStreamInformation );
  78. _pFileStreamInformation = NULL;
  79. }
  80. DfpAssert( NULL != _pBlockingLock );
  81. _pBlockingLock->Release();
  82. }
  83. inline VOID
  84. CNtfsSTATSTGArray::AddRef()
  85. {
  86. LONG cRefs;
  87. cRefs = InterlockedIncrement( &_cRefs );
  88. nffDebug(( DEB_REFCOUNT, "CNtfsSTATSTGArray::AddRef(this==%x) == %d\n",
  89. this, cRefs));
  90. }
  91. inline VOID
  92. CNtfsSTATSTGArray::Release()
  93. {
  94. LONG cRefs;
  95. cRefs = InterlockedDecrement( &_cRefs );
  96. if( 0 == cRefs )
  97. delete this;
  98. nffDebug((DEB_REFCOUNT, "CNtfsSTATSTGArray::Release(this=%x) == %d\n",
  99. this, cRefs));
  100. }
  101. inline ULONG
  102. CNtfsSTATSTGArray::GetCount()
  103. {
  104. nffITrace( "CNtfsSTATSTGArray::GetCount" );
  105. return( _cFileStreamInformation );
  106. }
  107. //+============================================================================
  108. //
  109. // Class: CNtfsEnumSTATSTG
  110. //
  111. // This class IEnum-erates STATSTG structures for the NTFS IStorage
  112. // implementation (CNtfsStorage). The data for this enumerator is actually
  113. // held in a CNtfsSTATSTGArray object.
  114. //
  115. //+============================================================================
  116. #define NTFSENUMSTATSTG_SIG LONGSIG('N','T','S','E')
  117. #define NTFSENUMSTATSTG_SIGDEL LONGSIG('N','T','S','e')
  118. class CNtfsEnumSTATSTG: public IEnumSTATSTG
  119. {
  120. public:
  121. CNtfsEnumSTATSTG( IBlockingLock *pBlockingLock );
  122. CNtfsEnumSTATSTG( CNtfsEnumSTATSTG &Other );
  123. ~CNtfsEnumSTATSTG();
  124. public:
  125. STDMETHOD(QueryInterface)( REFIID riid, void **ppvObject);
  126. STDMETHOD_(ULONG, AddRef)(void);
  127. STDMETHOD_(ULONG, Release)(void);
  128. STDMETHOD(Next)(ULONG celt, STATSTG * rgelt, ULONG * pceltFetched);
  129. STDMETHOD(Skip)(ULONG celt);
  130. STDMETHOD(Reset)();
  131. STDMETHOD(Clone)(IEnumSTATSTG **ppenum);
  132. public:
  133. STDMETHOD(Init)(HANDLE hFile);
  134. private:
  135. ULONG _ulSig;
  136. LONG _cRefs;
  137. ULONG _istatNextToRead;
  138. IBlockingLock *_pBlockingLock;
  139. CNtfsSTATSTGArray *_pstatstgarray;
  140. }; // class CNtfsEnumSTATSTG
  141. inline
  142. CNtfsEnumSTATSTG::CNtfsEnumSTATSTG( IBlockingLock *pBlockingLock )
  143. {
  144. nffXTrace( "CNtfsEnumSTATSTG::CNtfsEnumSTATSTG(pBlockingLock)" );
  145. _ulSig = NTFSENUMSTATSTG_SIG;
  146. _cRefs = 1;
  147. _istatNextToRead = 0;
  148. _pstatstgarray = NULL;
  149. _pBlockingLock = pBlockingLock;
  150. _pBlockingLock->AddRef();
  151. }
  152. inline
  153. CNtfsEnumSTATSTG::CNtfsEnumSTATSTG( CNtfsEnumSTATSTG &Other )
  154. {
  155. nffXTrace( "CNtfsEnumSTATSTG::CNtfsEnumSTATSTG(CntfsEnumSTATSTG)" );
  156. Other._pBlockingLock->Lock( INFINITE );
  157. // Initialize
  158. new(this) CNtfsEnumSTATSTG( Other._pBlockingLock );
  159. // Load state from Other
  160. _pstatstgarray = Other._pstatstgarray;
  161. _pstatstgarray->AddRef();
  162. _istatNextToRead = Other._istatNextToRead;
  163. Other._pBlockingLock->Unlock();
  164. }
  165. inline
  166. CNtfsEnumSTATSTG::~CNtfsEnumSTATSTG()
  167. {
  168. nffXTrace( "CNtfsEnumSTATSTG::~CNtfsEnumSTATSTG" );
  169. if( NULL != _pstatstgarray )
  170. _pstatstgarray->Release();
  171. if( NULL != _pBlockingLock )
  172. _pBlockingLock->Release();
  173. _ulSig = NTFSENUMSTATSTG_SIGDEL;
  174. }
  175. inline HRESULT STDMETHODCALLTYPE
  176. CNtfsEnumSTATSTG::Init( HANDLE hFile )
  177. {
  178. nffITrace( "CNtfsEnumSTATSTG::Init" );
  179. HRESULT hr = S_OK;
  180. // Create a STATSTG Array handler
  181. _pstatstgarray = new CNtfsSTATSTGArray( _pBlockingLock );
  182. if( NULL == _pstatstgarray )
  183. {
  184. hr = E_OUTOFMEMORY;
  185. goto Exit;
  186. }
  187. // Load the array from the handle
  188. hr = _pstatstgarray->Init( hFile );
  189. if( FAILED(hr) ) goto Exit;
  190. Exit:
  191. return( hr );
  192. }
  193. //+----------------------------------------------------------------------------
  194. //
  195. // Class: CNtfsStorageForPropSetStg
  196. //
  197. // This class presents an IStorage implementation that behaves exactly
  198. // as CPropertySetStorage expects. It primary calls to CNtfsStorage,
  199. // but implements Create/OpenStorage by creating a DocFile on an NTFS
  200. // stream.
  201. //
  202. //+----------------------------------------------------------------------------
  203. class CNtfsStorage;
  204. class CNtfsStorageForPropSetStg : public IStorage
  205. {
  206. public:
  207. CNtfsStorageForPropSetStg( );
  208. ~CNtfsStorageForPropSetStg();
  209. inline void Init( CNtfsStorage *pNtfsStorage );
  210. public:
  211. HRESULT STDMETHODCALLTYPE QueryInterface( REFIID riid, void** ppvObject );
  212. ULONG STDMETHODCALLTYPE AddRef();
  213. ULONG STDMETHODCALLTYPE Release();
  214. HRESULT STDMETHODCALLTYPE CreateStream(
  215. /* [string][in] */ const OLECHAR __RPC_FAR *pwcsName,
  216. /* [in] */ DWORD grfMode,
  217. /* [in] */ DWORD reserved1,
  218. /* [in] */ DWORD reserved2,
  219. /* [out] */ IStream __RPC_FAR *__RPC_FAR *ppstm);
  220. HRESULT STDMETHODCALLTYPE OpenStream(
  221. /* [string][in] */ const OLECHAR __RPC_FAR *pwcsName,
  222. /* [unique][in] */ void __RPC_FAR *reserved1,
  223. /* [in] */ DWORD grfMode,
  224. /* [in] */ DWORD reserved2,
  225. /* [out] */ IStream __RPC_FAR *__RPC_FAR *ppstm);
  226. HRESULT STDMETHODCALLTYPE CreateStorage(
  227. /* [string][in] */ const OLECHAR __RPC_FAR *pwcsName,
  228. /* [in] */ DWORD grfMode,
  229. /* [in] */ DWORD reserved1,
  230. /* [in] */ DWORD reserved2,
  231. /* [out] */ IStorage __RPC_FAR *__RPC_FAR *ppstg);
  232. HRESULT STDMETHODCALLTYPE OpenStorage(
  233. /* [string][unique][in] */ const OLECHAR __RPC_FAR *pwcsName,
  234. /* [unique][in] */ IStorage __RPC_FAR *pstgPriority,
  235. /* [in] */ DWORD grfMode,
  236. /* [unique][in] */ SNB snbExclude,
  237. /* [in] */ DWORD reserved,
  238. /* [out] */ IStorage __RPC_FAR *__RPC_FAR *ppstg);
  239. HRESULT STDMETHODCALLTYPE CopyTo(
  240. /* [in] */ DWORD ciidExclude,
  241. /* [size_is][unique][in] */ const IID __RPC_FAR *rgiidExclude,
  242. /* [unique][in] */ SNB snbExclude,
  243. /* [unique][in] */ IStorage __RPC_FAR *pstgDest);
  244. HRESULT STDMETHODCALLTYPE MoveElementTo(
  245. /* [string][in] */ const OLECHAR __RPC_FAR *pwcsName,
  246. /* [unique][in] */ IStorage __RPC_FAR *pstgDest,
  247. /* [string][in] */ const OLECHAR __RPC_FAR *pwcsNewName,
  248. /* [in] */ DWORD grfFlags);
  249. HRESULT STDMETHODCALLTYPE Commit(
  250. /* [in] */ DWORD grfCommitFlags);
  251. HRESULT STDMETHODCALLTYPE Revert( void);
  252. HRESULT STDMETHODCALLTYPE EnumElements(
  253. /* [in] */ DWORD reserved1,
  254. /* [size_is][unique][in] */ void __RPC_FAR *reserved2,
  255. /* [in] */ DWORD reserved3,
  256. /* [out] */ IEnumSTATSTG __RPC_FAR *__RPC_FAR *ppenum);
  257. HRESULT STDMETHODCALLTYPE DestroyElement(
  258. /* [string][in] */ const OLECHAR __RPC_FAR *pwcsName);
  259. HRESULT STDMETHODCALLTYPE RenameElement(
  260. /* [string][in] */ const OLECHAR __RPC_FAR *pwcsOldName,
  261. /* [string][in] */ const OLECHAR __RPC_FAR *pwcsNewName);
  262. HRESULT STDMETHODCALLTYPE SetElementTimes(
  263. /* [string][unique][in] */ const OLECHAR __RPC_FAR *pwcsName,
  264. /* [unique][in] */ const FILETIME __RPC_FAR *pctime,
  265. /* [unique][in] */ const FILETIME __RPC_FAR *patime,
  266. /* [unique][in] */ const FILETIME __RPC_FAR *pmtime);
  267. HRESULT STDMETHODCALLTYPE SetClass(
  268. /* [in] */ REFCLSID clsid);
  269. HRESULT STDMETHODCALLTYPE SetStateBits(
  270. /* [in] */ DWORD grfStateBits,
  271. /* [in] */ DWORD grfMask);
  272. HRESULT STDMETHODCALLTYPE Stat(
  273. /* [out] */ STATSTG __RPC_FAR *pstatstg,
  274. /* [in] */ DWORD grfStatFlag);
  275. public:
  276. static HRESULT
  277. CreateOrOpenStorageOnILockBytes( ILockBytes *plkb, IStorage *pstgPriority, DWORD grfMode,
  278. SNB snbExclude, BOOL fCreate, IStorage **ppstg );
  279. private:
  280. HRESULT CreateOrOpenStorage( const OLECHAR *pwcsName, IStorage *pstgPriority, DWORD grfMode,
  281. SNB snbExclude, BOOL fCreate, IStorage **ppstg );
  282. private:
  283. // This CNtfsStorage is considered the same COM object as this IPropertySetStorage.
  284. // We don't keep a ref on this, and forward all Unk calls to it (except we
  285. // intercept IStorage/IUnknown from QI).
  286. CNtfsStorage *_pNtfsStorage;
  287. }; // class CNtfsStorageForPropSetStg : public IStorage
  288. inline
  289. CNtfsStorageForPropSetStg::CNtfsStorageForPropSetStg( )
  290. {
  291. nffXTrace( "CNtfsStorageForPropSetStg::CNtfsStorageForPropSetStg" );
  292. }
  293. inline
  294. CNtfsStorageForPropSetStg::~CNtfsStorageForPropSetStg()
  295. {
  296. nffXTrace( "CNtfsStorageForPropSetStg::~CNtfsStorageForPropSetStg" );
  297. _pNtfsStorage = NULL;
  298. }
  299. inline void
  300. CNtfsStorageForPropSetStg::Init( CNtfsStorage *pNtfsStorage )
  301. {
  302. _pNtfsStorage = pNtfsStorage;
  303. }
  304. //+============================================================================
  305. //
  306. // Class: CNFFTreeMutex
  307. //
  308. // This class implements the Tree Mutex for and NFF file.
  309. //
  310. // The tree mutex is taken at the top of all IStorage and IStream calls.
  311. //
  312. //+============================================================================
  313. class CNFFTreeMutex: public IBlockingLock
  314. {
  315. // ------------
  316. // Construction
  317. // ------------
  318. public:
  319. inline CNFFTreeMutex( );
  320. inline ~CNFFTreeMutex();
  321. inline HRESULT Init();
  322. // --------
  323. // IUnknown
  324. // --------
  325. public:
  326. HRESULT STDMETHODCALLTYPE QueryInterface( REFIID riid, void** ppvObject );
  327. ULONG STDMETHODCALLTYPE AddRef();
  328. ULONG STDMETHODCALLTYPE Release();
  329. // -------------
  330. // IBlockingLock
  331. // -------------
  332. public:
  333. virtual HRESULT STDMETHODCALLTYPE Lock(DWORD dwTimeout);
  334. virtual HRESULT STDMETHODCALLTYPE Unlock();
  335. public:
  336. #if DBG
  337. LONG GetLockCount();
  338. #endif
  339. private:
  340. LONG _cRefs;
  341. BOOL _fInitialized;
  342. mutable CRITICAL_SECTION _cs;
  343. };
  344. inline
  345. CNFFTreeMutex::CNFFTreeMutex()
  346. {
  347. _cRefs = 1;
  348. _fInitialized = FALSE;
  349. }
  350. inline
  351. HRESULT CNFFTreeMutex::Init()
  352. {
  353. if (_fInitialized == FALSE)
  354. {
  355. NTSTATUS nts = RtlInitializeCriticalSection(&_cs);
  356. if (!NT_SUCCESS(nts))
  357. return NtStatusToScode (nts);
  358. _fInitialized = TRUE;
  359. }
  360. return S_OK;
  361. }
  362. inline
  363. CNFFTreeMutex::~CNFFTreeMutex()
  364. {
  365. if (_fInitialized)
  366. DeleteCriticalSection( &_cs );
  367. }
  368. //+============================================================================
  369. //
  370. // Class: CNtfsStorage
  371. //
  372. // This class is both an IStorage and an IPropertySetStorage. It also offers
  373. // a special IStorage interface which is used by the CPropertySetStorage
  374. // implementation, this special IStorage is implemented in the
  375. // CNtfsStorageForPropSetStg contained class.
  376. //
  377. // When this class is opened, it opens the default data stream (aka the
  378. // unnamed data stream aka the Contents stream). It puts that stream handle
  379. // in a member CNtfsStream object, when then owns the handle, though this
  380. // class also continues to use the handle.
  381. //
  382. // There is no place in an NTFS file to store a Storage's clsid or
  383. // state bits, so these are stored in seperate "Control Stream" (which is
  384. // not enumerated by CNtfsEnumSTATSTG).
  385. //
  386. //+============================================================================
  387. #define NTFSSTORAGE_SIG LONGSIG('N','T','S','T')
  388. #define NTFSSTORAGE_SIGDEL LONGSIG('N','T','S','t')
  389. ////////////////////////////////////////////////////////////////
  390. // IStorage for an NTFS File. Hungarian Prefix "nffstg"
  391. //
  392. class CNtfsStorage : public IStorage,
  393. public IBlockingLock,
  394. public ITimeAndNoticeControl,
  395. public CPropertySetStorage
  396. #if DBG
  397. , public IStorageTest
  398. #endif
  399. {
  400. friend CNtfsStorageForPropSetStg;
  401. // ------------
  402. // Construction
  403. // ------------
  404. public:
  405. inline CNtfsStorage( DWORD grfMode );
  406. inline ~CNtfsStorage();
  407. private:
  408. // --------
  409. // IUnknown
  410. // --------
  411. public:
  412. HRESULT STDMETHODCALLTYPE QueryInterface( REFIID riid, void** ppvObject );
  413. ULONG STDMETHODCALLTYPE AddRef();
  414. ULONG STDMETHODCALLTYPE Release();
  415. // --------
  416. // IStorage
  417. // --------
  418. public:
  419. virtual HRESULT STDMETHODCALLTYPE CreateStream(
  420. /* [string][in] */ const OLECHAR __RPC_FAR *pwcsName,
  421. /* [in] */ DWORD grfMode,
  422. /* [in] */ DWORD reserved1,
  423. /* [in] */ DWORD reserved2,
  424. /* [out] */ IStream __RPC_FAR *__RPC_FAR *ppstm);
  425. virtual HRESULT STDMETHODCALLTYPE OpenStream(
  426. /* [string][in] */ const OLECHAR __RPC_FAR *pwcsName,
  427. /* [unique][in] */ void __RPC_FAR *reserved1,
  428. /* [in] */ DWORD grfMode,
  429. /* [in] */ DWORD reserved2,
  430. /* [out] */ IStream __RPC_FAR *__RPC_FAR *ppstm);
  431. virtual HRESULT STDMETHODCALLTYPE CreateStorage(
  432. /* [string][in] */ const OLECHAR __RPC_FAR *pwcsName,
  433. /* [in] */ DWORD grfMode,
  434. /* [in] */ DWORD reserved1,
  435. /* [in] */ DWORD reserved2,
  436. /* [out] */ IStorage __RPC_FAR *__RPC_FAR *ppstg);
  437. virtual HRESULT STDMETHODCALLTYPE OpenStorage(
  438. /* [string][unique][in] */ const OLECHAR __RPC_FAR *pwcsName,
  439. /* [unique][in] */ IStorage __RPC_FAR *pstgPriority,
  440. /* [in] */ DWORD grfMode,
  441. /* [unique][in] */ SNB snbExclude,
  442. /* [in] */ DWORD reserved,
  443. /* [out] */ IStorage __RPC_FAR *__RPC_FAR *ppstg);
  444. virtual HRESULT STDMETHODCALLTYPE CopyTo(
  445. /* [in] */ DWORD ciidExclude,
  446. /* [size_is][unique][in] */ const IID __RPC_FAR *rgiidExclude,
  447. /* [unique][in] */ SNB snbExclude,
  448. /* [unique][in] */ IStorage __RPC_FAR *pstgDest);
  449. virtual HRESULT STDMETHODCALLTYPE MoveElementTo(
  450. /* [string][in] */ const OLECHAR __RPC_FAR *pwcsName,
  451. /* [unique][in] */ IStorage __RPC_FAR *pstgDest,
  452. /* [string][in] */ const OLECHAR __RPC_FAR *pwcsNewName,
  453. /* [in] */ DWORD grfFlags);
  454. virtual HRESULT STDMETHODCALLTYPE Commit(
  455. /* [in] */ DWORD grfCommitFlags);
  456. virtual HRESULT STDMETHODCALLTYPE Revert( void);
  457. virtual HRESULT STDMETHODCALLTYPE EnumElements(
  458. /* [in] */ DWORD reserved1,
  459. /* [size_is][unique][in] */ void __RPC_FAR *reserved2,
  460. /* [in] */ DWORD reserved3,
  461. /* [out] */ IEnumSTATSTG __RPC_FAR *__RPC_FAR *ppenum);
  462. virtual HRESULT STDMETHODCALLTYPE DestroyElement(
  463. /* [string][in] */ const OLECHAR __RPC_FAR *pwcsName);
  464. virtual HRESULT STDMETHODCALLTYPE RenameElement(
  465. /* [string][in] */ const OLECHAR __RPC_FAR *pwcsOldName,
  466. /* [string][in] */ const OLECHAR __RPC_FAR *pwcsNewName);
  467. virtual HRESULT STDMETHODCALLTYPE SetElementTimes(
  468. /* [string][unique][in] */ const OLECHAR __RPC_FAR *pwcsName,
  469. /* [unique][in] */ const FILETIME __RPC_FAR *pctime,
  470. /* [unique][in] */ const FILETIME __RPC_FAR *patime,
  471. /* [unique][in] */ const FILETIME __RPC_FAR *pmtime);
  472. virtual HRESULT STDMETHODCALLTYPE SetClass(
  473. /* [in] */ REFCLSID clsid);
  474. virtual HRESULT STDMETHODCALLTYPE SetStateBits(
  475. /* [in] */ DWORD grfStateBits,
  476. /* [in] */ DWORD grfMask);
  477. virtual HRESULT STDMETHODCALLTYPE Stat(
  478. /* [out] */ STATSTG __RPC_FAR *pstatstg,
  479. /* [in] */ DWORD grfStatFlag);
  480. // -------------
  481. // IBlockingLock
  482. // -------------
  483. public:
  484. virtual HRESULT STDMETHODCALLTYPE Lock(DWORD dwTimeout);
  485. virtual HRESULT STDMETHODCALLTYPE Unlock();
  486. // ---------------------
  487. // ITimeAndNoticeControl
  488. // ---------------------
  489. #define NFF_SUPPRESS_NOTIFY 1
  490. public:
  491. virtual HRESULT STDMETHODCALLTYPE SuppressChanges(DWORD, DWORD);
  492. // ------------
  493. // IStorageTest
  494. // ------------
  495. public:
  496. #if DBG
  497. STDMETHOD(UseNTFS4Streams)( BOOL fUseNTFS4Streams );
  498. STDMETHOD(GetFormatVersion)(WORD *pw);
  499. STDMETHOD(SimulateLowMemory)( BOOL fSimulate );
  500. STDMETHOD(GetLockCount)();
  501. STDMETHOD(IsDirty)();
  502. #endif
  503. // -----------------------------------------
  504. // Public methods (not part of an interface)
  505. // -----------------------------------------
  506. public:
  507. HRESULT InitFromName( const WCHAR *pwszName,
  508. BOOL fCreate,
  509. DWORD dwFlags );
  510. HRESULT InitFromMainStreamHandle( HANDLE* phFileContents,
  511. const WCHAR* wcszPath,
  512. BOOL fCreate,
  513. DWORD dwOpenFlags,
  514. DWORD fmtKnown );
  515. HRESULT GetStreamHandle( HANDLE *phStream,
  516. const WCHAR *pwcsName,
  517. DWORD grfMode,
  518. BOOL fCreateAPI);
  519. HRESULT NewCNtfsStream( const WCHAR *pwcsName,
  520. DWORD grfMode,
  521. BOOL fCreateAPI,
  522. CNtfsStream **ppstm );
  523. static HRESULT IsNffAppropriate( const WCHAR* pwszName );
  524. // ----------------
  525. // Internal Methods
  526. // ----------------
  527. public:
  528. HRESULT DestroyStreamElement( const OLECHAR *poszName );
  529. HRESULT InitCNtfsStream( CNtfsStream *pnffstm,
  530. HANDLE hStream,
  531. DWORD grfMode,
  532. const WCHAR * pwcsName );
  533. protected:
  534. static HRESULT IsNffAppropriate( HANDLE hFile, const WCHAR* wcszPath );
  535. HRESULT OpenControlStream( BOOL fCreateAPI );
  536. HRESULT DeleteControlStream();
  537. HRESULT WriteControlStream();
  538. HRESULT StreamExists( const WCHAR *pwszName );
  539. HRESULT SetAllStreamsTimes( const FILETIME *pctime,
  540. const FILETIME *patime,
  541. const FILETIME *pmtime);
  542. HRESULT MarkAllStreamsAux();
  543. private:
  544. HRESULT ShutDownStorage();
  545. HRESULT CheckReverted();
  546. HRESULT GetFilePath( WCHAR** ppwszPath );
  547. BOOL FindAlreadyOpenStream( const OLECHAR* pwcsName,
  548. CNtfsStream** pstm);
  549. static HRESULT ModeToNtFlags(DWORD grfMode,
  550. DWORD dwFlags,
  551. BOOL fCreateAPI,
  552. ACCESS_MASK *pam,
  553. ULONG *pulAttributes,
  554. ULONG *pulSharing,
  555. ULONG *pulCreateDisposition,
  556. ULONG *pulCreateOptions);
  557. HRESULT OpenNtStream( const CNtfsStreamName& nsnName,
  558. DWORD grfMode,
  559. DWORD grfAttrs,
  560. BOOL fCreate,
  561. HANDLE *ph);
  562. static HRESULT OpenNtFileHandle( const UNICODE_STRING& usNtfsName,
  563. HANDLE hParent,
  564. DWORD grfMode,
  565. DWORD grfAttrs,
  566. BOOL fCreate,
  567. HANDLE *ph);
  568. static HRESULT IsOfflineFile( HANDLE hFile );
  569. static HRESULT TestNt4StreamNameBug(
  570. PFILE_STREAM_INFORMATION pfsiBuf,
  571. const WCHAR* wcszPath );
  572. static BOOL IsControlStreamExtant(
  573. PFILE_STREAM_INFORMATION pfsiBuf );
  574. static BOOL AreAnyNtPropertyStreamsExtant(
  575. PFILE_STREAM_INFORMATION pfsiBuf );
  576. // --------------
  577. // Internal state
  578. // --------------
  579. protected:
  580. // _cReferences; is in the base class (CPropertySetStorage)
  581. ULONG _sig;
  582. CNFFTreeMutex * _pTreeMutex;
  583. // Mode used to open/create this storage, used by Stat
  584. DWORD _grfMode;
  585. // E.g. "D:" or "\", used to compose full path name in Stat
  586. WCHAR _wcDriveLetter;
  587. // Implementation of IStorage for CPropertySetStorage
  588. CNtfsStorageForPropSetStg _NtfsStorageForPropSetStg;
  589. // Linked list of open streams.
  590. CNtfsStream *_pstmOpenList;
  591. // File handle for the file (::DATA$ stream)
  592. HANDLE _hFileMainStream;
  593. // Control stream, used to store clsid & state bits
  594. HANDLE _hFileControlStream;
  595. WORD _hsmStatus;
  596. DWORD _dwStgStateBits; // Cache of GetStateBits()
  597. CLSID _clsidStgClass; // Cache for GetClass()
  598. // Property bag. This is a member since it is QI-eqivalent to
  599. // the IStorage interface
  600. CPropertyBagEx _PropertyBagEx;
  601. // Various state flags
  602. // #define NFF_UPDATE_MTIME 0x0001 Not Implemented
  603. #define NFF_NO_TIME_CHANGE 0x0002
  604. #define NFF_REVERTED 0x0004
  605. #define NFF_INIT_COMPLETED 0x0008
  606. #define NFF_FILE_CLOSED 0x0010
  607. #define NFF_MARK_AUX 0x0020
  608. DWORD _dwState;
  609. // Saved filetime
  610. FILETIME _filetime;
  611. }; // class CNtfsStorage
  612. //
  613. // Version Zero structure of the data in the control stream.
  614. //
  615. typedef struct tagNFFCONTROLBITS {
  616. WORD sig;
  617. WORD hsmStatus;
  618. DWORD bits; // Set/Get StateBits
  619. CLSID clsid; // Set/Get Class
  620. } NFFCONTROLBITS;
  621. inline HRESULT
  622. CNtfsStorage::CheckReverted()
  623. {
  624. if(NFF_REVERTED & _dwState)
  625. return STG_E_REVERTED;
  626. return S_OK;
  627. }
  628. #define STGM_READ_ATTRIBUTE 0x04 // Not a real STGM_ flag.
  629. // Values for the "dwFlags" argument in NFFOpen*()
  630. //
  631. #define NFFOPEN_NORMAL 0x0
  632. //#define NFFOPEN_ASYNC 0x0
  633. #define NFFOPEN_SYNC 0x0001
  634. #define NFFOPEN_CONTENTSTREAM 0x0004
  635. #define NFFOPEN_SUPPRESS_CHANGES 0x0008
  636. #define NFFOPEN_CLEANUP 0x0010
  637. //-----------------------------------------------------------
  638. //
  639. // NFFOpen();
  640. //
  641. // Routine for the rest of Storage to use to open NFF files
  642. // without knowing a lot of details.
  643. //
  644. HRESULT NFFOpen(const WCHAR *pwszName,
  645. DWORD grfMode,
  646. DWORD dwFlags,
  647. BOOL fCreate,
  648. REFIID riid,
  649. void **ppv);
  650. HRESULT
  651. NFFOpenOnHandle( BOOL fCreate,
  652. DWORD grfMode,
  653. DWORD stgfmt,
  654. HANDLE* phStream,
  655. REFIID riid,
  656. void **ppv);
  657. HRESULT EnumNtStreams (HANDLE h,
  658. FILE_STREAM_INFORMATION ** ppfsi,
  659. ULONG *pulBufferSize,
  660. BOOL fGrow);
  661. const FILE_STREAM_INFORMATION *
  662. FindStreamInFSI( IN const FILE_STREAM_INFORMATION *pfsi,
  663. IN const WCHAR *pwszNtStreamName // In :*:$data format
  664. );
  665. BOOL
  666. FindStreamPrefixInFSI( IN const FILE_STREAM_INFORMATION *pfsi,
  667. IN const WCHAR *pwszPrefix
  668. );
  669. BOOL IsNtStreamExtant( const FILE_STREAM_INFORMATION *pfsi,
  670. const WCHAR *pwsz );
  671. //+----------------------------------------------------------------------------
  672. //
  673. // Method: CNtfsEnumSTATSTG::NextFSI (private)
  674. //
  675. // Advances the FILE Stream Information pointer to the nex record
  676. // Returns NULL after the last record.
  677. //
  678. //+----------------------------------------------------------------------------
  679. inline PFILE_STREAM_INFORMATION
  680. NextFSI( const FILE_STREAM_INFORMATION *pFSI )
  681. {
  682. if( 0 == pFSI->NextEntryOffset )
  683. return NULL;
  684. else
  685. return (PFILE_STREAM_INFORMATION) ((PBYTE)pFSI + pFSI->NextEntryOffset);
  686. }
  687. inline BOOL
  688. IsNtStreamExtant( const FILE_STREAM_INFORMATION *pfsi,
  689. const WCHAR *pwszNtStreamName // In :*:$data format
  690. )
  691. {
  692. return( NULL != FindStreamInFSI( pfsi, pwszNtStreamName ));
  693. }