Piotr Caban : ole32: Make clipboard latest_snapshot access thread safe.
Alexandre Julliard
julliard at wine.codeweavers.com
Tue Dec 29 15:49:00 CST 2015
Module: wine
Branch: master
Commit: d90ec79be2104acb3e2f59e31d3309591cd4f50d
URL: http://source.winehq.org/git/wine.git/?a=commit;h=d90ec79be2104acb3e2f59e31d3309591cd4f50d
Author: Piotr Caban <piotr at codeweavers.com>
Date: Tue Dec 29 14:39:01 2015 +0100
ole32: Make clipboard latest_snapshot access thread safe.
Signed-off-by: Piotr Caban <piotr at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
dlls/ole32/clipboard.c | 31 +++++++++++++++++++++++++------
dlls/ole32/tests/clipboard.c | 33 +++++++++++++++++++++++++++++++++
2 files changed, 58 insertions(+), 6 deletions(-)
diff --git a/dlls/ole32/clipboard.c b/dlls/ole32/clipboard.c
index db1e4a8..ca9520f 100644
--- a/dlls/ole32/clipboard.c
+++ b/dlls/ole32/clipboard.c
@@ -174,6 +174,15 @@ typedef struct PresentationDataHeader
*/
static ole_clipbrd* theOleClipboard;
+static CRITICAL_SECTION latest_snapshot_cs;
+static CRITICAL_SECTION_DEBUG latest_snapshot_cs_debug =
+{
+ 0, 0, &latest_snapshot_cs,
+ { &latest_snapshot_cs_debug.ProcessLocksList, &latest_snapshot_cs_debug.ProcessLocksList },
+ 0, 0, { (DWORD_PTR)(__FILE__ ": clipboard last snapshot") }
+};
+static CRITICAL_SECTION latest_snapshot_cs = { &latest_snapshot_cs_debug, -1, 0, 0, 0, 0 };
+
static inline HRESULT get_ole_clipbrd(ole_clipbrd **clipbrd)
{
struct oletls *info = COM_CurrentInfo();
@@ -1042,13 +1051,17 @@ static ULONG WINAPI snapshot_Release(IDataObject *iface)
if (ref == 0)
{
- ole_clipbrd *clipbrd;
- HRESULT hr = get_ole_clipbrd(&clipbrd);
+ EnterCriticalSection(&latest_snapshot_cs);
+ if (This->ref)
+ {
+ LeaveCriticalSection(&latest_snapshot_cs);
+ return ref;
+ }
+ if (theOleClipboard->latest_snapshot == This)
+ theOleClipboard->latest_snapshot = NULL;
+ LeaveCriticalSection(&latest_snapshot_cs);
if(This->data) IDataObject_Release(This->data);
-
- if(SUCCEEDED(hr) && clipbrd->latest_snapshot == This)
- clipbrd->latest_snapshot = NULL;
HeapFree(GetProcessHeap(), 0, This);
}
@@ -2192,17 +2205,23 @@ HRESULT WINAPI OleGetClipboard(IDataObject **obj)
if(FAILED(hr = get_ole_clipbrd(&clipbrd))) return hr;
seq_no = GetClipboardSequenceNumber();
+ EnterCriticalSection(&latest_snapshot_cs);
if(clipbrd->latest_snapshot && clipbrd->latest_snapshot->seq_no != seq_no)
clipbrd->latest_snapshot = NULL;
if(!clipbrd->latest_snapshot)
{
clipbrd->latest_snapshot = snapshot_construct(seq_no);
- if(!clipbrd->latest_snapshot) return E_OUTOFMEMORY;
+ if(!clipbrd->latest_snapshot)
+ {
+ LeaveCriticalSection(&latest_snapshot_cs);
+ return E_OUTOFMEMORY;
+ }
}
*obj = &clipbrd->latest_snapshot->IDataObject_iface;
IDataObject_AddRef(*obj);
+ LeaveCriticalSection(&latest_snapshot_cs);
return S_OK;
}
diff --git a/dlls/ole32/tests/clipboard.c b/dlls/ole32/tests/clipboard.c
index 81b3a1c..02097ea 100644
--- a/dlls/ole32/tests/clipboard.c
+++ b/dlls/ole32/tests/clipboard.c
@@ -1539,6 +1539,38 @@ static void test_getdatahere(void)
}
+static DWORD CALLBACK test_data_obj(void *arg)
+{
+ IDataObject *data_obj = arg;
+
+ IDataObject_Release(data_obj);
+ return 0;
+}
+
+static void test_multithreaded_clipboard(void)
+{
+ IDataObject *data_obj;
+ HANDLE thread;
+ HRESULT hr;
+ DWORD ret;
+
+ OleInitialize(NULL);
+
+ hr = OleGetClipboard(&data_obj);
+ ok(hr == S_OK, "OleGetClipboard returned %x\n", hr);
+
+ thread = CreateThread(NULL, 0, test_data_obj, data_obj, 0, NULL);
+ ok(thread != NULL, "CreateThread failed (%d)\n", GetLastError());
+ ret = WaitForSingleObject(thread, 5000);
+ ok(ret == WAIT_OBJECT_0, "WaitForSingleObject returned %x\n", ret);
+
+ hr = OleGetClipboard(&data_obj);
+ ok(hr == S_OK, "OleGetClipboard returned %x\n", hr);
+ IDataObject_Release(data_obj);
+
+ OleUninitialize();
+}
+
START_TEST(clipboard)
{
test_set_clipboard();
@@ -1546,4 +1578,5 @@ START_TEST(clipboard)
test_flushed_getdata();
test_nonole_clipboard();
test_getdatahere();
+ test_multithreaded_clipboard();
}
More information about the wine-cvs
mailing list