Commit 08d4352f authored by Huw Davies's avatar Huw Davies Committed by Alexandre Julliard

ole32: Add support for enumerating non-ole clipboard formats.

parent 575b0e14
......@@ -132,26 +132,6 @@ static inline DWORD_PTR td_get_offs(ole_priv_data *data, DWORD idx)
return (char*)data->entries[idx].fmtetc.ptd - (char*)data;
}
/*****************************************************************************
* create_empty_priv_data
*
* Create an empty data structure. The only thing that really matters
* here is setting count and size members. This is used by the enumerator as a
* convenience when there's an empty list.
*/
static HRESULT create_empty_priv_data(ole_priv_data **data)
{
ole_priv_data *ptr;
*data = NULL;
ptr = HeapAlloc(GetProcessHeap(), 0, sizeof(*ptr));
if(!ptr) return E_OUTOFMEMORY;
ptr->size = sizeof(*ptr);
ptr->count = 0;
*data = ptr;
return S_OK;
}
/****************************************************************************
* Consumer snapshot. Represents the state of the ole clipboard
* returned by OleGetClipboard().
......@@ -939,6 +919,26 @@ end:
return hr;
}
static DWORD get_tymed_from_nonole_cf(UINT cf)
{
if(cf >= 0xc000) return TYMED_ISTREAM | TYMED_HGLOBAL;
switch(cf)
{
case CF_TEXT:
case CF_OEMTEXT:
case CF_UNICODETEXT:
return TYMED_ISTREAM | TYMED_HGLOBAL;
case CF_ENHMETAFILE:
return TYMED_ENHMF;
case CF_METAFILEPICT:
return TYMED_MFPICT;
default:
FIXME("returning TYMED_NULL for cf %04x\n", cf);
return TYMED_NULL;
}
}
/***********************************************************
* get_priv_data
*
......@@ -948,6 +948,7 @@ static HRESULT get_priv_data(ole_priv_data **data)
{
HGLOBAL handle;
HRESULT hr = S_OK;
ole_priv_data *ret = NULL;
*data = NULL;
......@@ -960,24 +961,55 @@ static HRESULT get_priv_data(ole_priv_data **data)
DWORD i;
/* FIXME: sanity check on size */
*data = HeapAlloc(GetProcessHeap(), 0, src->size);
if(!*data)
ret = HeapAlloc(GetProcessHeap(), 0, src->size);
if(!ret)
{
GlobalUnlock(handle);
return E_OUTOFMEMORY;
}
memcpy(*data, src, src->size);
memcpy(ret, src, src->size);
GlobalUnlock(handle);
/* Fixup any target device offsets to ptrs */
for(i = 0; i < (*data)->count; i++)
(*data)->entries[i].fmtetc.ptd =
td_offs_to_ptr(*data, (DWORD_PTR)(*data)->entries[i].fmtetc.ptd);
for(i = 0; i < ret->count; i++)
ret->entries[i].fmtetc.ptd =
td_offs_to_ptr(ret, (DWORD_PTR) ret->entries[i].fmtetc.ptd);
}
}
if(!*data) hr = create_empty_priv_data(data);
if(!ret) /* Non-ole data */
{
UINT cf;
DWORD count = 0, idx, size = FIELD_OFFSET(ole_priv_data, entries);
for(cf = 0; (cf = EnumClipboardFormats(cf)) != 0; count++)
{
char buf[100];
GetClipboardFormatNameA(cf, buf, sizeof(buf));
TRACE("\tcf %04x %s\n", cf, buf);
;
}
TRACE("count %d\n", count);
size += count * sizeof(ret->entries[0]);
/* There are holes in fmtetc so zero init */
ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
if(!ret) return E_OUTOFMEMORY;
ret->size = size;
ret->count = count;
for(cf = 0, idx = 0; (cf = EnumClipboardFormats(cf)) != 0; idx++)
{
ret->entries[idx].fmtetc.cfFormat = cf;
ret->entries[idx].fmtetc.ptd = NULL;
ret->entries[idx].fmtetc.dwAspect = DVASPECT_CONTENT;
ret->entries[idx].fmtetc.lindex = -1;
ret->entries[idx].fmtetc.tymed = get_tymed_from_nonole_cf(cf);
ret->entries[idx].first_use = 1;
}
}
*data = ret;
return hr;
}
......
......@@ -1163,9 +1163,157 @@ static void test_flushed_getdata(void)
OleUninitialize();
}
static HGLOBAL create_text(void)
{
HGLOBAL h = GlobalAlloc(GMEM_DDESHARE|GMEM_MOVEABLE, 5);
char *p = GlobalLock(h);
strcpy(p, "test");
GlobalUnlock(h);
return h;
}
static HENHMETAFILE create_emf(void)
{
const RECT rect = {0, 0, 100, 100};
HDC hdc = CreateEnhMetaFileA(NULL, NULL, &rect, "HENHMETAFILE Ole Clipboard Test\0Test\0\0");
ExtTextOutA(hdc, 0, 0, ETO_OPAQUE, &rect, "Test String", strlen("Test String"), NULL);
return CloseEnhMetaFile(hdc);
}
static void test_nonole_clipboard(void)
{
HRESULT hr;
BOOL r;
IDataObject *get;
IEnumFORMATETC *enum_fmt;
FORMATETC fmt;
HGLOBAL h, hblob, htext;
HENHMETAFILE emf;
r = OpenClipboard(NULL);
ok(r, "gle %d\n", GetLastError());
r = EmptyClipboard();
ok(r, "gle %d\n", GetLastError());
r = CloseClipboard();
ok(r, "gle %d\n", GetLastError());
OleInitialize(NULL);
/* empty clipboard */
hr = OleGetClipboard(&get);
ok(hr == S_OK, "got %08x\n", hr);
hr = IDataObject_EnumFormatEtc(get, DATADIR_GET, &enum_fmt);
ok(hr == S_OK, "got %08x\n", hr);
hr = IEnumFORMATETC_Next(enum_fmt, 1, &fmt, NULL);
ok(hr == S_FALSE, "got %08x\n", hr);
IEnumFORMATETC_Release(enum_fmt);
IDataObject_Release(get);
/* set a user defined clipboard type */
htext = create_text();
hblob = GlobalAlloc(GMEM_DDESHARE|GMEM_MOVEABLE|GMEM_ZEROINIT, 10);
emf = create_emf();
r = OpenClipboard(NULL);
ok(r, "gle %d\n", GetLastError());
h = SetClipboardData(CF_TEXT, htext);
ok(h == htext, "got %p\n", h);
h = SetClipboardData(cf_onemore, hblob);
ok(h == hblob, "got %p\n", h);
h = SetClipboardData(CF_ENHMETAFILE, emf);
ok(h == emf, "got %p\n", h);
r = CloseClipboard();
ok(r, "gle %d\n", GetLastError());
hr = OleGetClipboard(&get);
ok(hr == S_OK, "got %08x\n", hr);
hr = IDataObject_EnumFormatEtc(get, DATADIR_GET, &enum_fmt);
ok(hr == S_OK, "got %08x\n", hr);
hr = IEnumFORMATETC_Next(enum_fmt, 1, &fmt, NULL);
ok(hr == S_OK, "got %08x\n", hr);
ok(fmt.cfFormat == CF_TEXT, "cf %04x\n", fmt.cfFormat);
ok(fmt.ptd == NULL, "ptd %p\n", fmt.ptd);
ok(fmt.dwAspect == DVASPECT_CONTENT, "aspect %x\n", fmt.dwAspect);
ok(fmt.lindex == -1, "lindex %d\n", fmt.lindex);
ok(fmt.tymed == (TYMED_ISTREAM | TYMED_HGLOBAL), "tymed %x\n", fmt.tymed);
hr = IEnumFORMATETC_Next(enum_fmt, 1, &fmt, NULL);
ok(hr == S_OK, "got %08x\n", hr);
ok(fmt.cfFormat == cf_onemore, "cf %04x\n", fmt.cfFormat);
ok(fmt.ptd == NULL, "ptd %p\n", fmt.ptd);
ok(fmt.dwAspect == DVASPECT_CONTENT, "aspect %x\n", fmt.dwAspect);
ok(fmt.lindex == -1, "lindex %d\n", fmt.lindex);
ok(fmt.tymed == (TYMED_ISTREAM | TYMED_HGLOBAL), "tymed %x\n", fmt.tymed);
hr = IEnumFORMATETC_Next(enum_fmt, 1, &fmt, NULL);
ok(hr == S_OK, "got %08x\n", hr);
ok(fmt.cfFormat == CF_ENHMETAFILE, "cf %04x\n", fmt.cfFormat);
ok(fmt.ptd == NULL, "ptd %p\n", fmt.ptd);
ok(fmt.dwAspect == DVASPECT_CONTENT, "aspect %x\n", fmt.dwAspect);
ok(fmt.lindex == -1, "lindex %d\n", fmt.lindex);
ok(fmt.tymed == TYMED_ENHMF, "tymed %x\n", fmt.tymed);
hr = IEnumFORMATETC_Next(enum_fmt, 1, &fmt, NULL);
ok(hr == S_OK, "got %08x\n", hr); /* User32 adds some synthesised formats */
todo_wine ok(fmt.cfFormat == CF_LOCALE, "cf %04x\n", fmt.cfFormat);
if(fmt.cfFormat == CF_LOCALE)
{
ok(fmt.ptd == NULL, "ptd %p\n", fmt.ptd);
ok(fmt.dwAspect == DVASPECT_CONTENT, "aspect %x\n", fmt.dwAspect);
ok(fmt.lindex == -1, "lindex %d\n", fmt.lindex);
ok(fmt.tymed == (TYMED_ISTREAM | TYMED_HGLOBAL), "tymed %x\n", fmt.tymed);
hr = IEnumFORMATETC_Next(enum_fmt, 1, &fmt, NULL);
ok(hr == S_OK, "got %08x\n", hr);
}
ok(fmt.cfFormat == CF_OEMTEXT, "cf %04x\n", fmt.cfFormat);
ok(fmt.ptd == NULL, "ptd %p\n", fmt.ptd);
ok(fmt.dwAspect == DVASPECT_CONTENT, "aspect %x\n", fmt.dwAspect);
ok(fmt.lindex == -1, "lindex %d\n", fmt.lindex);
ok(fmt.tymed == (TYMED_ISTREAM | TYMED_HGLOBAL), "tymed %x\n", fmt.tymed);
hr = IEnumFORMATETC_Next(enum_fmt, 1, &fmt, NULL);
ok(hr == S_OK, "got %08x\n", hr);
ok(fmt.cfFormat == CF_UNICODETEXT, "cf %04x\n", fmt.cfFormat);
ok(fmt.ptd == NULL, "ptd %p\n", fmt.ptd);
ok(fmt.dwAspect == DVASPECT_CONTENT, "aspect %x\n", fmt.dwAspect);
ok(fmt.lindex == -1, "lindex %d\n", fmt.lindex);
ok(fmt.tymed == (TYMED_ISTREAM | TYMED_HGLOBAL), "tymed %x\n", fmt.tymed);
hr = IEnumFORMATETC_Next(enum_fmt, 1, &fmt, NULL);
ok(hr == S_OK, "got %08x\n", hr);
ok(fmt.cfFormat == CF_METAFILEPICT, "cf %04x\n", fmt.cfFormat);
ok(fmt.ptd == NULL, "ptd %p\n", fmt.ptd);
ok(fmt.dwAspect == DVASPECT_CONTENT, "aspect %x\n", fmt.dwAspect);
ok(fmt.lindex == -1, "lindex %d\n", fmt.lindex);
ok(fmt.tymed == TYMED_MFPICT, "tymed %x\n", fmt.tymed);
hr = IEnumFORMATETC_Next(enum_fmt, 1, &fmt, NULL);
ok(hr == S_FALSE, "got %08x\n", hr);
IEnumFORMATETC_Release(enum_fmt);
IDataObject_Release(get);
r = OpenClipboard(NULL);
ok(r, "gle %d\n", GetLastError());
r = EmptyClipboard();
ok(r, "gle %d\n", GetLastError());
r = CloseClipboard();
ok(r, "gle %d\n", GetLastError());
OleUninitialize();
}
START_TEST(clipboard)
{
test_set_clipboard();
test_consumer_refs();
test_flushed_getdata();
test_nonole_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