Huw Davies : ole32: Add support for enumerating non-ole clipboard formats.
Alexandre Julliard
julliard at winehq.org
Tue Apr 21 11:45:44 CDT 2009
Module: wine
Branch: master
Commit: 08d4352f9bf26cae93b5b15a6d9d7f7964ff1281
URL: http://source.winehq.org/git/wine.git/?a=commit;h=08d4352f9bf26cae93b5b15a6d9d7f7964ff1281
Author: Huw Davies <huw at codeweavers.com>
Date: Fri Apr 17 15:20:12 2009 +0100
ole32: Add support for enumerating non-ole clipboard formats.
---
dlls/ole32/clipboard.c | 86 +++++++++++++++++--------
dlls/ole32/tests/clipboard.c | 148 ++++++++++++++++++++++++++++++++++++++++++
2 files changed, 207 insertions(+), 27 deletions(-)
diff --git a/dlls/ole32/clipboard.c b/dlls/ole32/clipboard.c
index c28b2f4..7255323 100644
--- a/dlls/ole32/clipboard.c
+++ b/dlls/ole32/clipboard.c
@@ -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;
}
diff --git a/dlls/ole32/tests/clipboard.c b/dlls/ole32/tests/clipboard.c
index 4e5f497..17a30a7 100644
--- a/dlls/ole32/tests/clipboard.c
+++ b/dlls/ole32/tests/clipboard.c
@@ -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();
}
More information about the wine-cvs
mailing list