| 1 | // Licensed to the .NET Foundation under one or more agreements. |
| 2 | // The .NET Foundation licenses this file to you under the MIT license. |
| 3 | // See the LICENSE file in the project root for more information. |
| 4 | //***************************************************************************** |
| 5 | // StgTiggerStorage.h |
| 6 | // |
| 7 | |
| 8 | // |
| 9 | // TiggerStorage is a stripped down version of compound doc files. Doc files |
| 10 | // have some very useful and complex features to them, unfortunately nothing |
| 11 | // comes for free. Given the incredibly tuned format of existing .tlb files, |
| 12 | // every single byte counts and 10% added by doc files is just too exspensive. |
| 13 | // |
| 14 | // The storage itself is made up of a bunch of streams (each aligned to a 4 byte |
| 15 | // value), followed at the end of the file with the header. The header is |
| 16 | // put at the end so that you can continue to write as many streams as you |
| 17 | // like without thrashing the disk. |
| 18 | // +-------------------+ |
| 19 | // | Signature | |
| 20 | // +-------------------+ |
| 21 | // | Stream 1, 2, [] | |
| 22 | // +-------------------+ |
| 23 | // | STORAGEHEADER | |
| 24 | // | Extra data | |
| 25 | // | STORAGESTREAM[] | |
| 26 | // +-------------------+ |
| 27 | // | offset | |
| 28 | // +-------------------+ |
| 29 | // |
| 30 | // The STORAGEHEADER contains flags describing the rest of the file, including |
| 31 | // the ability to have extra data stored in the header. If there is extra |
| 32 | // data, then immediately after the STORAGEHEADER struct is a 4 byte size of |
| 33 | // that data, followed immediately by the extra data. The length must be |
| 34 | // 4 byte aligned so that the first STORAGESTREAM starts on an aligned |
| 35 | // boundary. The contents of the extra data is caller defined. |
| 36 | // |
| 37 | // This code handles the signature at the start of the file, and the list of |
| 38 | // streams at the end (kept in the header). The data in each stream is, of |
| 39 | // course, caller specific. |
| 40 | // |
| 41 | // This code requires the StgIO code to handle the input and output from the |
| 42 | // backing storage, whatever scheme that may be. There are no consistency |
| 43 | // checks on the data (for example crc's) due to the expense in computation |
| 44 | // required. There is a signature at the front of the file and in the header. |
| 45 | // |
| 46 | //***************************************************************************** |
| 47 | #ifndef __StgTiggerStorage_h__ |
| 48 | #define __StgTiggerStorage_h__ |
| 49 | |
| 50 | //#include "utilcode.h" // Helpers. |
| 51 | |
| 52 | #include "mdfileformat.h" |
| 53 | |
| 54 | typedef CDynArray<STORAGESTREAM> STORAGESTREAMLST; |
| 55 | |
| 56 | |
| 57 | // Forwards. |
| 58 | class TiggerStream; |
| 59 | class StgIO; |
| 60 | |
| 61 | |
| 62 | |
| 63 | class TiggerStorage : |
| 64 | public IStorage |
| 65 | { |
| 66 | friend class TiggerStream; |
| 67 | public: |
| 68 | TiggerStorage(); |
| 69 | virtual ~TiggerStorage(); |
| 70 | |
| 71 | // IUnknown so you can ref count this thing. |
| 72 | virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, PVOID *pp) |
| 73 | { return (BadError(E_NOTIMPL)); } |
| 74 | virtual ULONG STDMETHODCALLTYPE AddRef() |
| 75 | { return (InterlockedIncrement(&m_cRef)); } |
| 76 | virtual ULONG STDMETHODCALLTYPE Release() |
| 77 | { |
| 78 | SUPPORTS_DAC_HOST_ONLY; |
| 79 | ULONG cRef; |
| 80 | if ((cRef = InterlockedDecrement(&m_cRef)) == 0) |
| 81 | delete this; |
| 82 | return (cRef); |
| 83 | } |
| 84 | |
| 85 | |
| 86 | //***************************************************************************** |
| 87 | // Init this storage object on top of the given storage unit. |
| 88 | //***************************************************************************** |
| 89 | HRESULT Init( // Return code. |
| 90 | StgIO *pStgIO, // The I/O subsystem. |
| 91 | __in __in_z LPSTR pVersion); // Compiler-supplied CLR version |
| 92 | |
| 93 | //***************************************************************************** |
| 94 | // Retrieves a the size and a pointer to the extra data that can optionally be |
| 95 | // written in the header of the storage system. This data is not required to |
| 96 | // be in the file, in which case *pcbExtra will come back as 0 and pbData will |
| 97 | // be set to null. You must have initialized the storage using Init() before |
| 98 | // calling this function. |
| 99 | //***************************************************************************** |
| 100 | HRESULT ( // Return code. |
| 101 | ULONG *, // Return size of extra data. |
| 102 | BYTE *&pbData); // Return a pointer to extra data. |
| 103 | |
| 104 | //***************************************************************************** |
| 105 | // Flushes the header to disk. |
| 106 | //***************************************************************************** |
| 107 | HRESULT ( // Return code. |
| 108 | STORAGESTREAMLST *pList, // List of streams. |
| 109 | ULONG , // Size of extra data, may be 0. |
| 110 | BYTE *); // Pointer to extra data for header. |
| 111 | |
| 112 | //***************************************************************************** |
| 113 | // Called when all data has been written. Forces cached data to be flushed |
| 114 | // and stream lists to be validated. |
| 115 | //***************************************************************************** |
| 116 | HRESULT WriteFinished( // Return code. |
| 117 | STORAGESTREAMLST *pList, // List of streams. |
| 118 | ULONG *pcbSaveSize, // Return size of total data. |
| 119 | BOOL fDeltaSave); // Was this a delta |
| 120 | |
| 121 | //***************************************************************************** |
| 122 | // Called after a successful rewrite of an existing file. The in memory |
| 123 | // backing store is no longer valid because all new data is in memory and |
| 124 | // on disk. This is essentially the same state as created, so free up some |
| 125 | // working set and remember this state. |
| 126 | //***************************************************************************** |
| 127 | HRESULT ResetBackingStore(); // Return code. |
| 128 | |
| 129 | //***************************************************************************** |
| 130 | // Called to restore the original file. If this operation is successful, then |
| 131 | // the backup file is deleted as requested. The restore of the file is done |
| 132 | // in write through mode to the disk help ensure the contents are not lost. |
| 133 | // This is not good enough to fulfill ACID props, but it ain't that bad. |
| 134 | //***************************************************************************** |
| 135 | HRESULT Restore( // Return code. |
| 136 | __in __in_z LPWSTR szBackup, // If non-0, backup the file. |
| 137 | int bDeleteOnSuccess); // Delete backup file if successful. |
| 138 | |
| 139 | //***************************************************************************** |
| 140 | // Given the name of a stream that will be persisted into a stream in this |
| 141 | // storage type, figure out how big that stream would be including the user's |
| 142 | // stream data and the header overhead the file format incurs. The name is |
| 143 | // stored in ANSI and the header struct is aligned to 4 bytes. |
| 144 | //***************************************************************************** |
| 145 | static HRESULT GetStreamSaveSize( // Return code. |
| 146 | LPCWSTR szStreamName, // Name of stream. |
| 147 | UINT32 cbDataSize, // Size of data to go into stream. |
| 148 | UINT32 *pcbSaveSize); // Return data size plus stream overhead. |
| 149 | |
| 150 | //***************************************************************************** |
| 151 | // Return the fixed size overhead for the storage implementation. This includes |
| 152 | // the signature and fixed header overhead. The overhead in the header for each |
| 153 | // stream is calculated as part of GetStreamSaveSize because these structs are |
| 154 | // variable sized on the name. |
| 155 | //***************************************************************************** |
| 156 | static HRESULT GetStorageSaveSize( // Return code. |
| 157 | ULONG *pcbSaveSize, // [in] current size, [out] plus overhead. |
| 158 | ULONG , // How much extra data to store in header. |
| 159 | LPCSTR pRuntimeVersion); // The version string as it's length is part of the total size. |
| 160 | |
| 161 | //***************************************************************************** |
| 162 | // Adjust the offset in each known stream to match where it will wind up after |
| 163 | // a save operation. |
| 164 | //***************************************************************************** |
| 165 | static HRESULT CalcOffsets( // Return code. |
| 166 | STORAGESTREAMLST *pStreamList, // List of streams for header. |
| 167 | ULONG , // Size of variable extra data in header. |
| 168 | LPCSTR pRuntimeVersion); // The version string as it's length is part of the total size. |
| 169 | |
| 170 | |
| 171 | |
| 172 | //***************************************************************************** |
| 173 | // Returns the size of the signature plus the verion information |
| 174 | //***************************************************************************** |
| 175 | static HRESULT SizeOfStorageSignature( |
| 176 | LPCSTR pRuntimeVersion, // The version string as it's length is part of the total size. |
| 177 | ULONG *pcbSignatureSize); |
| 178 | |
| 179 | // IStorage |
| 180 | virtual HRESULT STDMETHODCALLTYPE CreateStream( |
| 181 | const OLECHAR *pwcsName, |
| 182 | DWORD grfMode, |
| 183 | DWORD reserved1, |
| 184 | DWORD reserved2, |
| 185 | IStream **ppstm); |
| 186 | |
| 187 | virtual HRESULT STDMETHODCALLTYPE CreateStream( |
| 188 | LPCSTR szName, |
| 189 | DWORD grfMode, |
| 190 | DWORD reserved1, |
| 191 | DWORD reserved2, |
| 192 | IStream **ppstm) |
| 193 | DAC_UNEXPECTED(); |
| 194 | |
| 195 | virtual HRESULT STDMETHODCALLTYPE OpenStream( |
| 196 | const OLECHAR *pwcsName, |
| 197 | void *reserved1, |
| 198 | DWORD grfMode, |
| 199 | DWORD reserved2, |
| 200 | IStream **ppstm); |
| 201 | |
| 202 | virtual HRESULT STDMETHODCALLTYPE CreateStorage( |
| 203 | const OLECHAR *pwcsName, |
| 204 | DWORD grfMode, |
| 205 | DWORD dwStgFmt, |
| 206 | DWORD reserved2, |
| 207 | IStorage **ppstg); |
| 208 | |
| 209 | virtual HRESULT STDMETHODCALLTYPE OpenStorage( |
| 210 | const OLECHAR * wcsName, |
| 211 | IStorage * pStgPriority, |
| 212 | DWORD dwMode, |
| 213 | __in |
| 214 | SNB snbExclude, |
| 215 | DWORD reserved, |
| 216 | IStorage ** ppStg); |
| 217 | |
| 218 | virtual HRESULT STDMETHODCALLTYPE CopyTo( |
| 219 | DWORD cIidExclude, |
| 220 | const IID * rgIidExclude, |
| 221 | __in |
| 222 | SNB snbExclude, |
| 223 | IStorage * pStgDest); |
| 224 | |
| 225 | virtual HRESULT STDMETHODCALLTYPE MoveElementTo( |
| 226 | const OLECHAR *pwcsName, |
| 227 | IStorage *pstgDest, |
| 228 | const OLECHAR *pwcsNewName, |
| 229 | DWORD grfFlags); |
| 230 | |
| 231 | virtual HRESULT STDMETHODCALLTYPE Commit( |
| 232 | DWORD grfCommitFlags); |
| 233 | |
| 234 | virtual HRESULT STDMETHODCALLTYPE Revert(); |
| 235 | |
| 236 | virtual HRESULT STDMETHODCALLTYPE EnumElements( |
| 237 | DWORD reserved1, |
| 238 | void *reserved2, |
| 239 | DWORD reserved3, |
| 240 | IEnumSTATSTG **ppenum); |
| 241 | |
| 242 | virtual HRESULT STDMETHODCALLTYPE DestroyElement( |
| 243 | const OLECHAR *pwcsName); |
| 244 | |
| 245 | virtual HRESULT STDMETHODCALLTYPE RenameElement( |
| 246 | const OLECHAR *pwcsOldName, |
| 247 | const OLECHAR *pwcsNewName); |
| 248 | |
| 249 | virtual HRESULT STDMETHODCALLTYPE SetElementTimes( |
| 250 | const OLECHAR *pwcsName, |
| 251 | const FILETIME *pctime, |
| 252 | const FILETIME *patime, |
| 253 | const FILETIME *pmtime); |
| 254 | |
| 255 | virtual HRESULT STDMETHODCALLTYPE SetClass( |
| 256 | REFCLSID clsid); |
| 257 | |
| 258 | virtual HRESULT STDMETHODCALLTYPE SetStateBits( |
| 259 | DWORD grfStateBits, |
| 260 | DWORD grfMask); |
| 261 | |
| 262 | virtual HRESULT STDMETHODCALLTYPE Stat( |
| 263 | STATSTG *pstatstg, |
| 264 | DWORD grfStatFlag); |
| 265 | |
| 266 | virtual HRESULT STDMETHODCALLTYPE OpenStream( |
| 267 | LPCWSTR szStream, |
| 268 | ULONG *pcbData, |
| 269 | void **ppAddress); |
| 270 | |
| 271 | // Access storage object. |
| 272 | StgIO *GetStgIO() |
| 273 | { return (m_pStgIO); } |
| 274 | |
| 275 | #if defined(_DEBUG) |
| 276 | ULONG PrintSizeInfo( // Size of streams. |
| 277 | bool verbose); // Be verbose? |
| 278 | #endif |
| 279 | |
| 280 | protected: |
| 281 | HRESULT Write( // Return code. |
| 282 | LPCSTR szName, // Name of stream we're writing. |
| 283 | const void *pData, // Data to write. |
| 284 | ULONG cbData, // Size of data. |
| 285 | ULONG *pcbWritten); // How much did we write. |
| 286 | |
| 287 | private: |
| 288 | HRESULT FindStream(LPCSTR szName, __out PSTORAGESTREAM *stream); |
| 289 | HRESULT WriteSignature(LPCSTR pVersion); |
| 290 | HRESULT VerifySignature(PSTORAGESIGNATURE pSig); |
| 291 | HRESULT (); |
| 292 | HRESULT (); |
| 293 | |
| 294 | static HRESULT GetDefaultVersion(LPCSTR* ppVersion); |
| 295 | |
| 296 | public: |
| 297 | // This function is a workaround to allow access to the "version requested" string. |
| 298 | HRESULT (const void **ppv, ULONG *pcb); |
| 299 | |
| 300 | private: |
| 301 | // State data. |
| 302 | StgIO *m_pStgIO; // Storage subsystem. |
| 303 | LONG m_cRef; // Ref count for COM. |
| 304 | |
| 305 | // Header data. |
| 306 | STORAGEHEADER m_StgHdr; // Header for storage. |
| 307 | STORAGESTREAMLST m_Streams; // List of streams in the storage. |
| 308 | PSTORAGESTREAM m_pStreamList; // For read mode. |
| 309 | void *; // Pointer to extra data if on disk. |
| 310 | }; |
| 311 | |
| 312 | |
| 313 | //***************************************************************************** |
| 314 | // Debugging helpers. #define __SAVESIZE_TRACE__ to enable. |
| 315 | //***************************************************************************** |
| 316 | |
| 317 | // #define __SAVESIZE_TRACE__ |
| 318 | #ifdef __SAVESIZE_TRACE__ |
| 319 | #define SAVETRACE(func) DEBUG_STMT(func) |
| 320 | #else |
| 321 | #define SAVETRACE(func) |
| 322 | #endif // __SAVESIZE_TRACE__ |
| 323 | |
| 324 | #endif // StgTiggerStorage |
| 325 | |
| 326 | |
| 327 | |
| 328 | // EOF |
| 329 | |