ole32: Use the storage vtable to resize streams.

This commit is contained in:
Vincent Povirk 2009-11-30 15:05:41 -06:00 committed by Alexandre Julliard
parent 1d4c698ef3
commit 6d06c43e53
3 changed files with 108 additions and 88 deletions

View File

@ -483,7 +483,6 @@ static HRESULT WINAPI StgStreamImpl_SetSize(
{
StgStreamImpl* const This=(StgStreamImpl*)iface;
DirEntry currentEntry;
HRESULT hr;
TRACE("(%p, %d)\n", iface, libNewSize.u.LowPart);
@ -512,99 +511,17 @@ static HRESULT WINAPI StgStreamImpl_SetSize(
return STG_E_ACCESSDENIED;
}
/* In simple mode keep the stream size above the small block limit */
if (This->parentStorage->openFlags & STGM_SIMPLE)
libNewSize.u.LowPart = max(libNewSize.u.LowPart, LIMIT_TO_USE_SMALL_BLOCK);
if (This->streamSize.u.LowPart == libNewSize.u.LowPart)
return S_OK;
/*
* This will happen if we're creating a stream
*/
if ((This->smallBlockChain == 0) && (This->bigBlockChain == 0))
{
if (libNewSize.u.LowPart < LIMIT_TO_USE_SMALL_BLOCK)
{
This->smallBlockChain = SmallBlockChainStream_Construct(
This->parentStorage->ancestorStorage,
NULL,
This->dirEntry);
}
else
{
This->bigBlockChain = BlockChainStream_Construct(
This->parentStorage->ancestorStorage,
NULL,
This->dirEntry);
}
}
/*
* Read this stream's size to see if it's small blocks or big blocks
*/
StorageBaseImpl_ReadDirEntry(This->parentStorage,
This->dirEntry,
&currentEntry);
/*
* Determine if we have to switch from small to big blocks or vice versa
*/
if ( (This->smallBlockChain!=0) &&
(currentEntry.size.u.LowPart < LIMIT_TO_USE_SMALL_BLOCK) )
{
if (libNewSize.u.LowPart >= LIMIT_TO_USE_SMALL_BLOCK)
{
/*
* Transform the small block chain into a big block chain
*/
This->bigBlockChain = Storage32Impl_SmallBlocksToBigBlocks(
This->parentStorage->ancestorStorage,
&This->smallBlockChain);
}
}
else if ( (This->bigBlockChain!=0) &&
(currentEntry.size.u.LowPart >= LIMIT_TO_USE_SMALL_BLOCK) )
{
if (libNewSize.u.LowPart < LIMIT_TO_USE_SMALL_BLOCK)
{
/*
* Transform the big block chain into a small block chain
*/
This->smallBlockChain = Storage32Impl_BigBlocksToSmallBlocks(
This->parentStorage->ancestorStorage,
&This->bigBlockChain);
}
}
if (This->smallBlockChain!=0)
{
SmallBlockChainStream_SetSize(This->smallBlockChain, libNewSize);
}
else
{
BlockChainStream_SetSize(This->bigBlockChain, libNewSize);
}
/*
* Write the new information about this stream to the directory entry
*/
hr = StorageBaseImpl_ReadDirEntry(This->parentStorage,
This->dirEntry,
&currentEntry);
currentEntry.size.u.HighPart = libNewSize.u.HighPart;
currentEntry.size.u.LowPart = libNewSize.u.LowPart;
hr = StorageBaseImpl_StreamSetSize(This->parentStorage, This->dirEntry, libNewSize);
if (SUCCEEDED(hr))
{
StorageBaseImpl_WriteDirEntry(This->parentStorage,
This->dirEntry,
&currentEntry);
This->streamSize = libNewSize;
}
This->streamSize = libNewSize;
return S_OK;
return hr;
}
/***

View File

@ -2246,6 +2246,93 @@ static HRESULT StorageImpl_StreamReadAt(StorageBaseImpl *base, DirRef index,
}
}
static HRESULT StorageImpl_StreamSetSize(StorageBaseImpl *base, DirRef index,
ULARGE_INTEGER newsize)
{
StorageImpl *This = (StorageImpl*)base;
DirEntry data;
HRESULT hr;
SmallBlockChainStream *smallblock=NULL;
BlockChainStream *bigblock=NULL;
hr = StorageImpl_ReadDirEntry(This, index, &data);
if (FAILED(hr)) return hr;
/* In simple mode keep the stream size above the small block limit */
if (This->base.openFlags & STGM_SIMPLE)
newsize.QuadPart = max(newsize.QuadPart, LIMIT_TO_USE_SMALL_BLOCK);
if (data.size.QuadPart == newsize.QuadPart)
return S_OK;
/* Create a block chain object of the appropriate type */
if (data.size.QuadPart == 0)
{
if (newsize.QuadPart < LIMIT_TO_USE_SMALL_BLOCK)
{
smallblock = SmallBlockChainStream_Construct(This, NULL, index);
if (!smallblock) return E_OUTOFMEMORY;
}
else
{
bigblock = BlockChainStream_Construct(This, NULL, index);
if (!bigblock) return E_OUTOFMEMORY;
}
}
else if (data.size.QuadPart < LIMIT_TO_USE_SMALL_BLOCK)
{
smallblock = SmallBlockChainStream_Construct(This, NULL, index);
if (!smallblock) return E_OUTOFMEMORY;
}
else
{
bigblock = BlockChainStream_Construct(This, NULL, index);
if (!bigblock) return E_OUTOFMEMORY;
}
/* Change the block chain type if necessary. */
if (smallblock && newsize.QuadPart >= LIMIT_TO_USE_SMALL_BLOCK)
{
bigblock = Storage32Impl_SmallBlocksToBigBlocks(This, &smallblock);
if (!bigblock)
{
SmallBlockChainStream_Destroy(smallblock);
return E_FAIL;
}
}
else if (bigblock && newsize.QuadPart < LIMIT_TO_USE_SMALL_BLOCK)
{
smallblock = Storage32Impl_BigBlocksToSmallBlocks(This, &bigblock);
if (!smallblock)
{
BlockChainStream_Destroy(bigblock);
return E_FAIL;
}
}
/* Set the size of the block chain. */
if (smallblock)
{
SmallBlockChainStream_SetSize(smallblock, newsize);
SmallBlockChainStream_Destroy(smallblock);
}
else
{
BlockChainStream_SetSize(bigblock, newsize);
BlockChainStream_Destroy(bigblock);
}
/* Set the size in the directory entry. */
hr = StorageImpl_ReadDirEntry(This, index, &data);
if (SUCCEEDED(hr))
{
data.size = newsize;
hr = StorageImpl_WriteDirEntry(This, index, &data);
}
return hr;
}
static HRESULT StorageImpl_StreamWriteAt(StorageBaseImpl *base, DirRef index,
ULARGE_INTEGER offset, ULONG size, const void *buffer, ULONG *bytesWritten)
{
@ -2325,7 +2412,8 @@ static const StorageBaseImplVtbl StorageImpl_BaseVtbl =
StorageImpl_BaseReadDirEntry,
StorageImpl_DestroyDirEntry,
StorageImpl_StreamReadAt,
StorageImpl_StreamWriteAt
StorageImpl_StreamWriteAt,
StorageImpl_StreamSetSize
};
static HRESULT StorageImpl_Construct(
@ -3787,6 +3875,13 @@ static HRESULT StorageInternalImpl_StreamWriteAt(StorageBaseImpl *base,
index, offset, size, buffer, bytesWritten);
}
static HRESULT StorageInternalImpl_StreamSetSize(StorageBaseImpl *base,
DirRef index, ULARGE_INTEGER newsize)
{
return StorageBaseImpl_StreamSetSize(&base->ancestorStorage->base,
index, newsize);
}
/******************************************************************************
**
** Storage32InternalImpl_Commit
@ -4235,7 +4330,8 @@ static const StorageBaseImplVtbl StorageInternalImpl_BaseVtbl =
StorageInternalImpl_ReadDirEntry,
StorageInternalImpl_DestroyDirEntry,
StorageInternalImpl_StreamReadAt,
StorageInternalImpl_StreamWriteAt
StorageInternalImpl_StreamWriteAt,
StorageInternalImpl_StreamSetSize
};
/******************************************************************************

View File

@ -254,6 +254,7 @@ struct StorageBaseImplVtbl {
HRESULT (*DestroyDirEntry)(StorageBaseImpl*,DirRef);
HRESULT (*StreamReadAt)(StorageBaseImpl*,DirRef,ULARGE_INTEGER,ULONG,void*,ULONG*);
HRESULT (*StreamWriteAt)(StorageBaseImpl*,DirRef,ULARGE_INTEGER,ULONG,const void*,ULONG*);
HRESULT (*StreamSetSize)(StorageBaseImpl*,DirRef,ULARGE_INTEGER);
};
static inline void StorageBaseImpl_Destroy(StorageBaseImpl *This)
@ -299,6 +300,12 @@ static inline HRESULT StorageBaseImpl_StreamWriteAt(StorageBaseImpl *This,
return This->baseVtbl->StreamWriteAt(This, index, offset, size, buffer, bytesWritten);
}
static inline HRESULT StorageBaseImpl_StreamSetSize(StorageBaseImpl *This,
DirRef index, ULARGE_INTEGER newsize)
{
return This->baseVtbl->StreamSetSize(This, index, newsize);
}
/****************************************************************************
* StorageBaseImpl stream list handlers
*/