storage32.h 15.4 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
 *
 * 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
27
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, 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
/*
 * Forward declarations of all the structures used by the storage
 * module.
 */
118 119
typedef struct StorageBaseImpl     StorageBaseImpl;
typedef struct StorageImpl         StorageImpl;
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
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
151
 * same sized blocks. The implementation for the methods described in
152 153 154 155 156 157 158 159 160
 * this section appear in stg_bigblockfile.c
 */

typedef struct BigBlockFile BigBlockFile,*LPBIGBLOCKFILE;

/*
 * Declaration of the functions used to manipulate the BigBlockFile
 * data structure.
 */
161
BigBlockFile*  BIGBLOCKFILE_Construct(HANDLE hFile,
162
                                      ILockBytes* pLkByt,
163
                                      DWORD openFlags,
164 165
                                      ULONG blocksize,
                                      BOOL fileBased);
166
void           BIGBLOCKFILE_Destructor(LPBIGBLOCKFILE This);
167 168
HRESULT        BIGBLOCKFILE_EnsureExists(LPBIGBLOCKFILE This, ULONG index);
HRESULT        BIGBLOCKFILE_SetSize(LPBIGBLOCKFILE This, ULARGE_INTEGER newSize);
169 170 171
HRESULT        BIGBLOCKFILE_ReadAt(LPBIGBLOCKFILE This, ULARGE_INTEGER offset,
           void* buffer, ULONG size, ULONG* bytesRead);
HRESULT        BIGBLOCKFILE_WriteAt(LPBIGBLOCKFILE This, ULARGE_INTEGER offset,
172
           const void* buffer, ULONG size, ULONG* bytesRead);
173

Patrik Stridvall's avatar
Patrik Stridvall committed
174 175 176 177 178 179 180
/*************************************************************************
 * Ole Convert support
 */

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

181 182 183
/****************************************************************************
 * Storage32BaseImpl definitions.
 *
Alexandre Julliard's avatar
Alexandre Julliard committed
184 185
 * This structure defines the base information contained in all implementations
 * of IStorage32 contained in this file storage implementation.
186 187 188 189
 *
 * In OOP terms, this is the base class for all the IStorage32 implementations
 * contained in this file.
 */
190
struct StorageBaseImpl
191
{
192
  const IStorageVtbl *lpVtbl;    /* Needs to be the first item in the struct
193
			    * since we want to cast this in a Storage32 pointer */
194

195
  const IPropertySetStorageVtbl *pssVtbl; /* interface for adding a properties stream */
196

197 198 199 200 201 202
  /*
   * Stream tracking list
   */

  struct list strmHead;

203 204 205
  /*
   * Reference count of this object
   */
206
  LONG ref;
207 208 209

  /*
   * Ancestor storage (top level)
210
   */
211 212
  StorageImpl* ancestorStorage;

213 214 215 216 217
  /*
   * Index of the property for the root of
   * this storage
   */
  ULONG rootPropertySetIndex;
218 219

  /*
220 221
   * virtual Destructor method.
   */
222
  void (*v_destructor)(StorageBaseImpl*);
223 224 225 226 227

  /*
   * flags that this storage was opened or created with
   */
  DWORD openFlags;
228 229 230 231 232

  /*
   * State bits appear to only be preserved while running. No in the stream
   */
  DWORD stateBits;
233 234
};

235 236 237 238
/****************************************************************************
 * StorageBaseImpl stream list handlers
 */

239
void StorageBaseImpl_AddStream(StorageBaseImpl * stg, StgStreamImpl * strm);
240
void StorageBaseImpl_RemoveStream(StorageBaseImpl * stg, StgStreamImpl * strm);
241 242 243 244 245 246 247

/****************************************************************************
 * Storage32Impl definitions.
 *
 * This implementation of the IStorage32 interface represents a root
 * storage. Basically, a document file.
 */
