diff options
Diffstat (limited to 'src/md/inc/stgtiggerstorage.h')
-rw-r--r-- | src/md/inc/stgtiggerstorage.h | 329 |
1 files changed, 329 insertions, 0 deletions
diff --git a/src/md/inc/stgtiggerstorage.h b/src/md/inc/stgtiggerstorage.h new file mode 100644 index 0000000000..d00b6a49b1 --- /dev/null +++ b/src/md/inc/stgtiggerstorage.h @@ -0,0 +1,329 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// +//***************************************************************************** +// StgTiggerStorage.h +// + +// +// TiggerStorage is a stripped down version of compound doc files. Doc files +// have some very useful and complex features to them, unfortunately nothing +// comes for free. Given the incredibly tuned format of existing .tlb files, +// every single byte counts and 10% added by doc files is just too exspensive. +// +// The storage itself is made up of a bunch of streams (each aligned to a 4 byte +// value), followed at the end of the file with the header. The header is +// put at the end so that you can continue to write as many streams as you +// like without thrashing the disk. +// +-------------------+ +// | Signature | +// +-------------------+ +// | Stream 1, 2, [] | +// +-------------------+ +// | STORAGEHEADER | +// | Extra data | +// | STORAGESTREAM[] | +// +-------------------+ +// | offset | +// +-------------------+ +// +// The STORAGEHEADER contains flags describing the rest of the file, including +// the ability to have extra data stored in the header. If there is extra +// data, then immediately after the STORAGEHEADER struct is a 4 byte size of +// that data, followed immediately by the extra data. The length must be +// 4 byte aligned so that the first STORAGESTREAM starts on an aligned +// boundary. The contents of the extra data is caller defined. +// +// This code handles the signature at the start of the file, and the list of +// streams at the end (kept in the header). The data in each stream is, of +// course, caller specific. +// +// This code requires the StgIO code to handle the input and output from the +// backing storage, whatever scheme that may be. There are no consistency +// checks on the data (for example crc's) due to the expense in computation +// required. There is a signature at the front of the file and in the header. +// +//***************************************************************************** +#ifndef __StgTiggerStorage_h__ +#define __StgTiggerStorage_h__ + +//#include "utilcode.h" // Helpers. + +#include "mdfileformat.h" + +typedef CDynArray<STORAGESTREAM> STORAGESTREAMLST; + + +// Forwards. +class TiggerStream; +class StgIO; + + + +class TiggerStorage : + public IStorage +{ +friend class TiggerStream; +public: + TiggerStorage(); + ~TiggerStorage(); + +// IUnknown so you can ref count this thing. + virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, PVOID *pp) + { return (BadError(E_NOTIMPL)); } + virtual ULONG STDMETHODCALLTYPE AddRef() + { return (InterlockedIncrement(&m_cRef)); } + virtual ULONG STDMETHODCALLTYPE Release() + { + SUPPORTS_DAC_HOST_ONLY; + ULONG cRef; + if ((cRef = InterlockedDecrement(&m_cRef)) == 0) + delete this; + return (cRef); + } + + +//***************************************************************************** +// Init this storage object on top of the given storage unit. +//***************************************************************************** + HRESULT Init( // Return code. + StgIO *pStgIO, // The I/O subsystem. + __in __in_z LPSTR pVersion); // Compiler-supplied CLR version + +//***************************************************************************** +// Retrieves a the size and a pointer to the extra data that can optionally be +// written in the header of the storage system. This data is not required to +// be in the file, in which case *pcbExtra will come back as 0 and pbData will +// be set to null. You must have initialized the storage using Init() before +// calling this function. +//***************************************************************************** + HRESULT GetExtraData( // Return code. + ULONG *pcbExtra, // Return size of extra data. + BYTE *&pbData); // Return a pointer to extra data. + +//***************************************************************************** +// Flushes the header to disk. +//***************************************************************************** + HRESULT WriteHeader( // Return code. + STORAGESTREAMLST *pList, // List of streams. + ULONG cbExtraData, // Size of extra data, may be 0. + BYTE *pbExtraData); // Pointer to extra data for header. + +//***************************************************************************** +// Called when all data has been written. Forces cached data to be flushed +// and stream lists to be validated. +//***************************************************************************** + HRESULT WriteFinished( // Return code. + STORAGESTREAMLST *pList, // List of streams. + ULONG *pcbSaveSize, // Return size of total data. + BOOL fDeltaSave); // Was this a delta + +//***************************************************************************** +// Called after a successful rewrite of an existing file. The in memory +// backing store is no longer valid because all new data is in memory and +// on disk. This is essentially the same state as created, so free up some +// working set and remember this state. +//***************************************************************************** + HRESULT ResetBackingStore(); // Return code. + +//***************************************************************************** +// Called to restore the original file. If this operation is successful, then +// the backup file is deleted as requested. The restore of the file is done +// in write through mode to the disk help ensure the contents are not lost. +// This is not good enough to fulfill ACID props, but it ain't that bad. +//***************************************************************************** + HRESULT Restore( // Return code. + __in __in_z LPWSTR szBackup, // If non-0, backup the file. + int bDeleteOnSuccess); // Delete backup file if successful. + +//***************************************************************************** +// Given the name of a stream that will be persisted into a stream in this +// storage type, figure out how big that stream would be including the user's +// stream data and the header overhead the file format incurs. The name is +// stored in ANSI and the header struct is aligned to 4 bytes. +//***************************************************************************** + static HRESULT GetStreamSaveSize( // Return code. + LPCWSTR szStreamName, // Name of stream. + UINT32 cbDataSize, // Size of data to go into stream. + UINT32 *pcbSaveSize); // Return data size plus stream overhead. + +//***************************************************************************** +// Return the fixed size overhead for the storage implementation. This includes +// the signature and fixed header overhead. The overhead in the header for each +// stream is calculated as part of GetStreamSaveSize because these structs are +// variable sized on the name. +//***************************************************************************** + static HRESULT GetStorageSaveSize( // Return code. + ULONG *pcbSaveSize, // [in] current size, [out] plus overhead. + ULONG cbExtra, // How much extra data to store in header. + LPCSTR pRuntimeVersion); // The version string as it's length is part of the total size. + +//***************************************************************************** +// Adjust the offset in each known stream to match where it will wind up after +// a save operation. +//***************************************************************************** + static HRESULT CalcOffsets( // Return code. + STORAGESTREAMLST *pStreamList, // List of streams for header. + ULONG cbExtra, // Size of variable extra data in header. + LPCSTR pRuntimeVersion); // The version string as it's length is part of the total size. + + + +//***************************************************************************** +// Returns the size of the signature plus the verion information +//***************************************************************************** + static HRESULT SizeOfStorageSignature( + LPCSTR pRuntimeVersion, // The version string as it's length is part of the total size. + ULONG *pcbSignatureSize); + +// IStorage + virtual HRESULT STDMETHODCALLTYPE CreateStream( + const OLECHAR *pwcsName, + DWORD grfMode, + DWORD reserved1, + DWORD reserved2, + IStream **ppstm); + + virtual HRESULT STDMETHODCALLTYPE CreateStream( + LPCSTR szName, + DWORD grfMode, + DWORD reserved1, + DWORD reserved2, + IStream **ppstm) + DAC_UNEXPECTED(); + + virtual HRESULT STDMETHODCALLTYPE OpenStream( + const OLECHAR *pwcsName, + void *reserved1, + DWORD grfMode, + DWORD reserved2, + IStream **ppstm); + + virtual HRESULT STDMETHODCALLTYPE CreateStorage( + const OLECHAR *pwcsName, + DWORD grfMode, + DWORD dwStgFmt, + DWORD reserved2, + IStorage **ppstg); + + virtual HRESULT STDMETHODCALLTYPE OpenStorage( + const OLECHAR * wcsName, + IStorage * pStgPriority, + DWORD dwMode, + __in + SNB snbExclude, + DWORD reserved, + IStorage ** ppStg); + + virtual HRESULT STDMETHODCALLTYPE CopyTo( + DWORD cIidExclude, + const IID * rgIidExclude, + __in + SNB snbExclude, + IStorage * pStgDest); + + virtual HRESULT STDMETHODCALLTYPE MoveElementTo( + const OLECHAR *pwcsName, + IStorage *pstgDest, + const OLECHAR *pwcsNewName, + DWORD grfFlags); + + virtual HRESULT STDMETHODCALLTYPE Commit( + DWORD grfCommitFlags); + + virtual HRESULT STDMETHODCALLTYPE Revert(); + + virtual HRESULT STDMETHODCALLTYPE EnumElements( + DWORD reserved1, + void *reserved2, + DWORD reserved3, + IEnumSTATSTG **ppenum); + + virtual HRESULT STDMETHODCALLTYPE DestroyElement( + const OLECHAR *pwcsName); + + virtual HRESULT STDMETHODCALLTYPE RenameElement( + const OLECHAR *pwcsOldName, + const OLECHAR *pwcsNewName); + + virtual HRESULT STDMETHODCALLTYPE SetElementTimes( + const OLECHAR *pwcsName, + const FILETIME *pctime, + const FILETIME *patime, + const FILETIME *pmtime); + + virtual HRESULT STDMETHODCALLTYPE SetClass( + REFCLSID clsid); + + virtual HRESULT STDMETHODCALLTYPE SetStateBits( + DWORD grfStateBits, + DWORD grfMask); + + virtual HRESULT STDMETHODCALLTYPE Stat( + STATSTG *pstatstg, + DWORD grfStatFlag); + + virtual HRESULT STDMETHODCALLTYPE OpenStream( + LPCWSTR szStream, + ULONG *pcbData, + void **ppAddress); + + // Access storage object. + StgIO *GetStgIO() + { return (m_pStgIO); } + +#if defined(_DEBUG) + ULONG PrintSizeInfo( // Size of streams. + bool verbose); // Be verbose? +#endif + +protected: + HRESULT Write( // Return code. + LPCSTR szName, // Name of stream we're writing. + const void *pData, // Data to write. + ULONG cbData, // Size of data. + ULONG *pcbWritten); // How much did we write. + +private: + HRESULT FindStream(LPCSTR szName, __out PSTORAGESTREAM *stream); + HRESULT WriteSignature(LPCSTR pVersion); + HRESULT VerifySignature(PSTORAGESIGNATURE pSig); + HRESULT ReadHeader(); + HRESULT VerifyHeader(); + + static HRESULT GetDefaultVersion(LPCSTR* ppVersion); + +public: + // This function is a workaround to allow access to the "version requested" string. + HRESULT GetHeaderPointer(const void **ppv, ULONG *pcb); + +private: + // State data. + StgIO *m_pStgIO; // Storage subsystem. + LONG m_cRef; // Ref count for COM. + + // Header data. + STORAGEHEADER m_StgHdr; // Header for storage. + STORAGESTREAMLST m_Streams; // List of streams in the storage. + PSTORAGESTREAM m_pStreamList; // For read mode. + void *m_pbExtra; // Pointer to extra data if on disk. +}; + + +//***************************************************************************** +// Debugging helpers. #define __SAVESIZE_TRACE__ to enable. +//***************************************************************************** + +// #define __SAVESIZE_TRACE__ +#ifdef __SAVESIZE_TRACE__ +#define SAVETRACE(func) DEBUG_STMT(func) +#else +#define SAVETRACE(func) +#endif // __SAVESIZE_TRACE__ + +#endif // StgTiggerStorage + + + +// EOF |