Huw Davies : ole32: Set the 'Ole Private Data' clipboard format.

Alexandre Julliard julliard at winehq.org
Thu Mar 26 11:05:48 CDT 2009


Module: wine
Branch: master
Commit: 690202440ece0283b7ee8b2853a4c70a2a6e71a0
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=690202440ece0283b7ee8b2853a4c70a2a6e71a0

Author: Huw Davies <huw at codeweavers.com>
Date:   Thu Mar 26 13:32:16 2009 +0000

ole32: Set the 'Ole Private Data' clipboard format.

---

 dlls/ole32/clipboard.c       |   92 ++++++++++++++++++++++++++++++++++++++---
 dlls/ole32/tests/clipboard.c |    1 -
 2 files changed, 85 insertions(+), 8 deletions(-)

diff --git a/dlls/ole32/clipboard.c b/dlls/ole32/clipboard.c
index 34946ff..5dbcca8 100644
--- a/dlls/ole32/clipboard.c
+++ b/dlls/ole32/clipboard.c
@@ -151,15 +151,26 @@ static ole_clipbrd* theOleClipboard;
 static const CHAR OLEClipbrd_WNDCLASS[] = "CLIPBRDWNDCLASS";
 
 static UINT dataobject_clipboard_format;
+static UINT ole_priv_data_clipboard_format;
 
-/*
- *  If we need to store state info we can store it here.
- *  For now we don't need this functionality.
- *
-typedef struct tagClipboardWindowInfo
+/* Structure of 'Ole Private Data' clipboard format */
+typedef struct
 {
-} ClipboardWindowInfo;
- */
+    FORMATETC fmtetc;
+    DWORD first_use;  /* Has this cf been added to the list already */
+    DWORD unk[2];
+} ole_priv_data_entry;
+
+typedef struct
+{
+    DWORD unk1;
+    DWORD size; /* in bytes of the entire structure */
+    DWORD unk2;
+    DWORD count; /* no. of format entries */
+    DWORD unk3[2];
+    ole_priv_data_entry entries[1]; /* array of size count */
+    /* then follows any DVTARGETDEVICE structures referenced in the FORMATETCs */
+} ole_priv_data;
 
 /*---------------------------------------------------------------------*
  *  Implementation of the internal IEnumFORMATETC interface returned by
@@ -1180,9 +1191,12 @@ static ole_clipbrd* OLEClipbrd_Construct(void)
 static void register_clipboard_formats(void)
 {
     static const WCHAR DataObjectW[] = { 'D','a','t','a','O','b','j','e','c','t',0 };
+    static const WCHAR OlePrivateDataW[] = { 'O','l','e',' ','P','r','i','v','a','t','e',' ','D','a','t','a',0 };
 
     if(!dataobject_clipboard_format)
         dataobject_clipboard_format = RegisterClipboardFormatW(DataObjectW);
+    if(!ole_priv_data_clipboard_format)
+        ole_priv_data_clipboard_format = RegisterClipboardFormatW(OlePrivateDataW);
 }
 
 /***********************************************************************
@@ -1271,6 +1285,16 @@ static HWND OLEClipbrd_CreateWindow(void)
   return hwnd;
 }
 
+static inline BOOL is_format_in_list(ole_priv_data_entry *entries, DWORD num, UINT cf)
+{
+    DWORD i;
+    for(i = 0; i < num; i++)
+        if(entries[i].fmtetc.cfFormat == cf)
+            return TRUE;
+
+    return FALSE;
+}
+
 /*********************************************************************
  *          set_clipboard_formats
  *
@@ -1285,12 +1309,47 @@ static HRESULT set_clipboard_formats(IDataObject *data)
     HRESULT hr;
     FORMATETC fmt;
     IEnumFORMATETC *enum_fmt;
+    HGLOBAL priv_data_handle;
+    DWORD target_offset;
+    ole_priv_data *priv_data;
+    DWORD count = 0, needed = sizeof(*priv_data), idx;
 
     hr = IDataObject_EnumFormatEtc(data, DATADIR_GET, &enum_fmt);
     if(FAILED(hr)) return hr;
 
     while(IEnumFORMATETC_Next(enum_fmt, 1, &fmt, NULL) == S_OK)
     {
+        count++;
+        needed += sizeof(priv_data->entries[0]);
+        if(fmt.ptd)
+        {
+            needed += fmt.ptd->tdSize;
+            CoTaskMemFree(fmt.ptd);
+        }
+    }
+
+    /* Windows pads the list with two empty ole_priv_data_entries, one
+     * after the entries array and one after the target device data.
+     * Allocating with zero init to zero these pads. */
+
+    needed += sizeof(priv_data->entries[0]); /* initialisation of needed includes one of these. */
+    priv_data_handle = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE | GMEM_ZEROINIT, needed);
+    priv_data = GlobalLock(priv_data_handle);
+
+    priv_data->unk1 = 0;
+    priv_data->size = needed;
+    priv_data->unk2 = 1;
+    priv_data->count = count;
+    priv_data->unk3[0] = 0;
+    priv_data->unk3[1] = 0;
+
+    IEnumFORMATETC_Reset(enum_fmt);
+
+    idx = 0;
+    target_offset = FIELD_OFFSET(ole_priv_data, entries[count + 1]); /* count entries + one pad. */
+
+    while(IEnumFORMATETC_Next(enum_fmt, 1, &fmt, NULL) == S_OK)
+    {
         if (fmt.tymed == TYMED_HGLOBAL)
         {
             char fmt_name[80];
@@ -1299,9 +1358,28 @@ static HRESULT set_clipboard_formats(IDataObject *data)
 
             SetClipboardData(fmt.cfFormat, NULL);
         }
+
+        priv_data->entries[idx].fmtetc = fmt;
+        if(fmt.ptd)
+        {
+            memcpy((char*)priv_data + target_offset, fmt.ptd, fmt.ptd->tdSize);
+            priv_data->entries[idx].fmtetc.ptd = (DVTARGETDEVICE*)target_offset;
+            target_offset += fmt.ptd->tdSize;
+            CoTaskMemFree(fmt.ptd);
+        }
+
+        priv_data->entries[idx].first_use = !is_format_in_list(priv_data->entries, idx, fmt.cfFormat);
+        priv_data->entries[idx].unk[0] = 0;
+        priv_data->entries[idx].unk[1] = 0;
+
+        idx++;
     }
 
     IEnumFORMATETC_Release(enum_fmt);
+
+    GlobalUnlock(priv_data_handle);
+    SetClipboardData(ole_priv_data_clipboard_format, priv_data_handle);
+
     return S_OK;
 }
 
diff --git a/dlls/ole32/tests/clipboard.c b/dlls/ole32/tests/clipboard.c
index 121783d..47921af 100644
--- a/dlls/ole32/tests/clipboard.c
+++ b/dlls/ole32/tests/clipboard.c
@@ -616,7 +616,6 @@ static void test_cf_dataobject(IDataObject *data)
     } while(cf);
     CloseClipboard();
     ok(found_dataobject, "didn't find cf_dataobject\n");
-todo_wine
     ok(found_priv_data, "didn't find cf_ole_priv_data\n");
 }
 




More information about the wine-cvs mailing list