ole32: Fix stream ref counting.
[wine] / dlls / ole32 / storage32.h
1 /*
2  * Compound Storage (32 bit version)
3  *
4  * Implemented using the documentation of the LAOLA project at
5  * <URL:http://wwwwbs.cs.tu-berlin.de/~schwartz/pmh/index.html>
6  * (Thanks to Martin Schwartz <schwartz@cs.tu-berlin.de>)
7  *
8  * This include file contains definitions of types and function
9  * prototypes that are used in the many files implementing the
10  * storage functionality
11  *
12  * Copyright 1998,1999 Francis Beaudet
13  * Copyright 1998,1999 Thuy Nguyen
14  *
15  * This library is free software; you can redistribute it and/or
16  * modify it under the terms of the GNU Lesser General Public
17  * License as published by the Free Software Foundation; either
18  * version 2.1 of the License, or (at your option) any later version.
19  *
20  * This library is distributed in the hope that it will be useful,
21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
23  * Lesser General Public License for more details.
24  *
25  * You should have received a copy of the GNU Lesser General Public
26  * License along with this library; if not, write to the Free Software
27  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
28  */
29 #ifndef __STORAGE32_H__
30 #define __STORAGE32_H__
31
32 #include <stdarg.h>
33
34 #include "windef.h"
35 #include "winbase.h"
36 #include "winnt.h"
37 #include "objbase.h"
38 #include "winreg.h"
39 #include "winternl.h"
40 #include "wine/list.h"
41
42 /*
43  * Definitions for the file format offsets.
44  */
45 static const ULONG OFFSET_BIGBLOCKSIZEBITS   = 0x0000001e;
46 static const ULONG OFFSET_SMALLBLOCKSIZEBITS = 0x00000020;
47 static const ULONG OFFSET_BBDEPOTCOUNT       = 0x0000002C;
48 static const ULONG OFFSET_ROOTSTARTBLOCK     = 0x00000030;
49 static const ULONG OFFSET_SBDEPOTSTART       = 0x0000003C;
50 static const ULONG OFFSET_SBDEPOTCOUNT       = 0x00000040;
51 static const ULONG OFFSET_EXTBBDEPOTSTART    = 0x00000044;
52 static const ULONG OFFSET_EXTBBDEPOTCOUNT    = 0x00000048;
53 static const ULONG OFFSET_BBDEPOTSTART       = 0x0000004C;
54 static const ULONG OFFSET_PS_NAME            = 0x00000000;
55 static const ULONG OFFSET_PS_NAMELENGTH      = 0x00000040;
56 static const ULONG OFFSET_PS_PROPERTYTYPE    = 0x00000042;
57 static const ULONG OFFSET_PS_PREVIOUSPROP    = 0x00000044;
58 static const ULONG OFFSET_PS_NEXTPROP        = 0x00000048;
59 static const ULONG OFFSET_PS_DIRPROP         = 0x0000004C;
60 static const ULONG OFFSET_PS_GUID            = 0x00000050;
61 static const ULONG OFFSET_PS_TSS1            = 0x00000064;
62 static const ULONG OFFSET_PS_TSD1            = 0x00000068;
63 static const ULONG OFFSET_PS_TSS2            = 0x0000006C;
64 static const ULONG OFFSET_PS_TSD2            = 0x00000070;
65 static const ULONG OFFSET_PS_STARTBLOCK      = 0x00000074;
66 static const ULONG OFFSET_PS_SIZE            = 0x00000078;
67 static const WORD  DEF_BIG_BLOCK_SIZE_BITS   = 0x0009;
68 static const WORD  DEF_SMALL_BLOCK_SIZE_BITS = 0x0006;
69 static const WORD  DEF_BIG_BLOCK_SIZE        = 0x0200;
70 static const WORD  DEF_SMALL_BLOCK_SIZE      = 0x0040;
71 static const ULONG BLOCK_EXTBBDEPOT          = 0xFFFFFFFC;
72 static const ULONG BLOCK_SPECIAL             = 0xFFFFFFFD;
73 static const ULONG BLOCK_END_OF_CHAIN        = 0xFFFFFFFE;
74 static const ULONG BLOCK_UNUSED              = 0xFFFFFFFF;
75 static const ULONG PROPERTY_NULL             = 0xFFFFFFFF;
76
77 #define PROPERTY_NAME_MAX_LEN    0x20
78 #define PROPERTY_NAME_BUFFER_LEN 0x40
79
80 #define PROPSET_BLOCK_SIZE 0x00000080
81
82 /*
83  * Property type of relation
84  */
85 #define PROPERTY_RELATION_PREVIOUS 0
86 #define PROPERTY_RELATION_NEXT     1
87 #define PROPERTY_RELATION_DIR      2
88
89 /*
90  * Property type constants
91  */
92 #define PROPTYPE_STORAGE 0x01
93 #define PROPTYPE_STREAM  0x02
94 #define PROPTYPE_ROOT    0x05
95
96 /*
97  * These defines assume a hardcoded blocksize. The code will assert
98  * if the blocksize is different. Some changes will have to be done if it
99  * becomes the case.
100  */
101 #define BIG_BLOCK_SIZE           0x200
102 #define COUNT_BBDEPOTINHEADER    109
103 #define LIMIT_TO_USE_SMALL_BLOCK 0x1000
104 #define NUM_BLOCKS_PER_DEPOT_BLOCK 128
105
106 #define STGM_ACCESS_MODE(stgm)   ((stgm)&0x0000f)
107 #define STGM_SHARE_MODE(stgm)    ((stgm)&0x000f0)
108 #define STGM_CREATE_MODE(stgm)   ((stgm)&0x0f000)
109
110 #define STGM_KNOWN_FLAGS (0xf0ff | \
111      STGM_TRANSACTED | STGM_CONVERT | STGM_PRIORITY | STGM_NOSCRATCH | \
112      STGM_NOSNAPSHOT | STGM_DIRECT_SWMR | STGM_DELETEONRELEASE | STGM_SIMPLE)
113
114 /*
115  * These are signatures to detect the type of Document file.
116  */
117 static const BYTE STORAGE_magic[8]    ={0xd0,0xcf,0x11,0xe0,0xa1,0xb1,0x1a,0xe1};
118 static const BYTE STORAGE_oldmagic[8] ={0xd0,0xcf,0x11,0xe0,0x0e,0x11,0xfc,0x0d};
119
120 /*
121  * Forward declarations of all the structures used by the storage
122  * module.
123  */
124 typedef struct StorageBaseImpl     StorageBaseImpl;
125 typedef struct StorageImpl         StorageImpl;
126 typedef struct StorageInternalImpl StorageInternalImpl;
127 typedef struct BlockChainStream      BlockChainStream;
128 typedef struct SmallBlockChainStream SmallBlockChainStream;
129 typedef struct IEnumSTATSTGImpl      IEnumSTATSTGImpl;
130 typedef struct StgProperty           StgProperty;
131 typedef struct StgStreamImpl         StgStreamImpl;
132
133 /*
134  * This utility structure is used to read/write the information in a storage
135  * property.
136  */
137 struct StgProperty
138 {
139   WCHAR          name[PROPERTY_NAME_MAX_LEN];
140   WORD           sizeOfNameString;
141   BYTE           propertyType;
142   ULONG          previousProperty;
143   ULONG          nextProperty;
144   ULONG          dirProperty;
145   GUID           propertyUniqueID;
146   ULONG          timeStampS1;
147   ULONG          timeStampD1;
148   ULONG          timeStampS2;
149   ULONG          timeStampD2;
150   ULONG          startingBlock;
151   ULARGE_INTEGER size;
152 };
153
154 /*************************************************************************
155  * Big Block File support
156  *
157  * The big block file is an abstraction of a flat file separated in
158  * same sized blocks. The implementation for the methods described in
159  * this section appear in stg_bigblockfile.c
160  */
161
162 /*
163  * Declaration of the data structures
164  */
165 typedef struct BigBlockFile BigBlockFile,*LPBIGBLOCKFILE;
166 typedef struct MappedPage   MappedPage,*LPMAPPEDPAGE;
167
168 struct BigBlockFile
169 {
170   BOOL fileBased;
171   ULARGE_INTEGER filesize;
172   ULONG blocksize;
173   HANDLE hfile;
174   HANDLE hfilemap;
175   DWORD flProtect;
176   MappedPage *maplist;
177   MappedPage *victimhead, *victimtail;
178   ULONG num_victim_pages;
179   ILockBytes *pLkbyt;
180   HGLOBAL hbytearray;
181   LPVOID pbytearray;
182 };
183
184 /*
185  * Declaration of the functions used to manipulate the BigBlockFile
186  * data structure.
187  */
188 BigBlockFile*  BIGBLOCKFILE_Construct(HANDLE hFile,
189                                       ILockBytes* pLkByt,
190                                       DWORD openFlags,
191                                       ULONG blocksize,
192                                       BOOL fileBased);
193 void           BIGBLOCKFILE_Destructor(LPBIGBLOCKFILE This);
194 void*          BIGBLOCKFILE_GetBigBlock(LPBIGBLOCKFILE This, ULONG index);
195 void*          BIGBLOCKFILE_GetROBigBlock(LPBIGBLOCKFILE This, ULONG index);
196 void           BIGBLOCKFILE_ReleaseBigBlock(LPBIGBLOCKFILE This, void *pBlock);
197 void           BIGBLOCKFILE_SetSize(LPBIGBLOCKFILE This, ULARGE_INTEGER newSize);
198 ULARGE_INTEGER BIGBLOCKFILE_GetSize(LPBIGBLOCKFILE This);
199
200 /*************************************************************************
201  * Ole Convert support
202  */
203
204 void OLECONVERT_CreateOleStream(LPSTORAGE pStorage);
205 HRESULT OLECONVERT_CreateCompObjStream(LPSTORAGE pStorage, LPCSTR strOleTypeName);
206
207 /****************************************************************************
208  * Storage32BaseImpl definitions.
209  *
210  * This structure defines the base information contained in all implementations
211  * of IStorage32 contained in this file storage implementation.
212  *
213  * In OOP terms, this is the base class for all the IStorage32 implementations
214  * contained in this file.
215  */
216 struct StorageBaseImpl
217 {
218   const IStorageVtbl *lpVtbl;    /* Needs to be the first item in the struct
219                             * since we want to cast this in a Storage32 pointer */
220
221   const IPropertySetStorageVtbl *pssVtbl; /* interface for adding a properties stream */
222
223   /*
224    * Stream tracking list
225    */
226
227   struct list strmHead;
228
229   /*
230    * Reference count of this object
231    */
232   LONG ref;
233
234   /*
235    * Ancestor storage (top level)
236    */
237   StorageImpl* ancestorStorage;
238
239   /*
240    * Index of the property for the root of
241    * this storage
242    */
243   ULONG rootPropertySetIndex;
244
245   /*
246    * virtual Destructor method.
247    */
248   void (*v_destructor)(StorageBaseImpl*);
249
250   /*
251    * flags that this storage was opened or created with
252    */
253   DWORD openFlags;
254 };
255
256 /****************************************************************************
257  * StorageBaseImpl stream list handlers
258  */
259
260 void StorageBaseImpl_AddStream(StorageBaseImpl * stg, StgStreamImpl * strm);
261 void StorageBaseImpl_RemoveStream(StorageBaseImpl * stg, StgStreamImpl * strm);
262 void StorageBaseImpl_DeleteAll(StorageBaseImpl * stg);
263
264 /****************************************************************************
265  * Storage32Impl definitions.
266  *
267  * This implementation of the IStorage32 interface represents a root
268  * storage. Basically, a document file.
269  */
270 struct StorageImpl
271 {
272   struct StorageBaseImpl base;
273
274   /*
275    * The following data members are specific to the Storage32Impl
276    * class
277    */
278   HANDLE           hFile;      /* Physical support for the Docfile */
279   LPOLESTR         pwcsName;   /* Full path of the document file */
280
281   /* FIXME: should this be in Storage32BaseImpl ? */
282   WCHAR            filename[PROPERTY_NAME_BUFFER_LEN];
283
284   /*
285    * File header
286    */
287   WORD  bigBlockSizeBits;
288   WORD  smallBlockSizeBits;
289   ULONG bigBlockSize;
290   ULONG smallBlockSize;
291   ULONG bigBlockDepotCount;
292   ULONG rootStartBlock;
293   ULONG smallBlockDepotStart;
294   ULONG extBigBlockDepotStart;
295   ULONG extBigBlockDepotCount;
296   ULONG bigBlockDepotStart[COUNT_BBDEPOTINHEADER];
297
298   ULONG blockDepotCached[NUM_BLOCKS_PER_DEPOT_BLOCK];
299   ULONG indexBlockDepotCached;
300   ULONG prevFreeBlock;
301
302   /*
303    * Abstraction of the big block chains for the chains of the header.
304    */
305   BlockChainStream* rootBlockChain;
306   BlockChainStream* smallBlockDepotChain;
307   BlockChainStream* smallBlockRootChain;
308
309   /*
310    * Pointer to the big block file abstraction
311    */
312   BigBlockFile* bigBlockFile;
313 };
314
315 void StorageImpl_Destroy(
316             StorageBaseImpl* This);
317
318 HRESULT StorageImpl_Construct(
319             StorageImpl* This,
320             HANDLE       hFile,
321             LPCOLESTR    pwcsName,
322             ILockBytes*  pLkbyt,
323             DWORD        openFlags,
324             BOOL         fileBased,
325             BOOL         fileCreate);
326
327 BOOL StorageImpl_ReadBigBlock(
328             StorageImpl* This,
329             ULONG          blockIndex,
330             void*          buffer);
331
332 BOOL StorageImpl_WriteBigBlock(
333             StorageImpl* This,
334             ULONG          blockIndex,
335             void*          buffer);
336
337 void* StorageImpl_GetROBigBlock(
338             StorageImpl* This,
339             ULONG          blockIndex);
340
341 void* StorageImpl_GetBigBlock(
342             StorageImpl* This,
343             ULONG          blockIndex);
344
345 void StorageImpl_ReleaseBigBlock(
346             StorageImpl* This,
347             void*          pBigBlock);
348
349 ULONG StorageImpl_GetNextFreeBigBlock(
350             StorageImpl* This);
351
352 void StorageImpl_FreeBigBlock(
353             StorageImpl* This,
354             ULONG blockIndex);
355
356 HRESULT StorageImpl_GetNextBlockInChain(
357             StorageImpl* This,
358             ULONG blockIndex,
359             ULONG* nextBlockIndex);
360
361 void StorageImpl_SetNextBlockInChain(
362             StorageImpl* This,
363             ULONG blockIndex,
364             ULONG nextBlock);
365
366 HRESULT StorageImpl_LoadFileHeader(
367             StorageImpl* This);
368
369 void StorageImpl_SaveFileHeader(
370             StorageImpl* This);
371
372 BOOL StorageImpl_ReadProperty(
373             StorageImpl* This,
374             ULONG          index,
375             StgProperty*    buffer);
376
377 BOOL StorageImpl_WriteProperty(
378             StorageImpl* This,
379             ULONG          index,
380             StgProperty*   buffer);
381
382 BlockChainStream* Storage32Impl_SmallBlocksToBigBlocks(
383                       StorageImpl* This,
384                       SmallBlockChainStream** ppsbChain);
385
386 ULONG Storage32Impl_GetNextExtendedBlock(StorageImpl* This,
387                                          ULONG blockIndex);
388
389 void Storage32Impl_AddBlockDepot(StorageImpl* This,
390                                  ULONG blockIndex);
391
392 ULONG Storage32Impl_AddExtBlockDepot(StorageImpl* This);
393
394 ULONG Storage32Impl_GetExtDepotBlock(StorageImpl* This,
395                                      ULONG depotIndex);
396
397 void Storage32Impl_SetExtDepotBlock(StorageImpl* This,
398                                     ULONG depotIndex,
399                                     ULONG blockIndex);
400 /****************************************************************************
401  * Storage32InternalImpl definitions.
402  *
403  * Definition of the implementation structure for the IStorage32 interface.
404  * This one implements the IStorage32 interface for storage that are
405  * inside another storage.
406  */
407 struct StorageInternalImpl
408 {
409   struct StorageBaseImpl base;
410
411   /*
412    * There is no specific data for this class.
413    */
414 };
415
416 /*
417  * Method definitions for the Storage32InternalImpl class.
418  */
419 StorageInternalImpl* StorageInternalImpl_Construct(
420             StorageImpl* ancestorStorage,
421             DWORD          openFlags,
422             ULONG          rootTropertyIndex);
423
424 void StorageInternalImpl_Destroy(
425             StorageBaseImpl* This);
426
427 HRESULT WINAPI StorageInternalImpl_Commit(
428             IStorage*            iface,
429             DWORD                  grfCommitFlags); /* [in] */
430
431 HRESULT WINAPI StorageInternalImpl_Revert(
432             IStorage*            iface);
433
434
435 /****************************************************************************
436  * IEnumSTATSTGImpl definitions.
437  *
438  * Definition of the implementation structure for the IEnumSTATSTGImpl interface.
439  * This class allows iterating through the content of a storage and to find
440  * specific items inside it.
441  */
442 struct IEnumSTATSTGImpl
443 {
444   const IEnumSTATSTGVtbl *lpVtbl;    /* Needs to be the first item in the struct
445                                 * since we want to cast this in an IEnumSTATSTG pointer */
446
447   LONG           ref;                   /* Reference count */
448   StorageImpl* parentStorage;         /* Reference to the parent storage */
449   ULONG          firstPropertyNode;     /* Index of the root of the storage to enumerate */
450
451   /*
452    * The current implementation of the IEnumSTATSTGImpl class uses a stack
453    * to walk the property sets to get the content of a storage. This stack
454    * is implemented by the following 3 data members
455    */
456   ULONG          stackSize;
457   ULONG          stackMaxSize;
458   ULONG*         stackToVisit;
459
460 #define ENUMSTATSGT_SIZE_INCREMENT 10
461 };
462
463 IEnumSTATSTGImpl* IEnumSTATSTGImpl_Construct(
464             StorageImpl* This,
465             ULONG          firstPropertyNode);
466
467 void IEnumSTATSTGImpl_Destroy(
468             IEnumSTATSTGImpl* This);
469
470 void IEnumSTATSTGImpl_PushSearchNode(
471             IEnumSTATSTGImpl* This,
472             ULONG             nodeToPush);
473
474 ULONG IEnumSTATSTGImpl_PopSearchNode(
475             IEnumSTATSTGImpl* This,
476             BOOL            remove);
477
478 ULONG IEnumSTATSTGImpl_FindProperty(
479             IEnumSTATSTGImpl* This,
480             const OLECHAR*  lpszPropName,
481             StgProperty*      buffer);
482
483 INT IEnumSTATSTGImpl_FindParentProperty(
484   IEnumSTATSTGImpl *This,
485   ULONG             childProperty,
486   StgProperty      *currentProperty,
487   ULONG            *propertyId);
488
489
490 /****************************************************************************
491  * StgStreamImpl definitions.
492  *
493  * This class imlements the IStream32 inteface and represents a stream
494  * located inside a storage object.
495  */
496 struct StgStreamImpl
497 {
498   const IStreamVtbl *lpVtbl;  /* Needs to be the first item in the struct
499                          * since we want to cast this to an IStream pointer */
500
501   /*
502    * We are an entry in the storage object's stream handler list
503    */
504
505   struct list StrmListEntry;
506
507   /*
508    * Reference count
509    */
510   LONG               ref;
511
512   /*
513    * Storage that is the parent(owner) of the stream
514    */
515   StorageBaseImpl* parentStorage;
516
517   /*
518    * Access mode of this stream.
519    */
520   DWORD grfMode;
521
522   /*
523    * Index of the property that owns (points to) this stream.
524    */
525   ULONG              ownerProperty;
526
527   /*
528    * Helper variable that contains the size of the stream
529    */
530   ULARGE_INTEGER     streamSize;
531
532   /*
533    * This is the current position of the cursor in the stream
534    */
535   ULARGE_INTEGER     currentPosition;
536
537   /*
538    * The information in the stream is represented by a chain of small blocks
539    * or a chain of large blocks. Depending on the case, one of the two
540    * following variabled points to that information.
541    */
542   BlockChainStream*      bigBlockChain;
543   SmallBlockChainStream* smallBlockChain;
544 };
545
546 /*
547  * Method definition for the StgStreamImpl class.
548  */
549 StgStreamImpl* StgStreamImpl_Construct(
550                 StorageBaseImpl* parentStorage,
551     DWORD            grfMode,
552     ULONG            ownerProperty);
553
554
555 /******************************************************************************
556  * Endian conversion macros
557  */
558 #ifdef WORDS_BIGENDIAN
559
560 #define htole32(x) RtlUlongByteSwap(x)
561 #define htole16(x) RtlUshortByteSwap(x)
562 #define le32toh(x) RtlUlongByteSwap(x)
563 #define le16toh(x) RtlUshortByteSwap(x)
564
565 #else
566
567 #define htole32(x) (x)
568 #define htole16(x) (x)
569 #define le32toh(x) (x)
570 #define le16toh(x) (x)
571
572 #endif
573
574 /******************************************************************************
575  * The StorageUtl_ functions are miscellaneous utility functions. Most of which
576  * are abstractions used to read values from file buffers without having to
577  * worry about bit order
578  */
579 void StorageUtl_ReadWord(const BYTE* buffer, ULONG offset, WORD* value);
580 void StorageUtl_WriteWord(BYTE* buffer, ULONG offset, WORD value);
581 void StorageUtl_ReadDWord(const BYTE* buffer, ULONG offset, DWORD* value);
582 void StorageUtl_WriteDWord(BYTE* buffer, ULONG offset, DWORD value);
583 void StorageUtl_ReadULargeInteger(const BYTE* buffer, ULONG offset,
584  ULARGE_INTEGER* value);
585 void StorageUtl_WriteULargeInteger(BYTE* buffer, ULONG offset,
586  const ULARGE_INTEGER *value);
587 void StorageUtl_ReadGUID(const BYTE* buffer, ULONG offset, GUID* value);
588 void StorageUtl_WriteGUID(BYTE* buffer, ULONG offset, const GUID* value);
589 void StorageUtl_CopyPropertyToSTATSTG(STATSTG*     destination,
590                                              StgProperty* source,
591                                              int          statFlags);
592
593 /****************************************************************************
594  * BlockChainStream definitions.
595  *
596  * The BlockChainStream class is a utility class that is used to create an
597  * abstraction of the big block chains in the storage file.
598  */
599 struct BlockChainStream
600 {
601   StorageImpl* parentStorage;
602   ULONG*       headOfStreamPlaceHolder;
603   ULONG        ownerPropertyIndex;
604   ULONG        lastBlockNoInSequence;
605   ULONG        lastBlockNoInSequenceIndex;
606   ULONG        tailIndex;
607   ULONG        numBlocks;
608 };
609
610 /*
611  * Methods for the BlockChainStream class.
612  */
613 BlockChainStream* BlockChainStream_Construct(
614                 StorageImpl* parentStorage,
615                 ULONG*         headOfStreamPlaceHolder,
616                 ULONG          propertyIndex);
617
618 void BlockChainStream_Destroy(
619                 BlockChainStream* This);
620
621 ULONG BlockChainStream_GetHeadOfChain(
622                 BlockChainStream* This);
623
624 BOOL BlockChainStream_ReadAt(
625                 BlockChainStream* This,
626                 ULARGE_INTEGER offset,
627                 ULONG          size,
628                 void*          buffer,
629                 ULONG*         bytesRead);
630
631 BOOL BlockChainStream_WriteAt(
632                 BlockChainStream* This,
633                 ULARGE_INTEGER offset,
634                 ULONG          size,
635                 const void*    buffer,
636                 ULONG*         bytesWritten);
637
638 BOOL BlockChainStream_SetSize(
639                 BlockChainStream* This,
640                 ULARGE_INTEGER    newSize);
641
642 ULARGE_INTEGER BlockChainStream_GetSize(
643     BlockChainStream* This);
644
645 ULONG BlockChainStream_GetCount(
646     BlockChainStream* This);
647
648 /****************************************************************************
649  * SmallBlockChainStream definitions.
650  *
651  * The SmallBlockChainStream class is a utility class that is used to create an
652  * abstraction of the small block chains in the storage file.
653  */
654 struct SmallBlockChainStream
655 {
656   StorageImpl* parentStorage;
657   ULONG          ownerPropertyIndex;
658 };
659
660 /*
661  * Methods of the SmallBlockChainStream class.
662  */
663 SmallBlockChainStream* SmallBlockChainStream_Construct(
664                StorageImpl* parentStorage,
665                ULONG          propertyIndex);
666
667 void SmallBlockChainStream_Destroy(
668                SmallBlockChainStream* This);
669
670 ULONG SmallBlockChainStream_GetHeadOfChain(
671                SmallBlockChainStream* This);
672
673 HRESULT SmallBlockChainStream_GetNextBlockInChain(
674                SmallBlockChainStream* This,
675                ULONG                  blockIndex,
676                ULONG*                 nextBlockIndex);
677
678 void SmallBlockChainStream_SetNextBlockInChain(
679          SmallBlockChainStream* This,
680          ULONG                  blockIndex,
681          ULONG                  nextBlock);
682
683 void SmallBlockChainStream_FreeBlock(
684          SmallBlockChainStream* This,
685          ULONG                  blockIndex);
686
687 ULONG SmallBlockChainStream_GetNextFreeBlock(
688          SmallBlockChainStream* This);
689
690 HRESULT SmallBlockChainStream_ReadAt(
691                SmallBlockChainStream* This,
692                ULARGE_INTEGER offset,
693                ULONG          size,
694                void*          buffer,
695                ULONG*         bytesRead);
696
697 BOOL SmallBlockChainStream_WriteAt(
698                SmallBlockChainStream* This,
699                ULARGE_INTEGER offset,
700                ULONG          size,
701                const void*    buffer,
702                ULONG*         bytesWritten);
703
704 BOOL SmallBlockChainStream_SetSize(
705                SmallBlockChainStream* This,
706                ULARGE_INTEGER          newSize);
707
708 ULARGE_INTEGER SmallBlockChainStream_GetSize(
709          SmallBlockChainStream* This);
710
711 ULONG SmallBlockChainStream_GetCount(
712          SmallBlockChainStream* This);
713
714
715 #endif /* __STORAGE32_H__ */