summaryrefslogtreecommitdiff
path: root/src/md/inc/stgtiggerstorage.h
blob: d00b6a49b182cead5a37f71090e25d03743dd30e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
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