248
struct StorageImpl
249
{
250
  struct StorageBaseImpl base;
251

252 253 254 255
  /*
   * The following data members are specific to the Storage32Impl
   * class
   */
256
  HANDLE           hFile;      /* Physical support for the Docfile */
257
  LPOLESTR         pwcsName;   /* Full path of the document file */
258 259
  BOOL             create;     /* Was the storage created or opened.
                                  The behaviour of STGM_SIMPLE depends on this */
260

Alexandre Julliard's avatar
Alexandre Julliard committed
261 262 263
  /* FIXME: should this be in Storage32BaseImpl ? */
  WCHAR            filename[PROPERTY_NAME_BUFFER_LEN];

264 265 266 267 268 269 270 271 272 273 274 275 276
  /*
   * File header
   */
  WORD  bigBlockSizeBits;
  WORD  smallBlockSizeBits;
  ULONG bigBlockSize;
  ULONG smallBlockSize;
  ULONG bigBlockDepotCount;
  ULONG rootStartBlock;
  ULONG smallBlockDepotStart;
  ULONG extBigBlockDepotStart;
  ULONG extBigBlockDepotCount;
  ULONG bigBlockDepotStart[COUNT_BBDEPOTINHEADER];
277 278 279

  ULONG blockDepotCached[NUM_BLOCKS_PER_DEPOT_BLOCK];
  ULONG indexBlockDepotCached;
280
  ULONG prevFreeBlock;
281

282 283 284 285 286
  /*
   * Abstraction of the big block chains for the chains of the header.
   */
  BlockChainStream* rootBlockChain;
  BlockChainStream* smallBlockDepotChain;
287
  BlockChainStream* smallBlockRootChain;
288 289 290 291

  /*
   * Pointer to the big block file abstraction
   */
292
  BigBlockFile* bigBlockFile;
293 294
};

295
BOOL StorageImpl_ReadProperty(
296 297 298
            StorageImpl*    This,
            ULONG           index,
            StgProperty*    buffer);
299

300
BOOL StorageImpl_WriteProperty(
301 302 303
            StorageImpl*        This,
            ULONG               index,
            const StgProperty*  buffer);
304

305
BlockChainStream* Storage32Impl_SmallBlocksToBigBlocks(
306
                      StorageImpl* This,
307
                      SmallBlockChainStream** ppsbChain);
308

309 310 311 312
SmallBlockChainStream* Storage32Impl_BigBlocksToSmallBlocks(
                      StorageImpl* This,
                      BlockChainStream** ppbbChain);

313 314 315
/****************************************************************************
 * StgStreamImpl definitions.
 *
316
 * This class implements the IStream32 interface and represents a stream
317 318 319 320
 * located inside a storage object.
 */
struct StgStreamImpl
{
321
  const IStreamVtbl *lpVtbl;  /* Needs to be the first item in the struct
322
			 * since we want to cast this to an IStream pointer */
323

324 325 326 327 328 329
  /*
   * We are an entry in the storage object's stream handler list
   */

  struct list StrmListEntry;

330 331 332
  /*
   * Reference count
   */
333
  LONG		     ref;
334 335 336 337

  /*
   * Storage that is the parent(owner) of the stream
   */
338
  StorageBaseImpl* parentStorage;
339

340 341 342 343 344
  /*
   * Access mode of this stream.
   */
  DWORD grfMode;

345 346 347 348 349 350 351 352 353 354 355 356 357 358
  /*
   * 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;
359

360 361 362
  /*
   * 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
Austin English's avatar
Austin English committed
363
   * following variables points to that information.
364 365 366 367 368 369 370 371 372
   */
  BlockChainStream*      bigBlockChain;
  SmallBlockChainStream* smallBlockChain;
};

/*
 * Method definition for the StgStreamImpl class.
 */
StgStreamImpl* StgStreamImpl_Construct(
373
		StorageBaseImpl* parentStorage,
374 375
    DWORD            grfMode,
    ULONG            ownerProperty);
376 377


378 379 380 381 382 383 384
/******************************************************************************
 * Endian conversion macros
 */
#ifdef WORDS_BIGENDIAN

