|
|
#pragma once
//+============================================================================
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1994 - 1998.
//
// File: hntfsstg.hxx
//
// This file provides the NFF (NTFS Flat File) IStorage declaration.
//
// History:
// 5/6/98 MikeHill
// - Split the Init method into two methods, one which is
// file name based and the other which is handle based.
// 5/18/98 MikeHill
// - Simplified constructur and added Init method.
//
//+============================================================================
#include "prophdr.hxx"
#include "stgprops.hxx"
#include <new.h>
#include "psetstg.hxx"
#include "cli.hxx" // CLargeInteger/CULargeInteger
#include "hntfsstm.hxx"
#include "bag.hxx" // CPropertyBagEx
#include "names.hxx"
#ifndef ELEMENTS
#define ELEMENTS(x) (sizeof(x)/sizeof(x[0]))
#endif
//+============================================================================
//
// Class CNtfsSTATSTGArray
//
// This class maintains an array of STATSTG structures. It's used by
// CNtfsEnumSTATSTG. We separate this out from that class so that if you
// clone a CNtfsEnumSTATSTG enumerator, the data can be shared, but the
// clone can maintain its own seek pointer.
//
//+============================================================================
class CNtfsSTATSTGArray { public:
CNtfsSTATSTGArray( IBlockingLock *pBlockingLock ); ~CNtfsSTATSTGArray(); HRESULT Init( HANDLE hFile );
public:
HRESULT NextAt( ULONG iNext, STATSTG *prgstatstg, ULONG *pcFetched );
inline VOID AddRef(); inline VOID Release(); inline ULONG GetCount();
private:
HRESULT ReadFileStreamInfo( HANDLE hFile );
private:
LONG _cRefs; IBlockingLock *_pBlockingLock;
// A cache of the FileStreamInformation. To refresh this cache, the
// caller must release the IEnum and re-create it.
PFILE_STREAM_INFORMATION _pFileStreamInformation; ULONG _cFileStreamInformation;
}; // class CNtfsSTATSTGArray
inline CNtfsSTATSTGArray::CNtfsSTATSTGArray( IBlockingLock *pBlockingLock ) { nffXTrace( "CNtfsSTATSTGArray::CNtfsSTATSTGArray" );
_cFileStreamInformation = 0; _cRefs = 1; _pFileStreamInformation = NULL;
_pBlockingLock = pBlockingLock; _pBlockingLock->AddRef(); }
inline CNtfsSTATSTGArray::~CNtfsSTATSTGArray() { nffXTrace( "CNtfsSTATSTGArray::~CNtfsSTATSTGArray" ); if( NULL != _pFileStreamInformation ) { CoTaskMemFree( _pFileStreamInformation ); _pFileStreamInformation = NULL; }
DfpAssert( NULL != _pBlockingLock ); _pBlockingLock->Release(); }
inline VOID CNtfsSTATSTGArray::AddRef() { LONG cRefs;
cRefs = InterlockedIncrement( &_cRefs );
nffDebug(( DEB_REFCOUNT, "CNtfsSTATSTGArray::AddRef(this==%x) == %d\n", this, cRefs));
}
inline VOID CNtfsSTATSTGArray::Release() { LONG cRefs;
cRefs = InterlockedDecrement( &_cRefs );
if( 0 == cRefs ) delete this;
nffDebug((DEB_REFCOUNT, "CNtfsSTATSTGArray::Release(this=%x) == %d\n", this, cRefs)); }
inline ULONG CNtfsSTATSTGArray::GetCount() { nffITrace( "CNtfsSTATSTGArray::GetCount" ); return( _cFileStreamInformation ); }
//+============================================================================
//
// Class: CNtfsEnumSTATSTG
//
// This class IEnum-erates STATSTG structures for the NTFS IStorage
// implementation (CNtfsStorage). The data for this enumerator is actually
// held in a CNtfsSTATSTGArray object.
//
//+============================================================================
#define NTFSENUMSTATSTG_SIG LONGSIG('N','T','S','E')
#define NTFSENUMSTATSTG_SIGDEL LONGSIG('N','T','S','e')
class CNtfsEnumSTATSTG: public IEnumSTATSTG { public:
CNtfsEnumSTATSTG( IBlockingLock *pBlockingLock ); CNtfsEnumSTATSTG( CNtfsEnumSTATSTG &Other ); ~CNtfsEnumSTATSTG();
public:
STDMETHOD(QueryInterface)( REFIID riid, void **ppvObject); STDMETHOD_(ULONG, AddRef)(void); STDMETHOD_(ULONG, Release)(void);
STDMETHOD(Next)(ULONG celt, STATSTG * rgelt, ULONG * pceltFetched); STDMETHOD(Skip)(ULONG celt); STDMETHOD(Reset)(); STDMETHOD(Clone)(IEnumSTATSTG **ppenum);
public:
STDMETHOD(Init)(HANDLE hFile);
private:
ULONG _ulSig; LONG _cRefs; ULONG _istatNextToRead; IBlockingLock *_pBlockingLock; CNtfsSTATSTGArray *_pstatstgarray;
}; // class CNtfsEnumSTATSTG
inline CNtfsEnumSTATSTG::CNtfsEnumSTATSTG( IBlockingLock *pBlockingLock ) { nffXTrace( "CNtfsEnumSTATSTG::CNtfsEnumSTATSTG(pBlockingLock)" ); _ulSig = NTFSENUMSTATSTG_SIG; _cRefs = 1; _istatNextToRead = 0; _pstatstgarray = NULL;
_pBlockingLock = pBlockingLock; _pBlockingLock->AddRef(); }
inline CNtfsEnumSTATSTG::CNtfsEnumSTATSTG( CNtfsEnumSTATSTG &Other ) { nffXTrace( "CNtfsEnumSTATSTG::CNtfsEnumSTATSTG(CntfsEnumSTATSTG)" ); Other._pBlockingLock->Lock( INFINITE );
// Initialize
new(this) CNtfsEnumSTATSTG( Other._pBlockingLock );
// Load state from Other
_pstatstgarray = Other._pstatstgarray; _pstatstgarray->AddRef(); _istatNextToRead = Other._istatNextToRead;
Other._pBlockingLock->Unlock(); }
inline CNtfsEnumSTATSTG::~CNtfsEnumSTATSTG() { nffXTrace( "CNtfsEnumSTATSTG::~CNtfsEnumSTATSTG" ); if( NULL != _pstatstgarray ) _pstatstgarray->Release();
if( NULL != _pBlockingLock ) _pBlockingLock->Release();
_ulSig = NTFSENUMSTATSTG_SIGDEL; }
inline HRESULT STDMETHODCALLTYPE CNtfsEnumSTATSTG::Init( HANDLE hFile ) { nffITrace( "CNtfsEnumSTATSTG::Init" ); HRESULT hr = S_OK;
// Create a STATSTG Array handler
_pstatstgarray = new CNtfsSTATSTGArray( _pBlockingLock ); if( NULL == _pstatstgarray ) { hr = E_OUTOFMEMORY; goto Exit; }
// Load the array from the handle
hr = _pstatstgarray->Init( hFile ); if( FAILED(hr) ) goto Exit;
Exit:
return( hr ); }
//+----------------------------------------------------------------------------
//
// Class: CNtfsStorageForPropSetStg
//
// This class presents an IStorage implementation that behaves exactly
// as CPropertySetStorage expects. It primary calls to CNtfsStorage,
// but implements Create/OpenStorage by creating a DocFile on an NTFS
// stream.
//
//+----------------------------------------------------------------------------
class CNtfsStorage;
class CNtfsStorageForPropSetStg : public IStorage { public:
CNtfsStorageForPropSetStg( ); ~CNtfsStorageForPropSetStg(); inline void Init( CNtfsStorage *pNtfsStorage );
public:
HRESULT STDMETHODCALLTYPE QueryInterface( REFIID riid, void** ppvObject ); ULONG STDMETHODCALLTYPE AddRef(); ULONG STDMETHODCALLTYPE Release();
HRESULT STDMETHODCALLTYPE CreateStream( /* [string][in] */ const OLECHAR __RPC_FAR *pwcsName, /* [in] */ DWORD grfMode, /* [in] */ DWORD reserved1, /* [in] */ DWORD reserved2, /* [out] */ IStream __RPC_FAR *__RPC_FAR *ppstm);
HRESULT STDMETHODCALLTYPE OpenStream( /* [string][in] */ const OLECHAR __RPC_FAR *pwcsName, /* [unique][in] */ void __RPC_FAR *reserved1, /* [in] */ DWORD grfMode, /* [in] */ DWORD reserved2, /* [out] */ IStream __RPC_FAR *__RPC_FAR *ppstm);
HRESULT STDMETHODCALLTYPE CreateStorage( /* [string][in] */ const OLECHAR __RPC_FAR *pwcsName, /* [in] */ DWORD grfMode, /* [in] */ DWORD reserved1, /* [in] */ DWORD reserved2, /* [out] */ IStorage __RPC_FAR *__RPC_FAR *ppstg);
HRESULT STDMETHODCALLTYPE OpenStorage( /* [string][unique][in] */ const OLECHAR __RPC_FAR *pwcsName, /* [unique][in] */ IStorage __RPC_FAR *pstgPriority, /* [in] */ DWORD grfMode, /* [unique][in] */ SNB snbExclude, /* [in] */ DWORD reserved, /* [out] */ IStorage __RPC_FAR *__RPC_FAR *ppstg);
HRESULT STDMETHODCALLTYPE CopyTo( /* [in] */ DWORD ciidExclude, /* [size_is][unique][in] */ const IID __RPC_FAR *rgiidExclude, /* [unique][in] */ SNB snbExclude, /* [unique][in] */ IStorage __RPC_FAR *pstgDest);
HRESULT STDMETHODCALLTYPE MoveElementTo( /* [string][in] */ const OLECHAR __RPC_FAR *pwcsName, /* [unique][in] */ IStorage __RPC_FAR *pstgDest, /* [string][in] */ const OLECHAR __RPC_FAR *pwcsNewName, /* [in] */ DWORD grfFlags);
HRESULT STDMETHODCALLTYPE Commit( /* [in] */ DWORD grfCommitFlags);
HRESULT STDMETHODCALLTYPE Revert( void);
HRESULT STDMETHODCALLTYPE EnumElements( /* [in] */ DWORD reserved1, /* [size_is][unique][in] */ void __RPC_FAR *reserved2, /* [in] */ DWORD reserved3, /* [out] */ IEnumSTATSTG __RPC_FAR *__RPC_FAR *ppenum);
HRESULT STDMETHODCALLTYPE DestroyElement( /* [string][in] */ const OLECHAR __RPC_FAR *pwcsName);
HRESULT STDMETHODCALLTYPE RenameElement( /* [string][in] */ const OLECHAR __RPC_FAR *pwcsOldName, /* [string][in] */ const OLECHAR __RPC_FAR *pwcsNewName);
HRESULT STDMETHODCALLTYPE SetElementTimes( /* [string][unique][in] */ const OLECHAR __RPC_FAR *pwcsName, /* [unique][in] */ const FILETIME __RPC_FAR *pctime, /* [unique][in] */ const FILETIME __RPC_FAR *patime, /* [unique][in] */ const FILETIME __RPC_FAR *pmtime);
HRESULT STDMETHODCALLTYPE SetClass( /* [in] */ REFCLSID clsid);
HRESULT STDMETHODCALLTYPE SetStateBits( /* [in] */ DWORD grfStateBits, /* [in] */ DWORD grfMask);
HRESULT STDMETHODCALLTYPE Stat( /* [out] */ STATSTG __RPC_FAR *pstatstg, /* [in] */ DWORD grfStatFlag);
public:
static HRESULT CreateOrOpenStorageOnILockBytes( ILockBytes *plkb, IStorage *pstgPriority, DWORD grfMode, SNB snbExclude, BOOL fCreate, IStorage **ppstg );
private:
HRESULT CreateOrOpenStorage( const OLECHAR *pwcsName, IStorage *pstgPriority, DWORD grfMode, SNB snbExclude, BOOL fCreate, IStorage **ppstg );
private:
// This CNtfsStorage is considered the same COM object as this IPropertySetStorage.
CNtfsStorage *_pNtfsStorage;
}; // class CNtfsStorageForPropSetStg : public IStorage
inline CNtfsStorageForPropSetStg::CNtfsStorageForPropSetStg( ) { nffXTrace( "CNtfsStorageForPropSetStg::CNtfsStorageForPropSetStg" ); }
inline CNtfsStorageForPropSetStg::~CNtfsStorageForPropSetStg() { nffXTrace( "CNtfsStorageForPropSetStg::~CNtfsStorageForPropSetStg" ); _pNtfsStorage = NULL; }
inline void CNtfsStorageForPropSetStg::Init( CNtfsStorage *pNtfsStorage ) { _pNtfsStorage = pNtfsStorage; }
//+============================================================================
//
// Class: CNFFTreeMutex
//
// This class implements the Tree Mutex for and NFF file.
//
// The tree mutex is taken at the top of all IStorage and IStream calls.
//
//+============================================================================
class CNFFTreeMutex: public IBlockingLock { // ------------
// Construction
// ------------
public:
inline CNFFTreeMutex( ); inline ~CNFFTreeMutex(); inline HRESULT Init();
// --------
// IUnknown
// --------
public:
HRESULT STDMETHODCALLTYPE QueryInterface( REFIID riid, void** ppvObject ); ULONG STDMETHODCALLTYPE AddRef(); ULONG STDMETHODCALLTYPE Release();
// -------------
// IBlockingLock
// -------------
public:
virtual HRESULT STDMETHODCALLTYPE Lock(DWORD dwTimeout); virtual HRESULT STDMETHODCALLTYPE Unlock();
public:
#if DBG
LONG GetLockCount(); #endif
private: LONG _cRefs; BOOL _fInitialized; mutable CRITICAL_SECTION _cs; };
inline CNFFTreeMutex::CNFFTreeMutex() { _cRefs = 1; _fInitialized = FALSE; }
inline HRESULT CNFFTreeMutex::Init() { if (_fInitialized == FALSE) { NTSTATUS nts = RtlInitializeCriticalSection(&_cs);
if (!NT_SUCCESS(nts)) return NtStatusToScode (nts);
_fInitialized = TRUE; } return S_OK; }
inline CNFFTreeMutex::~CNFFTreeMutex() { if (_fInitialized) DeleteCriticalSection( &_cs ); }
//+============================================================================
//
// Class: CNtfsStorage
//
// This class is both an IStorage and an IPropertySetStorage. It also offers
// a special IStorage interface which is used by the CPropertySetStorage
// implementation, this special IStorage is implemented in the
// CNtfsStorageForPropSetStg contained class.
//
// When this class is opened, it opens the default data stream (aka the
// unnamed data stream aka the Contents stream). It puts that stream handle
// in a member CNtfsStream object, when then owns the handle, though this
// class also continues to use the handle.
//
// There is no place in an NTFS file to store a Storage's clsid or
// state bits, so these are stored in seperate "Control Stream" (which is
// not enumerated by CNtfsEnumSTATSTG).
//
//+============================================================================
#define NTFSSTORAGE_SIG LONGSIG('N','T','S','T')
#define NTFSSTORAGE_SIGDEL LONGSIG('N','T','S','t')
////////////////////////////////////////////////////////////////
// IStorage for an NTFS File. Hungarian Prefix "nffstg"
//
class CNtfsStorage : public IStorage, public IBlockingLock, public ITimeAndNoticeControl, public CPropertySetStorage #if DBG
, public IStorageTest #endif
{
friend CNtfsStorageForPropSetStg;
// ------------
// Construction
// ------------
public:
inline CNtfsStorage( DWORD grfMode ); inline ~CNtfsStorage();
private:
// --------
// IUnknown
// --------
public:
HRESULT STDMETHODCALLTYPE QueryInterface( REFIID riid, void** ppvObject ); ULONG STDMETHODCALLTYPE AddRef(); ULONG STDMETHODCALLTYPE Release();
// --------
// IStorage
// --------
public:
virtual HRESULT STDMETHODCALLTYPE CreateStream( /* [string][in] */ const OLECHAR __RPC_FAR *pwcsName, /* [in] */ DWORD grfMode, /* [in] */ DWORD reserved1, /* [in] */ DWORD reserved2, /* [out] */ IStream __RPC_FAR *__RPC_FAR *ppstm);
virtual HRESULT STDMETHODCALLTYPE OpenStream( /* [string][in] */ const OLECHAR __RPC_FAR *pwcsName, /* [unique][in] */ void __RPC_FAR *reserved1, /* [in] */ DWORD grfMode, /* [in] */ DWORD reserved2, /* [out] */ IStream __RPC_FAR *__RPC_FAR *ppstm);
virtual HRESULT STDMETHODCALLTYPE CreateStorage( /* [string][in] */ const OLECHAR __RPC_FAR *pwcsName, /* [in] */ DWORD grfMode, /* [in] */ DWORD reserved1, /* [in] */ DWORD reserved2, /* [out] */ IStorage __RPC_FAR *__RPC_FAR *ppstg);
virtual HRESULT STDMETHODCALLTYPE OpenStorage( /* [string][unique][in] */ const OLECHAR __RPC_FAR *pwcsName, /* [unique][in] */ IStorage __RPC_FAR *pstgPriority, /* [in] */ DWORD grfMode, /* [unique][in] */ SNB snbExclude, /* [in] */ DWORD reserved, /* [out] */ IStorage __RPC_FAR *__RPC_FAR *ppstg);
virtual HRESULT STDMETHODCALLTYPE CopyTo( /* [in] */ DWORD ciidExclude, /* [size_is][unique][in] */ const IID __RPC_FAR *rgiidExclude, /* [unique][in] */ SNB snbExclude, /* [unique][in] */ IStorage __RPC_FAR *pstgDest);
virtual HRESULT STDMETHODCALLTYPE MoveElementTo( /* [string][in] */ const OLECHAR __RPC_FAR *pwcsName, /* [unique][in] */ IStorage __RPC_FAR *pstgDest, /* [string][in] */ const OLECHAR __RPC_FAR *pwcsNewName, /* [in] */ DWORD grfFlags);
virtual HRESULT STDMETHODCALLTYPE Commit( /* [in] */ DWORD grfCommitFlags);
virtual HRESULT STDMETHODCALLTYPE Revert( void);
virtual HRESULT STDMETHODCALLTYPE EnumElements( /* [in] */ DWORD reserved1, /* [size_is][unique][in] */ void __RPC_FAR *reserved2, /* [in] */ DWORD reserved3, /* [out] */ IEnumSTATSTG __RPC_FAR *__RPC_FAR *ppenum);
virtual HRESULT STDMETHODCALLTYPE DestroyElement( /* [string][in] */ const OLECHAR __RPC_FAR *pwcsName);
virtual HRESULT STDMETHODCALLTYPE RenameElement( /* [string][in] */ const OLECHAR __RPC_FAR *pwcsOldName, /* [string][in] */ const OLECHAR __RPC_FAR *pwcsNewName);
virtual HRESULT STDMETHODCALLTYPE SetElementTimes( /* [string][unique][in] */ const OLECHAR __RPC_FAR *pwcsName, /* [unique][in] */ const FILETIME __RPC_FAR *pctime, /* [unique][in] */ const FILETIME __RPC_FAR *patime, /* [unique][in] */ const FILETIME __RPC_FAR *pmtime);
virtual HRESULT STDMETHODCALLTYPE SetClass( /* [in] */ REFCLSID clsid);
virtual HRESULT STDMETHODCALLTYPE SetStateBits( /* [in] */ DWORD grfStateBits, /* [in] */ DWORD grfMask);
virtual HRESULT STDMETHODCALLTYPE Stat( /* [out] */ STATSTG __RPC_FAR *pstatstg, /* [in] */ DWORD grfStatFlag);
// -------------
// IBlockingLock
// -------------
public:
virtual HRESULT STDMETHODCALLTYPE Lock(DWORD dwTimeout); virtual HRESULT STDMETHODCALLTYPE Unlock();
// ---------------------
// ITimeAndNoticeControl
// ---------------------
#define NFF_SUPPRESS_NOTIFY 1
public: virtual HRESULT STDMETHODCALLTYPE SuppressChanges(DWORD, DWORD);
// ------------
// IStorageTest
// ------------
public:
#if DBG
STDMETHOD(UseNTFS4Streams)( BOOL fUseNTFS4Streams ); STDMETHOD(GetFormatVersion)(WORD *pw); STDMETHOD(SimulateLowMemory)( BOOL fSimulate ); STDMETHOD(GetLockCount)(); STDMETHOD(IsDirty)(); #endif
// -----------------------------------------
// Public methods (not part of an interface)
// -----------------------------------------
public:
HRESULT InitFromName( const WCHAR *pwszName, BOOL fCreate, DWORD dwFlags );
HRESULT InitFromMainStreamHandle( HANDLE* phFileContents, const WCHAR* wcszPath, BOOL fCreate, DWORD dwOpenFlags, DWORD fmtKnown );
HRESULT GetStreamHandle( HANDLE *phStream, const WCHAR *pwcsName, DWORD grfMode, BOOL fCreateAPI);
HRESULT NewCNtfsStream( const WCHAR *pwcsName, DWORD grfMode, BOOL fCreateAPI, CNtfsStream **ppstm );
static HRESULT IsNffAppropriate( const WCHAR* pwszName );
// ----------------
// Internal Methods
// ----------------
public:
HRESULT DestroyStreamElement( const OLECHAR *poszName ); HRESULT InitCNtfsStream( CNtfsStream *pnffstm, HANDLE hStream, DWORD grfMode, const WCHAR * pwcsName );
protected:
static HRESULT IsNffAppropriate( HANDLE hFile, const WCHAR* wcszPath );
HRESULT OpenControlStream( BOOL fCreateAPI ); HRESULT DeleteControlStream(); HRESULT WriteControlStream();
HRESULT StreamExists( const WCHAR *pwszName );
HRESULT SetAllStreamsTimes( const FILETIME *pctime, const FILETIME *patime, const FILETIME *pmtime);
HRESULT MarkAllStreamsAux();
HRESULT InitUsnInfo();
static DWORD WINAPI OplockWait(PVOID pvThis);
private:
HRESULT ShutDownStorage(); HRESULT CheckReverted(); HRESULT GetFilePath( WCHAR** ppwszPath ); BOOL FindAlreadyOpenStream( const OLECHAR* pwcsName, CNtfsStream** pstm);
static HRESULT ModeToNtFlags(DWORD grfMode, DWORD dwFlags, BOOL fCreateAPI, ACCESS_MASK *pam, ULONG *pulAttributes, ULONG *pulSharing, ULONG *pulCreateDisposition, ULONG *pulCreateOptions);
HRESULT OpenNtStream( const CNtfsStreamName& nsnName, DWORD grfMode, DWORD grfAttrs, BOOL fCreate, HANDLE *ph);
static HRESULT OpenNtFileHandle( const UNICODE_STRING& usNtfsName, HANDLE hParent, DWORD grfMode, DWORD grfAttrs, BOOL fCreate, HANDLE *ph);
HRESULT TakeOplock( const UNICODE_STRING& us );
static HRESULT IsOfflineFile( HANDLE hFile );
static HRESULT TestNt4StreamNameBug( PFILE_STREAM_INFORMATION pfsiBuf, const WCHAR* wcszPath );
static BOOL IsControlStreamExtant( PFILE_STREAM_INFORMATION pfsiBuf );
static BOOL AreAnyNtPropertyStreamsExtant( PFILE_STREAM_INFORMATION pfsiBuf );
// --------------
// Internal state
// --------------
protected:
// _cReferences; is in the base class (CPropertySetStorage)
ULONG _sig;
CNFFTreeMutex * _pTreeMutex;
// Mode used to open/create this storage, used by Stat
DWORD _grfMode;
// E.g. "D:" or "\", used to compose full path name in Stat
WCHAR _wcDriveLetter;
// Implementation of IStorage for CPropertySetStorage
CNtfsStorageForPropSetStg _NtfsStorageForPropSetStg;
// Linked list of open streams.
CNtfsStream *_pstmOpenList;
// File handle for the file (::DATA$ stream)
HANDLE _hFileMainStream;
// File handle for the READ_ATTRIBUTES Oplock File Open
HANDLE _hFileOplock;
// Control stream, used to store clsid & state bits
HANDLE _hFileControlStream; WORD _hsmStatus; DWORD _dwStgStateBits; // Cache of GetStateBits()
CLSID _clsidStgClass; // Cache for GetClass()
// Property bag. This is a member since it is QI-eqivalent to
// the IStorage interface
CPropertyBagEx _PropertyBagEx;
// Various state flags
// #define NFF_UPDATE_MTIME 0x0001 Not Implemented
#define NFF_NO_TIME_CHANGE 0x0002
#define NFF_REVERTED 0x0004
#define NFF_INIT_COMPLETED 0x0008
#define NFF_FILE_CLOSED 0x0010
#define NFF_MARK_AUX 0x0020
#define NFF_OPLOCKED 0x0040
DWORD _dwState;
// Saved filetime
FILETIME _filetime;
OVERLAPPED _ovlpOplock; HANDLE _hOplockThread; MARK_HANDLE_INFO _mhi;
}; // class CNtfsStorage
//
// Version Zero structure of the data in the control stream.
//
typedef struct tagNFFCONTROLBITS { WORD sig; WORD hsmStatus; DWORD bits; // Set/Get StateBits
CLSID clsid; // Set/Get Class
} NFFCONTROLBITS;
inline HRESULT CNtfsStorage::CheckReverted() { if(NFF_REVERTED & _dwState) return STG_E_REVERTED; return S_OK; }
#define STGM_READ_ATTRIBUTE 0x04 // Not a real STGM_ flag.
// Values for the "dwFlags" argument in NFFOpen*()
//
#define NFFOPEN_NORMAL 0x0
#define NFFOPEN_ASYNC 0x0
#define NFFOPEN_SYNC 0x0001
#define NFFOPEN_OPLOCK 0x0002
#define NFFOPEN_CONTENTSTREAM 0x0004
#define NFFOPEN_SUPPRESS_CHANGES 0x0008
#define NFFOPEN_CLEANUP 0x0010
//-----------------------------------------------------------
//
// NFFOpen();
//
// Routine for the rest of Storage to use to open NFF files
// without knowing a lot of details.
//
HRESULT NFFOpen(const WCHAR *pwszName, DWORD grfMode, DWORD dwFlags, BOOL fCreate, REFIID riid, void **ppv);
HRESULT NFFOpenOnHandle( BOOL fCreate, DWORD grfMode, DWORD stgfmt, HANDLE* phStream, REFIID riid, void **ppv);
HRESULT EnumNtStreams (HANDLE h, FILE_STREAM_INFORMATION ** ppfsi, ULONG *pulBufferSize, BOOL fGrow);
const FILE_STREAM_INFORMATION * FindStreamInFSI( IN const FILE_STREAM_INFORMATION *pfsi, IN const WCHAR *pwszNtStreamName // In :*:$data format
);
BOOL FindStreamPrefixInFSI( IN const FILE_STREAM_INFORMATION *pfsi, IN const WCHAR *pwszPrefix );
BOOL IsNtStreamExtant( const FILE_STREAM_INFORMATION *pfsi, const WCHAR *pwsz ); //+----------------------------------------------------------------------------
//
// Method: CNtfsEnumSTATSTG::NextFSI (private)
//
// Advances the FILE Stream Information pointer to the nex record
// Returns NULL after the last record.
//
//+----------------------------------------------------------------------------
inline PFILE_STREAM_INFORMATION NextFSI( const FILE_STREAM_INFORMATION *pFSI ) { if( 0 == pFSI->NextEntryOffset ) return NULL; else return (PFILE_STREAM_INFORMATION) ((PBYTE)pFSI + pFSI->NextEntryOffset); }
inline BOOL IsNtStreamExtant( const FILE_STREAM_INFORMATION *pfsi, const WCHAR *pwszNtStreamName // In :*:$data format
) { return( NULL != FindStreamInFSI( pfsi, pwszNtStreamName )); }
|