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