#define htole32(x) RtlUlongByteSwap(x)
#define htole16(x) RtlUshortByteSwap(x)
385 386
#define lendian32toh(x) RtlUlongByteSwap(x)
#define lendian16toh(x) RtlUshortByteSwap(x)
387 388 389 390 391

#else

#define htole32(x) (x)
#define htole16(x) (x)
392 393
#define lendian32toh(x) (x)
#define lendian16toh(x) (x)
394 395 396 397 398 399 400

#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
401
 */
402 403 404 405
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
406 407 408 409
void StorageUtl_ReadULargeInteger(const BYTE* buffer, ULONG offset,
 ULARGE_INTEGER* value);
void StorageUtl_WriteULargeInteger(BYTE* buffer, ULONG offset,
 const ULARGE_INTEGER *value);
410 411
void StorageUtl_ReadGUID(const BYTE* buffer, ULONG offset, GUID* value);
void StorageUtl_WriteGUID(BYTE* buffer, ULONG offset, const GUID* value);
412 413
void StorageUtl_CopyPropertyToSTATSTG(STATSTG* destination, const StgProperty* source,
 int statFlags);
414 415 416 417 418 419 420 421 422

/****************************************************************************
 * 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
{
423
  StorageImpl* parentStorage;
Thuy Nguyen's avatar
Thuy Nguyen committed
424 425 426 427 428 429
  ULONG*       headOfStreamPlaceHolder;
  ULONG        ownerPropertyIndex;
  ULONG        lastBlockNoInSequence;
  ULONG        lastBlockNoInSequenceIndex;
  ULONG        tailIndex;
  ULONG        numBlocks;
430 431 432 433 434 435
};

/*
 * Methods for the BlockChainStream class.
 */
BlockChainStream* BlockChainStream_Construct(
436
		StorageImpl* parentStorage,
437 438 439 440 441 442
		ULONG*         headOfStreamPlaceHolder,
		ULONG          propertyIndex);

void BlockChainStream_Destroy(
		BlockChainStream* This);

443
HRESULT BlockChainStream_ReadAt(
444 445 446 447 448 449
		BlockChainStream* This,
		ULARGE_INTEGER offset,
		ULONG          size,
		void*          buffer,
		ULONG*         bytesRead);

450
HRESULT BlockChainStream_WriteAt(
451 452 453 454 455 456
		BlockChainStream* This,
		ULARGE_INTEGER offset,
		ULONG          size,
		const void*    buffer,
		ULONG*         bytesWritten);

457
BOOL BlockChainStream_SetSize(
458 459 460 461 462 463 464 465 466 467 468
		BlockChainStream* This,
		ULARGE_INTEGER    newSize);

/****************************************************************************
 * 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
{
469
  StorageImpl* parentStorage;
470
  ULONG          ownerPropertyIndex;
471
  ULONG*         headOfStreamPlaceHolder;
472 473 474 475 476 477
};

/*
 * Methods of the SmallBlockChainStream class.
 */
SmallBlockChainStream* SmallBlockChainStream_Construct(
478 479 480
           StorageImpl*   parentStorage,
           ULONG*         headOfStreamPlaceHolder,
           ULONG          propertyIndex);
481 482 483 484

void SmallBlockChainStream_Destroy(
	       SmallBlockChainStream* This);

485
HRESULT SmallBlockChainStream_ReadAt(
486 487 488 489 490 491
	       SmallBlockChainStream* This,
	       ULARGE_INTEGER offset,
	       ULONG          size,
	       void*          buffer,
	       ULONG*         bytesRead);

492
HRESULT SmallBlockChainStream_WriteAt(
493 494 495 496 497 498
	       SmallBlockChainStream* This,
	       ULARGE_INTEGER offset,
	       ULONG          size,
	       const void*    buffer,
	       ULONG*         bytesWritten);

499
BOOL SmallBlockChainStream_SetSize(
500 501 502 503
	       SmallBlockChainStream* This,
	       ULARGE_INTEGER          newSize);


504
#endif /* __STORAGE32_H__ */