storage32.h 21 KB
Newer Older
1 2 3 4 5 6 7 8
/*
 * Compound Storage (32 bit version)
 *
 * Implemented using the documentation of the LAOLA project at
 * <URL:http://wwwwbs.cs.tu-berlin.de/~schwartz/pmh/index.html>
 * (Thanks to Martin Schwartz <schwartz@cs.tu-berlin.de>)
 *
 * This include file contains definitions of types and function
9
 * prototypes that are used in the many files implementing the
10 11 12 13
 * storage functionality
 *
 * Copyright 1998,1999 Francis Beaudet
 * Copyright 1998,1999 Thuy Nguyen
14 15 16 17 18 19 20 21 22 23 24 25 26 27
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
28 29 30 31
 */
#ifndef __STORAGE32_H__
#define __STORAGE32_H__

32 33 34 35
#include <stdarg.h>

#include "windef.h"
#include "winbase.h"
36
#include "winnt.h"
37
#include "objbase.h"
38 39
#include "winreg.h"
#include "winternl.h"
40
#include "wine/list.h"
41

42 43 44 45 46 47 48 49
/*
 * Definitions for the file format offsets.
 */
static const ULONG OFFSET_BIGBLOCKSIZEBITS   = 0x0000001e;
static const ULONG OFFSET_SMALLBLOCKSIZEBITS = 0x00000020;
static const ULONG OFFSET_BBDEPOTCOUNT	     = 0x0000002C;
static const ULONG OFFSET_ROOTSTARTBLOCK     = 0x00000030;
static const ULONG OFFSET_SBDEPOTSTART	     = 0x0000003C;
50
static const ULONG OFFSET_SBDEPOTCOUNT       = 0x00000040;
51 52 53
static const ULONG OFFSET_EXTBBDEPOTSTART    = 0x00000044;
static const ULONG OFFSET_EXTBBDEPOTCOUNT    = 0x00000048;
static const ULONG OFFSET_BBDEPOTSTART	     = 0x0000004C;
54 55 56 57
static const ULONG OFFSET_PS_NAME            = 0x00000000;
static const ULONG OFFSET_PS_NAMELENGTH	     = 0x00000040;
static const ULONG OFFSET_PS_PROPERTYTYPE    = 0x00000042;
static const ULONG OFFSET_PS_PREVIOUSPROP    = 0x00000044;
58
static const ULONG OFFSET_PS_NEXTPROP        = 0x00000048;
59 60 61 62 63 64
static const ULONG OFFSET_PS_DIRPROP	     = 0x0000004C;
static const ULONG OFFSET_PS_GUID            = 0x00000050;
static const ULONG OFFSET_PS_TSS1	     = 0x00000064;
static const ULONG OFFSET_PS_TSD1            = 0x00000068;
static const ULONG OFFSET_PS_TSS2            = 0x0000006C;
static const ULONG OFFSET_PS_TSD2            = 0x00000070;
65 66
static const ULONG OFFSET_PS_STARTBLOCK	     = 0x00000074;
static const ULONG OFFSET_PS_SIZE	     = 0x00000078;
67 68 69 70
static const WORD  DEF_BIG_BLOCK_SIZE_BITS   = 0x0009;
static const WORD  DEF_SMALL_BLOCK_SIZE_BITS = 0x0006;
static const WORD  DEF_BIG_BLOCK_SIZE        = 0x0200;
static const WORD  DEF_SMALL_BLOCK_SIZE      = 0x0040;
71 72 73 74
static const ULONG BLOCK_EXTBBDEPOT          = 0xFFFFFFFC;
static const ULONG BLOCK_SPECIAL             = 0xFFFFFFFD;
static const ULONG BLOCK_END_OF_CHAIN        = 0xFFFFFFFE;
static const ULONG BLOCK_UNUSED              = 0xFFFFFFFF;
75 76 77
static const ULONG PROPERTY_NULL             = 0xFFFFFFFF;

#define PROPERTY_NAME_MAX_LEN    0x20
78
#define PROPERTY_NAME_BUFFER_LEN 0x40
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

#define PROPSET_BLOCK_SIZE 0x00000080

/*
 * Property type of relation
 */
#define PROPERTY_RELATION_PREVIOUS 0
#define PROPERTY_RELATION_NEXT     1
#define PROPERTY_RELATION_DIR      2

/*
 * Property type constants
 */
