From 08d4352f9bf26cae93b5b15a6d9d7f7964ff1281 Mon Sep 17 00:00:00 2001 From: Huw Davies Date: Fri, 17 Apr 2009 15:20:12 +0100 Subject: [PATCH] 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 c28b2f45708..7255323ee0d 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 4e5f4973017..17a30a7aa78 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(); }