mirror of
https://gitlab.winehq.org/wine/wine-staging.git
synced 2024-11-21 16:46:54 -08:00
ole32-HGLOBALStream: Remove patches for thread safety.
On the recommendation of Huw Davies, on the grounds that no known application needs them, and that ole32 is in general not thread-safe.
This commit is contained in:
parent
150ce22fa2
commit
d9eb78e597
@ -1,422 +0,0 @@
|
||||
From 3c9954c3838d7504fad0213ade7363747e7a6805 Mon Sep 17 00:00:00 2001
|
||||
From: Dmitry Timoshkov <dmitry@baikal.ru>
|
||||
Date: Tue, 2 Feb 2016 13:03:58 +0800
|
||||
Subject: ole32: Add a wrapper for memory block managed by HGLOBAL based
|
||||
IStream.
|
||||
|
||||
Based on a suggestion of Sebastian Lackner <sebastian@fds-team.de>.
|
||||
---
|
||||
dlls/ole32/hglobalstream.c | 202 +++++++++++++++++++++++++++------------
|
||||
dlls/ole32/tests/hglobalstream.c | 12 ---
|
||||
2 files changed, 140 insertions(+), 74 deletions(-)
|
||||
|
||||
diff --git a/dlls/ole32/hglobalstream.c b/dlls/ole32/hglobalstream.c
|
||||
index b86de56..5eb6320 100644
|
||||
--- a/dlls/ole32/hglobalstream.c
|
||||
+++ b/dlls/ole32/hglobalstream.c
|
||||
@@ -5,6 +5,7 @@
|
||||
* for streams contained supported by an HGLOBAL pointer.
|
||||
*
|
||||
* Copyright 1999 Francis Beaudet
|
||||
+ * Copyright 2016 Dmitry Timoshkov
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@@ -42,7 +43,96 @@
|
||||
|
||||
#include "wine/debug.h"
|
||||
|
||||
-WINE_DEFAULT_DEBUG_CHANNEL(storage);
|
||||
+WINE_DEFAULT_DEBUG_CHANNEL(hglobalstream);
|
||||
+
|
||||
+struct handle_wrapper
|
||||
+{
|
||||
+ LONG ref;
|
||||
+ HGLOBAL hglobal;
|
||||
+ ULONG size;
|
||||
+ BOOL delete_on_release;
|
||||
+ CRITICAL_SECTION lock;
|
||||
+};
|
||||
+
|
||||
+static void handle_addref(struct handle_wrapper *handle)
|
||||
+{
|
||||
+ InterlockedIncrement(&handle->ref);
|
||||
+}
|
||||
+
|
||||
+static void handle_release(struct handle_wrapper *handle)
|
||||
+{
|
||||
+ ULONG ref = InterlockedDecrement(&handle->ref);
|
||||
+
|
||||
+ if (!ref)
|
||||
+ {
|
||||
+ if (handle->delete_on_release)
|
||||
+ {
|
||||
+ GlobalFree(handle->hglobal);
|
||||
+ handle->hglobal = NULL;
|
||||
+ }
|
||||
+
|
||||
+ DeleteCriticalSection(&handle->lock);
|
||||
+ HeapFree(GetProcessHeap(), 0, handle);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static void *handle_lock(struct handle_wrapper *handle)
|
||||
+{
|
||||
+ return GlobalLock(handle->hglobal);
|
||||
+}
|
||||
+
|
||||
+static void handle_unlock(struct handle_wrapper *handle)
|
||||
+{
|
||||
+ GlobalUnlock(handle->hglobal);
|
||||
+}
|
||||
+
|
||||
+static HGLOBAL handle_gethglobal(struct handle_wrapper *handle)
|
||||
+{
|
||||
+ return handle->hglobal;
|
||||
+}
|
||||
+
|
||||
+static HRESULT handle_setsize(struct handle_wrapper *handle, ULONG size)
|
||||
+{
|
||||
+ HRESULT hr = S_OK;
|
||||
+
|
||||
+ EnterCriticalSection(&handle->lock);
|
||||
+
|
||||
+ if (handle->size != size)
|
||||
+ {
|
||||
+ HGLOBAL hglobal = GlobalReAlloc(handle->hglobal, size, 0);
|
||||
+ if (hglobal)
|
||||
+ {
|
||||
+ handle->hglobal = hglobal;
|
||||
+ handle->size = size;
|
||||
+ }
|
||||
+ else
|
||||
+ hr = E_OUTOFMEMORY;
|
||||
+ }
|
||||
+
|
||||
+ LeaveCriticalSection(&handle->lock);
|
||||
+ return hr;
|
||||
+}
|
||||
+
|
||||
+static ULONG handle_getsize(struct handle_wrapper *handle)
|
||||
+{
|
||||
+ return handle->size;
|
||||
+}
|
||||
+
|
||||
+static struct handle_wrapper *handle_create(HGLOBAL hglobal, BOOL delete_on_release)
|
||||
+{
|
||||
+ struct handle_wrapper *handle;
|
||||
+
|
||||
+ handle = HeapAlloc(GetProcessHeap(), 0, sizeof(*handle));
|
||||
+ if (handle)
|
||||
+ {
|
||||
+ handle->ref = 1;
|
||||
+ handle->hglobal = hglobal;
|
||||
+ handle->size = GlobalSize(hglobal);
|
||||
+ handle->delete_on_release = delete_on_release;
|
||||
+ InitializeCriticalSection(&handle->lock);
|
||||
+ }
|
||||
+ return handle;
|
||||
+}
|
||||
|
||||
/****************************************************************************
|
||||
* HGLOBALStreamImpl definition.
|
||||
@@ -55,14 +145,7 @@ typedef struct
|
||||
IStream IStream_iface;
|
||||
LONG ref;
|
||||
|
||||
- /* support for the stream */
|
||||
- HGLOBAL supportHandle;
|
||||
-
|
||||
- /* if TRUE the HGLOBAL is destroyed when the stream is finally released */
|
||||
- BOOL deleteOnRelease;
|
||||
-
|
||||
- /* size of the stream */
|
||||
- ULARGE_INTEGER streamSize;
|
||||
+ struct handle_wrapper *handle;
|
||||
|
||||
/* current position of the cursor */
|
||||
ULARGE_INTEGER currentPosition;
|
||||
@@ -114,12 +197,7 @@ static ULONG WINAPI HGLOBALStreamImpl_Release(
|
||||
|
||||
if (!ref)
|
||||
{
|
||||
- if (This->deleteOnRelease)
|
||||
- {
|
||||
- GlobalFree(This->supportHandle);
|
||||
- This->supportHandle = NULL;
|
||||
- }
|
||||
-
|
||||
+ handle_release(This->handle);
|
||||
HeapFree(GetProcessHeap(), 0, This);
|
||||
}
|
||||
|
||||
@@ -161,15 +239,15 @@ static HRESULT WINAPI HGLOBALStreamImpl_Read(
|
||||
* Using the known size of the stream, calculate the number of bytes
|
||||
* to read from the block chain
|
||||
*/
|
||||
- bytesToReadFromBuffer = min( This->streamSize.u.LowPart - This->currentPosition.u.LowPart, cb);
|
||||
+ bytesToReadFromBuffer = min( handle_getsize(This->handle) - This->currentPosition.u.LowPart, cb);
|
||||
|
||||
/*
|
||||
* Lock the buffer in position and copy the data.
|
||||
*/
|
||||
- supportBuffer = GlobalLock(This->supportHandle);
|
||||
+ supportBuffer = handle_lock(This->handle);
|
||||
if (!supportBuffer)
|
||||
{
|
||||
- WARN("read from invalid hglobal %p\n", This->supportHandle);
|
||||
+ WARN("read from invalid hglobal %p\n", handle_gethglobal(This->handle));
|
||||
*pcbRead = 0;
|
||||
return S_OK;
|
||||
}
|
||||
@@ -189,7 +267,7 @@ static HRESULT WINAPI HGLOBALStreamImpl_Read(
|
||||
/*
|
||||
* Cleanup
|
||||
*/
|
||||
- GlobalUnlock(This->supportHandle);
|
||||
+ handle_unlock(This->handle);
|
||||
|
||||
/*
|
||||
* Always returns S_OK even if the end of the stream is reached before the
|
||||
@@ -241,7 +319,7 @@ static HRESULT WINAPI HGLOBALStreamImpl_Write(
|
||||
/*
|
||||
* Verify if we need to grow the stream
|
||||
*/
|
||||
- if (newSize.u.LowPart > This->streamSize.u.LowPart)
|
||||
+ if (newSize.u.LowPart > handle_getsize(This->handle))
|
||||
{
|
||||
/* grow stream */
|
||||
HRESULT hr = IStream_SetSize(iface, newSize);
|
||||
@@ -255,10 +333,10 @@ static HRESULT WINAPI HGLOBALStreamImpl_Write(
|
||||
/*
|
||||
* Lock the buffer in position and copy the data.
|
||||
*/
|
||||
- supportBuffer = GlobalLock(This->supportHandle);
|
||||
+ supportBuffer = handle_lock(This->handle);
|
||||
if (!supportBuffer)
|
||||
{
|
||||
- WARN("write to invalid hglobal %p\n", This->supportHandle);
|
||||
+ WARN("write to invalid hglobal %p\n", handle_gethglobal(This->handle));
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
@@ -272,7 +350,7 @@ static HRESULT WINAPI HGLOBALStreamImpl_Write(
|
||||
/*
|
||||
* Cleanup
|
||||
*/
|
||||
- GlobalUnlock(This->supportHandle);
|
||||
+ handle_unlock(This->handle);
|
||||
|
||||
out:
|
||||
/*
|
||||
@@ -318,7 +396,7 @@ static HRESULT WINAPI HGLOBALStreamImpl_Seek(
|
||||
case STREAM_SEEK_CUR:
|
||||
break;
|
||||
case STREAM_SEEK_END:
|
||||
- newPosition = This->streamSize;
|
||||
+ newPosition.QuadPart = handle_getsize(This->handle);
|
||||
break;
|
||||
default:
|
||||
hr = STG_E_SEEKERROR;
|
||||
@@ -363,29 +441,13 @@ static HRESULT WINAPI HGLOBALStreamImpl_SetSize(
|
||||
ULARGE_INTEGER libNewSize) /* [in] */
|
||||
{
|
||||
HGLOBALStreamImpl* This = impl_from_IStream(iface);
|
||||
- HGLOBAL supportHandle;
|
||||
|
||||
TRACE("(%p, %d)\n", iface, libNewSize.u.LowPart);
|
||||
|
||||
/*
|
||||
* HighPart is ignored as shown in tests
|
||||
*/
|
||||
-
|
||||
- if (This->streamSize.u.LowPart == libNewSize.u.LowPart)
|
||||
- return S_OK;
|
||||
-
|
||||
- /*
|
||||
- * Re allocate the HGlobal to fit the new size of the stream.
|
||||
- */
|
||||
- supportHandle = GlobalReAlloc(This->supportHandle, libNewSize.u.LowPart, 0);
|
||||
-
|
||||
- if (supportHandle == 0)
|
||||
- return E_OUTOFMEMORY;
|
||||
-
|
||||
- This->supportHandle = supportHandle;
|
||||
- This->streamSize.u.LowPart = libNewSize.u.LowPart;
|
||||
-
|
||||
- return S_OK;
|
||||
+ return handle_setsize(This->handle, libNewSize.u.LowPart);
|
||||
}
|
||||
|
||||
/***
|
||||
@@ -533,24 +595,49 @@ static HRESULT WINAPI HGLOBALStreamImpl_Stat(
|
||||
|
||||
pstatstg->pwcsName = NULL;
|
||||
pstatstg->type = STGTY_STREAM;
|
||||
- pstatstg->cbSize = This->streamSize;
|
||||
+ pstatstg->cbSize.QuadPart = handle_getsize(This->handle);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
+static const IStreamVtbl HGLOBALStreamImplVtbl;
|
||||
+
|
||||
+static HGLOBALStreamImpl *HGLOBALStreamImpl_Create(void)
|
||||
+{
|
||||
+ HGLOBALStreamImpl *This;
|
||||
+
|
||||
+ This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
|
||||
+ if (This)
|
||||
+ {
|
||||
+ This->IStream_iface.lpVtbl = &HGLOBALStreamImplVtbl;
|
||||
+ This->ref = 1;
|
||||
+ }
|
||||
+ return This;
|
||||
+}
|
||||
+
|
||||
static HRESULT WINAPI HGLOBALStreamImpl_Clone(
|
||||
IStream* iface,
|
||||
IStream** ppstm) /* [out] */
|
||||
{
|
||||
HGLOBALStreamImpl* This = impl_from_IStream(iface);
|
||||
+ HGLOBALStreamImpl* clone;
|
||||
ULARGE_INTEGER dummy;
|
||||
LARGE_INTEGER offset;
|
||||
- HRESULT hr;
|
||||
|
||||
- TRACE(" Cloning %p (deleteOnRelease=%d seek position=%ld)\n",iface,This->deleteOnRelease,(long)This->currentPosition.QuadPart);
|
||||
- hr = CreateStreamOnHGlobal(This->supportHandle, FALSE, ppstm);
|
||||
- if(FAILED(hr))
|
||||
- return hr;
|
||||
+ if (!ppstm) return E_INVALIDARG;
|
||||
+
|
||||
+ *ppstm = NULL;
|
||||
+
|
||||
+ TRACE(" Cloning %p (seek position=%d)\n", iface, This->currentPosition.u.LowPart);
|
||||
+
|
||||
+ clone = HGLOBALStreamImpl_Create();
|
||||
+ if (!clone) return E_OUTOFMEMORY;
|
||||
+
|
||||
+ *ppstm = &clone->IStream_iface;
|
||||
+
|
||||
+ handle_addref(This->handle);
|
||||
+ clone->handle = This->handle;
|
||||
+
|
||||
offset.QuadPart = (LONGLONG)This->currentPosition.QuadPart;
|
||||
IStream_Seek(*ppstm, offset, STREAM_SEEK_SET, &dummy);
|
||||
return S_OK;
|
||||
@@ -587,28 +674,19 @@ HRESULT WINAPI CreateStreamOnHGlobal(
|
||||
if (!ppstm)
|
||||
return E_INVALIDARG;
|
||||
|
||||
- This = HeapAlloc(GetProcessHeap(), 0, sizeof(HGLOBALStreamImpl));
|
||||
+ This = HGLOBALStreamImpl_Create();
|
||||
if (!This) return E_OUTOFMEMORY;
|
||||
|
||||
- This->IStream_iface.lpVtbl = &HGLOBALStreamImplVtbl;
|
||||
- This->ref = 1;
|
||||
-
|
||||
- /* initialize the support */
|
||||
- This->supportHandle = hGlobal;
|
||||
- This->deleteOnRelease = fDeleteOnRelease;
|
||||
-
|
||||
/* allocate a handle if one is not supplied */
|
||||
- if (!This->supportHandle)
|
||||
- This->supportHandle = GlobalAlloc(GMEM_MOVEABLE|GMEM_NODISCARD|GMEM_SHARE, 0);
|
||||
+ if (!hGlobal)
|
||||
+ hGlobal = GlobalAlloc(GMEM_MOVEABLE|GMEM_NODISCARD|GMEM_SHARE, 0);
|
||||
+
|
||||
+ This->handle = handle_create(hGlobal, fDeleteOnRelease);
|
||||
|
||||
/* start at the beginning */
|
||||
This->currentPosition.u.HighPart = 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;
|
||||
|
||||
return S_OK;
|
||||
@@ -630,7 +708,7 @@ HRESULT WINAPI GetHGlobalFromStream(IStream* pstm, HGLOBAL* phglobal)
|
||||
* Verify that the stream object was created with CreateStreamOnHGlobal.
|
||||
*/
|
||||
if (pStream->IStream_iface.lpVtbl == &HGLOBALStreamImplVtbl)
|
||||
- *phglobal = pStream->supportHandle;
|
||||
+ *phglobal = handle_gethglobal(pStream->handle);
|
||||
else
|
||||
{
|
||||
*phglobal = 0;
|
||||
diff --git a/dlls/ole32/tests/hglobalstream.c b/dlls/ole32/tests/hglobalstream.c
|
||||
index 0453e54..afda4e6 100644
|
||||
--- a/dlls/ole32/tests/hglobalstream.c
|
||||
+++ b/dlls/ole32/tests/hglobalstream.c
|
||||
@@ -579,14 +579,12 @@ static void test_IStream_Clone(void)
|
||||
|
||||
stream_info(clone, &hmem_clone, &size, &pos);
|
||||
ok(hmem_clone == hmem, "handles should match\n");
|
||||
-todo_wine
|
||||
ok(size == 13, "unexpected %d\n", size);
|
||||
ok(pos == 0, "unexpected %d\n", pos);
|
||||
|
||||
buf[0] = 0;
|
||||
hr = IStream_Read(clone, buf, sizeof(buf), NULL);
|
||||
ok(hr == S_OK, "unexpected %#x\n", hr);
|
||||
-todo_wine
|
||||
ok(!strcmp(buf, hello), "wrong stream contents\n");
|
||||
|
||||
newsize.QuadPart = 0x8000;
|
||||
@@ -601,9 +599,7 @@ todo_wine
|
||||
|
||||
stream_info(clone, &hmem_clone, &size, &pos);
|
||||
ok(hmem_clone == hmem, "handles should match\n");
|
||||
-todo_wine
|
||||
ok(size == 0x8000, "unexpected %#x\n", size);
|
||||
-todo_wine
|
||||
ok(pos == 13, "unexpected %d\n", pos);
|
||||
|
||||
IStream_Release(clone);
|
||||
@@ -715,24 +711,19 @@ todo_wine
|
||||
|
||||
newsize.QuadPart = 0x8000;
|
||||
hr = IStream_SetSize(clone, newsize);
|
||||
-todo_wine
|
||||
ok(hr == S_OK, "unexpected %#x\n", hr);
|
||||
|
||||
stream_info(clone, &hmem_clone, &size, &pos);
|
||||
ok(hmem_clone == hmem, "handles should match\n");
|
||||
-todo_wine
|
||||
ok(size == 0x8000, "unexpected %#x\n", size);
|
||||
ok(pos == 0, "unexpected %d\n", pos);
|
||||
|
||||
hr = IStream_Write(clone, hello, sizeof(hello), NULL);
|
||||
-todo_wine
|
||||
ok(hr == S_OK, "unexpected %#x\n", hr);
|
||||
|
||||
stream_info(clone, &hmem_clone, &size, &pos);
|
||||
ok(hmem_clone == hmem, "handles should match\n");
|
||||
-todo_wine
|
||||
ok(size == 0x8000, "unexpected %#x\n", size);
|
||||
-todo_wine
|
||||
ok(pos == 13, "unexpected %d\n", pos);
|
||||
|
||||
offset.QuadPart = 0;
|
||||
@@ -742,14 +733,11 @@ todo_wine
|
||||
buf[0] = 0;
|
||||
hr = IStream_Read(clone, buf, sizeof(buf), NULL);
|
||||
ok(hr == S_OK, "unexpected %#x\n", hr);
|
||||
-todo_wine
|
||||
ok(!strcmp(buf, hello), "wrong stream contents\n");
|
||||
|
||||
stream_info(clone, &hmem_clone, &size, &pos);
|
||||
ok(hmem_clone == hmem, "handles should match\n");
|
||||
-todo_wine
|
||||
ok(size == 0x8000, "unexpected %#x\n", size);
|
||||
-todo_wine
|
||||
ok(pos == 32, "unexpected %d\n", pos);
|
||||
|
||||
ret = IStream_Release(clone);
|
||||
--
|
||||
2.7.0
|
||||
|
@ -1,32 +0,0 @@
|
||||
From e6b772e0000dac0c50a8070b46413352e9c86174 Mon Sep 17 00:00:00 2001
|
||||
From: Sebastian Lackner <sebastian@fds-team.de>
|
||||
Date: Sat, 6 Feb 2016 03:26:10 +0100
|
||||
Subject: ole32: Set DebugInfo->Spare[0] for handle_wrapper lock.
|
||||
|
||||
---
|
||||
dlls/ole32/hglobalstream.c | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
diff --git a/dlls/ole32/hglobalstream.c b/dlls/ole32/hglobalstream.c
|
||||
index 5eb6320..8b7e960 100644
|
||||
--- a/dlls/ole32/hglobalstream.c
|
||||
+++ b/dlls/ole32/hglobalstream.c
|
||||
@@ -71,6 +71,7 @@ static void handle_release(struct handle_wrapper *handle)
|
||||
handle->hglobal = NULL;
|
||||
}
|
||||
|
||||
+ handle->lock.DebugInfo->Spare[0] = 0;
|
||||
DeleteCriticalSection(&handle->lock);
|
||||
HeapFree(GetProcessHeap(), 0, handle);
|
||||
}
|
||||
@@ -130,6 +131,7 @@ static struct handle_wrapper *handle_create(HGLOBAL hglobal, BOOL delete_on_rele
|
||||
handle->size = GlobalSize(hglobal);
|
||||
handle->delete_on_release = delete_on_release;
|
||||
InitializeCriticalSection(&handle->lock);
|
||||
+ handle->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": handle_wrapper.lock");
|
||||
}
|
||||
return handle;
|
||||
}
|
||||
--
|
||||
2.7.0
|
||||
|
@ -1,115 +0,0 @@
|
||||
From f5c31437019892510e36f603cbde72d9204a4155 Mon Sep 17 00:00:00 2001
|
||||
From: Sebastian Lackner <sebastian@fds-team.de>
|
||||
Date: Sat, 6 Feb 2016 03:50:55 +0100
|
||||
Subject: ole32: Improve thread-safety of HGLOBALStreamImpl_Read.
|
||||
|
||||
---
|
||||
dlls/ole32/hglobalstream.c | 83 ++++++++++++++++++----------------------------
|
||||
1 file changed, 32 insertions(+), 51 deletions(-)
|
||||
|
||||
diff --git a/dlls/ole32/hglobalstream.c b/dlls/ole32/hglobalstream.c
|
||||
index 3e7f67b..27ac706 100644
|
||||
--- a/dlls/ole32/hglobalstream.c
|
||||
+++ b/dlls/ole32/hglobalstream.c
|
||||
@@ -87,6 +87,34 @@ static void handle_unlock(struct handle_wrapper *handle)
|
||||
GlobalUnlock(handle->hglobal);
|
||||
}
|
||||
|
||||
+static ULONG handle_read(struct handle_wrapper *handle, ULONG *pos, void *dest, ULONG len)
|
||||
+{
|
||||
+ void *source;
|
||||
+
|
||||
+ EnterCriticalSection(&handle->lock);
|
||||
+
|
||||
+ if (*pos < handle->size)
|
||||
+ len = min(handle->size - *pos, len);
|
||||
+ else
|
||||
+ len = 0;
|
||||
+
|
||||
+ source = GlobalLock(handle->hglobal);
|
||||
+ if (source)
|
||||
+ {
|
||||
+ memcpy(dest, (char *)source + *pos, len);
|
||||
+ *pos += len;
|
||||
+ GlobalUnlock(handle->hglobal);
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ WARN("read from invalid hglobal %p\n", handle->hglobal);
|
||||
+ len = 0;
|
||||
+ }
|
||||
+
|
||||
+ LeaveCriticalSection(&handle->lock);
|
||||
+ return len;
|
||||
+}
|
||||
+
|
||||
static HGLOBAL handle_gethglobal(struct handle_wrapper *handle)
|
||||
{
|
||||
return handle->hglobal;
|
||||
@@ -222,59 +250,12 @@ static HRESULT WINAPI HGLOBALStreamImpl_Read(
|
||||
ULONG* pcbRead) /* [out] */
|
||||
{
|
||||
HGLOBALStreamImpl* This = impl_from_IStream(iface);
|
||||
+ ULONG num_bytes;
|
||||
|
||||
- void* supportBuffer;
|
||||
- ULONG bytesReadBuffer;
|
||||
- ULONG bytesToReadFromBuffer;
|
||||
-
|
||||
- TRACE("(%p, %p, %d, %p)\n", iface,
|
||||
- pv, cb, pcbRead);
|
||||
-
|
||||
- /*
|
||||
- * If the caller is not interested in the number of bytes read,
|
||||
- * we use another buffer to avoid "if" statements in the code.
|
||||
- */
|
||||
- if (pcbRead==0)
|
||||
- pcbRead = &bytesReadBuffer;
|
||||
-
|
||||
- /*
|
||||
- * Using the known size of the stream, calculate the number of bytes
|
||||
- * to read from the block chain
|
||||
- */
|
||||
- bytesToReadFromBuffer = min( handle_getsize(This->handle) - This->currentPosition.u.LowPart, cb);
|
||||
-
|
||||
- /*
|
||||
- * Lock the buffer in position and copy the data.
|
||||
- */
|
||||
- supportBuffer = handle_lock(This->handle);
|
||||
- if (!supportBuffer)
|
||||
- {
|
||||
- WARN("read from invalid hglobal %p\n", handle_gethglobal(This->handle));
|
||||
- *pcbRead = 0;
|
||||
- return S_OK;
|
||||
- }
|
||||
-
|
||||
- memcpy(pv, (char *) supportBuffer+This->currentPosition.u.LowPart, bytesToReadFromBuffer);
|
||||
-
|
||||
- /*
|
||||
- * Move the current position to the new position
|
||||
- */
|
||||
- This->currentPosition.u.LowPart+=bytesToReadFromBuffer;
|
||||
-
|
||||
- /*
|
||||
- * Return the number of bytes read.
|
||||
- */
|
||||
- *pcbRead = bytesToReadFromBuffer;
|
||||
-
|
||||
- /*
|
||||
- * Cleanup
|
||||
- */
|
||||
- handle_unlock(This->handle);
|
||||
+ TRACE("(%p, %p, %d, %p)\n", iface, pv, cb, pcbRead);
|
||||
|
||||
- /*
|
||||
- * Always returns S_OK even if the end of the stream is reached before the
|
||||
- * buffer is filled
|
||||
- */
|
||||
+ num_bytes = handle_read(This->handle, &This->currentPosition.u.LowPart, pv, cb);
|
||||
+ if (pcbRead) *pcbRead = num_bytes;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
--
|
||||
2.7.0
|
||||
|
@ -1,158 +0,0 @@
|
||||
From 8656639654762bd3151593fe00a0c47080a085d8 Mon Sep 17 00:00:00 2001
|
||||
From: Sebastian Lackner <sebastian@fds-team.de>
|
||||
Date: Sat, 6 Feb 2016 04:09:45 +0100
|
||||
Subject: ole32: Improve thread-safety of HGLOBALStreamImpl_Write.
|
||||
|
||||
---
|
||||
dlls/ole32/hglobalstream.c | 117 ++++++++++++++++++---------------------------
|
||||
1 file changed, 46 insertions(+), 71 deletions(-)
|
||||
|
||||
diff --git a/dlls/ole32/hglobalstream.c b/dlls/ole32/hglobalstream.c
|
||||
index 27ac706..2c08710 100644
|
||||
--- a/dlls/ole32/hglobalstream.c
|
||||
+++ b/dlls/ole32/hglobalstream.c
|
||||
@@ -77,16 +77,6 @@ static void handle_release(struct handle_wrapper *handle)
|
||||
}
|
||||
}
|
||||
|
||||
-static void *handle_lock(struct handle_wrapper *handle)
|
||||
-{
|
||||
- return GlobalLock(handle->hglobal);
|
||||
-}
|
||||
-
|
||||
-static void handle_unlock(struct handle_wrapper *handle)
|
||||
-{
|
||||
- GlobalUnlock(handle->hglobal);
|
||||
-}
|
||||
-
|
||||
static ULONG handle_read(struct handle_wrapper *handle, ULONG *pos, void *dest, ULONG len)
|
||||
{
|
||||
void *source;
|
||||
@@ -115,6 +105,48 @@ static ULONG handle_read(struct handle_wrapper *handle, ULONG *pos, void *dest,
|
||||
return len;
|
||||
}
|
||||
|
||||
+static ULONG handle_write(struct handle_wrapper *handle, ULONG *pos, const void *source, ULONG len)
|
||||
+{
|
||||
+ void *dest;
|
||||
+
|
||||
+ if (!len)
|
||||
+ return 0;
|
||||
+
|
||||
+ EnterCriticalSection(&handle->lock);
|
||||
+
|
||||
+ if (*pos + len > handle->size)
|
||||
+ {
|
||||
+ HGLOBAL hglobal = GlobalReAlloc(handle->hglobal, *pos + len, GMEM_MOVEABLE);
|
||||
+ if (hglobal)
|
||||
+ {
|
||||
+ handle->hglobal = hglobal;
|
||||
+ handle->size = *pos + len;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ len = 0;
|
||||
+ goto done;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ dest = GlobalLock(handle->hglobal);
|
||||
+ if (dest)
|
||||
+ {
|
||||
+ memcpy((char *)dest + *pos, source, len);
|
||||
+ *pos += len;
|
||||
+ GlobalUnlock(handle->hglobal);
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ WARN("write to invalid hglobal %p\n", handle->hglobal);
|
||||
+ /* len = 0; */
|
||||
+ }
|
||||
+
|
||||
+done:
|
||||
+ LeaveCriticalSection(&handle->lock);
|
||||
+ return len;
|
||||
+}
|
||||
+
|
||||
static HGLOBAL handle_gethglobal(struct handle_wrapper *handle)
|
||||
{
|
||||
return handle->hglobal;
|
||||
@@ -277,71 +309,14 @@ static HRESULT WINAPI HGLOBALStreamImpl_Write(
|
||||
ULONG* pcbWritten) /* [out] */
|
||||
{
|
||||
HGLOBALStreamImpl* This = impl_from_IStream(iface);
|
||||
-
|
||||
- void* supportBuffer;
|
||||
- ULARGE_INTEGER newSize;
|
||||
- ULONG bytesWritten = 0;
|
||||
+ ULONG num_bytes;
|
||||
|
||||
TRACE("(%p, %p, %d, %p)\n", iface, pv, cb, pcbWritten);
|
||||
|
||||
- /*
|
||||
- * If the caller is not interested in the number of bytes written,
|
||||
- * we use another buffer to avoid "if" statements in the code.
|
||||
- */
|
||||
- if (pcbWritten == 0)
|
||||
- pcbWritten = &bytesWritten;
|
||||
-
|
||||
- if (cb == 0)
|
||||
- goto out;
|
||||
-
|
||||
- *pcbWritten = 0;
|
||||
-
|
||||
- newSize.u.HighPart = 0;
|
||||
- newSize.u.LowPart = This->currentPosition.u.LowPart + cb;
|
||||
-
|
||||
- /*
|
||||
- * Verify if we need to grow the stream
|
||||
- */
|
||||
- if (newSize.u.LowPart > handle_getsize(This->handle))
|
||||
- {
|
||||
- /* grow stream */
|
||||
- HRESULT hr = IStream_SetSize(iface, newSize);
|
||||
- if (FAILED(hr))
|
||||
- {
|
||||
- ERR("IStream_SetSize failed with error 0x%08x\n", hr);
|
||||
- return hr;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- /*
|
||||
- * Lock the buffer in position and copy the data.
|
||||
- */
|
||||
- supportBuffer = handle_lock(This->handle);
|
||||
- if (!supportBuffer)
|
||||
- {
|
||||
- WARN("write to invalid hglobal %p\n", handle_gethglobal(This->handle));
|
||||
- return S_OK;
|
||||
- }
|
||||
-
|
||||
- memcpy((char *) supportBuffer+This->currentPosition.u.LowPart, pv, cb);
|
||||
-
|
||||
- /*
|
||||
- * Move the current position to the new position
|
||||
- */
|
||||
- This->currentPosition.u.LowPart+=cb;
|
||||
-
|
||||
- /*
|
||||
- * Cleanup
|
||||
- */
|
||||
- handle_unlock(This->handle);
|
||||
-
|
||||
-out:
|
||||
- /*
|
||||
- * Return the number of bytes read.
|
||||
- */
|
||||
- *pcbWritten = cb;
|
||||
+ num_bytes = handle_write(This->handle, &This->currentPosition.u.LowPart, pv, cb);
|
||||
+ if (pcbWritten) *pcbWritten = num_bytes;
|
||||
|
||||
- return S_OK;
|
||||
+ return (num_bytes < cb) ? E_OUTOFMEMORY : S_OK;
|
||||
}
|
||||
|
||||
/***
|
||||
--
|
||||
2.7.0
|
||||
|
@ -1,2 +0,0 @@
|
||||
Fixes: [41738] Implement proper refcounting and locking for HGLOBAL based IStream
|
||||
Disabled: true
|
@ -205,6 +205,7 @@ patch_enable_all ()
|
||||
enable_nvcuda_CUDA_Support="$1"
|
||||
enable_nvcuvid_CUDA_Video_Support="$1"
|
||||
enable_nvencodeapi_Video_Encoder="$1"
|
||||
enable_ole32_HGLOBALStream="$1"
|
||||
enable_oleaut32_CreateTypeLib="$1"
|
||||
enable_oleaut32_Load_Save_EMF="$1"
|
||||
enable_oleaut32_OLEPictureImpl_SaveAsFile="$1"
|
||||
@ -705,6 +706,9 @@ patch_enable ()
|
||||
nvencodeapi-Video_Encoder)
|
||||
enable_nvencodeapi_Video_Encoder="$2"
|
||||
;;
|
||||
ole32-HGLOBALStream)
|
||||
enable_ole32_HGLOBALStream="$2"
|
||||
;;
|
||||
oleaut32-CreateTypeLib)
|
||||
enable_oleaut32_CreateTypeLib="$2"
|
||||
;;
|
||||
@ -4192,6 +4196,18 @@ if test "$enable_nvencodeapi_Video_Encoder" -eq 1; then
|
||||
) >> "$patchlist"
|
||||
fi
|
||||
|
||||
# Patchset ole32-HGLOBALStream
|
||||
# |
|
||||
# | Modified files:
|
||||
# | * dlls/ole32/hglobalstream.c, dlls/ole32/tests/hglobalstream.c
|
||||
# |
|
||||
if test "$enable_ole32_HGLOBALStream" -eq 1; then
|
||||
patch_apply ole32-HGLOBALStream/0002-ole32-Add-a-check-for-hglobal-pointer-to-GetHGlobalF.patch
|
||||
(
|
||||
printf '%s\n' '+ { "Dmitry Timoshkov", "ole32: Add a check for hglobal pointer to GetHGlobalFromStream.", 1 },';
|
||||
) >> "$patchlist"
|
||||
fi
|
||||
|
||||
# Patchset oleaut32-CreateTypeLib
|
||||
# |
|
||||
# | This patchset fixes the following Wine bugs:
|
||||
|
Loading…
Reference in New Issue
Block a user