ole32: Add a structure to hold memory block information.

Based on a patch by Dmitry Timoshkov which was based on a suggestion
by Sebastian Lackner.

Signed-off-by: Huw Davies <huw@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Huw Davies 2020-08-11 12:49:49 +01:00 committed by Alexandre Julliard
parent 3f4f6fca3c
commit 54b6cbc287
1 changed files with 60 additions and 42 deletions

View File

@ -5,6 +5,7 @@
* for streams contained supported by an HGLOBAL pointer. * for streams contained supported by an HGLOBAL pointer.
* *
* Copyright 1999 Francis Beaudet * Copyright 1999 Francis Beaudet
* Copyright 2016 Dmitry Timoshkov
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
@ -42,6 +43,40 @@
WINE_DEFAULT_DEBUG_CHANNEL(storage); WINE_DEFAULT_DEBUG_CHANNEL(storage);
struct handle_wrapper
{
HGLOBAL hglobal;
ULONG size;
BOOL delete_on_release;
};
static void handle_release(struct handle_wrapper *handle)
{
if (handle->delete_on_release) GlobalFree(handle->hglobal);
HeapFree(GetProcessHeap(), 0, handle);
}
static struct handle_wrapper *handle_create(HGLOBAL hglobal, BOOL delete_on_release)
{
struct handle_wrapper *handle;
handle = HeapAlloc(GetProcessHeap(), 0, sizeof(*handle));
if (!handle) return NULL;
/* allocate a handle if one is not supplied */
if (!hglobal) hglobal = GlobalAlloc(GMEM_MOVEABLE | GMEM_NODISCARD | GMEM_SHARE, 0);
if (!hglobal)
{
HeapFree(GetProcessHeap(), 0, handle);
return NULL;
}
handle->hglobal = hglobal;
handle->size = GlobalSize(hglobal);
handle->delete_on_release = delete_on_release;
return handle;
}
/**************************************************************************** /****************************************************************************
* HGLOBALStreamImpl definition. * HGLOBALStreamImpl definition.
* *
@ -53,14 +88,7 @@ typedef struct
IStream IStream_iface; IStream IStream_iface;
LONG ref; LONG ref;
/* support for the stream */ struct handle_wrapper *handle;
HGLOBAL supportHandle;
/* if TRUE the HGLOBAL is destroyed when the stream is finally released */
BOOL deleteOnRelease;
/* size of the stream */
ULARGE_INTEGER streamSize;
/* current position of the cursor */ /* current position of the cursor */
ULARGE_INTEGER currentPosition; ULARGE_INTEGER currentPosition;
@ -112,12 +140,7 @@ static ULONG WINAPI HGLOBALStreamImpl_Release(
if (!ref) if (!ref)
{ {
if (This->deleteOnRelease) handle_release(This->handle);
{
GlobalFree(This->supportHandle);
This->supportHandle = NULL;
}
HeapFree(GetProcessHeap(), 0, This); HeapFree(GetProcessHeap(), 0, This);
} }
@ -159,15 +182,15 @@ static HRESULT WINAPI HGLOBALStreamImpl_Read(
* Using the known size of the stream, calculate the number of bytes * Using the known size of the stream, calculate the number of bytes
* to read from the block chain * to read from the block chain
*/ */
bytesToReadFromBuffer = min( This->streamSize.u.LowPart - This->currentPosition.u.LowPart, cb); bytesToReadFromBuffer = min( This->handle->size - This->currentPosition.u.LowPart, cb);
/* /*
* Lock the buffer in position and copy the data. * Lock the buffer in position and copy the data.
*/ */
supportBuffer = GlobalLock(This->supportHandle); supportBuffer = GlobalLock(This->handle->hglobal);
if (!supportBuffer) if (!supportBuffer)
{ {
WARN("read from invalid hglobal %p\n", This->supportHandle); WARN("read from invalid hglobal %p\n", This->handle->hglobal);
*pcbRead = 0; *pcbRead = 0;
return S_OK; return S_OK;
} }
@ -187,7 +210,7 @@ static HRESULT WINAPI HGLOBALStreamImpl_Read(
/* /*
* Cleanup * Cleanup
*/ */
GlobalUnlock(This->supportHandle); GlobalUnlock(This->handle->hglobal);
/* /*
* Always returns S_OK even if the end of the stream is reached before the * Always returns S_OK even if the end of the stream is reached before the
@ -239,7 +262,7 @@ static HRESULT WINAPI HGLOBALStreamImpl_Write(
/* /*
* Verify if we need to grow the stream * Verify if we need to grow the stream
*/ */
if (newSize.u.LowPart > This->streamSize.u.LowPart) if (newSize.u.LowPart > This->handle->size)
{ {
/* grow stream */ /* grow stream */
HRESULT hr = IStream_SetSize(iface, newSize); HRESULT hr = IStream_SetSize(iface, newSize);
@ -253,10 +276,10 @@ static HRESULT WINAPI HGLOBALStreamImpl_Write(
/* /*
* Lock the buffer in position and copy the data. * Lock the buffer in position and copy the data.
*/ */
supportBuffer = GlobalLock(This->supportHandle); supportBuffer = GlobalLock(This->handle->hglobal);
if (!supportBuffer) if (!supportBuffer)
{ {
WARN("write to invalid hglobal %p\n", This->supportHandle); WARN("write to invalid hglobal %p\n", This->handle->hglobal);
return S_OK; return S_OK;
} }
@ -270,7 +293,7 @@ static HRESULT WINAPI HGLOBALStreamImpl_Write(
/* /*
* Cleanup * Cleanup
*/ */
GlobalUnlock(This->supportHandle); GlobalUnlock(This->handle->hglobal);
out: out:
/* /*
@ -316,7 +339,7 @@ static HRESULT WINAPI HGLOBALStreamImpl_Seek(
case STREAM_SEEK_CUR: case STREAM_SEEK_CUR:
break; break;
case STREAM_SEEK_END: case STREAM_SEEK_END:
newPosition = This->streamSize; newPosition.QuadPart = This->handle->size;
break; break;
default: default:
hr = STG_E_SEEKERROR; hr = STG_E_SEEKERROR;
@ -369,19 +392,19 @@ static HRESULT WINAPI HGLOBALStreamImpl_SetSize(
* HighPart is ignored as shown in tests * HighPart is ignored as shown in tests
*/ */
if (This->streamSize.u.LowPart == libNewSize.u.LowPart) if (This->handle->size == libNewSize.u.LowPart)
return S_OK; return S_OK;
/* /*
* Re allocate the HGlobal to fit the new size of the stream. * Re allocate the HGlobal to fit the new size of the stream.
*/ */
supportHandle = GlobalReAlloc(This->supportHandle, libNewSize.u.LowPart, 0); supportHandle = GlobalReAlloc(This->handle->hglobal, libNewSize.u.LowPart, 0);
if (supportHandle == 0) if (supportHandle == 0)
return E_OUTOFMEMORY; return E_OUTOFMEMORY;
This->supportHandle = supportHandle; This->handle->hglobal = supportHandle;
This->streamSize.u.LowPart = libNewSize.u.LowPart; This->handle->size = libNewSize.u.LowPart;
return S_OK; return S_OK;
} }
@ -531,7 +554,7 @@ static HRESULT WINAPI HGLOBALStreamImpl_Stat(
pstatstg->pwcsName = NULL; pstatstg->pwcsName = NULL;
pstatstg->type = STGTY_STREAM; pstatstg->type = STGTY_STREAM;
pstatstg->cbSize = This->streamSize; pstatstg->cbSize.QuadPart = This->handle->size;
return S_OK; return S_OK;
} }
@ -545,8 +568,8 @@ static HRESULT WINAPI HGLOBALStreamImpl_Clone(
LARGE_INTEGER offset; LARGE_INTEGER offset;
HRESULT hr; HRESULT hr;
TRACE(" Cloning %p (deleteOnRelease=%d seek position=%ld)\n",iface,This->deleteOnRelease,(long)This->currentPosition.QuadPart); TRACE(" Cloning %p (deleteOnRelease=%d seek position=%ld)\n",iface,This->handle->delete_on_release,(long)This->currentPosition.QuadPart);
hr = CreateStreamOnHGlobal(This->supportHandle, FALSE, ppstm); hr = CreateStreamOnHGlobal(This->handle->hglobal, FALSE, ppstm);
if(FAILED(hr)) if(FAILED(hr))
return hr; return hr;
offset.QuadPart = (LONGLONG)This->currentPosition.QuadPart; offset.QuadPart = (LONGLONG)This->currentPosition.QuadPart;
@ -591,22 +614,17 @@ HRESULT WINAPI CreateStreamOnHGlobal(
This->IStream_iface.lpVtbl = &HGLOBALStreamImplVtbl; This->IStream_iface.lpVtbl = &HGLOBALStreamImplVtbl;
This->ref = 1; This->ref = 1;
/* initialize the support */ This->handle = handle_create(hGlobal, fDeleteOnRelease);
This->supportHandle = hGlobal; if (!This->handle)
This->deleteOnRelease = fDeleteOnRelease; {
HeapFree(GetProcessHeap(), 0, This);
/* allocate a handle if one is not supplied */ return E_OUTOFMEMORY;
if (!This->supportHandle) }
This->supportHandle = GlobalAlloc(GMEM_MOVEABLE|GMEM_NODISCARD|GMEM_SHARE, 0);
/* start at the beginning */ /* start at the beginning */
This->currentPosition.u.HighPart = 0; This->currentPosition.u.HighPart = 0;
This->currentPosition.u.LowPart = 0; This->currentPosition.u.LowPart = 0;
/* initialize the size of the stream to the size of the handle */
This->streamSize.u.HighPart = 0;
This->streamSize.u.LowPart = GlobalSize(This->supportHandle);
*ppstm = &This->IStream_iface; *ppstm = &This->IStream_iface;
return S_OK; return S_OK;
@ -628,7 +646,7 @@ HRESULT WINAPI GetHGlobalFromStream(IStream* pstm, HGLOBAL* phglobal)
* Verify that the stream object was created with CreateStreamOnHGlobal. * Verify that the stream object was created with CreateStreamOnHGlobal.
*/ */
if (pStream->IStream_iface.lpVtbl == &HGLOBALStreamImplVtbl) if (pStream->IStream_iface.lpVtbl == &HGLOBALStreamImplVtbl)
*phglobal = pStream->supportHandle; *phglobal = pStream->handle->hglobal;
else else
{ {
*phglobal = 0; *phglobal = 0;