#define PROPTYPE_STORAGE 0x01
#define PROPTYPE_STREAM  0x02
#define PROPTYPE_ROOT    0x05

/*
 * These defines assume a hardcoded blocksize. The code will assert
 * if the blocksize is different. Some changes will have to be done if it
 * becomes the case.
 */
#define BIG_BLOCK_SIZE           0x200
#define COUNT_BBDEPOTINHEADER    109
#define LIMIT_TO_USE_SMALL_BLOCK 0x1000
104
#define NUM_BLOCKS_PER_DEPOT_BLOCK 128
105

106 107 108 109 110 111 112 113
#define STGM_ACCESS_MODE(stgm)   ((stgm)&0x0000f)
#define STGM_SHARE_MODE(stgm)    ((stgm)&0x000f0)
#define STGM_CREATE_MODE(stgm)   ((stgm)&0x0f000)

#define STGM_KNOWN_FLAGS (0xf0ff | \
     STGM_TRANSACTED | STGM_CONVERT | STGM_PRIORITY | STGM_NOSCRATCH | \
     STGM_NOSNAPSHOT | STGM_DIRECT_SWMR | STGM_DELETEONRELEASE | STGM_SIMPLE)

114 115 116 117 118 119 120 121 122 123
/*
 * These are signatures to detect the type of Document file.
 */
static const BYTE STORAGE_magic[8]    ={0xd0,0xcf,0x11,0xe0,0xa1,0xb1,0x1a,0xe1};
static const BYTE STORAGE_oldmagic[8] ={0xd0,0xcf,0x11,0xe0,0x0e,0x11,0xfc,0x0d};

/*
 * Forward declarations of all the structures used by the storage
 * module.
 */
124 125 126
typedef struct StorageBaseImpl     StorageBaseImpl;
typedef struct StorageImpl         StorageImpl;
typedef struct StorageInternalImpl StorageInternalImpl;
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
typedef struct BlockChainStream      BlockChainStream;
typedef struct SmallBlockChainStream SmallBlockChainStream;
typedef struct IEnumSTATSTGImpl      IEnumSTATSTGImpl;
typedef struct StgProperty           StgProperty;
typedef struct StgStreamImpl         StgStreamImpl;

/*
 * This utility structure is used to read/write the information in a storage
 * property.
 */
struct StgProperty
{
  WCHAR	         name[PROPERTY_NAME_MAX_LEN];
  WORD	         sizeOfNameString;
  BYTE	         propertyType;
  ULONG	         previousProperty;
  ULONG	         nextProperty;
  ULONG          dirProperty;
  GUID           propertyUniqueID;
  ULONG          timeStampS1;
  ULONG          timeStampD1;
  ULONG          timeStampS2;
  ULONG          timeStampD2;
  ULONG          startingBlock;
  ULARGE_INTEGER size;
};

/*************************************************************************
 * Big Block File support
 *
 * 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 160 161 162 163 164 165 166 167 168 169
 * this section appear in stg_bigblockfile.c
 */

/*
 * Declaration of the data structures
 */
typedef struct BigBlockFile BigBlockFile,*LPBIGBLOCKFILE;
typedef struct MappedPage   MappedPage,*LPMAPPEDPAGE;

struct BigBlockFile
{
170
  BOOL fileBased;
171 172
  ULARGE_INTEGER filesize;
  ULONG blocksize;
173 174
  HANDLE hfile;
  HANDLE hfilemap;
175
  DWORD flProtect;
176 177 178
  MappedPage *maplist;
  MappedPage *victimhead, *victimtail;
  ULONG num_victim_pages;
179 180 181
  ILockBytes *pLkbyt;
  HGLOBAL hbytearray;
  LPVOID pbytearray;
182 183 184 185 186 187
};

/*
 * Declaration of the functions used to manipulate the BigBlockFile
 * data structure.
 */
188
BigBlockFile*  BIGBLOCKFILE_Construct(HANDLE hFile,
189
                                      ILockBytes* pLkByt,
190
                                      DWORD openFlags,
191 192
                                      ULONG blocksize,
                                      BOOL fileBased);
193 194 195 196 197 198 199
void           BIGBLOCKFILE_Destructor(LPBIGBLOCKFILE This);
void*          BIGBLOCKFILE_GetBigBlock(LPBIGBLOCKFILE This, ULONG index);
void*          BIGBLOCKFILE_GetROBigBlock(LPBIGBLOCKFILE This, ULONG index);
void           BIGBLOCKFILE_ReleaseBigBlock(LPBIGBLOCKFILE This, void *pBlock);
void           BIGBLOCKFILE_SetSize(LPBIGBLOCKFILE This, ULARGE_INTEGER newSize);
ULARGE_INTEGER BIGBLOCKFILE_GetSize(LPBIGBLOCKFILE This);

