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.

920 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. CNtfsStorage *_pNtfsStorage;
  285. }; // class CNtfsStorageForPropSetStg : public IStorage
  286. inline
  287. CNtfsStorageForPropSetStg::CNtfsStorageForPropSetStg( )
  288. {
  289. nffXTrace( "CNtfsStorageForPropSetStg::CNtfsStorageForPropSetStg" );
  290. }
  291. inline
  292. CNtfsStorageForPropSetStg::~CNtfsStorageForPropSetStg()
  293. {
  294. nffXTrace( "CNtfsStorageForPropSetStg::~CNtfsStorageForPropSetStg" );
  295. _pNtfsStorage = NULL;
  296. }
  297. inline void
  298. CNtfsStorageForPropSetStg::Init( CNtfsStorage *pNtfsStorage )
  299. {
  300. _pNtfsStorage = pNtfsStorage;
  301. }
  302. //+============================================================================
  303. //
  304. // Class: CNFFTreeMutex
  305. //
  306. // This class implements the Tree Mutex for and NFF file.
  307. //
  308. // The tree mutex is taken at the top of all IStorage and IStream calls.
  309. //
  310. //+============================================================================
  311. class CNFFTreeMutex: public IBlockingLock
  312. {
  313. // ------------
  314. // Construction
  315. // ------------
  316. public:
  317. inline CNFFTreeMutex( );
  318. inline ~CNFFTreeMutex();
  319. inline HRESULT Init();
  320. // --------
  321. // IUnknown
  322. // --------
  323. public:
  324. HRESULT STDMETHODCALLTYPE QueryInterface( REFIID riid, void** ppvObject );
  325. ULONG STDMETHODCALLTYPE AddRef();
  326. ULONG STDMETHODCALLTYPE Release();
  327. // -------------
  328. // IBlockingLock
  329. // -------------
  330. public:
  331. virtual HRESULT STDMETHODCALLTYPE Lock(DWORD dwTimeout);
  332. virtual HRESULT STDMETHODCALLTYPE Unlock();
  333. public:
  334. #if DBG
  335. LONG GetLockCount();
  336. #endif
  337. private:
  338. LONG _cRefs;
  339. BOOL _fInitialized;
  340. mutable CRITICAL_SECTION _cs;
  341. };
  342. inline
  343. CNFFTreeMutex::CNFFTreeMutex()
  344. {
  345. _cRefs = 1;
  346. _fInitialized = FALSE;
  347. }
  348. inline
  349. HRESULT CNFFTreeMutex::Init()
  350. {
  351. if (_fInitialized == FALSE)
  352. {
  353. NTSTATUS nts = RtlInitializeCriticalSection(&_cs);
  354. if (!NT_SUCCESS(nts))
  355. return NtStatusToScode (nts);
  356. _fInitialized = TRUE;
  357. }
  358. return S_OK;
  359. }
  360. inline
  361. CNFFTreeMutex::~CNFFTreeMutex()
  362. {
  363. if (_fInitialized)
  364. DeleteCriticalSection( &_cs );
  365. }
  366. //+============================================================================
  367. //
  368. // Class: CNtfsStorage
  369. //
  370. // This class is both an IStorage and an IPropertySetStorage. It also offers
  371. // a special IStorage interface which is used by the CPropertySetStorage
  372. // implementation, this special IStorage is implemented in the
  373. // CNtfsStorageForPropSetStg contained class.
  374. //
  375. // When this class is opened, it opens the default data stream (aka the
  376. // unnamed data stream aka the Contents stream). It puts that stream handle
  377. // in a member CNtfsStream object, when then owns the handle, though this
  378. // class also continues to use the handle.
  379. //
  380. // There is no place in an NTFS file to store a Storage's clsid or
  381. // state bits, so these are stored in seperate "Control Stream" (which is
  382. // not enumerated by CNtfsEnumSTATSTG).
  383. //
  384. //+============================================================================
  385. #define NTFSSTORAGE_SIG LONGSIG('N','T','S','T')
  386. #define NTFSSTORAGE_SIGDEL LONGSIG('N','T','S','t')
  387. ////////////////////////////////////////////////////////////////
  388. // IStorage for an NTFS File. Hungarian Prefix "nffstg"
  389. //
  390. class CNtfsStorage : public IStorage,
  391. public IBlockingLock,
  392. public ITimeAndNoticeControl,
  393. public CPropertySetStorage
  394. #if DBG
  395. , public IStorageTest
  396. #endif
  397. {
  398. friend CNtfsStorageForPropSetStg;
  399. // ------------
  400. // Construction
  401. // ------------
  402. public:
  403. inline CNtfsStorage( DWORD grfMode );
  404. inline ~CNtfsStorage();
  405. private:
  406. // --------
  407. // IUnknown
  408. // --------
  409. public:
  410. HRESULT STDMETHODCALLTYPE QueryInterface( REFIID riid, void** ppvObject );
  411. ULONG STDMETHODCALLTYPE AddRef();
  412. ULONG STDMETHODCALLTYPE Release();
  413. // --------
  414. // IStorage
  415. // --------
  416. public:
  417. virtual HRESULT STDMETHODCALLTYPE CreateStream(
  418. /* [string][in] */ const OLECHAR __RPC_FAR *pwcsName,
  419. /* [in] */ DWORD grfMode,
  420. /* [in] */ DWORD reserved1,
  421. /* [in] */ DWORD reserved2,
  422. /* [out] */ IStream __RPC_FAR *__RPC_FAR *ppstm);
  423. virtual HRESULT STDMETHODCALLTYPE OpenStream(
  424. /* [string][in] */ const OLECHAR __RPC_FAR *pwcsName,
  425. /* [unique][in] */ void __RPC_FAR *reserved1,
  426. /* [in] */ DWORD grfMode,
  427. /* [in] */ DWORD reserved2,
  428. /* [out] */ IStream __RPC_FAR *__RPC_FAR *ppstm);
  429. virtual HRESULT STDMETHODCALLTYPE CreateStorage(
  430. /* [string][in] */ const OLECHAR __RPC_FAR *pwcsName,
  431. /* [in] */ DWORD grfMode,
  432. /* [in] */ DWORD reserved1,
  433. /* [in] */ DWORD reserved2,
  434. /* [out] */ IStorage __RPC_FAR *__RPC_FAR *ppstg);
  435. virtual HRESULT STDMETHODCALLTYPE OpenStorage(
  436. /* [string][unique][in] */ const OLECHAR __RPC_FAR *pwcsName,
  437. /* [unique][in] */ IStorage __RPC_FAR *pstgPriority,
  438. /* [in] */ DWORD grfMode,
  439. /* [unique][in] */ SNB snbExclude,
  440. /* [in] */ DWORD reserved,
  441. /* [out] */ IStorage __RPC_FAR *__RPC_FAR *ppstg);
  442. virtual HRESULT STDMETHODCALLTYPE CopyTo(
  443. /* [in] */ DWORD ciidExclude,
  444. /* [size_is][unique][in] */ const IID __RPC_FAR *rgiidExclude,
  445. /* [unique][in] */ SNB snbExclude,
  446. /* [unique][in] */ IStorage __RPC_FAR *pstgDest);
  447. virtual HRESULT STDMETHODCALLTYPE MoveElementTo(
  448. /* [string][in] */ const OLECHAR __RPC_FAR *pwcsName,
  449. /* [unique][in] */ IStorage __RPC_FAR *pstgDest,
  450. /* [string][in] */ const OLECHAR __RPC_FAR *pwcsNewName,
  451. /* [in] */ DWORD grfFlags);
  452. virtual HRESULT STDMETHODCALLTYPE Commit(
  453. /* [in] */ DWORD grfCommitFlags);
  454. virtual HRESULT STDMETHODCALLTYPE Revert( void);
  455. virtual HRESULT STDMETHODCALLTYPE EnumElements(
  456. /* [in] */ DWORD reserved1,
  457. /* [size_is][unique][in] */ void __RPC_FAR *reserved2,
  458. /* [in] */ DWORD reserved3,
  459. /* [out] */ IEnumSTATSTG __RPC_FAR *__RPC_FAR *ppenum);
  460. virtual HRESULT STDMETHODCALLTYPE DestroyElement(
  461. /* [string][in] */ const OLECHAR __RPC_FAR *pwcsName);
  462. virtual HRESULT STDMETHODCALLTYPE RenameElement(
  463. /* [string][in] */ const OLECHAR __RPC_FAR *pwcsOldName,
  464. /* [string][in] */ const OLECHAR __RPC_FAR *pwcsNewName);
  465. virtual HRESULT STDMETHODCALLTYPE SetElementTimes(
  466. /* [string][unique][in] */ const OLECHAR __RPC_FAR *pwcsName,
  467. /* [unique][in] */ const FILETIME __RPC_FAR *pctime,
  468. /* [unique][in] */ const FILETIME __RPC_FAR *patime,
  469. /* [unique][in] */ const FILETIME __RPC_FAR *pmtime);
  470. virtual HRESULT STDMETHODCALLTYPE SetClass(
  471. /* [in] */ REFCLSID clsid);
  472. virtual HRESULT STDMETHODCALLTYPE SetStateBits(
  473. /* [in] */ DWORD grfStateBits,
  474. /* [in] */ DWORD grfMask);
  475. virtual HRESULT STDMETHODCALLTYPE Stat(
  476. /* [out] */ STATSTG __RPC_FAR *pstatstg,
  477. /* [in] */ DWORD grfStatFlag);
  478. // -------------
  479. // IBlockingLock
  480. // -------------
  481. public:
  482. virtual HRESULT STDMETHODCALLTYPE Lock(DWORD dwTimeout);
  483. virtual HRESULT STDMETHODCALLTYPE Unlock();
  484. // ---------------------
  485. // ITimeAndNoticeControl
  486. // ---------------------
  487. #define NFF_SUPPRESS_NOTIFY 1
  488. public:
  489. virtual HRESULT STDMETHODCALLTYPE SuppressChanges(DWORD, DWORD);
  490. // ------------
  491. // IStorageTest
  492. // ------------
  493. public:
  494. #if DBG
  495. STDMETHOD(UseNTFS4Streams)( BOOL fUseNTFS4Streams );
  496. STDMETHOD(GetFormatVersion)(WORD *pw);
  497. STDMETHOD(SimulateLowMemory)( BOOL fSimulate );
  498. STDMETHOD(GetLockCount)();
  499. STDMETHOD(IsDirty)();
  500. #endif
  501. // -----------------------------------------
  502. // Public methods (not part of an interface)
  503. // -----------------------------------------
  504. public:
  505. HRESULT InitFromName( const WCHAR *pwszName,
  506. BOOL fCreate,
  507. DWORD dwFlags );
  508. HRESULT InitFromMainStreamHandle( HANDLE* phFileContents,
  509. const WCHAR* wcszPath,
  510. BOOL fCreate,
  511. DWORD dwOpenFlags,
  512. DWORD fmtKnown );
  513. HRESULT GetStreamHandle( HANDLE *phStream,
  514. const WCHAR *pwcsName,
  515. DWORD grfMode,
  516. BOOL fCreateAPI);
  517. HRESULT NewCNtfsStream( const WCHAR *pwcsName,
  518. DWORD grfMode,
  519. BOOL fCreateAPI,
  520. CNtfsStream **ppstm );
  521. static HRESULT IsNffAppropriate( const WCHAR* pwszName );
  522. // ----------------
  523. // Internal Methods
  524. // ----------------
  525. public:
  526. HRESULT DestroyStreamElement( const OLECHAR *poszName );
  527. HRESULT InitCNtfsStream( CNtfsStream *pnffstm,
  528. HANDLE hStream,
  529. DWORD grfMode,
  530. const WCHAR * pwcsName );
  531. protected:
  532. static HRESULT IsNffAppropriate( HANDLE hFile, const WCHAR* wcszPath );
  533. HRESULT OpenControlStream( BOOL fCreateAPI );
  534. HRESULT DeleteControlStream();
  535. HRESULT WriteControlStream();
  536. HRESULT StreamExists( const WCHAR *pwszName );
  537. HRESULT SetAllStreamsTimes( const FILETIME *pctime,
  538. const FILETIME *patime,
  539. const FILETIME *pmtime);
  540. HRESULT MarkAllStreamsAux();
  541. HRESULT InitUsnInfo();
  542. static DWORD WINAPI OplockWait(PVOID pvThis);
  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. HRESULT TakeOplock( const UNICODE_STRING& us );
  569. static HRESULT IsOfflineFile( HANDLE hFile );
  570. static HRESULT TestNt4StreamNameBug(
  571. PFILE_STREAM_INFORMATION pfsiBuf,
  572. const WCHAR* wcszPath );
  573. static BOOL IsControlStreamExtant(
  574. PFILE_STREAM_INFORMATION pfsiBuf );
  575. static BOOL AreAnyNtPropertyStreamsExtant(
  576. PFILE_STREAM_INFORMATION pfsiBuf );
  577. // --------------
  578. // Internal state
  579. // --------------
  580. protected:
  581. // _cReferences; is in the base class (CPropertySetStorage)
  582. ULONG _sig;
  583. CNFFTreeMutex * _pTreeMutex;
  584. // Mode used to open/create this storage, used by Stat
  585. DWORD _grfMode;
  586. // E.g. "D:" or "\", used to compose full path name in Stat
  587. WCHAR _wcDriveLetter;
  588. // Implementation of IStorage for CPropertySetStorage
  589. CNtfsStorageForPropSetStg _NtfsStorageForPropSetStg;
  590. // Linked list of open streams.
  591. CNtfsStream *_pstmOpenList;
  592. // File handle for the file (::DATA$ stream)
  593. HANDLE _hFileMainStream;
  594. // File handle for the READ_ATTRIBUTES Oplock File Open
  595. HANDLE _hFileOplock;
  596. // Control stream, used to store clsid & state bits
  597. HANDLE _hFileControlStream;
  598. WORD _hsmStatus;
  599. DWORD _dwStgStateBits; // Cache of GetStateBits()
  600. CLSID _clsidStgClass; // Cache for GetClass()
  601. // Property bag. This is a member since it is QI-eqivalent to
  602. // the IStorage interface
  603. CPropertyBagEx _PropertyBagEx;
  604. // Various state flags
  605. // #define NFF_UPDATE_MTIME 0x0001 Not Implemented
  606. #define NFF_NO_TIME_CHANGE 0x0002
  607. #define NFF_REVERTED 0x0004
  608. #define NFF_INIT_COMPLETED 0x0008
  609. #define NFF_FILE_CLOSED 0x0010
  610. #define NFF_MARK_AUX 0x0020
  611. #define NFF_OPLOCKED 0x0040
  612. DWORD _dwState;
  613. // Saved filetime
  614. FILETIME _filetime;
  615. OVERLAPPED _ovlpOplock;
  616. HANDLE _hOplockThread;
  617. MARK_HANDLE_INFO _mhi;
  618. }; // class CNtfsStorage
  619. //
  620. // Version Zero structure of the data in the control stream.
  621. //
  622. typedef struct tagNFFCONTROLBITS {
  623. WORD sig;
  624. WORD hsmStatus;
  625. DWORD bits; // Set/Get StateBits
  626. CLSID clsid; // Set/Get Class
  627. } NFFCONTROLBITS;
  628. inline HRESULT
  629. CNtfsStorage::CheckReverted()
  630. {
  631. if(NFF_REVERTED & _dwState)
  632. return STG_E_REVERTED;
  633. return S_OK;
  634. }
  635. #define STGM_READ_ATTRIBUTE 0x04 // Not a real STGM_ flag.
  636. // Values for the "dwFlags" argument in NFFOpen*()
  637. //
  638. #define NFFOPEN_NORMAL 0x0
  639. #define NFFOPEN_ASYNC 0x0
  640. #define NFFOPEN_SYNC 0x0001
  641. #define NFFOPEN_OPLOCK 0x0002
  642. #define NFFOPEN_CONTENTSTREAM 0x0004
  643. #define NFFOPEN_SUPPRESS_CHANGES 0x0008
  644. #define NFFOPEN_CLEANUP 0x0010
  645. //-----------------------------------------------------------
  646. //
  647. // NFFOpen();
  648. //
  649. // Routine for the rest of Storage to use to open NFF files
  650. // without knowing a lot of details.
  651. //
  652. HRESULT NFFOpen(const WCHAR *pwszName,
  653. DWORD grfMode,
  654. DWORD dwFlags,
  655. BOOL fCreate,
  656. REFIID riid,
  657. void **ppv);
  658. HRESULT
  659. NFFOpenOnHandle( BOOL fCreate,
  660. DWORD grfMode,
  661. DWORD stgfmt,
  662. HANDLE* phStream,
  663. REFIID riid,
  664. void **ppv);
  665. HRESULT EnumNtStreams (HANDLE h,
  666. FILE_STREAM_INFORMATION ** ppfsi,
  667. ULONG *pulBufferSize,
  668. BOOL fGrow);
  669. const FILE_STREAM_INFORMATION *
  670. FindStreamInFSI( IN const FILE_STREAM_INFORMATION *pfsi,
  671. IN const WCHAR *pwszNtStreamName // In :*:$data format
  672. );
  673. BOOL
  674. FindStreamPrefixInFSI( IN const FILE_STREAM_INFORMATION *pfsi,
  675. IN const WCHAR *pwszPrefix
  676. );
  677. BOOL IsNtStreamExtant( const FILE_STREAM_INFORMATION *pfsi,
  678. const WCHAR *pwsz );
  679. //+----------------------------------------------------------------------------
  680. //
  681. // Method: CNtfsEnumSTATSTG::NextFSI (private)
  682. //
  683. // Advances the FILE Stream Information pointer to the nex record
  684. // Returns NULL after the last record.
  685. //
  686. //+----------------------------------------------------------------------------
  687. inline PFILE_STREAM_INFORMATION
  688. NextFSI( const FILE_STREAM_INFORMATION *pFSI )
  689. {
  690. if( 0 == pFSI->NextEntryOffset )
  691. return NULL;
  692. else
  693. return (PFILE_STREAM_INFORMATION) ((PBYTE)pFSI + pFSI->NextEntryOffset);
  694. }
  695. inline BOOL
  696. IsNtStreamExtant( const FILE_STREAM_INFORMATION *pfsi,
  697. const WCHAR *pwszNtStreamName // In :*:$data format
  698. )
  699. {
  700. return( NULL != FindStreamInFSI( pfsi, pwszNtStreamName ));
  701. }