2 * OLE 2 clipboard support
4 * Copyright 1999 Noel Borthwick <noel@macadamian.com>
5 * Copyright 2000 Abey George <abey@macadamian.com>
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 * This file contains the implementation for the OLE Clipboard and its
23 * internal interfaces. The OLE clipboard interacts with an IDataObject
24 * interface via the OleSetClipboard, OleGetClipboard and
25 * OleIsCurrentClipboard API's. An internal IDataObject delegates
26 * to a client supplied IDataObject or the WIN32 clipboard API depending
27 * on whether OleSetClipboard has been invoked.
28 * Here are some operating scenarios:
30 * 1. OleSetClipboard called: In this case the internal IDataObject
31 * delegates to the client supplied IDataObject. Additionally OLE takes
32 * ownership of the Windows clipboard and any HGLOCBAL IDataObject
33 * items are placed on the Windows clipboard. This allows non OLE aware
34 * applications to access these. A local WinProc fields WM_RENDERFORMAT
35 * and WM_RENDERALLFORMATS messages in this case.
37 * 2. OleGetClipboard called without previous OleSetClipboard. Here the internal
38 * IDataObject functionality wraps around the WIN32 clipboard API.
40 * 3. OleGetClipboard called after previous OleSetClipboard. Here the internal
41 * IDataObject delegates to the source IDataObjects functionality directly,
42 * thereby bypassing the Windows clipboard.
44 * Implementation references : Inside OLE 2'nd edition by Kraig Brockschmidt
47 * - Support for pasting between different processes. OLE clipboard support
48 * currently works only for in process copy and paste. Since we internally
49 * store a pointer to the source's IDataObject and delegate to that, this
50 * will fail if the IDataObject client belongs to a different process.
51 * - IDataObject::GetDataHere is not implemented
52 * - OleFlushClipboard needs to additionally handle TYMED_IStorage media
53 * by copying the storage into global memory. Subsequently the default
54 * data object exposed through OleGetClipboard must convert this TYMED_HGLOBAL
55 * back to TYMED_IStorage.
56 * - OLE1 compatibility formats to be synthesized from OLE2 formats and put on
57 * clipboard in OleSetClipboard.
67 #define NONAMELESSUNION
68 #define NONAMELESSSTRUCT
77 #include "wine/debug.h"
80 #include "storage32.h"
82 #include "compobj_private.h"
84 WINE_DEFAULT_DEBUG_CHANNEL(ole);
86 #define HANDLE_ERROR(err) do { hr = err; TRACE("(HRESULT=%x)\n", (HRESULT)err); goto CLEANUP; } while (0)
88 /* Structure of 'Ole Private Data' clipboard format */
92 DWORD first_use; /* Has this cf been added to the list already */
94 } ole_priv_data_entry;
99 DWORD size; /* in bytes of the entire structure */
101 DWORD count; /* no. of format entries */
103 ole_priv_data_entry entries[1]; /* array of size count */
104 /* then follows any DVTARGETDEVICE structures referenced in the FORMATETCs */
107 /*****************************************************************************
108 * create_empty_priv_data
110 * Create an empty data structure. The only thing that really matters
111 * here is setting count and size members. This is used by the enumerator as a
112 * convenience when there's an empty list.
114 static HRESULT create_empty_priv_data(ole_priv_data **data)
119 ptr = HeapAlloc(GetProcessHeap(), 0, sizeof(*ptr));
120 if(!ptr) return E_OUTOFMEMORY;
121 ptr->size = sizeof(*ptr);
128 /****************************************************************************
131 typedef struct ole_clipbrd
133 const IDataObjectVtbl* lpvtbl; /* Exposed IDataObject vtable */
137 HWND window; /* Hidden clipboard window */
138 IDataObject *src_data; /* Source object passed to OleSetClipboard */
139 ole_priv_data *cached_enum; /* Cached result from the enumeration of src data object */
140 IStream *marshal_data; /* Stream onto which to marshal src_data */
143 static inline ole_clipbrd *impl_from_IDataObject(IDataObject *iface)
145 return (ole_clipbrd*)((char*)iface - FIELD_OFFSET(ole_clipbrd, lpvtbl));
148 typedef struct PresentationDataHeader
151 DWORD dwObjectExtentX;
152 DWORD dwObjectExtentY;
154 } PresentationDataHeader;
157 * The one and only ole_clipbrd object which is created by OLEClipbrd_Initialize()
159 static ole_clipbrd* theOleClipboard;
161 static inline HRESULT get_ole_clipbrd(ole_clipbrd **clipbrd)
163 struct oletls *info = COM_CurrentInfo();
167 return CO_E_NOTINITIALIZED;
168 *clipbrd = theOleClipboard;
174 * Name of our registered OLE clipboard window class
176 static const WCHAR clipbrd_wndclass[] = {'C','L','I','P','B','R','D','W','N','D','C','L','A','S','S',0};
178 static const WCHAR wine_marshal_dataobject[] = {'W','i','n','e',' ','m','a','r','s','h','a','l',' ','d','a','t','a','o','b','j','e','c','t',0};
180 static UINT dataobject_clipboard_format;
181 static UINT ole_priv_data_clipboard_format;
182 static UINT embed_source_clipboard_format;
184 static inline char *dump_fmtetc(FORMATETC *fmt)
186 static char buf[100];
188 snprintf(buf, sizeof(buf), "cf %04x ptd %p aspect %x lindex %d tymed %x",
189 fmt->cfFormat, fmt->ptd, fmt->dwAspect, fmt->lindex, fmt->tymed);
193 /*---------------------------------------------------------------------*
194 * Implementation of the internal IEnumFORMATETC interface returned by
195 * the OLE clipboard's IDataObject.
196 *---------------------------------------------------------------------*/
198 typedef struct enum_fmtetc
200 const IEnumFORMATETCVtbl *lpVtbl;
203 UINT pos; /* current enumerator position */
207 static inline enum_fmtetc *impl_from_IEnumFORMATETC(IEnumFORMATETC *iface)
209 return (enum_fmtetc*)((char*)iface - FIELD_OFFSET(enum_fmtetc, lpVtbl));
212 /************************************************************************
213 * OLEClipbrd_IEnumFORMATETC_QueryInterface (IUnknown)
215 * See Windows documentation for more details on IUnknown methods.
217 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_QueryInterface
218 (LPENUMFORMATETC iface, REFIID riid, LPVOID* ppvObj)
220 enum_fmtetc *This = impl_from_IEnumFORMATETC(iface);
222 TRACE("(%p)->(IID: %s, %p)\n", This, debugstr_guid(riid), ppvObj);
226 if(IsEqualIID(riid, &IID_IUnknown) ||
227 IsEqualIID(riid, &IID_IEnumFORMATETC))
234 IEnumFORMATETC_AddRef((IEnumFORMATETC*)*ppvObj);
235 TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
239 TRACE("-- Interface: E_NOINTERFACE\n");
240 return E_NOINTERFACE;
243 /************************************************************************
244 * OLEClipbrd_IEnumFORMATETC_AddRef (IUnknown)
247 static ULONG WINAPI OLEClipbrd_IEnumFORMATETC_AddRef(LPENUMFORMATETC iface)
249 enum_fmtetc *This = impl_from_IEnumFORMATETC(iface);
250 TRACE("(%p)->(count=%u)\n",This, This->ref);
252 return InterlockedIncrement(&This->ref);
255 /************************************************************************
256 * OLEClipbrd_IEnumFORMATETC_Release (IUnknown)
258 * See Windows documentation for more details on IUnknown methods.
260 static ULONG WINAPI OLEClipbrd_IEnumFORMATETC_Release(LPENUMFORMATETC iface)
262 enum_fmtetc *This = impl_from_IEnumFORMATETC(iface);
265 TRACE("(%p)->(count=%u)\n",This, This->ref);
267 ref = InterlockedDecrement(&This->ref);
270 TRACE("() - destroying IEnumFORMATETC(%p)\n",This);
271 HeapFree(GetProcessHeap(), 0, This->data);
272 HeapFree(GetProcessHeap(), 0, This);
277 /************************************************************************
278 * OLEClipbrd_IEnumFORMATETC_Next (IEnumFORMATETC)
280 * Standard enumerator members for IEnumFORMATETC
282 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Next
283 (LPENUMFORMATETC iface, ULONG celt, FORMATETC *rgelt, ULONG *pceltFethed)
285 enum_fmtetc *This = impl_from_IEnumFORMATETC(iface);
287 HRESULT hres = S_FALSE;
289 TRACE("(%p)->(pos=%u)\n", This, This->pos);
291 if (This->pos < This->data->count)
293 cfetch = This->data->count - This->pos;
300 for(i = 0; i < cfetch; i++)
302 rgelt[i] = This->data->entries[This->pos++].fmtetc;
305 DVTARGETDEVICE *target = (DVTARGETDEVICE *)((char *)This->data + (DWORD)rgelt[i].ptd);
306 rgelt[i].ptd = CoTaskMemAlloc(target->tdSize);
307 if(!rgelt[i].ptd) return E_OUTOFMEMORY;
308 memcpy(rgelt[i].ptd, target, target->tdSize);
319 *pceltFethed = cfetch;
325 /************************************************************************
326 * OLEClipbrd_IEnumFORMATETC_Skip (IEnumFORMATETC)
328 * Standard enumerator members for IEnumFORMATETC
330 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Skip(LPENUMFORMATETC iface, ULONG celt)
332 enum_fmtetc *This = impl_from_IEnumFORMATETC(iface);
333 TRACE("(%p)->(num=%u)\n", This, celt);
336 if (This->pos > This->data->count)
338 This->pos = This->data->count;
344 /************************************************************************
345 * OLEClipbrd_IEnumFORMATETC_Reset (IEnumFORMATETC)
347 * Standard enumerator members for IEnumFORMATETC
349 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Reset(LPENUMFORMATETC iface)
351 enum_fmtetc *This = impl_from_IEnumFORMATETC(iface);
352 TRACE("(%p)->()\n", This);
358 static HRESULT enum_fmtetc_construct(ole_priv_data *data, UINT pos, IEnumFORMATETC **obj);
360 /************************************************************************
361 * OLEClipbrd_IEnumFORMATETC_Clone (IEnumFORMATETC)
363 * Standard enumerator members for IEnumFORMATETC
365 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Clone
366 (LPENUMFORMATETC iface, LPENUMFORMATETC* obj)
368 enum_fmtetc *This = impl_from_IEnumFORMATETC(iface);
369 ole_priv_data *new_data;
371 TRACE("(%p)->(%p)\n", This, obj);
373 if ( !obj ) return E_INVALIDARG;
376 new_data = HeapAlloc(GetProcessHeap(), 0, This->data->size);
377 if(!new_data) return E_OUTOFMEMORY;
379 return enum_fmtetc_construct(new_data, This->pos, obj);
382 static const IEnumFORMATETCVtbl efvt =
384 OLEClipbrd_IEnumFORMATETC_QueryInterface,
385 OLEClipbrd_IEnumFORMATETC_AddRef,
386 OLEClipbrd_IEnumFORMATETC_Release,
387 OLEClipbrd_IEnumFORMATETC_Next,
388 OLEClipbrd_IEnumFORMATETC_Skip,
389 OLEClipbrd_IEnumFORMATETC_Reset,
390 OLEClipbrd_IEnumFORMATETC_Clone
393 /************************************************************************
394 * enum_fmtetc_construct
396 * Creates an IEnumFORMATETC enumerator from ole_priv_data which it then owns.
398 static HRESULT enum_fmtetc_construct(ole_priv_data *data, UINT pos, IEnumFORMATETC **obj)
403 ef = HeapAlloc(GetProcessHeap(), 0, sizeof(*ef));
404 if (!ef) return E_OUTOFMEMORY;
411 TRACE("(%p)->()\n", ef);
412 *obj = (IEnumFORMATETC *)ef;
416 /***********************************************************************
419 * Helper method to duplicate an HGLOBAL chunk of memory
421 static HRESULT dup_global_mem( HGLOBAL src, DWORD flags, HGLOBAL *dst )
423 void *src_ptr, *dst_ptr;
427 if ( !src ) return S_FALSE;
429 size = GlobalSize(src);
431 *dst = GlobalAlloc( flags, size );
432 if ( !*dst ) return E_OUTOFMEMORY;
434 src_ptr = GlobalLock(src);
435 dst_ptr = GlobalLock(*dst);
437 memcpy(dst_ptr, src_ptr, size);
445 /************************************************************
446 * render_embed_source_hack
448 * This is clearly a hack and has no place in the clipboard code.
451 static HRESULT render_embed_source_hack(IDataObject *data, LPFORMATETC fmt)
454 HGLOBAL hStorage = 0;
456 ILockBytes *ptrILockBytes;
458 memset(&std, 0, sizeof(STGMEDIUM));
459 std.tymed = fmt->tymed = TYMED_ISTORAGE;
461 hStorage = GlobalAlloc(GMEM_SHARE|GMEM_MOVEABLE, 0);
462 if (hStorage == NULL) return E_OUTOFMEMORY;
463 hr = CreateILockBytesOnHGlobal(hStorage, FALSE, &ptrILockBytes);
464 hr = StgCreateDocfileOnILockBytes(ptrILockBytes, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &std.u.pstg);
465 ILockBytes_Release(ptrILockBytes);
467 if (FAILED(hr = IDataObject_GetDataHere(theOleClipboard->src_data, fmt, &std)))
469 WARN("() : IDataObject_GetDataHere failed to render clipboard data! (%x)\n", hr);
470 GlobalFree(hStorage);
474 if (1) /* check whether the presentation data is already -not- present */
478 METAFILEPICT *mfp = 0;
480 fmt2.cfFormat = CF_METAFILEPICT;
482 fmt2.dwAspect = DVASPECT_CONTENT;
484 fmt2.tymed = TYMED_MFPICT;
486 memset(&std2, 0, sizeof(STGMEDIUM));
487 std2.tymed = TYMED_MFPICT;
489 /* Get the metafile picture out of it */
491 if (SUCCEEDED(hr = IDataObject_GetData(theOleClipboard->src_data, &fmt2, &std2)))
493 mfp = GlobalLock(std2.u.hGlobal);
498 OLECHAR name[]={ 2, 'O', 'l', 'e', 'P', 'r', 'e', 's', '0', '0', '0', 0};
499 IStream *pStream = 0;
501 PresentationDataHeader pdh;
505 CHAR strOleTypeName[51];
506 BYTE OlePresStreamHeader [] =
508 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00,
509 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
510 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
511 0x00, 0x00, 0x00, 0x00
514 nSize = GetMetaFileBitsEx(mfp->hMF, 0, NULL);
516 memset(&pdh, 0, sizeof(PresentationDataHeader));
517 memcpy(&pdh, OlePresStreamHeader, sizeof(OlePresStreamHeader));
519 pdh.dwObjectExtentX = mfp->xExt;
520 pdh.dwObjectExtentY = mfp->yExt;
523 hr = IStorage_CreateStream(std.u.pstg, name, STGM_CREATE|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, 0, &pStream);
525 hr = IStream_Write(pStream, &pdh, sizeof(PresentationDataHeader), NULL);
527 mfBits = HeapAlloc(GetProcessHeap(), 0, nSize);
528 nSize = GetMetaFileBitsEx(mfp->hMF, nSize, mfBits);
530 hr = IStream_Write(pStream, mfBits, nSize, NULL);
532 IStream_Release(pStream);
534 HeapFree(GetProcessHeap(), 0, mfBits);
536 GlobalUnlock(std2.u.hGlobal);
537 ReleaseStgMedium(&std2);
539 ReadClassStg(std.u.pstg, &clsID);
540 ProgIDFromCLSID(&clsID, &strProgID);
542 WideCharToMultiByte( CP_ACP, 0, strProgID, -1, strOleTypeName, sizeof(strOleTypeName), NULL, NULL );
543 OLECONVERT_CreateOleStream(std.u.pstg);
544 OLECONVERT_CreateCompObjStream(std.u.pstg, strOleTypeName);
548 if ( !SetClipboardData( fmt->cfFormat, hStorage ) )
550 WARN("() : Failed to set rendered clipboard data into clipboard!\n");
551 GlobalFree(hStorage);
552 hr = CLIPBRD_E_CANT_SET;
555 ReleaseStgMedium(&std);
559 /************************************************************************
560 * find_format_in_list
562 * Returns the first entry that matches the provided clipboard format.
564 static inline ole_priv_data_entry *find_format_in_list(ole_priv_data_entry *entries, DWORD num, UINT cf)
567 for(i = 0; i < num; i++)
568 if(entries[i].fmtetc.cfFormat == cf)
574 /***************************************************************************
575 * get_data_from_storage
577 * Returns storage data in an HGLOBAL.
579 static HRESULT get_data_from_storage(IDataObject *data, FORMATETC *fmt, HGLOBAL *mem)
590 h = GlobalAlloc( GMEM_DDESHARE|GMEM_MOVEABLE, 0 );
591 if(!h) return E_OUTOFMEMORY;
593 hr = CreateILockBytesOnHGlobal(h, FALSE, &lbs);
596 hr = StgCreateDocfileOnILockBytes(lbs, STGM_CREATE|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &stg);
597 ILockBytes_Release(lbs);
606 med.tymed = stg_fmt.tymed = TYMED_ISTORAGE;
608 med.pUnkForRelease = NULL;
610 hr = IDataObject_GetDataHere(data, &stg_fmt, &med);
614 hr = IDataObject_GetData(data, &stg_fmt, &med);
615 if(FAILED(hr)) goto end;
617 hr = IStorage_CopyTo(med.u.pstg, 0, NULL, NULL, stg);
618 ReleaseStgMedium(&med);
619 if(FAILED(hr)) goto end;
624 IStorage_Release(stg);
625 if(FAILED(hr)) GlobalFree(h);
629 /***************************************************************************
630 * get_data_from_stream
632 * Returns stream data in an HGLOBAL.
634 static HRESULT get_data_from_stream(IDataObject *data, FORMATETC *fmt, HGLOBAL *mem)
644 h = GlobalAlloc( GMEM_DDESHARE|GMEM_MOVEABLE, 0 );
645 if(!h) return E_OUTOFMEMORY;
647 hr = CreateStreamOnHGlobal(h, FALSE, &stm);
648 if(FAILED(hr)) goto error;
651 med.tymed = stm_fmt.tymed = TYMED_ISTREAM;
653 med.pUnkForRelease = NULL;
655 hr = IDataObject_GetDataHere(data, &stm_fmt, &med);
662 hr = IDataObject_GetData(data, &stm_fmt, &med);
663 if(FAILED(hr)) goto error;
666 IStream_Seek(med.u.pstm, offs, STREAM_SEEK_CUR, &pos);
667 IStream_Seek(med.u.pstm, offs, STREAM_SEEK_SET, NULL);
668 hr = IStream_CopyTo(med.u.pstm, stm, pos, NULL, NULL);
669 ReleaseStgMedium(&med);
670 if(FAILED(hr)) goto error;
673 IStream_Release(stm);
677 if(stm) IStream_Release(stm);
682 /***************************************************************************
683 * get_data_from_global
685 * Returns global data in an HGLOBAL.
687 static HRESULT get_data_from_global(IDataObject *data, FORMATETC *fmt, HGLOBAL *mem)
697 mem_fmt.tymed = TYMED_HGLOBAL;
699 hr = IDataObject_GetData(data, &mem_fmt, &med);
700 if(FAILED(hr)) return hr;
702 hr = dup_global_mem(med.u.hGlobal, GMEM_DDESHARE|GMEM_MOVEABLE, &h);
704 if(SUCCEEDED(hr)) *mem = h;
706 ReleaseStgMedium(&med);
711 /***********************************************************************
714 * Render the clipboard data. Note that this call will delegate to the
715 * source data object.
717 static HRESULT render_format(IDataObject *data, LPFORMATETC fmt)
719 HGLOBAL clip_data = NULL;
722 /* Embed source hack */
723 if(fmt->cfFormat == embed_source_clipboard_format)
725 return render_embed_source_hack(data, fmt);
728 if(fmt->tymed & TYMED_ISTORAGE)
730 hr = get_data_from_storage(data, fmt, &clip_data);
732 else if(fmt->tymed & TYMED_ISTREAM)
734 hr = get_data_from_stream(data, fmt, &clip_data);
736 else if(fmt->tymed & TYMED_HGLOBAL)
738 hr = get_data_from_global(data, fmt, &clip_data);
742 FIXME("Unhandled tymed %x\n", fmt->tymed);
748 if ( !SetClipboardData(fmt->cfFormat, clip_data) )
750 WARN("() : Failed to set rendered clipboard data into clipboard!\n");
751 GlobalFree(clip_data);
752 hr = CLIPBRD_E_CANT_SET;
759 /*---------------------------------------------------------------------*
760 * Implementation of the internal IDataObject interface exposed by
762 *---------------------------------------------------------------------*/
765 /************************************************************************
766 * OLEClipbrd_IDataObject_QueryInterface (IUnknown)
768 * See Windows documentation for more details on IUnknown methods.
770 static HRESULT WINAPI OLEClipbrd_IDataObject_QueryInterface(
775 ole_clipbrd *This = impl_from_IDataObject(iface);
776 TRACE("(%p)->(IID:%s, %p)\n", This, debugstr_guid(riid), ppvObject);
778 if ( (This==0) || (ppvObject==0) )
783 if (IsEqualIID(&IID_IUnknown, riid) ||
784 IsEqualIID(&IID_IDataObject, riid))
790 WARN( "() : asking for unsupported interface %s\n", debugstr_guid(riid));
791 return E_NOINTERFACE;
794 IUnknown_AddRef((IUnknown*)*ppvObject);
799 /************************************************************************
800 * OLEClipbrd_IDataObject_AddRef (IUnknown)
802 * See Windows documentation for more details on IUnknown methods.
804 static ULONG WINAPI OLEClipbrd_IDataObject_AddRef(
807 ole_clipbrd *This = impl_from_IDataObject(iface);
809 TRACE("(%p)->(count=%u)\n",This, This->ref);
811 return InterlockedIncrement(&This->ref);
814 /***********************************************************************
815 * destroy_clipbrd_window
816 * Destroy the clipboard window and unregister its class
818 static void destroy_clipbrd_window(HWND hwnd)
820 static const WCHAR ole32W[] = {'o','l','e','3','2',0};
821 HINSTANCE hinst = GetModuleHandleW(ole32W);
824 UnregisterClassW( clipbrd_wndclass, hinst );
827 static void OLEClipbrd_Destroy(ole_clipbrd* This)
833 if ( This->window ) destroy_clipbrd_window(This->window);
835 IStream_Release(This->marshal_data);
836 HeapFree(GetProcessHeap(), 0, This);
839 /************************************************************************
840 * OLEClipbrd_IDataObject_Release (IUnknown)
842 * See Windows documentation for more details on IUnknown methods.
844 static ULONG WINAPI OLEClipbrd_IDataObject_Release(
847 ole_clipbrd *This = impl_from_IDataObject(iface);
850 TRACE("(%p)->(count=%u)\n",This, This->ref);
852 ref = InterlockedDecrement(&This->ref);
856 OLEClipbrd_Destroy(This);
863 /************************************************************************
864 * OLEClipbrd_IDataObject_GetData (IDataObject)
866 * The OLE Clipboard's implementation of this method delegates to
867 * a data source if there is one or wraps around the windows clipboard
869 * See Windows documentation for more details on IDataObject methods.
871 static HRESULT WINAPI OLEClipbrd_IDataObject_GetData(
873 LPFORMATETC pformatetcIn,
877 ole_clipbrd *This = impl_from_IDataObject(iface);
880 TRACE("(%p,%p,%p)\n", iface, pformatetcIn, pmedium);
882 if ( !pformatetcIn || !pmedium )
886 * If we have a data source placed on the clipboard (via OleSetClipboard)
887 * simply delegate to the source object's QueryGetData
888 * NOTE: This code assumes that the IDataObject is in the same address space!
889 * We will need to add marshalling support when Wine handles multiple processes.
891 if ( This->src_data )
893 return IDataObject_GetData(This->src_data, pformatetcIn, pmedium);
896 if ( pformatetcIn->lindex != -1 )
897 return DV_E_FORMATETC;
899 if ( (pformatetcIn->tymed & TYMED_HGLOBAL) != TYMED_HGLOBAL )
902 if ( pformatetcIn->dwAspect != DVASPECT_CONTENT )
903 return DV_E_DVASPECT;
907 * Otherwise, get the data from the windows clipboard using GetClipboardData
909 if ( !OpenClipboard(NULL)) return CLIPBRD_E_CANT_OPEN;
911 h = GetClipboardData(pformatetcIn->cfFormat);
912 hr = dup_global_mem(h, GMEM_MOVEABLE, &hData);
915 * Return the clipboard data in the storage medium structure
917 pmedium->tymed = (hData == 0) ? TYMED_NULL : TYMED_HGLOBAL;
918 pmedium->u.hGlobal = hData;
919 pmedium->pUnkForRelease = NULL;
921 if ( !CloseClipboard() ) return CLIPBRD_E_CANT_CLOSE;
923 if(FAILED(hr)) return hr;
924 return (hData == 0) ? DV_E_FORMATETC : S_OK;
927 static HRESULT WINAPI OLEClipbrd_IDataObject_GetDataHere(
929 LPFORMATETC pformatetc,
936 /************************************************************************
937 * OLEClipbrd_IDataObject_QueryGetData (IDataObject)
939 * The OLE Clipboard's implementation of this method delegates to
940 * a data source if there is one or wraps around the windows clipboard
941 * function IsClipboardFormatAvailable() otherwise.
943 * See Windows documentation for more details on IDataObject methods.
945 static HRESULT WINAPI OLEClipbrd_IDataObject_QueryGetData(
947 LPFORMATETC pformatetc)
949 TRACE("(%p, %p)\n", iface, pformatetc);
954 if ( pformatetc->dwAspect != DVASPECT_CONTENT )
955 return DV_E_FORMATETC;
957 if ( pformatetc->lindex != -1 )
958 return DV_E_FORMATETC;
961 * Delegate to the Windows clipboard function IsClipboardFormatAvailable
963 return (IsClipboardFormatAvailable(pformatetc->cfFormat)) ? S_OK : DV_E_CLIPFORMAT;
966 /************************************************************************
967 * OLEClipbrd_IDataObject_GetCanonicalFormatEtc (IDataObject)
969 * See Windows documentation for more details on IDataObject methods.
971 static HRESULT WINAPI OLEClipbrd_IDataObject_GetCanonicalFormatEtc(
973 LPFORMATETC pformatectIn,
974 LPFORMATETC pformatetcOut)
976 TRACE("(%p, %p, %p)\n", iface, pformatectIn, pformatetcOut);
978 if ( !pformatectIn || !pformatetcOut )
981 *pformatetcOut = *pformatectIn;
982 return DATA_S_SAMEFORMATETC;
985 /************************************************************************
986 * OLEClipbrd_IDataObject_SetData (IDataObject)
988 * The OLE Clipboard's does not implement this method
990 * See Windows documentation for more details on IDataObject methods.
992 static HRESULT WINAPI OLEClipbrd_IDataObject_SetData(
994 LPFORMATETC pformatetc,
1002 /************************************************************************
1003 * OLEClipbrd_IDataObject_EnumFormatEtc (IDataObject)
1005 * See Windows documentation for more details on IDataObject methods.
1007 static HRESULT WINAPI OLEClipbrd_IDataObject_EnumFormatEtc(
1010 IEnumFORMATETC** enum_fmt)
1014 ole_priv_data *data = NULL;
1016 TRACE("(%p, %x, %p)\n", iface, dwDirection, enum_fmt);
1020 if ( dwDirection != DATADIR_GET ) return E_NOTIMPL;
1021 if ( !OpenClipboard(NULL) ) return CLIPBRD_E_CANT_OPEN;
1023 handle = GetClipboardData( ole_priv_data_clipboard_format );
1026 ole_priv_data *src = GlobalLock(handle);
1029 /* FIXME: sanity check on size */
1030 data = HeapAlloc(GetProcessHeap(), 0, src->size);
1033 GlobalUnlock(handle);
1037 memcpy(data, src, src->size);
1038 GlobalUnlock(handle);
1042 if(!data) hr = create_empty_priv_data(&data);
1043 if(FAILED(hr)) goto end;
1045 hr = enum_fmtetc_construct( data, 0, enum_fmt );
1048 if ( !CloseClipboard() ) hr = CLIPBRD_E_CANT_CLOSE;
1052 /************************************************************************
1053 * OLEClipbrd_IDataObject_DAdvise (IDataObject)
1055 * The OLE Clipboard's does not implement this method
1057 * See Windows documentation for more details on IDataObject methods.
1059 static HRESULT WINAPI OLEClipbrd_IDataObject_DAdvise(
1061 FORMATETC* pformatetc,
1063 IAdviseSink* pAdvSink,
1064 DWORD* pdwConnection)
1070 /************************************************************************
1071 * OLEClipbrd_IDataObject_DUnadvise (IDataObject)
1073 * The OLE Clipboard's does not implement this method
1075 * See Windows documentation for more details on IDataObject methods.
1077 static HRESULT WINAPI OLEClipbrd_IDataObject_DUnadvise(
1085 /************************************************************************
1086 * OLEClipbrd_IDataObject_EnumDAdvise (IDataObject)
1088 * The OLE Clipboard does not implement this method
1090 * See Windows documentation for more details on IDataObject methods.
1092 static HRESULT WINAPI OLEClipbrd_IDataObject_EnumDAdvise(
1094 IEnumSTATDATA** ppenumAdvise)
1100 static const IDataObjectVtbl OLEClipbrd_IDataObject_VTable =
1102 OLEClipbrd_IDataObject_QueryInterface,
1103 OLEClipbrd_IDataObject_AddRef,
1104 OLEClipbrd_IDataObject_Release,
1105 OLEClipbrd_IDataObject_GetData,
1106 OLEClipbrd_IDataObject_GetDataHere,
1107 OLEClipbrd_IDataObject_QueryGetData,
1108 OLEClipbrd_IDataObject_GetCanonicalFormatEtc,
1109 OLEClipbrd_IDataObject_SetData,
1110 OLEClipbrd_IDataObject_EnumFormatEtc,
1111 OLEClipbrd_IDataObject_DAdvise,
1112 OLEClipbrd_IDataObject_DUnadvise,
1113 OLEClipbrd_IDataObject_EnumDAdvise
1116 /*---------------------------------------------------------------------*
1117 * Internal implementation methods for the OLE clipboard
1118 *---------------------------------------------------------------------*/
1120 /*********************************************************
1121 * Construct the OLEClipbrd class.
1123 static ole_clipbrd* OLEClipbrd_Construct(void)
1128 This = HeapAlloc( GetProcessHeap(), 0, sizeof(*This) );
1129 if (!This) return NULL;
1131 This->lpvtbl = &OLEClipbrd_IDataObject_VTable;
1134 This->window = NULL;
1135 This->src_data = NULL;
1136 This->cached_enum = NULL;
1138 h = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE, 0);
1141 if(FAILED(CreateStreamOnHGlobal(h, TRUE, &This->marshal_data)))
1147 if(h) GlobalFree(h);
1148 HeapFree(GetProcessHeap(), 0, This);
1152 static void register_clipboard_formats(void)
1154 static const WCHAR DataObjectW[] = { 'D','a','t','a','O','b','j','e','c','t',0 };
1155 static const WCHAR OlePrivateDataW[] = { 'O','l','e',' ','P','r','i','v','a','t','e',' ','D','a','t','a',0 };
1156 static const WCHAR EmbedSourceW[] = { 'E','m','b','e','d',' ','S','o','u','r','c','e',0 };
1158 if(!dataobject_clipboard_format)
1159 dataobject_clipboard_format = RegisterClipboardFormatW(DataObjectW);
1160 if(!ole_priv_data_clipboard_format)
1161 ole_priv_data_clipboard_format = RegisterClipboardFormatW(OlePrivateDataW);
1162 if(!embed_source_clipboard_format)
1163 embed_source_clipboard_format = RegisterClipboardFormatW(EmbedSourceW);
1166 /***********************************************************************
1167 * OLEClipbrd_Initialize()
1168 * Initializes the OLE clipboard.
1170 void OLEClipbrd_Initialize(void)
1172 register_clipboard_formats();
1174 if ( !theOleClipboard )
1177 theOleClipboard = OLEClipbrd_Construct();
1182 /***********************************************************************
1183 * OLEClipbrd_UnInitialize()
1184 * Un-Initializes the OLE clipboard
1186 void OLEClipbrd_UnInitialize(void)
1190 * Destroy the clipboard if no one holds a reference to us.
1191 * Note that the clipboard was created with a reference count of 1.
1193 if ( theOleClipboard && (theOleClipboard->ref <= 1) )
1195 OLEClipbrd_Destroy( theOleClipboard );
1196 theOleClipboard = NULL;
1200 WARN( "() : OLEClipbrd_UnInitialize called while client holds an IDataObject reference!\n");
1204 /*********************************************************************
1205 * set_clipboard_formats
1207 * Enumerate all formats supported by the source and make
1208 * those formats available using delayed rendering using SetClipboardData.
1209 * Cache the enumeration list and make that list visibile as the
1210 * 'Ole Private Data' format on the clipboard.
1213 static HRESULT set_clipboard_formats(ole_clipbrd *clipbrd, IDataObject *data)
1217 IEnumFORMATETC *enum_fmt;
1218 HGLOBAL priv_data_handle;
1219 DWORD target_offset;
1220 ole_priv_data *priv_data;
1221 DWORD count = 0, needed = sizeof(*priv_data), idx;
1223 hr = IDataObject_EnumFormatEtc(data, DATADIR_GET, &enum_fmt);
1224 if(FAILED(hr)) return hr;
1226 while(IEnumFORMATETC_Next(enum_fmt, 1, &fmt, NULL) == S_OK)
1229 needed += sizeof(priv_data->entries[0]);
1232 needed += fmt.ptd->tdSize;
1233 CoTaskMemFree(fmt.ptd);
1237 /* Windows pads the list with two empty ole_priv_data_entries, one
1238 * after the entries array and one after the target device data.
1239 * Allocating with zero init to zero these pads. */
1241 needed += sizeof(priv_data->entries[0]); /* initialisation of needed includes one of these. */
1242 priv_data_handle = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE | GMEM_ZEROINIT, needed);
1243 priv_data = GlobalLock(priv_data_handle);
1245 priv_data->unk1 = 0;
1246 priv_data->size = needed;
1247 priv_data->unk2 = 1;
1248 priv_data->count = count;
1249 priv_data->unk3[0] = 0;
1250 priv_data->unk3[1] = 0;
1252 IEnumFORMATETC_Reset(enum_fmt);
1255 target_offset = FIELD_OFFSET(ole_priv_data, entries[count + 1]); /* count entries + one pad. */
1257 while(IEnumFORMATETC_Next(enum_fmt, 1, &fmt, NULL) == S_OK)
1259 TRACE("%s\n", dump_fmtetc(&fmt));
1261 priv_data->entries[idx].fmtetc = fmt;
1264 memcpy((char*)priv_data + target_offset, fmt.ptd, fmt.ptd->tdSize);
1265 priv_data->entries[idx].fmtetc.ptd = (DVTARGETDEVICE*)target_offset;
1266 target_offset += fmt.ptd->tdSize;
1267 CoTaskMemFree(fmt.ptd);
1270 priv_data->entries[idx].first_use = !find_format_in_list(priv_data->entries, idx, fmt.cfFormat);
1271 priv_data->entries[idx].unk[0] = 0;
1272 priv_data->entries[idx].unk[1] = 0;
1274 if (priv_data->entries[idx].first_use)
1275 SetClipboardData(fmt.cfFormat, NULL);
1280 IEnumFORMATETC_Release(enum_fmt);
1282 /* Cache the list and fixup any target device offsets to ptrs */
1283 clipbrd->cached_enum = HeapAlloc(GetProcessHeap(), 0, needed);
1284 memcpy(clipbrd->cached_enum, priv_data, needed);
1285 for(idx = 0; idx < clipbrd->cached_enum->count; idx++)
1286 if(clipbrd->cached_enum->entries[idx].fmtetc.ptd)
1287 clipbrd->cached_enum->entries[idx].fmtetc.ptd =
1288 (DVTARGETDEVICE *)((char*)clipbrd->cached_enum + (DWORD)clipbrd->cached_enum->entries[idx].fmtetc.ptd);
1290 GlobalUnlock(priv_data_handle);
1291 SetClipboardData(ole_priv_data_clipboard_format, priv_data_handle);
1296 static HWND create_clipbrd_window(void);
1298 /***********************************************************************
1299 * get_clipbrd_window
1301 static inline HRESULT get_clipbrd_window(ole_clipbrd *clipbrd, HWND *wnd)
1303 if ( !clipbrd->window )
1304 clipbrd->window = create_clipbrd_window();
1306 *wnd = clipbrd->window;
1307 return *wnd ? S_OK : E_FAIL;
1311 /**********************************************************************
1312 * release_marshal_data
1314 * Releases the data and sets the stream back to zero size.
1316 static inline void release_marshal_data(IStream *stm)
1319 ULARGE_INTEGER size;
1320 pos.QuadPart = size.QuadPart = 0;
1322 IStream_Seek(stm, pos, STREAM_SEEK_SET, NULL);
1323 CoReleaseMarshalData(stm);
1324 IStream_Seek(stm, pos, STREAM_SEEK_SET, NULL);
1325 IStream_SetSize(stm, size);
1328 /***********************************************************************
1329 * set_src_dataobject
1331 * Clears and sets the clipboard's src IDataObject.
1333 * To marshal the source dataobject we do something rather different from Windows.
1334 * We set a window prop which contains the marshalled data.
1335 * Windows set two props one of which is an IID, the other is an endpoint number.
1337 static HRESULT set_src_dataobject(ole_clipbrd *clipbrd, IDataObject *data)
1342 if(FAILED(hr = get_clipbrd_window(clipbrd, &wnd))) return hr;
1344 if(clipbrd->src_data)
1346 RemovePropW(wnd, wine_marshal_dataobject);
1347 release_marshal_data(clipbrd->marshal_data);
1349 IDataObject_Release(clipbrd->src_data);
1350 clipbrd->src_data = NULL;
1351 HeapFree(GetProcessHeap(), 0, clipbrd->cached_enum);
1352 clipbrd->cached_enum = NULL;
1360 IDataObject_AddRef(data);
1361 clipbrd->src_data = data;
1363 IDataObject_QueryInterface(data, &IID_IUnknown, (void**)&unk);
1364 hr = CoMarshalInterface(clipbrd->marshal_data, &IID_IDataObject, unk,
1365 MSHCTX_LOCAL, NULL, MSHLFLAGS_TABLESTRONG);
1366 IUnknown_Release(unk); /* Don't hold a ref on IUnknown, we have one on IDataObject. */
1367 if(FAILED(hr)) return hr;
1368 GetHGlobalFromStream(clipbrd->marshal_data, &h);
1369 SetPropW(wnd, wine_marshal_dataobject, h);
1370 hr = set_clipboard_formats(clipbrd, data);
1375 /***********************************************************************
1378 static LRESULT CALLBACK clipbrd_wndproc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
1380 ole_clipbrd *clipbrd;
1382 get_ole_clipbrd(&clipbrd);
1386 case WM_RENDERFORMAT:
1389 ole_priv_data_entry *entry;
1391 TRACE("(): WM_RENDERFORMAT(cfFormat=%x)\n", cf);
1392 entry = find_format_in_list(clipbrd->cached_enum->entries, clipbrd->cached_enum->count, cf);
1395 render_format(clipbrd->src_data, &entry->fmtetc);
1400 case WM_RENDERALLFORMATS:
1403 ole_priv_data_entry *entries = clipbrd->cached_enum->entries;
1405 TRACE("(): WM_RENDERALLFORMATS\n");
1407 for(i = 0; i < clipbrd->cached_enum->count; i++)
1409 if(entries[i].first_use)
1410 render_format(clipbrd->src_data, &entries[i].fmtetc);
1415 case WM_DESTROYCLIPBOARD:
1417 TRACE("(): WM_DESTROYCLIPBOARD\n");
1419 set_src_dataobject(clipbrd, NULL);
1424 return DefWindowProcW(hwnd, message, wparam, lparam);
1431 /***********************************************************************
1432 * create_clipbrd_window
1434 static HWND create_clipbrd_window(void)
1437 static const WCHAR ole32W[] = {'o','l','e','3','2',0};
1438 static const WCHAR title[] = {'C','l','i','p','b','o','a','r','d','W','i','n','d','o','w',0};
1439 HINSTANCE hinst = GetModuleHandleW(ole32W);
1441 class.cbSize = sizeof(class);
1443 class.lpfnWndProc = clipbrd_wndproc;
1444 class.cbClsExtra = 0;
1445 class.cbWndExtra = 0;
1446 class.hInstance = hinst;
1449 class.hbrBackground = 0;
1450 class.lpszMenuName = NULL;
1451 class.lpszClassName = clipbrd_wndclass;
1452 class.hIconSm = NULL;
1454 RegisterClassExW(&class);
1456 return CreateWindowW(clipbrd_wndclass, title, WS_POPUP | WS_CLIPSIBLINGS | WS_OVERLAPPED,
1457 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
1458 NULL, NULL, hinst, 0);
1461 /*********************************************************************
1462 * set_dataobject_format
1464 * Windows creates a 'DataObject' clipboard format that contains the
1465 * clipboard window's HWND or NULL if the Ole clipboard has been flushed.
1467 static HRESULT set_dataobject_format(HWND hwnd)
1469 HGLOBAL h = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE, sizeof(hwnd));
1472 if(!h) return E_OUTOFMEMORY;
1474 data = GlobalLock(h);
1478 if(!SetClipboardData(dataobject_clipboard_format, h))
1481 return CLIPBRD_E_CANT_SET;
1487 /*---------------------------------------------------------------------*
1488 * Win32 OLE clipboard API
1489 *---------------------------------------------------------------------*/
1491 /***********************************************************************
1492 * OleSetClipboard [OLE32.@]
1493 * Places a pointer to the specified data object onto the clipboard,
1494 * making the data object accessible to the OleGetClipboard function.
1498 * S_OK IDataObject pointer placed on the clipboard
1499 * CLIPBRD_E_CANT_OPEN OpenClipboard failed
1500 * CLIPBRD_E_CANT_EMPTY EmptyClipboard failed
1501 * CLIPBRD_E_CANT_CLOSE CloseClipboard failed
1502 * CLIPBRD_E_CANT_SET SetClipboard failed
1505 HRESULT WINAPI OleSetClipboard(IDataObject* data)
1508 ole_clipbrd *clipbrd;
1511 TRACE("(%p)\n", data);
1513 if(FAILED(hr = get_ole_clipbrd(&clipbrd))) return hr;
1515 if(FAILED(hr = get_clipbrd_window(clipbrd, &wnd))) return hr;
1517 if ( !OpenClipboard(wnd) ) return CLIPBRD_E_CANT_OPEN;
1519 if ( !EmptyClipboard() )
1521 hr = CLIPBRD_E_CANT_EMPTY;
1525 hr = set_src_dataobject(clipbrd, data);
1526 if(FAILED(hr)) goto end;
1528 hr = set_dataobject_format(wnd);
1532 if ( !CloseClipboard() ) hr = CLIPBRD_E_CANT_CLOSE;
1536 set_src_dataobject(clipbrd, NULL);
1543 /***********************************************************************
1544 * OleGetClipboard [OLE32.@]
1545 * Returns a pointer to our internal IDataObject which represents the conceptual
1546 * state of the Windows clipboard. If the current clipboard already contains
1547 * an IDataObject, our internal IDataObject will delegate to this object.
1549 HRESULT WINAPI OleGetClipboard(IDataObject** ppDataObj)
1552 ole_clipbrd *clipbrd;
1555 if(FAILED(hr = get_ole_clipbrd(&clipbrd))) return hr;
1557 hr = IDataObject_QueryInterface( (IDataObject*)&(clipbrd->lpvtbl),
1558 &IID_IDataObject, (void**)ppDataObj);
1562 /******************************************************************************
1563 * OleFlushClipboard [OLE32.@]
1564 * Renders the data from the source IDataObject into the windows clipboard
1566 * TODO: OleFlushClipboard needs to additionally handle TYMED_IStorage media
1567 * by copying the storage into global memory. Subsequently the default
1568 * data object exposed through OleGetClipboard must convert this TYMED_HGLOBAL
1569 * back to TYMED_IStorage.
1571 HRESULT WINAPI OleFlushClipboard(void)
1573 IEnumFORMATETC* penumFormatetc = NULL;
1576 ole_clipbrd *clipbrd;
1581 if(FAILED(hr = get_ole_clipbrd(&clipbrd))) return hr;
1583 if(FAILED(hr = get_clipbrd_window(clipbrd, &wnd))) return hr;
1586 * Already flushed or no source DataObject? Nothing to do.
1588 if (!clipbrd->src_data) return S_OK;
1590 if (!OpenClipboard(wnd)) return CLIPBRD_E_CANT_OPEN;
1593 * Render all HGLOBAL formats supported by the source into
1594 * the windows clipboard.
1596 if ( FAILED( hr = IDataObject_EnumFormatEtc( clipbrd->src_data,
1602 while ( S_OK == IEnumFORMATETC_Next(penumFormatetc, 1, &rgelt, NULL) )
1604 if ( rgelt.tymed == TYMED_HGLOBAL )
1607 TRACE("(cfFormat=%d:%s)\n", rgelt.cfFormat,
1608 GetClipboardFormatNameA(rgelt.cfFormat, szFmtName, sizeof(szFmtName)-1)
1611 if ( FAILED(render_format( clipbrd->src_data, &rgelt )) )
1616 IEnumFORMATETC_Release(penumFormatetc);
1618 hr = set_dataobject_format(NULL);
1620 set_src_dataobject(clipbrd, NULL);
1624 if ( !CloseClipboard() ) hr = CLIPBRD_E_CANT_CLOSE;
1630 /***********************************************************************
1631 * OleIsCurrentClipboard [OLE32.@]
1633 HRESULT WINAPI OleIsCurrentClipboard(IDataObject *data)
1636 ole_clipbrd *clipbrd;
1639 if(FAILED(hr = get_ole_clipbrd(&clipbrd))) return hr;
1641 if (data == NULL) return S_FALSE;
1643 return (data == clipbrd->src_data) ? S_OK : S_FALSE;