Patrik Stridvall's avatar
Patrik Stridvall committed
200 201 202 203 204 205 206
/*************************************************************************
 * Ole Convert support
 */

void OLECONVERT_CreateOleStream(LPSTORAGE pStorage);
HRESULT OLECONVERT_CreateCompObjStream(LPSTORAGE pStorage, LPCSTR strOleTypeName);

207 208 209
/****************************************************************************
 * Storage32BaseImpl definitions.
 *
Alexandre Julliard's avatar
Alexandre Julliard committed
210 211
 * This structure defines the base information contained in all implementations
 * of IStorage32 contained in this file storage implementation.
212 213 214 215
 *
 * In OOP terms, this is the base class for all the IStorage32 implementations
 * contained in this file.
 */
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 225 226 227 228
  /*
   * Stream tracking list
   */

  struct list strmHead;

229 230 231
  /*
   * Reference count of this object
   */
232
  LONG ref;
233 234 235

  /*
   * Ancestor storage (top level)
236
   */
237 238
  StorageImpl* ancestorStorage;

239 240 241 242 243
  /*
   * Index of the property for the root of
   * this storage
   */
  ULONG rootPropertySetIndex;
244 245

  /*
246 247
   * virtual Destructor method.
   */
248
  void (*v_destructor)(StorageBaseImpl*);
249 250 251 252 253

  /*
   * flags that this storage was opened or created with
   */
  DWORD openFlags;
254 255
};

256 257 258 259 260 261 262
/****************************************************************************
 * StorageBaseImpl stream list handlers
 */

void StorageBaseImpl_AddStream(StorageBaseImpl * stg, StgStreamImpl * strm);
void StorageBaseImpl_RemoveStream(StorageBaseImpl * stg, StgStreamImpl * strm);
void StorageBaseImpl_DeleteAll(StorageBaseImpl * stg);
263 264 265 266 267 268 269

/****************************************************************************
 * Storage32Impl definitions.
 *
 * This implementation of the IStorage32 interface represents a root
 * storage. Basically, a document file.
 */
270
struct StorageImpl
271
{
272
  struct StorageBaseImpl base;
273

274 275 276 277
  /*
   * The following data members are specific to the Storage32Impl
   * class
   */
278
  HANDLE           hFile;      /* Physical support for the Docfile */
279 280
  LPOLESTR         pwcsName;   /* Full path of the document file */

Alexandre Julliard's avatar
Alexandre Julliard committed
281 282 283
  /* FIXME: should this be in Storage32BaseImpl ? */
  WCHAR            filename[PROPERTY_NAME_BUFFER_LEN];

284 285 286 287 288 289 290 291 292 293 294 295 296
  /*
   * File header
   */
  WORD  bigBlockSizeBits;
  WORD  smallBlockSizeBits;
  ULONG bigBlockSize;
  ULONG smallBlockSize;
  ULONG bigBlockDepotCount;
  ULONG rootStartBlock;
  ULONG smallBlockDepotStart;
  ULONG extBigBlockDepotStart;
  ULONG extBigBlockDepotCount;
  ULONG bigBlockDepotStart[COUNT_BBDEPOTINHEADER];
297 298 299

  ULONG blockDepotCached[NUM_BLOCKS_PER_DEPOT_BLOCK];
  ULONG indexBlockDepotCached;
300
  ULONG prevFreeBlock;
301

302 303 304 305 306
  /*
   * Abstraction of the big block chains for the chains of the header.
   */
  BlockChainStream* rootBlockChain;
  BlockChainStream* smallBlockDepotChain;
307
  BlockChainStream* smallBlockRootChain;
308 309 310 311

  /*
   * Pointer to the big block file abstraction
   */
312
  BigBlockFile* bigBlockFile;
313 314
};

315
void StorageImpl_Destroy(
316
	    StorageBaseImpl* This);
317

318
HRESULT StorageImpl_Construct(
319 320
            StorageImpl* This,
            HANDLE       hFile,
321
            LPCOLESTR    pwcsName,
322 323 324 325
            ILockBytes*  pLkbyt,
            DWORD        openFlags,
            BOOL         fileBased,
            BOOL         fileCreate);
