Commit d90ec79b authored by Piotr Caban's avatar Piotr Caban Committed by Alexandre Julliard

ole32: Make clipboard latest_snapshot access thread safe.

parent 81bd7264
......@@ -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;
}
......
......@@ -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();
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment