25f4ed0966d5735a8714cf8940c183a78f42c5c1
[reactos.git] / reactos / dll / win32 / 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 * Copyright 2010 Vincent Povirk for CodeWeavers
15 *
16 * This library is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU Lesser General Public
18 * License as published by the Free Software Foundation; either
19 * version 2.1 of the License, or (at your option) any later version.
20 *
21 * This library is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24 * Lesser General Public License for more details.
25 *
26 * You should have received a copy of the GNU Lesser General Public
27 * License along with this library; if not, write to the Free Software
28 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
29 */
30 #ifndef __STORAGE32_H__
31 #define __STORAGE32_H__
32
33 #define WIN32_NO_STATUS
34 #define _INC_WINDOWS
35
36 #include <stdarg.h>
37
38 #include <windef.h>
39 #include <winbase.h>
40 //#include "winnt.h"
41 #include <objbase.h>
42 #include <winreg.h>
43 #include "winternl.h"
44 #include <wine/list.h>
45
46 /*
47 * Definitions for the file format offsets.
48 */
49 static const ULONG OFFSET_MINORVERSION = 0x00000018;
50 static const ULONG OFFSET_MAJORVERSION = 0x0000001a;
51 static const ULONG OFFSET_BYTEORDERMARKER = 0x0000001c;
52 static const ULONG OFFSET_BIGBLOCKSIZEBITS = 0x0000001e;
53 static const ULONG OFFSET_SMALLBLOCKSIZEBITS = 0x00000020;
54 static const ULONG OFFSET_DIRSECTORCOUNT = 0x00000028;
55 static const ULONG OFFSET_BBDEPOTCOUNT = 0x0000002C;
56 static const ULONG OFFSET_ROOTSTARTBLOCK = 0x00000030;
57 static const ULONG OFFSET_SMALLBLOCKLIMIT = 0x00000038;
58 static const ULONG OFFSET_SBDEPOTSTART = 0x0000003C;
59 static const ULONG OFFSET_SBDEPOTCOUNT = 0x00000040;
60 static const ULONG OFFSET_EXTBBDEPOTSTART = 0x00000044;
61 static const ULONG OFFSET_EXTBBDEPOTCOUNT = 0x00000048;
62 static const ULONG OFFSET_BBDEPOTSTART = 0x0000004C;
63 static const ULONG OFFSET_PS_NAME = 0x00000000;
64 static const ULONG OFFSET_PS_NAMELENGTH = 0x00000040;
65 static const ULONG OFFSET_PS_STGTYPE = 0x00000042;
66 static const ULONG OFFSET_PS_LEFTCHILD = 0x00000044;
67 static const ULONG OFFSET_PS_RIGHTCHILD = 0x00000048;
68 static const ULONG OFFSET_PS_DIRROOT = 0x0000004C;
69 static const ULONG OFFSET_PS_GUID = 0x00000050;
70 static const ULONG OFFSET_PS_CTIMELOW = 0x00000064;
71 static const ULONG OFFSET_PS_CTIMEHIGH = 0x00000068;
72 static const ULONG OFFSET_PS_MTIMELOW = 0x0000006C;
73 static const ULONG OFFSET_PS_MTIMEHIGH = 0x00000070;
74 static const ULONG OFFSET_PS_STARTBLOCK = 0x00000074;
75 static const ULONG OFFSET_PS_SIZE = 0x00000078;
76 static const WORD DEF_BIG_BLOCK_SIZE_BITS = 0x0009;
77 static const WORD MIN_BIG_BLOCK_SIZE_BITS = 0x0009;
78 static const WORD MAX_BIG_BLOCK_SIZE_BITS = 0x000c;
79 static const WORD DEF_SMALL_BLOCK_SIZE_BITS = 0x0006;
80 static const WORD DEF_BIG_BLOCK_SIZE = 0x0200;
81 static const WORD DEF_SMALL_BLOCK_SIZE = 0x0040;
82 static const ULONG BLOCK_EXTBBDEPOT = 0xFFFFFFFC;
83 static const ULONG BLOCK_SPECIAL = 0xFFFFFFFD;
84 static const ULONG BLOCK_END_OF_CHAIN = 0xFFFFFFFE;
85 static const ULONG BLOCK_UNUSED = 0xFFFFFFFF;
86 static const ULONG DIRENTRY_NULL = 0xFFFFFFFF;
87
88 #define DIRENTRY_NAME_MAX_LEN 0x20
89 #define DIRENTRY_NAME_BUFFER_LEN 0x40
90
91 #define RAW_DIRENTRY_SIZE 0x00000080
92
93 #define HEADER_SIZE 512
94
95 #define MIN_BIG_BLOCK_SIZE 0x200
96 #define MAX_BIG_BLOCK_SIZE 0x1000
97
98 /*
99 * Type of child entry link
100 */
101 #define DIRENTRY_RELATION_PREVIOUS 0
102 #define DIRENTRY_RELATION_NEXT 1
103 #define DIRENTRY_RELATION_DIR 2
104
105 /*
106 * type constant used in files for the root storage
107 */
108 #define STGTY_ROOT 0x05
109
110 #define COUNT_BBDEPOTINHEADER 109
111
112 /* FIXME: This value is stored in the header, but we hard-code it to 0x1000. */
113 #define LIMIT_TO_USE_SMALL_BLOCK 0x1000
114
115 #define STGM_ACCESS_MODE(stgm) ((stgm)&0x0000f)
116 #define STGM_SHARE_MODE(stgm) ((stgm)&0x000f0)
117 #define STGM_CREATE_MODE(stgm) ((stgm)&0x0f000)
118
119 #define STGM_KNOWN_FLAGS (0xf0ff | \
120 STGM_TRANSACTED | STGM_CONVERT | STGM_PRIORITY | STGM_NOSCRATCH | \
121 STGM_NOSNAPSHOT | STGM_DIRECT_SWMR | STGM_DELETEONRELEASE | STGM_SIMPLE)
122
123 /*
124 * Forward declarations of all the structures used by the storage
125 * module.
126 */
127 typedef struct StorageBaseImpl StorageBaseImpl;
128 typedef struct StorageBaseImplVtbl StorageBaseImplVtbl;
129 typedef struct StorageImpl StorageImpl;
130 typedef struct BlockChainStream BlockChainStream;
131 typedef struct SmallBlockChainStream SmallBlockChainStream;
132 typedef struct IEnumSTATSTGImpl IEnumSTATSTGImpl;
133 typedef struct DirEntry DirEntry;
134 typedef struct StgStreamImpl StgStreamImpl;
135
136 /*
137 * A reference to a directory entry in the file or a transacted cache.
138 */
139 typedef ULONG DirRef;
140
141 /*
142 * This utility structure is used to read/write the information in a directory
143 * entry.
144 */
145 struct DirEntry
146 {
147 WCHAR name[DIRENTRY_NAME_MAX_LEN];
148 WORD sizeOfNameString;
149 BYTE stgType;
150 DirRef leftChild;
151 DirRef rightChild;
152 DirRef dirRootEntry;
153 GUID clsid;
154 FILETIME ctime;
155 FILETIME mtime;
156 ULONG startingBlock;
157 ULARGE_INTEGER size;
158 };
159
160 HRESULT FileLockBytesImpl_Construct(HANDLE hFile, DWORD openFlags, LPCWSTR pwcsName, ILockBytes **pLockBytes) DECLSPEC_HIDDEN;
161
162 /*************************************************************************
163 * Ole Convert support
164 */
165
166 HRESULT STORAGE_CreateOleStream(IStorage*, DWORD) DECLSPEC_HIDDEN;
167 HRESULT OLECONVERT_CreateCompObjStream(LPSTORAGE pStorage, LPCSTR strOleTypeName) DECLSPEC_HIDDEN;
168
169 enum swmr_mode
170 {
171 SWMR_None,
172 SWMR_Writer,
173 SWMR_Reader
174 };
175
176 /****************************************************************************
177 * StorageBaseImpl definitions.
178 *
179 * This structure defines the base information contained in all implementations
180 * of IStorage contained in this file storage implementation.
181 *
182 * In OOP terms, this is the base class for all the IStorage implementations
183 * contained in this file.
184 */
185 struct StorageBaseImpl
186 {
187 IStorage IStorage_iface;
188 IPropertySetStorage IPropertySetStorage_iface; /* interface for adding a properties stream */
189 IDirectWriterLock IDirectWriterLock_iface;
190 LONG ref;
191
192 /*
193 * Stream tracking list
194 */
195
196 struct list strmHead;
197
198 /*
199 * Storage tracking list
200 */
201 struct list storageHead;
202
203 /*
204 * TRUE if this object has been invalidated
205 */
206 int reverted;
207
208 /*
209 * Index of the directory entry of this storage
210 */
211 DirRef storageDirEntry;
212
213 /*
214 * virtual methods.
215 */
216 const StorageBaseImplVtbl *baseVtbl;
217
218 /*
219 * flags that this storage was opened or created with
220 */
221 DWORD openFlags;
222
223 /*
224 * State bits appear to only be preserved while running. No in the stream
225 */
226 DWORD stateBits;
227
228 BOOL create; /* Was the storage created or opened.
229 The behaviour of STGM_SIMPLE depends on this */
230 /*
231 * If this storage was opened in transacted mode, the object that implements
232 * the transacted snapshot or cache.
233 */
234 StorageBaseImpl *transactedChild;
235 enum swmr_mode lockingrole;
236 };
237
238 /* virtual methods for StorageBaseImpl objects */
239 struct StorageBaseImplVtbl {
240 void (*Destroy)(StorageBaseImpl*);
241 void (*Invalidate)(StorageBaseImpl*);
242 HRESULT (*Flush)(StorageBaseImpl*);
243 HRESULT (*GetFilename)(StorageBaseImpl*,LPWSTR*);
244 HRESULT (*CreateDirEntry)(StorageBaseImpl*,const DirEntry*,DirRef*);
245 HRESULT (*WriteDirEntry)(StorageBaseImpl*,DirRef,const DirEntry*);
246 HRESULT (*ReadDirEntry)(StorageBaseImpl*,DirRef,DirEntry*);
247 HRESULT (*DestroyDirEntry)(StorageBaseImpl*,DirRef);
248 HRESULT (*StreamReadAt)(StorageBaseImpl*,DirRef,ULARGE_INTEGER,ULONG,void*,ULONG*);
249 HRESULT (*StreamWriteAt)(StorageBaseImpl*,DirRef,ULARGE_INTEGER,ULONG,const void*,ULONG*);
250 HRESULT (*StreamSetSize)(StorageBaseImpl*,DirRef,ULARGE_INTEGER);
251 HRESULT (*StreamLink)(StorageBaseImpl*,DirRef,DirRef);
252 };
253
254 static inline void StorageBaseImpl_Destroy(StorageBaseImpl *This)
255 {
256 This->baseVtbl->Destroy(This);
257 }
258
259 static inline void StorageBaseImpl_Invalidate(StorageBaseImpl *This)
260 {
261 This->baseVtbl->Invalidate(This);
262 }
263
264 static inline HRESULT StorageBaseImpl_Flush(StorageBaseImpl *This)
265 {
266 return This->baseVtbl->Flush(This);
267 }
268
269 static inline HRESULT StorageBaseImpl_GetFilename(StorageBaseImpl *This, LPWSTR *result)
270 {
271 return This->baseVtbl->GetFilename(This, result);
272 }
273
274 static inline HRESULT StorageBaseImpl_CreateDirEntry(StorageBaseImpl *This,
275 const DirEntry *newData, DirRef *index)
276 {
277 return This->baseVtbl->CreateDirEntry(This, newData, index);
278 }
279
280 static inline HRESULT StorageBaseImpl_WriteDirEntry(StorageBaseImpl *This,
281 DirRef index, const DirEntry *data)
282 {
283 return This->baseVtbl->WriteDirEntry(This, index, data);
284 }
285
286 static inline HRESULT StorageBaseImpl_ReadDirEntry(StorageBaseImpl *This,
287 DirRef index, DirEntry *data)
288 {
289 return This->baseVtbl->ReadDirEntry(This, index, data);
290 }
291
292 static inline HRESULT StorageBaseImpl_DestroyDirEntry(StorageBaseImpl *This,
293 DirRef index)
294 {
295 return This->baseVtbl->DestroyDirEntry(This, index);
296 }
297
298 /* Read up to size bytes from this directory entry's stream at the given offset. */
299 static inline HRESULT StorageBaseImpl_StreamReadAt(StorageBaseImpl *This,
300 DirRef index, ULARGE_INTEGER offset, ULONG size, void *buffer, ULONG *bytesRead)
301 {
302 return This->baseVtbl->StreamReadAt(This, index, offset, size, buffer, bytesRead);
303 }
304
305 /* Write size bytes to this directory entry's stream at the given offset,
306 * growing the stream if necessary. */
307 static inline HRESULT StorageBaseImpl_StreamWriteAt(StorageBaseImpl *This,
308 DirRef index, ULARGE_INTEGER offset, ULONG size, const void *buffer, ULONG *bytesWritten)
309 {
310 return This->baseVtbl->StreamWriteAt(This, index, offset, size, buffer, bytesWritten);
311 }
312
313 static inline HRESULT StorageBaseImpl_StreamSetSize(StorageBaseImpl *This,
314 DirRef index, ULARGE_INTEGER newsize)
315 {
316 return This->baseVtbl->StreamSetSize(This, index, newsize);
317 }
318
319 /* Make dst point to the same stream that src points to. Other stream operations
320 * will not work properly for entries that point to the same stream, so this
321 * must be a very temporary state, and only one entry pointing to a given stream
322 * may be reachable at any given time. */
323 static inline HRESULT StorageBaseImpl_StreamLink(StorageBaseImpl *This,
324 DirRef dst, DirRef src)
325 {
326 return This->baseVtbl->StreamLink(This, dst, src);
327 }
328
329 /****************************************************************************
330 * StorageBaseImpl stream list handlers
331 */
332
333 void StorageBaseImpl_AddStream(StorageBaseImpl * stg, StgStreamImpl * strm) DECLSPEC_HIDDEN;
334 void StorageBaseImpl_RemoveStream(StorageBaseImpl * stg, StgStreamImpl * strm) DECLSPEC_HIDDEN;
335
336 /* Number of BlockChainStream objects to cache in a StorageImpl */
337 #define BLOCKCHAIN_CACHE_SIZE 4
338
339 /****************************************************************************
340 * Storage32Impl definitions.
341 *
342 * This implementation of the IStorage32 interface represents a root
343 * storage. Basically, a document file.
344 */
345 struct StorageImpl
346 {
347 struct StorageBaseImpl base;
348
349 /*
350 * File header
351 */
352 WORD bigBlockSizeBits;
353 WORD smallBlockSizeBits;
354 ULONG bigBlockSize;
355 ULONG smallBlockSize;
356 ULONG bigBlockDepotCount;
357 ULONG rootStartBlock;
358 ULONG smallBlockLimit;
359 ULONG smallBlockDepotStart;
360 ULONG extBigBlockDepotStart;
361 ULONG *extBigBlockDepotLocations;
362 ULONG extBigBlockDepotLocationsSize;
363 ULONG extBigBlockDepotCount;
364 ULONG bigBlockDepotStart[COUNT_BBDEPOTINHEADER];
365
366 ULONG extBlockDepotCached[MAX_BIG_BLOCK_SIZE / 4];
367 ULONG indexExtBlockDepotCached;
368
369 ULONG blockDepotCached[MAX_BIG_BLOCK_SIZE / 4];
370 ULONG indexBlockDepotCached;
371 ULONG prevFreeBlock;
372
373 /* All small blocks before this one are known to be in use. */
374 ULONG firstFreeSmallBlock;
375
376 /*
377 * Abstraction of the big block chains for the chains of the header.
378 */
379 BlockChainStream* rootBlockChain;
380 BlockChainStream* smallBlockDepotChain;
381 BlockChainStream* smallBlockRootChain;
382
383 /* Cache of block chain streams objects for directory entries */
384 BlockChainStream* blockChainCache[BLOCKCHAIN_CACHE_SIZE];
385 UINT blockChainToEvict;
386
387 ILockBytes* lockBytes;
388 };
389
390 HRESULT StorageImpl_ReadRawDirEntry(
391 StorageImpl *This,
392 ULONG index,
393 BYTE *buffer) DECLSPEC_HIDDEN;
394
395 void UpdateRawDirEntry(
396 BYTE *buffer,
397 const DirEntry *newData) DECLSPEC_HIDDEN;
398
399 HRESULT StorageImpl_WriteRawDirEntry(
400 StorageImpl *This,
401 ULONG index,
402 const BYTE *buffer) DECLSPEC_HIDDEN;
403
404 HRESULT StorageImpl_ReadDirEntry(
405 StorageImpl* This,
406 DirRef index,
407 DirEntry* buffer) DECLSPEC_HIDDEN;
408
409 HRESULT StorageImpl_WriteDirEntry(
410 StorageImpl* This,
411 DirRef index,
412 const DirEntry* buffer) DECLSPEC_HIDDEN;
413
414 BlockChainStream* Storage32Impl_SmallBlocksToBigBlocks(
415 StorageImpl* This,
416 SmallBlockChainStream** ppsbChain) DECLSPEC_HIDDEN;
417
418 SmallBlockChainStream* Storage32Impl_BigBlocksToSmallBlocks(
419 StorageImpl* This,
420 BlockChainStream** ppbbChain,
421 ULARGE_INTEGER newSize) DECLSPEC_HIDDEN;
422
423 /****************************************************************************
424 * StgStreamImpl definitions.
425 *
426 * This class implements the IStream interface and represents a stream
427 * located inside a storage object.
428 */
429 struct StgStreamImpl
430 {
431 IStream IStream_iface;
432 LONG ref;
433
434 /*
435 * We are an entry in the storage object's stream handler list
436 */
437 struct list StrmListEntry;
438
439 /*
440 * Storage that is the parent(owner) of the stream
441 */
442 StorageBaseImpl* parentStorage;
443
444 /*
445 * Access mode of this stream.
446 */
447 DWORD grfMode;
448
449 /*
450 * Index of the directory entry that owns (points to) this stream.
451 */
452 DirRef dirEntry;
453
454 /*
455 * This is the current position of the cursor in the stream
456 */
457 ULARGE_INTEGER currentPosition;
458 };
459
460 static inline StgStreamImpl *impl_from_IStream( IStream *iface )
461 {
462 return CONTAINING_RECORD(iface, StgStreamImpl, IStream_iface);
463 }
464
465 /*
466 * Method definition for the StgStreamImpl class.
467 */
468 StgStreamImpl* StgStreamImpl_Construct(
469 StorageBaseImpl* parentStorage,
470 DWORD grfMode,
471 DirRef dirEntry) DECLSPEC_HIDDEN;
472
473
474 /******************************************************************************
475 * Endian conversion macros
476 */
477 #ifdef WORDS_BIGENDIAN
478
479 #define htole32(x) RtlUlongByteSwap(x)
480 #define htole16(x) RtlUshortByteSwap(x)
481 #define lendian32toh(x) RtlUlongByteSwap(x)
482 #define lendian16toh(x) RtlUshortByteSwap(x)
483
484 #else
485
486 #define htole32(x) (x)
487 #define htole16(x) (x)
488 #define lendian32toh(x) (x)
489 #define lendian16toh(x) (x)
490
491 #endif
492
493 /******************************************************************************
494 * The StorageUtl_ functions are miscellaneous utility functions. Most of which
495 * are abstractions used to read values from file buffers without having to
496 * worry about bit order
497 */
498 void StorageUtl_ReadWord(const BYTE* buffer, ULONG offset, WORD* value) DECLSPEC_HIDDEN;
499 void StorageUtl_WriteWord(BYTE* buffer, ULONG offset, WORD value) DECLSPEC_HIDDEN;
500 void StorageUtl_ReadDWord(const BYTE* buffer, ULONG offset, DWORD* value) DECLSPEC_HIDDEN;
501 void StorageUtl_WriteDWord(BYTE* buffer, ULONG offset, DWORD value) DECLSPEC_HIDDEN;
502 void StorageUtl_ReadULargeInteger(const BYTE* buffer, ULONG offset,
503 ULARGE_INTEGER* value) DECLSPEC_HIDDEN;
504 void StorageUtl_WriteULargeInteger(BYTE* buffer, ULONG offset,
505 const ULARGE_INTEGER *value) DECLSPEC_HIDDEN;
506 void StorageUtl_ReadGUID(const BYTE* buffer, ULONG offset, GUID* value) DECLSPEC_HIDDEN;
507 void StorageUtl_WriteGUID(BYTE* buffer, ULONG offset, const GUID* value) DECLSPEC_HIDDEN;
508 void StorageUtl_CopyDirEntryToSTATSTG(StorageBaseImpl *storage,STATSTG* destination,
509 const DirEntry* source, int statFlags) DECLSPEC_HIDDEN;
510
511 /****************************************************************************
512 * BlockChainStream definitions.
513 *
514 * The BlockChainStream class is a utility class that is used to create an
515 * abstraction of the big block chains in the storage file.
516 */
517 struct BlockChainRun
518 {
519 /* This represents a range of blocks that happen reside in consecutive sectors. */
520 ULONG firstSector;
521 ULONG firstOffset;
522 ULONG lastOffset;
523 };
524
525 typedef struct BlockChainBlock
526 {
527 ULONG index;
528 ULONG sector;
529 int read;
530 int dirty;
531 BYTE data[MAX_BIG_BLOCK_SIZE];
532 } BlockChainBlock;
533
534 struct BlockChainStream
535 {
536 StorageImpl* parentStorage;
537 ULONG* headOfStreamPlaceHolder;
538 DirRef ownerDirEntry;
539 struct BlockChainRun* indexCache;
540 ULONG indexCacheLen;
541 ULONG indexCacheSize;
542 BlockChainBlock cachedBlocks[2];
543 ULONG blockToEvict;
544 ULONG tailIndex;
545 ULONG numBlocks;
546 };
547
548 /*
549 * Methods for the BlockChainStream class.
550 */
551 BlockChainStream* BlockChainStream_Construct(
552 StorageImpl* parentStorage,
553 ULONG* headOfStreamPlaceHolder,
554 DirRef dirEntry) DECLSPEC_HIDDEN;
555
556 void BlockChainStream_Destroy(
557 BlockChainStream* This) DECLSPEC_HIDDEN;
558
559 HRESULT BlockChainStream_ReadAt(
560 BlockChainStream* This,
561 ULARGE_INTEGER offset,
562 ULONG size,
563 void* buffer,
564 ULONG* bytesRead) DECLSPEC_HIDDEN;
565
566 HRESULT BlockChainStream_WriteAt(
567 BlockChainStream* This,
568 ULARGE_INTEGER offset,
569 ULONG size,
570 const void* buffer,
571 ULONG* bytesWritten) DECLSPEC_HIDDEN;
572
573 BOOL BlockChainStream_SetSize(
574 BlockChainStream* This,
575 ULARGE_INTEGER newSize) DECLSPEC_HIDDEN;
576
577 HRESULT BlockChainStream_Flush(
578 BlockChainStream* This) DECLSPEC_HIDDEN;
579
580 /****************************************************************************
581 * SmallBlockChainStream definitions.
582 *
583 * The SmallBlockChainStream class is a utility class that is used to create an
584 * abstraction of the small block chains in the storage file.
585 */
586 struct SmallBlockChainStream
587 {
588 StorageImpl* parentStorage;
589 DirRef ownerDirEntry;
590 ULONG* headOfStreamPlaceHolder;
591 };
592
593 /*
594 * Methods of the SmallBlockChainStream class.
595 */
596 SmallBlockChainStream* SmallBlockChainStream_Construct(
597 StorageImpl* parentStorage,
598 ULONG* headOfStreamPlaceHolder,
599 DirRef dirEntry) DECLSPEC_HIDDEN;
600
601 void SmallBlockChainStream_Destroy(
602 SmallBlockChainStream* This) DECLSPEC_HIDDEN;
603
604 HRESULT SmallBlockChainStream_ReadAt(
605 SmallBlockChainStream* This,
606 ULARGE_INTEGER offset,
607 ULONG size,
608 void* buffer,
609 ULONG* bytesRead) DECLSPEC_HIDDEN;
610
611 HRESULT SmallBlockChainStream_WriteAt(
612 SmallBlockChainStream* This,
613 ULARGE_INTEGER offset,
614 ULONG size,
615 const void* buffer,
616 ULONG* bytesWritten) DECLSPEC_HIDDEN;
617
618 BOOL SmallBlockChainStream_SetSize(
619 SmallBlockChainStream* This,
620 ULARGE_INTEGER newSize) DECLSPEC_HIDDEN;
621
622
623 #endif /* __STORAGE32_H__ */