ole32: After a call to GetData the consumer should hold a ref on the source data object.
This commit is contained in:
parent
d2156f3894
commit
fca4ed5596
|
@ -134,6 +134,8 @@ typedef struct snapshot
|
|||
LONG ref;
|
||||
|
||||
DWORD seq_no; /* Clipboard sequence number corresponding to this snapshot */
|
||||
|
||||
IDataObject *data; /* If we unmarshal a remote data object we hold a ref here */
|
||||
} snapshot;
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -830,6 +832,8 @@ static ULONG WINAPI snapshot_Release(IDataObject *iface)
|
|||
ole_clipbrd *clipbrd;
|
||||
HRESULT hr = get_ole_clipbrd(&clipbrd);
|
||||
|
||||
if(This->data) IDataObject_Release(This->data);
|
||||
|
||||
if(SUCCEEDED(hr) && clipbrd->latest_snapshot == This)
|
||||
clipbrd->latest_snapshot = NULL;
|
||||
HeapFree(GetProcessHeap(), 0, This);
|
||||
|
@ -907,25 +911,26 @@ static HRESULT WINAPI snapshot_GetData(IDataObject *iface,
|
|||
FORMATETC *pformatetcIn,
|
||||
STGMEDIUM *pmedium)
|
||||
{
|
||||
HANDLE h, hData = 0;
|
||||
HRESULT hr;
|
||||
IDataObject *data;
|
||||
snapshot *This = impl_from_IDataObject(iface);
|
||||
HANDLE h, hData = 0;
|
||||
HRESULT hr;
|
||||
|
||||
TRACE("(%p,%p,%p)\n", iface, pformatetcIn, pmedium);
|
||||
TRACE("(%p,%p,%p)\n", iface, pformatetcIn, pmedium);
|
||||
|
||||
if ( !pformatetcIn || !pmedium )
|
||||
return E_INVALIDARG;
|
||||
if ( !pformatetcIn || !pmedium ) return E_INVALIDARG;
|
||||
|
||||
if ( !OpenClipboard(NULL)) return CLIPBRD_E_CANT_OPEN;
|
||||
if ( !OpenClipboard(NULL)) return CLIPBRD_E_CANT_OPEN;
|
||||
|
||||
if(!This->data)
|
||||
hr = get_current_dataobject(&This->data);
|
||||
|
||||
if(This->data)
|
||||
{
|
||||
hr = IDataObject_GetData(This->data, pformatetcIn, pmedium);
|
||||
CloseClipboard();
|
||||
return hr;
|
||||
}
|
||||
|
||||
hr = get_current_dataobject(&data);
|
||||
if ( hr == S_OK )
|
||||
{
|
||||
hr = IDataObject_GetData(data, pformatetcIn, pmedium);
|
||||
IDataObject_Release(data);
|
||||
CloseClipboard();
|
||||
return hr;
|
||||
}
|
||||
|
||||
/*
|
||||
* Otherwise, get the data from the windows clipboard using GetClipboardData
|
||||
|
@ -1130,6 +1135,7 @@ static snapshot *snapshot_construct(DWORD seq_no)
|
|||
This->lpVtbl = &snapshot_vtable;
|
||||
This->ref = 0;
|
||||
This->seq_no = seq_no;
|
||||
This->data = NULL;
|
||||
|
||||
return This;
|
||||
}
|
||||
|
|
|
@ -862,14 +862,27 @@ static void test_set_clipboard(void)
|
|||
OleUninitialize();
|
||||
}
|
||||
|
||||
static inline ULONG count_refs(IDataObject *d)
|
||||
{
|
||||
IDataObject_AddRef(d);
|
||||
return IDataObject_Release(d);
|
||||
}
|
||||
|
||||
static void test_consumer_refs(void)
|
||||
{
|
||||
HRESULT hr;
|
||||
IDataObject *src, *get1, *get2, *get3;
|
||||
LONG refs;
|
||||
ULONG refs, old_refs;
|
||||
FORMATETC fmt;
|
||||
STGMEDIUM med;
|
||||
|
||||
InitFormatEtc(fmt, CF_TEXT, TYMED_HGLOBAL);
|
||||
|
||||
OleInitialize(NULL);
|
||||
|
||||
/* First show that each clipboard state results in
|
||||
a different data object */
|
||||
|
||||
hr = DataObjectImpl_CreateText("data1", &src);
|
||||
ok(hr == S_OK, "got %08x\n", hr);
|
||||
|
||||
|
@ -888,6 +901,12 @@ static void test_consumer_refs(void)
|
|||
|
||||
OleFlushClipboard();
|
||||
|
||||
DataObjectImpl_GetData_calls = 0;
|
||||
hr = IDataObject_GetData(get1, &fmt, &med);
|
||||
ok(hr == S_OK, "got %08x\n", hr);
|
||||
ok(DataObjectImpl_GetData_calls == 0, "GetData called\n");
|
||||
ReleaseStgMedium(&med);
|
||||
|
||||
hr = OleGetClipboard(&get2);
|
||||
ok(hr == S_OK, "got %08x\n", hr);
|
||||
|
||||
|
@ -904,6 +923,46 @@ static void test_consumer_refs(void)
|
|||
IDataObject_Release(get3);
|
||||
IDataObject_Release(get2);
|
||||
IDataObject_Release(get1);
|
||||
|
||||
/* Now call GetData before the flush and show that this
|
||||
takes a ref on our src data obj. */
|
||||
|
||||
hr = OleSetClipboard(src);
|
||||
ok(hr == S_OK, "got %08x\n", hr);
|
||||
|
||||
old_refs = count_refs(src);
|
||||
trace("old_refs %d\n", old_refs);
|
||||
|
||||
hr = OleGetClipboard(&get1);
|
||||
ok(hr == S_OK, "got %08x\n", hr);
|
||||
|
||||
refs = count_refs(src);
|
||||
ok(refs == old_refs, "%d %d\n", refs, old_refs);
|
||||
|
||||
DataObjectImpl_GetData_calls = 0;
|
||||
hr = IDataObject_GetData(get1, &fmt, &med);
|
||||
ok(hr == S_OK, "got %08x\n", hr);
|
||||
ok(DataObjectImpl_GetData_calls == 1, "GetData not called\n");
|
||||
ReleaseStgMedium(&med);
|
||||
refs = count_refs(src);
|
||||
ok(refs == old_refs + 1, "%d %d\n", refs, old_refs);
|
||||
|
||||
OleFlushClipboard();
|
||||
|
||||
DataObjectImpl_GetData_calls = 0;
|
||||
hr = IDataObject_GetData(get1, &fmt, &med);
|
||||
ok(hr == S_OK, "got %08x\n", hr);
|
||||
ok(DataObjectImpl_GetData_calls == 1, "GetData not called\n");
|
||||
ReleaseStgMedium(&med);
|
||||
|
||||
refs = count_refs(src);
|
||||
ok(refs == 2, "%d\n", refs);
|
||||
|
||||
IDataObject_Release(get1);
|
||||
|
||||
refs = count_refs(src);
|
||||
ok(refs == 1, "%d\n", refs);
|
||||
|
||||
IDataObject_Release(src);
|
||||
|
||||
OleUninitialize();
|
||||
|
|
Loading…
Reference in New Issue