326

327 328
BOOL StorageImpl_ReadBigBlock(
            StorageImpl* This,
329 330 331
	    ULONG          blockIndex,
	    void*          buffer);

332 333
BOOL StorageImpl_WriteBigBlock(
            StorageImpl* This,
334 335 336
	    ULONG          blockIndex,
	    void*          buffer);

337 338
void* StorageImpl_GetROBigBlock(
            StorageImpl* This,
339 340
	    ULONG          blockIndex);

341 342
void* StorageImpl_GetBigBlock(
	    StorageImpl* This,
343 344
	    ULONG          blockIndex);

345 346
void StorageImpl_ReleaseBigBlock(
            StorageImpl* This,
347 348
            void*          pBigBlock);

349 350
ULONG StorageImpl_GetNextFreeBigBlock(
            StorageImpl* This);
351

352 353
void StorageImpl_FreeBigBlock(
            StorageImpl* This,
354 355
	    ULONG blockIndex);

356
HRESULT StorageImpl_GetNextBlockInChain(
357
            StorageImpl* This,
358 359
	    ULONG blockIndex,
	    ULONG* nextBlockIndex);
360

361 362
void StorageImpl_SetNextBlockInChain(
            StorageImpl* This,
363
	    ULONG blockIndex,
364
	    ULONG nextBlock);
365

366 367
HRESULT StorageImpl_LoadFileHeader(
	    StorageImpl* This);
368

369 370
void StorageImpl_SaveFileHeader(
            StorageImpl* This);
371

372 373
BOOL StorageImpl_ReadProperty(
            StorageImpl* This,
374 375 376
	    ULONG          index,
	    StgProperty*    buffer);

377 378
BOOL StorageImpl_WriteProperty(
            StorageImpl* This,
379 380 381
	    ULONG          index,
	    StgProperty*   buffer);

382
BlockChainStream* Storage32Impl_SmallBlocksToBigBlocks(
383
                      StorageImpl* This,
384
                      SmallBlockChainStream** ppsbChain);
385

386
ULONG Storage32Impl_GetNextExtendedBlock(StorageImpl* This,
387 388
                                         ULONG blockIndex);

389
void Storage32Impl_AddBlockDepot(StorageImpl* This,
390 391
                                 ULONG blockIndex);

392
ULONG Storage32Impl_AddExtBlockDepot(StorageImpl* This);
393

394
ULONG Storage32Impl_GetExtDepotBlock(StorageImpl* This,
395 396
                                     ULONG depotIndex);

397
void Storage32Impl_SetExtDepotBlock(StorageImpl* This,
398 399
                                    ULONG depotIndex,
                                    ULONG blockIndex);
400 401 402 403 404 405 406
/****************************************************************************
 * Storage32InternalImpl definitions.
 *
 * Definition of the implementation structure for the IStorage32 interface.
 * This one implements the IStorage32 interface for storage that are
 * inside another storage.
 */
407
struct StorageInternalImpl
408
{
409
  struct StorageBaseImpl base;
410 411 412 413 414 415 416 417 418

  /*
   * There is no specific data for this class.
   */
};

/*
 * Method definitions for the Storage32InternalImpl class.
 */
419
StorageInternalImpl* StorageInternalImpl_Construct(
420
	    StorageImpl* ancestorStorage,
421
            DWORD          openFlags,
422 423
	    ULONG          rootTropertyIndex);

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 437 438 439 440 441 442 443


/****************************************************************************
 * IEnumSTATSTGImpl definitions.
 *
 * Definition of the implementation structure for the IEnumSTATSTGImpl interface.
 * This class allows iterating through the content of a storage and to find
 * specific items inside it.
 */
struct IEnumSTATSTGImpl
{
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 450 451 452 453 454 455 456 457 458 459 460 461 462 463
  ULONG          firstPropertyNode;     /* Index of the root of the storage to enumerate */

  /*
   * The current implementation of the IEnumSTATSTGImpl class uses a stack
   * to walk the property sets to get the content of a storage. This stack
   * is implemented by the following 3 data members
   */
  ULONG          stackSize;
  ULONG          stackMaxSize;
  ULONG*         stackToVisit;

#define ENUMSTATSGT_SIZE_INCREMENT 10
};

IEnumSTATSTGImpl* IEnumSTATSTGImpl_Construct(
464
            StorageImpl* This,
465 466 467 468 469 470 471 472 473 474 475
	    ULONG          firstPropertyNode);

void IEnumSTATSTGImpl_Destroy(
            IEnumSTATSTGImpl* This);

void IEnumSTATSTGImpl_PushSearchNode(
	    IEnumSTATSTGImpl* This,
	    ULONG             nodeToPush);

ULONG IEnumSTATSTGImpl_PopSearchNode(
            IEnumSTATSTGImpl* This,
476
	    BOOL            remove);
477 478 479

ULONG IEnumSTATSTGImpl_FindProperty(
            IEnumSTATSTGImpl* This,
480
	    const OLECHAR*  lpszPropName,
481 482
	    StgProperty*      buffer);

483
INT IEnumSTATSTGImpl_FindParentProperty(
484 485 486 487 488 489 490 491 492 493 494 495 496 497
  IEnumSTATSTGImpl *This,
  ULONG             childProperty,
  StgProperty      *currentProperty,
  ULONG            *propertyId);


/****************************************************************************
 * StgStreamImpl definitions.
 *
 * This class imlements the IStream32 inteface and represents a stream
 * located inside a storage object.
 */
struct StgStreamImpl
{
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 503 504 505 506
  /*
   * We are an entry in the storage object's stream handler list
   */

  struct list StrmListEntry;

507 508 509
  /*
   * Reference count
   */
510
  LONG		     ref;
511 512 513 514

  /*
   * Storage that is the parent(owner) of the stream
   */
515
  StorageBaseImpl* parentStorage;
516

517 518 519 520 521
  /*
   * Access mode of this stream.
   */
  DWORD grfMode;

522 523 524 525 526 527 528 529 530 531 532 533 534 535
  /*
   * Index of the property that owns (points to) this stream.
   */
  ULONG              ownerProperty;

  /*
   * Helper variable that contains the size of the stream
   */
  ULARGE_INTEGER     streamSize;

  /*
   * This is the current position of the cursor in the stream
   */
  ULARGE_INTEGER     currentPosition;
536

537 538 539 540 541 542 543 544 545 546 547 548 549
  /*
   * The information in the stream is represented by a chain of small blocks
   * or a chain of large blocks. Depending on the case, one of the two
   * following variabled points to that information.
   */
  BlockChainStream*      bigBlockChain;
  SmallBlockChainStream* smallBlockChain;
};

/*
 * Method definition for the StgStreamImpl class.
 */
StgStreamImpl* StgStreamImpl_Construct(
550
		StorageBaseImpl* parentStorage,
551 552
    DWORD            grfMode,
    ULONG            ownerProperty);
553 554


555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577
/******************************************************************************
 * Endian conversion macros
 */
#ifdef WORDS_BIGENDIAN

#define htole32(x) RtlUlongByteSwap(x)
#define htole16(x) RtlUshortByteSwap(x)
#define le32toh(x) RtlUlongByteSwap(x)
#define le16toh(x) RtlUshortByteSwap(x)

#else

#define htole32(x) (x)
#define htole16(x) (x)
#define le32toh(x) (x)
#define le16toh(x) (x)

#endif

/******************************************************************************
 * The StorageUtl_ functions are miscellaneous utility functions. Most of which
 * are abstractions used to read values from file buffers without having to
 * worry about bit order
578
 */
579 580 581 582
void StorageUtl_ReadWord(const BYTE* buffer, ULONG offset, WORD* value);
void StorageUtl_WriteWord(BYTE* buffer, ULONG offset, WORD value);
void StorageUtl_ReadDWord(const BYTE* buffer, ULONG offset, DWORD* value);
void StorageUtl_WriteDWord(BYTE* buffer, ULONG offset, DWORD value);
Juan Lang's avatar
Juan Lang committed
583 584 585 586
void StorageUtl_ReadULargeInteger(const BYTE* buffer, ULONG offset,
 ULARGE_INTEGER* value);
void StorageUtl_WriteULargeInteger(BYTE* buffer, ULONG offset,
 const ULARGE_INTEGER *value);
587 588
void StorageUtl_ReadGUID(const BYTE* buffer, ULONG offset, GUID* value);
void StorageUtl_WriteGUID(BYTE* buffer, ULONG offset, const GUID* value);
589 590 591 592 593 594 595 596 597 598 599 600
void StorageUtl_CopyPropertyToSTATSTG(STATSTG*     destination,
					     StgProperty* source,
					     int          statFlags);

