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