ole32: Add a stub transacted storage type.

TransactedSnapshotImpl acts as a proxy between the user and the storage
interfaces that modify the file directly (or another transacted storage).
Currently, it does not change the operations.
This commit is contained in:
Vincent Povirk 2009-12-02 10:59:47 -06:00 committed by Alexandre Julliard
parent 42142200d5
commit d799f7e189
2 changed files with 271 additions and 10 deletions

View File

@ -118,6 +118,22 @@ static BOOL StorageImpl_ReadDWordFromBigBlock( StorageImpl* This,
static BOOL StorageBaseImpl_IsStreamOpen(StorageBaseImpl * stg, DirRef streamEntry);
static BOOL StorageBaseImpl_IsStorageOpen(StorageBaseImpl * stg, DirRef storageEntry);
/****************************************************************************
* Transacted storage object that reads/writes a snapshot file.
*/
typedef struct TransactedSnapshotImpl
{
struct StorageBaseImpl base;
/*
* Changes are committed to the transacted parent.
*/
StorageBaseImpl *transactedParent;
} TransactedSnapshotImpl;
/* Generic function to create a transacted wrapper for a direct storage object. */
static HRESULT Storage_ConstructTransacted(StorageBaseImpl* parent, StorageBaseImpl** result);
/* OLESTREAM memory structure to use for Get and Put Routines */
/* Used for OleConvertIStorageToOLESTREAM and OleConvertOLESTREAMToIStorage */
typedef struct
@ -508,7 +524,8 @@ static HRESULT WINAPI StorageBaseImpl_OpenStorage(
IStorage** ppstg) /* [out] */
{
StorageBaseImpl *This = (StorageBaseImpl *)iface;
StorageInternalImpl* newStorage;
StorageInternalImpl* newStorage;
StorageBaseImpl* newTransactedStorage;
DirEntry currentEntry;
DirRef storageEntryRef;
HRESULT res = STG_E_UNKNOWN;
@ -593,7 +610,22 @@ static HRESULT WINAPI StorageBaseImpl_OpenStorage(
if (newStorage != 0)
{
*ppstg = (IStorage*)newStorage;
if (grfMode & STGM_TRANSACTED)
{
res = Storage_ConstructTransacted(&newStorage->base, &newTransactedStorage);
if (FAILED(res))
{
HeapFree(GetProcessHeap(), 0, newStorage);
goto end;
}
*ppstg = (IStorage*)newTransactedStorage;
}
else
{
*ppstg = (IStorage*)newStorage;
}
list_add_tail(&This->storageHead, &newStorage->ParentListEntry);
@ -1886,6 +1918,13 @@ static void StorageBaseImpl_DeleteAll(StorageBaseImpl * stg)
childstg = LIST_ENTRY(cur,StorageInternalImpl,ParentListEntry);
StorageBaseImpl_Invalidate( &childstg->base );
}
if (stg->transactedChild)
{
StorageBaseImpl_Invalidate(stg->transactedChild);
stg->transactedChild = NULL;
}
}
@ -3822,6 +3861,223 @@ SmallBlockChainStream* Storage32Impl_BigBlocksToSmallBlocks(
return SmallBlockChainStream_Construct(This, NULL, streamEntryRef);
}
static HRESULT WINAPI TransactedSnapshotImpl_Commit(
IStorage* iface,
DWORD grfCommitFlags) /* [in] */
{
FIXME("(%p,%x): stub\n", iface, grfCommitFlags);
return S_OK;
}
static HRESULT WINAPI TransactedSnapshotImpl_Revert(
IStorage* iface)
{
FIXME("(%p): stub\n", iface);
return S_OK;
}
static void TransactedSnapshotImpl_Invalidate(StorageBaseImpl* This)
{
if (!This->reverted)
{
TRACE("Storage invalidated (stg=%p)\n", This);
This->reverted = 1;
StorageBaseImpl_DeleteAll(This);
}
}
static void TransactedSnapshotImpl_Destroy( StorageBaseImpl *iface)
{
TransactedSnapshotImpl* This = (TransactedSnapshotImpl*) iface;
TransactedSnapshotImpl_Invalidate(iface);
IStorage_Release((IStorage*)This->transactedParent);
HeapFree(GetProcessHeap(), 0, This);
}
static HRESULT TransactedSnapshotImpl_CreateDirEntry(StorageBaseImpl *base,
const DirEntry *newData, DirRef *index)
{
TransactedSnapshotImpl* This = (TransactedSnapshotImpl*) base;
return StorageBaseImpl_CreateDirEntry(This->transactedParent,
newData, index);
}
static HRESULT TransactedSnapshotImpl_WriteDirEntry(StorageBaseImpl *base,
DirRef index, const DirEntry *data)
{
TransactedSnapshotImpl* This = (TransactedSnapshotImpl*) base;
return StorageBaseImpl_WriteDirEntry(This->transactedParent,
index, data);
}
static HRESULT TransactedSnapshotImpl_ReadDirEntry(StorageBaseImpl *base,
DirRef index, DirEntry *data)
{
TransactedSnapshotImpl* This = (TransactedSnapshotImpl*) base;
return StorageBaseImpl_ReadDirEntry(This->transactedParent,
index, data);
}
static HRESULT TransactedSnapshotImpl_DestroyDirEntry(StorageBaseImpl *base,
DirRef index)
{
TransactedSnapshotImpl* This = (TransactedSnapshotImpl*) base;
return StorageBaseImpl_DestroyDirEntry(This->transactedParent,
index);
}
static HRESULT TransactedSnapshotImpl_StreamReadAt(StorageBaseImpl *base,
DirRef index, ULARGE_INTEGER offset, ULONG size, void *buffer, ULONG *bytesRead)
{
TransactedSnapshotImpl* This = (TransactedSnapshotImpl*) base;
return StorageBaseImpl_StreamReadAt(This->transactedParent,
index, offset, size, buffer, bytesRead);
}
static HRESULT TransactedSnapshotImpl_StreamWriteAt(StorageBaseImpl *base,
DirRef index, ULARGE_INTEGER offset, ULONG size, const void *buffer, ULONG *bytesWritten)
{
TransactedSnapshotImpl* This = (TransactedSnapshotImpl*) base;
return StorageBaseImpl_StreamWriteAt(This->transactedParent,
index, offset, size, buffer, bytesWritten);
}
static HRESULT TransactedSnapshotImpl_StreamSetSize(StorageBaseImpl *base,
DirRef index, ULARGE_INTEGER newsize)
{
TransactedSnapshotImpl* This = (TransactedSnapshotImpl*) base;
return StorageBaseImpl_StreamSetSize(This->transactedParent,
index, newsize);
}
static const IStorageVtbl TransactedSnapshotImpl_Vtbl =
{
StorageBaseImpl_QueryInterface,
StorageBaseImpl_AddRef,
StorageBaseImpl_Release,
StorageBaseImpl_CreateStream,
StorageBaseImpl_OpenStream,
StorageBaseImpl_CreateStorage,
StorageBaseImpl_OpenStorage,
StorageBaseImpl_CopyTo,
StorageBaseImpl_MoveElementTo,
TransactedSnapshotImpl_Commit,
TransactedSnapshotImpl_Revert,
StorageBaseImpl_EnumElements,
StorageBaseImpl_DestroyElement,
StorageBaseImpl_RenameElement,
StorageBaseImpl_SetElementTimes,
StorageBaseImpl_SetClass,
StorageBaseImpl_SetStateBits,
StorageBaseImpl_Stat
};
static const StorageBaseImplVtbl TransactedSnapshotImpl_BaseVtbl =
{
TransactedSnapshotImpl_Destroy,
TransactedSnapshotImpl_Invalidate,
TransactedSnapshotImpl_CreateDirEntry,
TransactedSnapshotImpl_WriteDirEntry,
TransactedSnapshotImpl_ReadDirEntry,
TransactedSnapshotImpl_DestroyDirEntry,
TransactedSnapshotImpl_StreamReadAt,
TransactedSnapshotImpl_StreamWriteAt,
TransactedSnapshotImpl_StreamSetSize
};
static HRESULT TransactedSnapshotImpl_Construct(StorageBaseImpl *parentStorage,
TransactedSnapshotImpl** result)
{
*result = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(TransactedSnapshotImpl));
if (*result)
{
(*result)->base.lpVtbl = &TransactedSnapshotImpl_Vtbl;
/* This is OK because the property set storage functions use the IStorage functions. */
(*result)->base.pssVtbl = parentStorage->pssVtbl;
(*result)->base.baseVtbl = &TransactedSnapshotImpl_BaseVtbl;
list_init(&(*result)->base.strmHead);
list_init(&(*result)->base.storageHead);
(*result)->base.ref = 1;
(*result)->base.storageDirEntry = parentStorage->storageDirEntry;
(*result)->base.openFlags = parentStorage->openFlags;
(*result)->base.filename = parentStorage->filename;
/* parentStorage already has 1 reference, which we take over here. */
(*result)->transactedParent = parentStorage;
parentStorage->transactedChild = (StorageBaseImpl*)*result;
return S_OK;
}
else
return E_OUTOFMEMORY;
}
static HRESULT Storage_ConstructTransacted(StorageBaseImpl *parentStorage,
StorageBaseImpl** result)
{
static int fixme=0;
if (parentStorage->openFlags & (STGM_NOSCRATCH|STGM_NOSNAPSHOT) && !fixme++)
{
FIXME("Unimplemented flags %x\n", parentStorage->openFlags);
}
return TransactedSnapshotImpl_Construct(parentStorage,
(TransactedSnapshotImpl**)result);
}
static HRESULT Storage_Construct(
HANDLE hFile,
LPCOLESTR pwcsName,
ILockBytes* pLkbyt,
DWORD openFlags,
BOOL fileBased,
BOOL create,
StorageBaseImpl** result)
{
StorageImpl *newStorage;
StorageBaseImpl *newTransactedStorage;
HRESULT hr;
hr = StorageImpl_Construct(hFile, pwcsName, pLkbyt, openFlags, fileBased, create, &newStorage);
if (FAILED(hr)) goto end;
if (openFlags & STGM_TRANSACTED)
{
hr = Storage_ConstructTransacted(&newStorage->base, &newTransactedStorage);
if (FAILED(hr))
IStorage_Release((IStorage*)newStorage);
else
*result = newTransactedStorage;
}
else
*result = &newStorage->base;
end:
return hr;
}
static void StorageInternalImpl_Invalidate( StorageBaseImpl *base )
{
StorageInternalImpl* This = (StorageInternalImpl*) base;
@ -5866,7 +6122,7 @@ HRESULT WINAPI StgCreateDocfile(
DWORD reserved,
IStorage **ppstgOpen)
{
StorageImpl* newStorage = 0;
StorageBaseImpl* newStorage = 0;
HANDLE hFile = INVALID_HANDLE_VALUE;
HRESULT hr = STG_E_INVALIDFLAG;
DWORD shareMode;
@ -5975,7 +6231,7 @@ HRESULT WINAPI StgCreateDocfile(
/*
* Allocate and initialize the new IStorage32object.
*/
hr = StorageImpl_Construct(
hr = Storage_Construct(
hFile,
pwcsName,
NULL,
@ -6108,7 +6364,7 @@ HRESULT WINAPI StgOpenStorage(
DWORD reserved,
IStorage **ppstgOpen)
{
StorageImpl* newStorage = 0;
StorageBaseImpl* newStorage = 0;
HRESULT hr = S_OK;
HANDLE hFile = 0;
DWORD shareMode;
@ -6247,7 +6503,7 @@ HRESULT WINAPI StgOpenStorage(
/*
* Allocate and initialize the new IStorage32object.
*/
hr = StorageImpl_Construct(
hr = Storage_Construct(
hFile,
pwcsName,
NULL,
@ -6285,7 +6541,7 @@ HRESULT WINAPI StgCreateDocfileOnILockBytes(
DWORD reserved,
IStorage** ppstgOpen)
{
StorageImpl* newStorage = 0;
StorageBaseImpl* newStorage = 0;
HRESULT hr = S_OK;
if ((ppstgOpen == 0) || (plkbyt == 0))
@ -6294,7 +6550,7 @@ HRESULT WINAPI StgCreateDocfileOnILockBytes(
/*
* Allocate and initialize the new IStorage object.
*/
hr = StorageImpl_Construct(
hr = Storage_Construct(
0,
0,
plkbyt,
@ -6327,7 +6583,7 @@ HRESULT WINAPI StgOpenStorageOnILockBytes(
DWORD reserved,
IStorage **ppstgOpen)
{
StorageImpl* newStorage = 0;
StorageBaseImpl* newStorage = 0;
HRESULT hr = S_OK;
if ((plkbyt == 0) || (ppstgOpen == 0))
@ -6341,7 +6597,7 @@ HRESULT WINAPI StgOpenStorageOnILockBytes(
/*
* Allocate and initialize the new IStorage object.
*/
hr = StorageImpl_Construct(
hr = Storage_Construct(
0,
0,
plkbyt,

View File

@ -243,6 +243,11 @@ struct StorageBaseImpl
BOOL create; /* Was the storage created or opened.
The behaviour of STGM_SIMPLE depends on this */
/*
* If this storage was opened in transacted mode, the object that implements
* the transacted snapshot or cache.
*/
StorageBaseImpl *transactedChild;
};
/* virtual methods for StorageBaseImpl objects */