/****************************************************************************
 * BlockChainStream definitions.
 *
 * The BlockChainStream class is a utility class that is used to create an
 * abstraction of the big block chains in the storage file.
 */
struct BlockChainStream
{
601
  StorageImpl* parentStorage;
Thuy Nguyen's avatar
Thuy Nguyen committed
602 603 604 605 606 607
  ULONG*       headOfStreamPlaceHolder;
  ULONG        ownerPropertyIndex;
  ULONG        lastBlockNoInSequence;
  ULONG        lastBlockNoInSequenceIndex;
  ULONG        tailIndex;
  ULONG        numBlocks;
608 609 610 611 612 613
};

/*
 * Methods for the BlockChainStream class.
 */
BlockChainStream* BlockChainStream_Construct(
614
		StorageImpl* parentStorage,
615 616 617 618 619 620 621 622 623
		ULONG*         headOfStreamPlaceHolder,
		ULONG          propertyIndex);

void BlockChainStream_Destroy(
		BlockChainStream* This);

ULONG BlockChainStream_GetHeadOfChain(
		BlockChainStream* This);

624
BOOL BlockChainStream_ReadAt(
625 626 627 628 629 630
		BlockChainStream* This,
		ULARGE_INTEGER offset,
		ULONG          size,
		void*          buffer,
		ULONG*         bytesRead);

631
BOOL BlockChainStream_WriteAt(
632 633 634 635 636 637
		BlockChainStream* This,
		ULARGE_INTEGER offset,
		ULONG          size,
		const void*    buffer,
		ULONG*         bytesWritten);

638
BOOL BlockChainStream_SetSize(
639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655
		BlockChainStream* This,
		ULARGE_INTEGER    newSize);

ULARGE_INTEGER BlockChainStream_GetSize(
    BlockChainStream* This);

ULONG BlockChainStream_GetCount(
    BlockChainStream* This);

/****************************************************************************
 * SmallBlockChainStream definitions.
 *
 * The SmallBlockChainStream class is a utility class that is used to create an
 * abstraction of the small block chains in the storage file.
 */
struct SmallBlockChainStream
{
656
  StorageImpl* parentStorage;
657 658 659 660 661 662 663
  ULONG          ownerPropertyIndex;
};

/*
 * Methods of the SmallBlockChainStream class.
 */
SmallBlockChainStream* SmallBlockChainStream_Construct(
664
	       StorageImpl* parentStorage,
665 666 667 668 669 670 671 672
	       ULONG          propertyIndex);

void SmallBlockChainStream_Destroy(
	       SmallBlockChainStream* This);

ULONG SmallBlockChainStream_GetHeadOfChain(
	       SmallBlockChainStream* This);

673
HRESULT SmallBlockChainStream_GetNextBlockInChain(
674
	       SmallBlockChainStream* This,
675 676
	       ULONG                  blockIndex,
	       ULONG*                 nextBlockIndex);
677 678 679 680 681 682 683 684 685 686 687 688 689

void SmallBlockChainStream_SetNextBlockInChain(
         SmallBlockChainStream* This,
         ULONG                  blockIndex,
         ULONG                  nextBlock);

void SmallBlockChainStream_FreeBlock(
         SmallBlockChainStream* This,
         ULONG                  blockIndex);

ULONG SmallBlockChainStream_GetNextFreeBlock(
         SmallBlockChainStream* This);

690
HRESULT SmallBlockChainStream_ReadAt(
691 692 693 694 695 696
	       SmallBlockChainStream* This,
	       ULARGE_INTEGER offset,
	       ULONG          size,
	       void*          buffer,
	       ULONG*         bytesRead);

697
BOOL SmallBlockChainStream_WriteAt(
698 699 700 701 702 703
	       SmallBlockChainStream* This,
	       ULARGE_INTEGER offset,
	       ULONG          size,
	       const void*    buffer,
	       ULONG*         bytesWritten);

704
BOOL SmallBlockChainStream_SetSize(
705 706 707 708 709 710 711 712 713 714
	       SmallBlockChainStream* This,
	       ULARGE_INTEGER          newSize);

ULARGE_INTEGER SmallBlockChainStream_GetSize(
         SmallBlockChainStream* This);

ULONG SmallBlockChainStream_GetCount(
         SmallBlockChainStream* This);


715
#endif /* __STORAGE32_H__ */