ole32: Use the storage vtable to resize streams.
This commit is contained in:
parent
1d4c698ef3
commit
6d06c43e53
|
@ -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,
|
||||
¤tEntry);
|
||||
/*
|
||||
* 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,
|
||||
¤tEntry);
|
||||
|
||||
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,
|
||||
¤tEntry);
|
||||
This->streamSize = libNewSize;
|
||||
}
|
||||
|
||||
This->streamSize = libNewSize;
|
||||
|
||||
return S_OK;
|
||||
return hr;
|
||||
}
|
||||
|
||||
/***
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
||||
/******************************************************************************
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
|
Loading…
Reference in New Issue