Module: wine Branch: master Commit: 690202440ece0283b7ee8b2853a4c70a2a6e71a0 URL: http://source.winehq.org/git/wine.git/?a=commit;h=690202440ece0283b7ee8b2853...
Author: Huw Davies huw@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"); }