Commit 66d04f8e authored by Huw Davies's avatar Huw Davies Committed by Alexandre Julliard

ole32: Implement GetDataHere.

parent 8a03ac58
......@@ -1197,7 +1197,7 @@ static HRESULT WINAPI snapshot_GetData(IDataObject *iface, FORMATETC *fmt,
hr = get_stgmed_for_stream(h, med);
else
{
FIXME("Unhandled tymed - emum tymed %x req tymed %x\n", entry->fmtetc.tymed, fmt->tymed);
FIXME("Unhandled tymed - mask %x req tymed %x\n", mask, fmt->tymed);
hr = E_FAIL;
goto end;
}
......@@ -1214,8 +1214,108 @@ end:
static HRESULT WINAPI snapshot_GetDataHere(IDataObject *iface, FORMATETC *fmt,
STGMEDIUM *med)
{
FIXME("(%p, %p {%s}, %p): stub\n", iface, fmt, dump_fmtetc(fmt), med);
return E_NOTIMPL;
snapshot *This = impl_from_IDataObject(iface);
HANDLE h;
HRESULT hr;
ole_priv_data *enum_data = NULL;
ole_priv_data_entry *entry;
TYMED supported;
TRACE("(%p, %p {%s}, %p (tymed %x)\n", iface, fmt, dump_fmtetc(fmt), med, med->tymed);
if ( !fmt || !med ) return E_INVALIDARG;
if ( !OpenClipboard(NULL)) return CLIPBRD_E_CANT_OPEN;
if(!This->data)
hr = get_current_dataobject(&This->data);
if(This->data)
{
hr = IDataObject_GetDataHere(This->data, fmt, med);
if(SUCCEEDED(hr))
{
CloseClipboard();
return hr;
}
}
h = GetClipboardData(fmt->cfFormat);
if(!h)
{
hr = DV_E_FORMATETC;
goto end;
}
hr = get_priv_data(&enum_data);
if(FAILED(hr)) goto end;
entry = find_format_in_list(enum_data->entries, enum_data->count, fmt->cfFormat);
if(entry)
{
if(!td_equal(fmt->ptd, entry->fmtetc.ptd))
{
hr = DV_E_FORMATETC;
goto end;
}
supported = entry->fmtetc.tymed;
}
else /* non-Ole format */
supported = TYMED_HGLOBAL;
switch(med->tymed)
{
case TYMED_HGLOBAL:
{
DWORD src_size = GlobalSize(h);
DWORD dst_size = GlobalSize(med->u.hGlobal);
hr = E_FAIL;
if(dst_size >= src_size)
{
void *src = GlobalLock(h);
void *dst = GlobalLock(med->u.hGlobal);
memcpy(dst, src, src_size);
GlobalUnlock(med->u.hGlobal);
GlobalUnlock(h);
hr = S_OK;
}
break;
}
case TYMED_ISTREAM:
{
DWORD src_size = GlobalSize(h);
void *src = GlobalLock(h);
hr = IStream_Write(med->u.pstm, src, src_size, NULL);
GlobalUnlock(h);
break;
}
case TYMED_ISTORAGE:
{
STGMEDIUM copy;
if(!(supported & TYMED_ISTORAGE))
{
hr = E_FAIL;
goto end;
}
hr = get_stgmed_for_storage(h, &copy);
if(SUCCEEDED(hr))
{
hr = IStorage_CopyTo(copy.u.pstg, 0, NULL, NULL, med->u.pstg);
ReleaseStgMedium(&copy);
}
break;
}
default:
FIXME("Unhandled tymed - supported %x req tymed %x\n", supported, med->tymed);
hr = E_FAIL;
goto end;
}
end:
HeapFree(GetProcessHeap(), 0, enum_data);
if ( !CloseClipboard() ) hr = CLIPBRD_E_CANT_CLOSE;
return hr;
}
/************************************************************************
......
......@@ -1361,10 +1361,160 @@ static void test_nonole_clipboard(void)
OleUninitialize();
}
static void test_getdatahere(void)
{
HRESULT hr;
IDataObject *src, *get;
FORMATETC fmt;
STGMEDIUM med;
OleInitialize(NULL);
hr = DataObjectImpl_CreateComplex(&src);
ok(hr == S_OK, "got %08x\n", hr);
hr = OleSetClipboard(src);
ok(hr == S_OK, "got %08x\n", hr);
hr = OleGetClipboard(&get);
ok(hr == S_OK, "got %08x\n", hr);
/* global format -> global & stream */
DataObjectImpl_GetData_calls = 0;
DataObjectImpl_GetDataHere_calls = 0;
InitFormatEtc(fmt, CF_TEXT, TYMED_HGLOBAL);
med.pUnkForRelease = NULL;
med.tymed = TYMED_HGLOBAL;
U(med).hGlobal = GlobalAlloc(GMEM_MOVEABLE, 100);
hr = IDataObject_GetDataHere(get, &fmt, &med);
ok(hr == S_OK, "got %08x\n", hr);
ok(med.tymed == TYMED_HGLOBAL, "got %x\n", med.tymed);
ReleaseStgMedium(&med);
ok(DataObjectImpl_GetDataHere_calls == 1, "called %d\n", DataObjectImpl_GetDataHere_calls);
ok(DataObjectImpl_GetData_calls == 1, "called %d\n", DataObjectImpl_GetData_calls);
InitFormatEtc(fmt, CF_TEXT, 0);
med.pUnkForRelease = NULL;
med.tymed = TYMED_HGLOBAL;
U(med).hGlobal = GlobalAlloc(GMEM_MOVEABLE, 100);
hr = IDataObject_GetDataHere(get, &fmt, &med);
ok(hr == S_OK, "got %08x\n", hr);
ok(med.tymed == TYMED_HGLOBAL, "got %x\n", med.tymed);
ReleaseStgMedium(&med);
ok(DataObjectImpl_GetDataHere_calls == 2, "called %d\n", DataObjectImpl_GetDataHere_calls);
ok(DataObjectImpl_GetData_calls == 1, "called %d\n", DataObjectImpl_GetData_calls);
med.pUnkForRelease = NULL;
med.tymed = TYMED_HGLOBAL;
U(med).hGlobal = GlobalAlloc(GMEM_MOVEABLE, 1);
hr = IDataObject_GetDataHere(get, &fmt, &med);
ok(hr == E_FAIL, "got %08x\n", hr);
ok(med.tymed == TYMED_HGLOBAL, "got %x\n", med.tymed);
ReleaseStgMedium(&med);
ok(DataObjectImpl_GetDataHere_calls == 3, "called %d\n", DataObjectImpl_GetDataHere_calls);
ok(DataObjectImpl_GetData_calls == 1, "called %d\n", DataObjectImpl_GetData_calls);
med.pUnkForRelease = NULL;
med.tymed = TYMED_ISTREAM;
CreateStreamOnHGlobal(NULL, TRUE, &U(med).pstm);
hr = IDataObject_GetDataHere(get, &fmt, &med);
ok(hr == S_OK, "got %08x\n", hr);
ok(med.tymed == TYMED_ISTREAM, "got %x\n", med.tymed);
ReleaseStgMedium(&med);
ok(DataObjectImpl_GetDataHere_calls == 4, "called %d\n", DataObjectImpl_GetDataHere_calls);
ok(DataObjectImpl_GetData_calls == 1, "called %d\n", DataObjectImpl_GetData_calls);
med.pUnkForRelease = NULL;
med.tymed = TYMED_ISTORAGE;
StgCreateDocfile(NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_DELETEONRELEASE, 0, &U(med).pstg);
hr = IDataObject_GetDataHere(get, &fmt, &med);
ok(hr == E_FAIL, "got %08x\n", hr);
ok(med.tymed == TYMED_ISTORAGE, "got %x\n", med.tymed);
ReleaseStgMedium(&med);
ok(DataObjectImpl_GetDataHere_calls == 5, "called %d\n", DataObjectImpl_GetDataHere_calls);
ok(DataObjectImpl_GetData_calls == 1, "called %d\n", DataObjectImpl_GetData_calls);
InitFormatEtc(fmt, cf_stream, 0);
med.pUnkForRelease = NULL;
med.tymed = TYMED_HGLOBAL;
U(med).hGlobal = GlobalAlloc(GMEM_MOVEABLE, 100);
hr = IDataObject_GetDataHere(get, &fmt, &med);
ok(hr == S_OK, "got %08x\n", hr);
ok(med.tymed == TYMED_HGLOBAL, "got %x\n", med.tymed);
ReleaseStgMedium(&med);
ok(DataObjectImpl_GetDataHere_calls == 7, "called %d\n", DataObjectImpl_GetDataHere_calls);
ok(DataObjectImpl_GetData_calls == 2, "called %d\n", DataObjectImpl_GetData_calls);
med.pUnkForRelease = NULL;
med.tymed = TYMED_ISTREAM;
CreateStreamOnHGlobal(NULL, TRUE, &U(med).pstm);
hr = IDataObject_GetDataHere(get, &fmt, &med);
ok(hr == S_OK, "got %08x\n", hr);
ok(med.tymed == TYMED_ISTREAM, "got %x\n", med.tymed);
ReleaseStgMedium(&med);
ok(DataObjectImpl_GetDataHere_calls == 8, "called %d\n", DataObjectImpl_GetDataHere_calls);
ok(DataObjectImpl_GetData_calls == 2, "called %d\n", DataObjectImpl_GetData_calls);
med.pUnkForRelease = NULL;
med.tymed = TYMED_ISTORAGE;
StgCreateDocfile(NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_DELETEONRELEASE, 0, &U(med).pstg);
hr = IDataObject_GetDataHere(get, &fmt, &med);
ok(hr == E_FAIL, "got %08x\n", hr);
ok(med.tymed == TYMED_ISTORAGE, "got %x\n", med.tymed);
ReleaseStgMedium(&med);
ok(DataObjectImpl_GetDataHere_calls == 9, "called %d\n", DataObjectImpl_GetDataHere_calls);
ok(DataObjectImpl_GetData_calls == 2, "called %d\n", DataObjectImpl_GetData_calls);
InitFormatEtc(fmt, cf_storage, 0);
med.pUnkForRelease = NULL;
med.tymed = TYMED_HGLOBAL;
U(med).hGlobal = GlobalAlloc(GMEM_MOVEABLE, 3000);
hr = IDataObject_GetDataHere(get, &fmt, &med);
ok(hr == S_OK, "got %08x\n", hr);
ok(med.tymed == TYMED_HGLOBAL, "got %x\n", med.tymed);
ReleaseStgMedium(&med);
ok(DataObjectImpl_GetDataHere_calls == 11, "called %d\n", DataObjectImpl_GetDataHere_calls);
ok(DataObjectImpl_GetData_calls == 3, "called %d\n", DataObjectImpl_GetData_calls);
med.pUnkForRelease = NULL;
med.tymed = TYMED_ISTREAM;
CreateStreamOnHGlobal(NULL, TRUE, &U(med).pstm);
hr = IDataObject_GetDataHere(get, &fmt, &med);
ok(hr == S_OK, "got %08x\n", hr);
ok(med.tymed == TYMED_ISTREAM, "got %x\n", med.tymed);
ReleaseStgMedium(&med);
ok(DataObjectImpl_GetDataHere_calls == 12, "called %d\n", DataObjectImpl_GetDataHere_calls);
ok(DataObjectImpl_GetData_calls == 3, "called %d\n", DataObjectImpl_GetData_calls);
med.pUnkForRelease = NULL;
med.tymed = TYMED_ISTORAGE;
StgCreateDocfile(NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_DELETEONRELEASE, 0, &U(med).pstg);
hr = IDataObject_GetDataHere(get, &fmt, &med);
ok(hr == S_OK, "got %08x\n", hr);
ok(med.tymed == TYMED_ISTORAGE, "got %x\n", med.tymed);
ReleaseStgMedium(&med);
ok(DataObjectImpl_GetDataHere_calls == 13, "called %d\n", DataObjectImpl_GetDataHere_calls);
ok(DataObjectImpl_GetData_calls == 3, "called %d\n", DataObjectImpl_GetData_calls);
IDataObject_Release(get);
IDataObject_Release(src);
OleUninitialize();
}
START_TEST(clipboard)
{
test_set_clipboard();
test_consumer_refs();
test_flushed_getdata();
test_nonole_clipboard();
test_getdatahere();
}
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