1999-01-30 14:24:23 +01:00
|
|
|
/*
|
|
|
|
* 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
|
2002-06-01 01:06:46 +02:00
|
|
|
* prototypes that are used in the many files implementing the
|
1999-01-30 14:24:23 +01:00
|
|
|
* storage functionality
|
|
|
|
*
|
|
|
|
* Copyright 1998,1999 Francis Beaudet
|
|
|
|
* Copyright 1998,1999 Thuy Nguyen
|
2010-07-17 18:56:17 +02:00
|
|
|
* Copyright 2010 Vincent Povirk for CodeWeavers
|
2002-03-10 00:29:33 +01:00
|
|
|
*
|
|
|
|
* 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
|
2006-05-18 14:49:52 +02:00
|
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
1999-01-30 14:24:23 +01:00
|
|
|
*/
|
|
|
|
#ifndef __STORAGE32_H__
|
|
|
|
#define __STORAGE32_H__
|
|
|
|
|
2003-09-06 01:08:26 +02:00
|
|
|
#include <stdarg.h>
|
|
|
|
|
|
|
|
#include "windef.h"
|
|
|
|
#include "winbase.h"
|
1999-08-18 20:35:57 +02:00
|
|
|
#include "winnt.h"
|
2002-12-05 21:33:07 +01:00
|
|
|
#include "objbase.h"
|
2005-04-24 19:22:26 +02:00
|
|
|
#include "winreg.h"
|
|
|
|
#include "winternl.h"
|
2006-02-21 09:03:36 +01:00
|
|
|
#include "wine/list.h"
|
1999-08-18 20:35:57 +02:00
|
|
|
|
1999-01-30 14:24:23 +01:00
|
|
|
/*
|
|
|
|
* Definitions for the file format offsets.
|
|
|
|
*/
|
2010-07-17 16:46:43 +02:00
|
|
|
static const ULONG OFFSET_MINORVERSION = 0x00000018;
|
|
|
|
static const ULONG OFFSET_MAJORVERSION = 0x0000001a;
|
|
|
|
static const ULONG OFFSET_BYTEORDERMARKER = 0x0000001c;
|
1999-01-30 14:24:23 +01:00
|
|
|
static const ULONG OFFSET_BIGBLOCKSIZEBITS = 0x0000001e;
|
|
|
|
static const ULONG OFFSET_SMALLBLOCKSIZEBITS = 0x00000020;
|
2010-07-17 16:46:43 +02:00
|
|
|
static const ULONG OFFSET_DIRSECTORCOUNT = 0x00000028;
|
1999-01-30 14:24:23 +01:00
|
|
|
static const ULONG OFFSET_BBDEPOTCOUNT = 0x0000002C;
|
|
|
|
static const ULONG OFFSET_ROOTSTARTBLOCK = 0x00000030;
|
2014-04-23 21:55:56 +02:00
|
|
|
static const ULONG OFFSET_TRANSACTIONSIG = 0x00000034;
|
2010-03-20 20:28:09 +01:00
|
|
|
static const ULONG OFFSET_SMALLBLOCKLIMIT = 0x00000038;
|
1999-01-30 14:24:23 +01:00
|
|
|
static const ULONG OFFSET_SBDEPOTSTART = 0x0000003C;
|
2002-08-16 21:55:14 +02:00
|
|
|
static const ULONG OFFSET_SBDEPOTCOUNT = 0x00000040;
|
1999-01-30 14:24:23 +01:00
|
|
|
static const ULONG OFFSET_EXTBBDEPOTSTART = 0x00000044;
|
|
|
|
static const ULONG OFFSET_EXTBBDEPOTCOUNT = 0x00000048;
|
|
|
|
static const ULONG OFFSET_BBDEPOTSTART = 0x0000004C;
|
1999-02-05 10:21:51 +01:00
|
|
|
static const ULONG OFFSET_PS_NAME = 0x00000000;
|
|
|
|
static const ULONG OFFSET_PS_NAMELENGTH = 0x00000040;
|
2009-11-10 21:21:31 +01:00
|
|
|
static const ULONG OFFSET_PS_STGTYPE = 0x00000042;
|
2009-10-27 19:09:16 +01:00
|
|
|
static const ULONG OFFSET_PS_LEFTCHILD = 0x00000044;
|
|
|
|
static const ULONG OFFSET_PS_RIGHTCHILD = 0x00000048;
|
2009-11-11 17:40:12 +01:00
|
|
|
static const ULONG OFFSET_PS_DIRROOT = 0x0000004C;
|
1999-02-05 10:21:51 +01:00
|
|
|
static const ULONG OFFSET_PS_GUID = 0x00000050;
|
2009-10-23 20:29:56 +02:00
|
|
|
static const ULONG OFFSET_PS_CTIMELOW = 0x00000064;
|
|
|
|
static const ULONG OFFSET_PS_CTIMEHIGH = 0x00000068;
|
|
|
|
static const ULONG OFFSET_PS_MTIMELOW = 0x0000006C;
|
|
|
|
static const ULONG OFFSET_PS_MTIMEHIGH = 0x00000070;
|
2002-06-01 01:06:46 +02:00
|
|
|
static const ULONG OFFSET_PS_STARTBLOCK = 0x00000074;
|
|
|
|
static const ULONG OFFSET_PS_SIZE = 0x00000078;
|
2014-05-20 23:08:09 +02:00
|
|
|
static const ULONG OFFSET_PS_SIZE_HIGH = 0x0000007C;
|
1999-01-30 14:24:23 +01:00
|
|
|
static const WORD DEF_BIG_BLOCK_SIZE_BITS = 0x0009;
|
2010-04-12 21:01:01 +02:00
|
|
|
static const WORD MIN_BIG_BLOCK_SIZE_BITS = 0x0009;
|
|
|
|
static const WORD MAX_BIG_BLOCK_SIZE_BITS = 0x000c;
|
1999-01-30 14:24:23 +01:00
|
|
|
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;
|
2014-12-29 15:44:47 +01:00
|
|
|
static const ULONG BLOCK_FIRST_SPECIAL = 0xFFFFFFFB;
|
1999-02-24 11:36:34 +01:00
|
|
|
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;
|
2009-11-10 21:55:25 +01:00
|
|
|
static const ULONG DIRENTRY_NULL = 0xFFFFFFFF;
|
1999-01-30 14:24:23 +01:00
|
|
|
|
2009-11-11 17:31:55 +01:00
|
|
|
#define DIRENTRY_NAME_MAX_LEN 0x20
|
|
|
|
#define DIRENTRY_NAME_BUFFER_LEN 0x40
|
1999-01-30 14:24:23 +01:00
|
|
|
|
2009-11-11 17:34:45 +01:00
|
|
|
#define RAW_DIRENTRY_SIZE 0x00000080
|
1999-01-30 14:24:23 +01:00
|
|
|
|
2010-03-10 20:49:04 +01:00
|
|
|
#define HEADER_SIZE 512
|
|
|
|
|
2010-03-10 21:46:53 +01:00
|
|
|
#define MIN_BIG_BLOCK_SIZE 0x200
|
|
|
|
#define MAX_BIG_BLOCK_SIZE 0x1000
|
|
|
|
|
1999-01-30 14:24:23 +01:00
|
|
|
/*
|
2009-11-11 17:42:19 +01:00
|
|
|
* Type of child entry link
|
1999-01-30 14:24:23 +01:00
|
|
|
*/
|
2009-11-11 17:42:19 +01:00
|
|
|
#define DIRENTRY_RELATION_PREVIOUS 0
|
|
|
|
#define DIRENTRY_RELATION_NEXT 1
|
|
|
|
#define DIRENTRY_RELATION_DIR 2
|
1999-01-30 14:24:23 +01:00
|
|
|
|
|
|
|
/*
|
2009-11-10 21:21:31 +01:00
|
|
|
* type constant used in files for the root storage
|
1999-01-30 14:24:23 +01:00
|
|
|
*/
|
2009-11-10 21:21:31 +01:00
|
|
|
#define STGTY_ROOT 0x05
|
1999-01-30 14:24:23 +01:00
|
|
|
|
|
|
|
#define COUNT_BBDEPOTINHEADER 109
|
2010-03-20 20:28:09 +01:00
|
|
|
|
|
|
|
/* FIXME: This value is stored in the header, but we hard-code it to 0x1000. */
|
1999-01-30 14:24:23 +01:00
|
|
|
#define LIMIT_TO_USE_SMALL_BLOCK 0x1000
|
|
|
|
|
2005-03-07 13:24:42 +01:00
|
|
|
#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)
|
|
|
|
|
1999-01-30 14:24:23 +01:00
|
|
|
/*
|
|
|
|
* Forward declarations of all the structures used by the storage
|
|
|
|
* module.
|
|
|
|
*/
|
1999-02-26 12:11:13 +01:00
|
|
|
typedef struct StorageBaseImpl StorageBaseImpl;
|
2009-11-25 22:07:57 +01:00
|
|
|
typedef struct StorageBaseImplVtbl StorageBaseImplVtbl;
|
1999-02-26 12:11:13 +01:00
|
|
|
typedef struct StorageImpl StorageImpl;
|
1999-01-30 14:24:23 +01:00
|
|
|
typedef struct BlockChainStream BlockChainStream;
|
|
|
|
typedef struct SmallBlockChainStream SmallBlockChainStream;
|
|
|
|
typedef struct IEnumSTATSTGImpl IEnumSTATSTGImpl;
|
2009-11-10 21:30:59 +01:00
|
|
|
typedef struct DirEntry DirEntry;
|
1999-01-30 14:24:23 +01:00
|
|
|
typedef struct StgStreamImpl StgStreamImpl;
|
|
|
|
|
2009-11-12 22:53:42 +01:00
|
|
|
/*
|
|
|
|
* A reference to a directory entry in the file or a transacted cache.
|
|
|
|
*/
|
|
|
|
typedef ULONG DirRef;
|
|
|
|
|
1999-01-30 14:24:23 +01:00
|
|
|
/*
|
2009-11-10 21:30:59 +01:00
|
|
|
* This utility structure is used to read/write the information in a directory
|
|
|
|
* entry.
|
1999-01-30 14:24:23 +01:00
|
|
|
*/
|
2009-11-10 21:30:59 +01:00
|
|
|
struct DirEntry
|
1999-01-30 14:24:23 +01:00
|
|
|
{
|
2009-11-11 17:31:55 +01:00
|
|
|
WCHAR name[DIRENTRY_NAME_MAX_LEN];
|
1999-01-30 14:24:23 +01:00
|
|
|
WORD sizeOfNameString;
|
2009-11-12 19:34:05 +01:00
|
|
|
BYTE stgType;
|
2009-11-12 22:53:42 +01:00
|
|
|
DirRef leftChild;
|
|
|
|
DirRef rightChild;
|
|
|
|
DirRef dirRootEntry;
|
2009-11-12 20:10:17 +01:00
|
|
|
GUID clsid;
|
2009-10-23 20:29:56 +02:00
|
|
|
FILETIME ctime;
|
|
|
|
FILETIME mtime;
|
1999-01-30 14:24:23 +01:00
|
|
|
ULONG startingBlock;
|
|
|
|
ULARGE_INTEGER size;
|
|
|
|
};
|
|
|
|
|
2011-04-21 10:45:36 +02:00
|
|
|
HRESULT FileLockBytesImpl_Construct(HANDLE hFile, DWORD openFlags, LPCWSTR pwcsName, ILockBytes **pLockBytes) DECLSPEC_HIDDEN;
|
1999-01-30 14:24:23 +01:00
|
|
|
|
2000-03-24 22:19:02 +01:00
|
|
|
/*************************************************************************
|
|
|
|
* Ole Convert support
|
|
|
|
*/
|
|
|
|
|
2012-07-17 08:31:08 +02:00
|
|
|
HRESULT STORAGE_CreateOleStream(IStorage*, DWORD) DECLSPEC_HIDDEN;
|
2011-04-21 10:45:36 +02:00
|
|
|
HRESULT OLECONVERT_CreateCompObjStream(LPSTORAGE pStorage, LPCSTR strOleTypeName) DECLSPEC_HIDDEN;
|
2000-03-24 22:19:02 +01:00
|
|
|
|
2013-04-19 10:37:01 +02:00
|
|
|
enum swmr_mode
|
|
|
|
{
|
|
|
|
SWMR_None,
|
|
|
|
SWMR_Writer,
|
|
|
|
SWMR_Reader
|
|
|
|
};
|
2009-11-25 22:07:57 +01:00
|
|
|
|
1999-01-30 14:24:23 +01:00
|
|
|
/****************************************************************************
|
2012-07-13 12:37:58 +02:00
|
|
|
* StorageBaseImpl definitions.
|
1999-01-30 14:24:23 +01:00
|
|
|
*
|
2002-01-31 22:01:35 +01:00
|
|
|
* This structure defines the base information contained in all implementations
|
2012-07-13 12:37:58 +02:00
|
|
|
* of IStorage contained in this file storage implementation.
|
1999-01-30 14:24:23 +01:00
|
|
|
*
|
2012-07-13 12:37:58 +02:00
|
|
|
* In OOP terms, this is the base class for all the IStorage implementations
|
1999-01-30 14:24:23 +01:00
|
|
|
* contained in this file.
|
|
|
|
*/
|
1999-02-26 12:11:13 +01:00
|
|
|
struct StorageBaseImpl
|
1999-01-30 14:24:23 +01:00
|
|
|
{
|
2012-07-13 12:37:58 +02:00
|
|
|
IStorage IStorage_iface;
|
2012-07-14 18:42:48 +02:00
|
|
|
IPropertySetStorage IPropertySetStorage_iface; /* interface for adding a properties stream */
|
2013-04-18 08:04:40 +02:00
|
|
|
IDirectWriterLock IDirectWriterLock_iface;
|
2012-07-13 12:37:58 +02:00
|
|
|
LONG ref;
|
2005-02-21 21:58:09 +01:00
|
|
|
|
2006-02-21 09:03:36 +01:00
|
|
|
/*
|
|
|
|
* Stream tracking list
|
|
|
|
*/
|
|
|
|
|
|
|
|
struct list strmHead;
|
|
|
|
|
2009-11-19 20:42:47 +01:00
|
|
|
/*
|
|
|
|
* Storage tracking list
|
|
|
|
*/
|
|
|
|
struct list storageHead;
|
|
|
|
|
2009-12-01 00:07:37 +01:00
|
|
|
/*
|
|
|
|
* TRUE if this object has been invalidated
|
|
|
|
*/
|
2013-10-15 00:27:16 +02:00
|
|
|
BOOL reverted;
|
2009-12-01 00:07:37 +01:00
|
|
|
|
1999-01-30 14:24:23 +01:00
|
|
|
/*
|
2009-11-12 20:19:37 +01:00
|
|
|
* Index of the directory entry of this storage
|
1999-01-30 14:24:23 +01:00
|
|
|
*/
|
2009-11-12 22:53:42 +01:00
|
|
|
DirRef storageDirEntry;
|
2002-06-01 01:06:46 +02:00
|
|
|
|
|
|
|
/*
|
2009-11-25 22:07:57 +01:00
|
|
|
* virtual methods.
|
1999-01-30 14:24:23 +01:00
|
|
|
*/
|
2009-11-25 22:07:57 +01:00
|
|
|
const StorageBaseImplVtbl *baseVtbl;
|
2005-05-13 15:58:43 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* flags that this storage was opened or created with
|
|
|
|
*/
|
|
|
|
DWORD openFlags;
|
2007-06-07 20:17:56 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* State bits appear to only be preserved while running. No in the stream
|
|
|
|
*/
|
|
|
|
DWORD stateBits;
|
2009-12-02 18:37:54 +01:00
|
|
|
|
2013-10-15 00:27:16 +02:00
|
|
|
BOOL create; /* Was the storage created or opened.
|
|
|
|
The behaviour of STGM_SIMPLE depends on this */
|
2009-12-02 17:59:47 +01:00
|
|
|
/*
|
|
|
|
* If this storage was opened in transacted mode, the object that implements
|
|
|
|
* the transacted snapshot or cache.
|
|
|
|
*/
|
|
|
|
StorageBaseImpl *transactedChild;
|
2013-04-19 10:37:01 +02:00
|
|
|
enum swmr_mode lockingrole;
|
1999-01-30 14:24:23 +01:00
|
|
|
};
|
|
|
|
|
2009-11-25 22:07:57 +01:00
|
|
|
/* virtual methods for StorageBaseImpl objects */
|
|
|
|
struct StorageBaseImplVtbl {
|
|
|
|
void (*Destroy)(StorageBaseImpl*);
|
2009-12-04 22:49:31 +01:00
|
|
|
void (*Invalidate)(StorageBaseImpl*);
|
2010-07-17 20:07:21 +02:00
|
|
|
HRESULT (*Flush)(StorageBaseImpl*);
|
2010-07-17 20:00:17 +02:00
|
|
|
HRESULT (*GetFilename)(StorageBaseImpl*,LPWSTR*);
|
2009-11-25 22:28:34 +01:00
|
|
|
HRESULT (*CreateDirEntry)(StorageBaseImpl*,const DirEntry*,DirRef*);
|
2009-11-25 23:53:05 +01:00
|
|
|
HRESULT (*WriteDirEntry)(StorageBaseImpl*,DirRef,const DirEntry*);
|
2009-11-26 00:01:27 +01:00
|
|
|
HRESULT (*ReadDirEntry)(StorageBaseImpl*,DirRef,DirEntry*);
|
2009-11-30 16:50:15 +01:00
|
|
|
HRESULT (*DestroyDirEntry)(StorageBaseImpl*,DirRef);
|
2009-11-30 17:35:55 +01:00
|
|
|
HRESULT (*StreamReadAt)(StorageBaseImpl*,DirRef,ULARGE_INTEGER,ULONG,void*,ULONG*);
|
2009-11-30 18:38:45 +01:00
|
|
|
HRESULT (*StreamWriteAt)(StorageBaseImpl*,DirRef,ULARGE_INTEGER,ULONG,const void*,ULONG*);
|
2009-11-30 22:05:41 +01:00
|
|
|
HRESULT (*StreamSetSize)(StorageBaseImpl*,DirRef,ULARGE_INTEGER);
|
2010-05-05 00:40:55 +02:00
|
|
|
HRESULT (*StreamLink)(StorageBaseImpl*,DirRef,DirRef);
|
2014-04-23 21:55:56 +02:00
|
|
|
HRESULT (*GetTransactionSig)(StorageBaseImpl*,ULONG*,BOOL);
|
|
|
|
HRESULT (*SetTransactionSig)(StorageBaseImpl*,ULONG);
|
2014-05-09 22:57:19 +02:00
|
|
|
HRESULT (*LockTransaction)(StorageBaseImpl*,BOOL);
|
|
|
|
HRESULT (*UnlockTransaction)(StorageBaseImpl*,BOOL);
|
2009-11-25 22:07:57 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
static inline void StorageBaseImpl_Destroy(StorageBaseImpl *This)
|
|
|
|
{
|
|
|
|
This->baseVtbl->Destroy(This);
|
|
|
|
}
|
|
|
|
|
2009-12-04 22:49:31 +01:00
|
|
|
static inline void StorageBaseImpl_Invalidate(StorageBaseImpl *This)
|
|
|
|
{
|
|
|
|
This->baseVtbl->Invalidate(This);
|
|
|
|
}
|
|
|
|
|
2010-07-17 20:07:21 +02:00
|
|
|
static inline HRESULT StorageBaseImpl_Flush(StorageBaseImpl *This)
|
|
|
|
{
|
|
|
|
return This->baseVtbl->Flush(This);
|
|
|
|
}
|
|
|
|
|
2010-07-17 20:00:17 +02:00
|
|
|
static inline HRESULT StorageBaseImpl_GetFilename(StorageBaseImpl *This, LPWSTR *result)
|
|
|
|
{
|
|
|
|
return This->baseVtbl->GetFilename(This, result);
|
|
|
|
}
|
|
|
|
|
2009-11-25 22:28:34 +01:00
|
|
|
static inline HRESULT StorageBaseImpl_CreateDirEntry(StorageBaseImpl *This,
|
|
|
|
const DirEntry *newData, DirRef *index)
|
|
|
|
{
|
|
|
|
return This->baseVtbl->CreateDirEntry(This, newData, index);
|
|
|
|
}
|
|
|
|
|
2009-11-25 23:53:05 +01:00
|
|
|
static inline HRESULT StorageBaseImpl_WriteDirEntry(StorageBaseImpl *This,
|
|
|
|
DirRef index, const DirEntry *data)
|
|
|
|
{
|
|
|
|
return This->baseVtbl->WriteDirEntry(This, index, data);
|
|
|
|
}
|
|
|
|
|
2009-11-26 00:01:27 +01:00
|
|
|
static inline HRESULT StorageBaseImpl_ReadDirEntry(StorageBaseImpl *This,
|
|
|
|
DirRef index, DirEntry *data)
|
|
|
|
{
|
|
|
|
return This->baseVtbl->ReadDirEntry(This, index, data);
|
|
|
|
}
|
|
|
|
|
2009-11-30 16:50:15 +01:00
|
|
|
static inline HRESULT StorageBaseImpl_DestroyDirEntry(StorageBaseImpl *This,
|
|
|
|
DirRef index)
|
|
|
|
{
|
|
|
|
return This->baseVtbl->DestroyDirEntry(This, index);
|
|
|
|
}
|
|
|
|
|
2009-11-30 17:35:55 +01:00
|
|
|
/* Read up to size bytes from this directory entry's stream at the given offset. */
|
|
|
|
static inline HRESULT StorageBaseImpl_StreamReadAt(StorageBaseImpl *This,
|
|
|
|
DirRef index, ULARGE_INTEGER offset, ULONG size, void *buffer, ULONG *bytesRead)
|
|
|
|
{
|
|
|
|
return This->baseVtbl->StreamReadAt(This, index, offset, size, buffer, bytesRead);
|
|
|
|
}
|
|
|
|
|
2009-11-30 22:40:53 +01:00
|
|
|
/* Write size bytes to this directory entry's stream at the given offset,
|
|
|
|
* growing the stream if necessary. */
|
2009-11-30 18:38:45 +01:00
|
|
|
static inline HRESULT StorageBaseImpl_StreamWriteAt(StorageBaseImpl *This,
|
|
|
|
DirRef index, ULARGE_INTEGER offset, ULONG size, const void *buffer, ULONG *bytesWritten)
|
|
|
|
{
|
|
|
|
return This->baseVtbl->StreamWriteAt(This, index, offset, size, buffer, bytesWritten);
|
|
|
|
}
|
|
|
|
|
2009-11-30 22:05:41 +01:00
|
|
|
static inline HRESULT StorageBaseImpl_StreamSetSize(StorageBaseImpl *This,
|
|
|
|
DirRef index, ULARGE_INTEGER newsize)
|
|
|
|
{
|
|
|
|
return This->baseVtbl->StreamSetSize(This, index, newsize);
|
|
|
|
}
|
|
|
|
|
2010-05-05 00:40:55 +02:00
|
|
|
/* Make dst point to the same stream that src points to. Other stream operations
|
|
|
|
* will not work properly for entries that point to the same stream, so this
|
|
|
|
* must be a very temporary state, and only one entry pointing to a given stream
|
|
|
|
* may be reachable at any given time. */
|
|
|
|
static inline HRESULT StorageBaseImpl_StreamLink(StorageBaseImpl *This,
|
|
|
|
DirRef dst, DirRef src)
|
|
|
|
{
|
|
|
|
return This->baseVtbl->StreamLink(This, dst, src);
|
|
|
|
}
|
|
|
|
|
2014-04-23 21:55:56 +02:00
|
|
|
static inline HRESULT StorageBaseImpl_GetTransactionSig(StorageBaseImpl *This,
|
|
|
|
ULONG* result, BOOL refresh)
|
|
|
|
{
|
|
|
|
return This->baseVtbl->GetTransactionSig(This, result, refresh);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline HRESULT StorageBaseImpl_SetTransactionSig(StorageBaseImpl *This,
|
|
|
|
ULONG value)
|
|
|
|
{
|
|
|
|
return This->baseVtbl->SetTransactionSig(This, value);
|
|
|
|
}
|
|
|
|
|
2014-05-09 22:57:19 +02:00
|
|
|
static inline HRESULT StorageBaseImpl_LockTransaction(StorageBaseImpl *This, BOOL write)
|
2014-04-23 21:55:56 +02:00
|
|
|
{
|
2014-05-09 22:57:19 +02:00
|
|
|
return This->baseVtbl->LockTransaction(This, write);
|
2014-04-23 21:55:56 +02:00
|
|
|
}
|
|
|
|
|
2014-05-09 22:57:19 +02:00
|
|
|
static inline HRESULT StorageBaseImpl_UnlockTransaction(StorageBaseImpl *This, BOOL write)
|
2014-04-23 21:55:56 +02:00
|
|
|
{
|
2014-05-09 22:57:19 +02:00
|
|
|
return This->baseVtbl->UnlockTransaction(This, write);
|
2014-04-23 21:55:56 +02:00
|
|
|
}
|
|
|
|
|
2006-02-21 09:03:36 +01:00
|
|
|
/****************************************************************************
|
|
|
|
* StorageBaseImpl stream list handlers
|
|
|
|
*/
|
|
|
|
|
2011-04-21 10:45:36 +02:00
|
|
|
void StorageBaseImpl_AddStream(StorageBaseImpl * stg, StgStreamImpl * strm) DECLSPEC_HIDDEN;
|
|
|
|
void StorageBaseImpl_RemoveStream(StorageBaseImpl * stg, StgStreamImpl * strm) DECLSPEC_HIDDEN;
|
1999-01-30 14:24:23 +01:00
|
|
|
|
2009-12-15 21:44:49 +01:00
|
|
|
/* Number of BlockChainStream objects to cache in a StorageImpl */
|
|
|
|
#define BLOCKCHAIN_CACHE_SIZE 4
|
|
|
|
|
1999-01-30 14:24:23 +01:00
|
|
|
/****************************************************************************
|
2015-05-02 23:51:22 +02:00
|
|
|
* StorageImpl definitions.
|
1999-01-30 14:24:23 +01:00
|
|
|
*
|
2015-05-02 23:51:22 +02:00
|
|
|
* This implementation of the IStorage interface represents a root
|
1999-01-30 14:24:23 +01:00
|
|
|
* storage. Basically, a document file.
|
|
|
|
*/
|
1999-02-26 12:11:13 +01:00
|
|
|
struct StorageImpl
|
1999-01-30 14:24:23 +01:00
|
|
|
{
|
2005-02-24 20:39:27 +01:00
|
|
|
struct StorageBaseImpl base;
|
2002-06-01 01:06:46 +02:00
|
|
|
|
1999-01-30 14:24:23 +01:00
|
|
|
/*
|
|
|
|
* File header
|
|
|
|
*/
|
|
|
|
WORD bigBlockSizeBits;
|
|
|
|
WORD smallBlockSizeBits;
|
|
|
|
ULONG bigBlockSize;
|
|
|
|
ULONG smallBlockSize;
|
|
|
|
ULONG bigBlockDepotCount;
|
|
|
|
ULONG rootStartBlock;
|
2010-03-20 20:28:09 +01:00
|
|
|
ULONG smallBlockLimit;
|
1999-01-30 14:24:23 +01:00
|
|
|
ULONG smallBlockDepotStart;
|
|
|
|
ULONG extBigBlockDepotStart;
|
2010-04-19 23:07:09 +02:00
|
|
|
ULONG *extBigBlockDepotLocations;
|
|
|
|
ULONG extBigBlockDepotLocationsSize;
|
1999-01-30 14:24:23 +01:00
|
|
|
ULONG extBigBlockDepotCount;
|
|
|
|
ULONG bigBlockDepotStart[COUNT_BBDEPOTINHEADER];
|
2014-04-23 21:55:56 +02:00
|
|
|
ULONG transactionSig;
|
1999-02-24 11:36:34 +01:00
|
|
|
|
2010-04-19 23:55:49 +02:00
|
|
|
ULONG extBlockDepotCached[MAX_BIG_BLOCK_SIZE / 4];
|
|
|
|
ULONG indexExtBlockDepotCached;
|
|
|
|
|
2010-03-10 21:51:37 +01:00
|
|
|
ULONG blockDepotCached[MAX_BIG_BLOCK_SIZE / 4];
|
1999-02-24 11:36:34 +01:00
|
|
|
ULONG indexBlockDepotCached;
|
1999-03-09 18:40:00 +01:00
|
|
|
ULONG prevFreeBlock;
|
1999-02-24 11:36:34 +01:00
|
|
|
|
2010-03-20 19:13:47 +01:00
|
|
|
/* All small blocks before this one are known to be in use. */
|
|
|
|
ULONG firstFreeSmallBlock;
|
|
|
|
|
1999-01-30 14:24:23 +01:00
|
|
|
/*
|
|
|
|
* Abstraction of the big block chains for the chains of the header.
|
|
|
|
*/
|
|
|
|
BlockChainStream* rootBlockChain;
|
|
|
|
BlockChainStream* smallBlockDepotChain;
|
2002-06-01 01:06:46 +02:00
|
|
|
BlockChainStream* smallBlockRootChain;
|
1999-01-30 14:24:23 +01:00
|
|
|
|
2009-12-15 21:44:49 +01:00
|
|
|
/* Cache of block chain streams objects for directory entries */
|
|
|
|
BlockChainStream* blockChainCache[BLOCKCHAIN_CACHE_SIZE];
|
|
|
|
UINT blockChainToEvict;
|
|
|
|
|
2010-07-17 18:56:17 +02:00
|
|
|
ILockBytes* lockBytes;
|
2014-04-18 23:37:56 +02:00
|
|
|
|
2014-05-02 19:52:00 +02:00
|
|
|
ULONG locked_bytes[8];
|
1999-01-30 14:24:23 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* StgStreamImpl definitions.
|
|
|
|
*
|
2012-07-13 07:45:37 +02:00
|
|
|
* This class implements the IStream interface and represents a stream
|
1999-01-30 14:24:23 +01:00
|
|
|
* located inside a storage object.
|
|
|
|
*/
|
|
|
|
struct StgStreamImpl
|
|
|
|
{
|
2012-07-13 07:45:37 +02:00
|
|
|
IStream IStream_iface;
|
|
|
|
LONG ref;
|
2002-06-01 01:06:46 +02:00
|
|
|
|
2006-02-21 09:03:36 +01:00
|
|
|
/*
|
|
|
|
* We are an entry in the storage object's stream handler list
|
|
|
|
*/
|
|
|
|
struct list StrmListEntry;
|
|
|
|
|
1999-01-30 14:24:23 +01:00
|
|
|
/*
|
|
|
|
* Storage that is the parent(owner) of the stream
|
|
|
|
*/
|
1999-02-26 12:11:13 +01:00
|
|
|
StorageBaseImpl* parentStorage;
|
1999-01-30 14:24:23 +01:00
|
|
|
|
2000-02-25 21:58:25 +01:00
|
|
|
/*
|
|
|
|
* Access mode of this stream.
|
|
|
|
*/
|
|
|
|
DWORD grfMode;
|
|
|
|
|
1999-01-30 14:24:23 +01:00
|
|
|
/*
|
2009-11-12 20:25:10 +01:00
|
|
|
* Index of the directory entry that owns (points to) this stream.
|
1999-01-30 14:24:23 +01:00
|
|
|
*/
|
2009-11-12 22:53:42 +01:00
|
|
|
DirRef dirEntry;
|
1999-01-30 14:24:23 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* This is the current position of the cursor in the stream
|
|
|
|
*/
|
|
|
|
ULARGE_INTEGER currentPosition;
|
|
|
|
};
|
|
|
|
|
2012-07-13 07:45:37 +02:00
|
|
|
static inline StgStreamImpl *impl_from_IStream( IStream *iface )
|
|
|
|
{
|
|
|
|
return CONTAINING_RECORD(iface, StgStreamImpl, IStream_iface);
|
|
|
|
}
|
|
|
|
|
1999-01-30 14:24:23 +01:00
|
|
|
/*
|
|
|
|
* Method definition for the StgStreamImpl class.
|
|
|
|
*/
|
|
|
|
StgStreamImpl* StgStreamImpl_Construct(
|
1999-02-26 12:11:13 +01:00
|
|
|
StorageBaseImpl* parentStorage,
|
2000-02-25 21:58:25 +01:00
|
|
|
DWORD grfMode,
|
2011-04-21 10:45:36 +02:00
|
|
|
DirRef dirEntry) DECLSPEC_HIDDEN;
|
1999-01-30 14:24:23 +01:00
|
|
|
|
|
|
|
|
2014-05-02 19:52:00 +02:00
|
|
|
/* Range lock constants.
|
|
|
|
*
|
|
|
|
* The storage format reserves the region from 0x7fffff00-0x7fffffff for
|
2015-03-10 20:29:17 +01:00
|
|
|
* locking and synchronization. Because it reserves the entire block containing
|
|
|
|
* that range, and the minimum block size is 512 bytes, 0x7ffffe00-0x7ffffeff
|
|
|
|
* also cannot be used for any other purpose.
|
|
|
|
* Unfortunately, the spec doesn't say which bytes
|
2014-05-02 19:52:00 +02:00
|
|
|
* within that range are used, and for what. These are guesses based on testing.
|
|
|
|
* In particular, ends of ranges may be wrong.
|
|
|
|
|
|
|
|
0x0 through 0x57: Unknown. Causes read-only exclusive opens to fail.
|
2014-05-09 21:51:07 +02:00
|
|
|
0x58 through 0x6b: Priority mode.
|
|
|
|
0x6c through 0x7f: No snapshot mode.
|
2014-05-02 19:52:00 +02:00
|
|
|
0x80: Commit lock.
|
|
|
|
0x81 through 0x91: Priority mode, again. Not sure why it uses two regions.
|
|
|
|
0x92: Lock-checking lock. Held while opening so ranges can be tested without
|
|
|
|
causing spurious failures if others try to grab or test those ranges at the
|
|
|
|
same time.
|
|
|
|
0x93 through 0xa6: Read mode.
|
|
|
|
0xa7 through 0xba: Write mode.
|
|
|
|
0xbb through 0xce: Deny read.
|
|
|
|
0xcf through 0xe2: Deny write.
|
|
|
|
0xe2 through 0xff: Unknown. Causes read-only exclusive opens to fail.
|
|
|
|
*/
|
|
|
|
|
2015-03-10 20:29:17 +01:00
|
|
|
#define RANGELOCK_UNK1_FIRST 0x7ffffe00
|
2014-05-02 19:52:00 +02:00
|
|
|
#define RANGELOCK_UNK1_LAST 0x7fffff57
|
|
|
|
#define RANGELOCK_PRIORITY1_FIRST 0x7fffff58
|
2014-05-09 21:51:07 +02:00
|
|
|
#define RANGELOCK_PRIORITY1_LAST 0x7fffff6b
|
|
|
|
#define RANGELOCK_NOSNAPSHOT_FIRST 0x7fffff6c
|
|
|
|
#define RANGELOCK_NOSNAPSHOT_LAST 0x7fffff7f
|
2014-05-02 19:52:00 +02:00
|
|
|
#define RANGELOCK_COMMIT 0x7fffff80
|
|
|
|
#define RANGELOCK_PRIORITY2_FIRST 0x7fffff81
|
|
|
|
#define RANGELOCK_PRIORITY2_LAST 0x7fffff91
|
|
|
|
#define RANGELOCK_CHECKLOCKS 0x7fffff92
|
|
|
|
#define RANGELOCK_READ_FIRST 0x7fffff93
|
|
|
|
#define RANGELOCK_READ_LAST 0x7fffffa6
|
|
|
|
#define RANGELOCK_WRITE_FIRST 0x7fffffa7
|
|
|
|
#define RANGELOCK_WRITE_LAST 0x7fffffba
|
|
|
|
#define RANGELOCK_DENY_READ_FIRST 0x7fffffbb
|
|
|
|
#define RANGELOCK_DENY_READ_LAST 0x7fffffce
|
|
|
|
#define RANGELOCK_DENY_WRITE_FIRST 0x7fffffcf
|
|
|
|
#define RANGELOCK_DENY_WRITE_LAST 0x7fffffe2
|
|
|
|
#define RANGELOCK_UNK2_FIRST 0x7fffffe3
|
|
|
|
#define RANGELOCK_UNK2_LAST 0x7fffffff
|
2014-05-09 21:51:07 +02:00
|
|
|
#define RANGELOCK_TRANSACTION_FIRST RANGELOCK_COMMIT
|
2014-05-02 19:52:00 +02:00
|
|
|
#define RANGELOCK_TRANSACTION_LAST RANGELOCK_CHECKLOCKS
|
|
|
|
#define RANGELOCK_FIRST RANGELOCK_UNK1_FIRST
|
|
|
|
#define RANGELOCK_LAST RANGELOCK_UNK2_LAST
|
|
|
|
|
|
|
|
|
2005-04-24 19:22:26 +02:00
|
|
|
/******************************************************************************
|
|
|
|
* Endian conversion macros
|
|
|
|
*/
|
|
|
|
#ifdef WORDS_BIGENDIAN
|
|
|
|
|
|
|
|
#define htole32(x) RtlUlongByteSwap(x)
|
|
|
|
#define htole16(x) RtlUshortByteSwap(x)
|
2009-04-23 18:17:49 +02:00
|
|
|
#define lendian32toh(x) RtlUlongByteSwap(x)
|
|
|
|
#define lendian16toh(x) RtlUshortByteSwap(x)
|
2005-04-24 19:22:26 +02:00
|
|
|
|
|
|
|
#else
|
|
|
|
|
|
|
|
#define htole32(x) (x)
|
|
|
|
#define htole16(x) (x)
|
2009-04-23 18:17:49 +02:00
|
|
|
#define lendian32toh(x) (x)
|
|
|
|
#define lendian16toh(x) (x)
|
2005-04-24 19:22:26 +02:00
|
|
|
|
|
|
|
#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
|
1999-01-30 14:24:23 +01:00
|
|
|
*/
|
2011-04-21 10:45:36 +02:00
|
|
|
void StorageUtl_ReadWord(const BYTE* buffer, ULONG offset, WORD* value) DECLSPEC_HIDDEN;
|
|
|
|
void StorageUtl_WriteWord(BYTE* buffer, ULONG offset, WORD value) DECLSPEC_HIDDEN;
|
|
|
|
void StorageUtl_ReadDWord(const BYTE* buffer, ULONG offset, DWORD* value) DECLSPEC_HIDDEN;
|
|
|
|
void StorageUtl_WriteDWord(BYTE* buffer, ULONG offset, DWORD value) DECLSPEC_HIDDEN;
|
2005-05-14 13:06:44 +02:00
|
|
|
void StorageUtl_ReadULargeInteger(const BYTE* buffer, ULONG offset,
|
2011-04-21 10:45:36 +02:00
|
|
|
ULARGE_INTEGER* value) DECLSPEC_HIDDEN;
|
2005-05-14 13:06:44 +02:00
|
|
|
void StorageUtl_WriteULargeInteger(BYTE* buffer, ULONG offset,
|
2011-04-21 10:45:36 +02:00
|
|
|
const ULARGE_INTEGER *value) DECLSPEC_HIDDEN;
|
|
|
|
void StorageUtl_ReadGUID(const BYTE* buffer, ULONG offset, GUID* value) DECLSPEC_HIDDEN;
|
|
|
|
void StorageUtl_WriteGUID(BYTE* buffer, ULONG offset, const GUID* value) DECLSPEC_HIDDEN;
|
2009-12-02 19:35:53 +01:00
|
|
|
void StorageUtl_CopyDirEntryToSTATSTG(StorageBaseImpl *storage,STATSTG* destination,
|
2011-04-21 10:45:36 +02:00
|
|
|
const DirEntry* source, int statFlags) DECLSPEC_HIDDEN;
|
1999-01-30 14:24:23 +01:00
|
|
|
|
|
|
|
|
1999-04-22 18:27:50 +02:00
|
|
|
#endif /* __STORAGE32_H__ */
|