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