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.
66 #define NONAMELESSUNION
67 #define NONAMELESSSTRUCT
76 #include "wine/debug.h"
79 #include "storage32.h"
81 #include "compobj_private.h"
83 WINE_DEFAULT_DEBUG_CHANNEL(ole);
85 #define HANDLE_ERROR(err) do { hr = err; TRACE("(HRESULT=%x)\n", (HRESULT)err); goto CLEANUP; } while (0)
88 /****************************************************************************
93 const IDataObjectVtbl* lpvtbl; /* Exposed IDataObject vtable */
97 HWND hWndClipboard; /* Hidden clipboard window */
98 IDataObject* pIDataObjectSrc; /* Source object passed to OleSetClipboard */
101 typedef struct ole_clipbrd ole_clipbrd;
103 static inline ole_clipbrd *impl_from_IDataObject(IDataObject *iface)
105 return (ole_clipbrd*)((char*)iface - FIELD_OFFSET(ole_clipbrd, lpvtbl));
108 typedef struct PresentationDataHeader
111 DWORD dwObjectExtentX;
112 DWORD dwObjectExtentY;
114 } PresentationDataHeader;
117 * The one and only ole_clipbrd object which is created by OLEClipbrd_Initialize()
119 static ole_clipbrd* theOleClipboard;
123 * Name of our registered OLE clipboard window class
125 static const CHAR OLEClipbrd_WNDCLASS[] = "CLIPBRDWNDCLASS";
127 static UINT dataobject_clipboard_format;
128 static UINT ole_priv_data_clipboard_format;
130 /* Structure of 'Ole Private Data' clipboard format */
134 DWORD first_use; /* Has this cf been added to the list already */
136 } ole_priv_data_entry;
141 DWORD size; /* in bytes of the entire structure */
143 DWORD count; /* no. of format entries */
145 ole_priv_data_entry entries[1]; /* array of size count */
146 /* then follows any DVTARGETDEVICE structures referenced in the FORMATETCs */
149 /* Create an empty data structure. The only thing that really matters
150 here is setting count and size members. This is used by the enumerator as a
151 convenience when there's an empty list. */
152 static HRESULT create_empty_priv_data(ole_priv_data **data)
157 ptr = HeapAlloc(GetProcessHeap(), 0, sizeof(*ptr));
158 if(!ptr) return E_OUTOFMEMORY;
159 ptr->size = sizeof(*ptr);
165 /*---------------------------------------------------------------------*
166 * Implementation of the internal IEnumFORMATETC interface returned by
167 * the OLE clipboard's IDataObject.
168 *---------------------------------------------------------------------*/
170 typedef struct enum_fmtetc
172 const IEnumFORMATETCVtbl *lpVtbl;
175 UINT pos; /* current enumerator position */
179 static inline enum_fmtetc *impl_from_IEnumFORMATETC(IEnumFORMATETC *iface)
181 return (enum_fmtetc*)((char*)iface - FIELD_OFFSET(enum_fmtetc, lpVtbl));
184 /************************************************************************
185 * OLEClipbrd_IEnumFORMATETC_QueryInterface (IUnknown)
187 * See Windows documentation for more details on IUnknown methods.
189 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_QueryInterface
190 (LPENUMFORMATETC iface, REFIID riid, LPVOID* ppvObj)
192 enum_fmtetc *This = impl_from_IEnumFORMATETC(iface);
194 TRACE("(%p)->(IID: %s, %p)\n", This, debugstr_guid(riid), ppvObj);
198 if(IsEqualIID(riid, &IID_IUnknown) ||
199 IsEqualIID(riid, &IID_IEnumFORMATETC))
206 IEnumFORMATETC_AddRef((IEnumFORMATETC*)*ppvObj);
207 TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
211 TRACE("-- Interface: E_NOINTERFACE\n");
212 return E_NOINTERFACE;
215 /************************************************************************
216 * OLEClipbrd_IEnumFORMATETC_AddRef (IUnknown)
219 static ULONG WINAPI OLEClipbrd_IEnumFORMATETC_AddRef(LPENUMFORMATETC iface)
221 enum_fmtetc *This = impl_from_IEnumFORMATETC(iface);
222 TRACE("(%p)->(count=%u)\n",This, This->ref);
224 return InterlockedIncrement(&This->ref);
227 /************************************************************************
228 * OLEClipbrd_IEnumFORMATETC_Release (IUnknown)
230 * See Windows documentation for more details on IUnknown methods.
232 static ULONG WINAPI OLEClipbrd_IEnumFORMATETC_Release(LPENUMFORMATETC iface)
234 enum_fmtetc *This = impl_from_IEnumFORMATETC(iface);
237 TRACE("(%p)->(count=%u)\n",This, This->ref);
239 ref = InterlockedDecrement(&This->ref);
242 TRACE("() - destroying IEnumFORMATETC(%p)\n",This);
243 HeapFree(GetProcessHeap(), 0, This->data);
244 HeapFree(GetProcessHeap(), 0, This);
249 /************************************************************************
250 * OLEClipbrd_IEnumFORMATETC_Next (IEnumFORMATETC)
252 * Standard enumerator members for IEnumFORMATETC
254 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Next
255 (LPENUMFORMATETC iface, ULONG celt, FORMATETC *rgelt, ULONG *pceltFethed)
257 enum_fmtetc *This = impl_from_IEnumFORMATETC(iface);
259 HRESULT hres = S_FALSE;
261 TRACE("(%p)->(pos=%u)\n", This, This->pos);
263 if (This->pos < This->data->count)
265 cfetch = This->data->count - This->pos;
272 for(i = 0; i < cfetch; i++)
274 rgelt[i] = This->data->entries[This->pos++].fmtetc;
277 DVTARGETDEVICE *target = (DVTARGETDEVICE *)((char *)This->data + (DWORD)rgelt[i].ptd);
278 rgelt[i].ptd = CoTaskMemAlloc(target->tdSize);
279 if(!rgelt[i].ptd) return E_OUTOFMEMORY;
280 memcpy(rgelt[i].ptd, target, target->tdSize);
291 *pceltFethed = cfetch;
297 /************************************************************************
298 * OLEClipbrd_IEnumFORMATETC_Skip (IEnumFORMATETC)
300 * Standard enumerator members for IEnumFORMATETC
302 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Skip(LPENUMFORMATETC iface, ULONG celt)
304 enum_fmtetc *This = impl_from_IEnumFORMATETC(iface);
305 TRACE("(%p)->(num=%u)\n", This, celt);
308 if (This->pos > This->data->count)
310 This->pos = This->data->count;
316 /************************************************************************
317 * OLEClipbrd_IEnumFORMATETC_Reset (IEnumFORMATETC)
319 * Standard enumerator members for IEnumFORMATETC
321 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Reset(LPENUMFORMATETC iface)
323 enum_fmtetc *This = impl_from_IEnumFORMATETC(iface);
324 TRACE("(%p)->()\n", This);
330 static HRESULT enum_fmtetc_construct(ole_priv_data *data, UINT pos, IEnumFORMATETC **obj);
332 /************************************************************************
333 * OLEClipbrd_IEnumFORMATETC_Clone (IEnumFORMATETC)
335 * Standard enumerator members for IEnumFORMATETC
337 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Clone
338 (LPENUMFORMATETC iface, LPENUMFORMATETC* obj)
340 enum_fmtetc *This = impl_from_IEnumFORMATETC(iface);
341 ole_priv_data *new_data;
343 TRACE("(%p)->(%p)\n", This, obj);
345 if ( !obj ) return E_INVALIDARG;
348 new_data = HeapAlloc(GetProcessHeap(), 0, This->data->size);
349 if(!new_data) return E_OUTOFMEMORY;
351 return enum_fmtetc_construct(new_data, This->pos, obj);
354 static const IEnumFORMATETCVtbl efvt =
356 OLEClipbrd_IEnumFORMATETC_QueryInterface,
357 OLEClipbrd_IEnumFORMATETC_AddRef,
358 OLEClipbrd_IEnumFORMATETC_Release,
359 OLEClipbrd_IEnumFORMATETC_Next,
360 OLEClipbrd_IEnumFORMATETC_Skip,
361 OLEClipbrd_IEnumFORMATETC_Reset,
362 OLEClipbrd_IEnumFORMATETC_Clone
365 /************************************************************************
366 * enum_fmtetc_construct
368 * Creates an IEnumFORMATETC enumerator from ole_priv_data which it then owns.
370 static HRESULT enum_fmtetc_construct(ole_priv_data *data, UINT pos, IEnumFORMATETC **obj)
375 ef = HeapAlloc(GetProcessHeap(), 0, sizeof(*ef));
376 if (!ef) return E_OUTOFMEMORY;
383 TRACE("(%p)->()\n", ef);
384 *obj = (IEnumFORMATETC *)ef;
388 /***********************************************************************
389 * OLEClipbrd_GlobalDupMem( HGLOBAL )
390 * Helper method to duplicate an HGLOBAL chunk of memory
392 static HGLOBAL OLEClipbrd_GlobalDupMem( HGLOBAL hGlobalSrc )
395 PVOID pGlobalSrc, pGlobalDest;
401 cBytes = GlobalSize(hGlobalSrc);
405 hGlobalDest = GlobalAlloc( GMEM_DDESHARE|GMEM_MOVEABLE,
410 pGlobalSrc = GlobalLock(hGlobalSrc);
411 pGlobalDest = GlobalLock(hGlobalDest);
412 if ( !pGlobalSrc || !pGlobalDest )
414 GlobalFree(hGlobalDest);
418 memcpy(pGlobalDest, pGlobalSrc, cBytes);
420 GlobalUnlock(hGlobalSrc);
421 GlobalUnlock(hGlobalDest);
426 #define MAX_CLIPFORMAT_NAME 80
428 /***********************************************************************
429 * OLEClipbrd_RenderFormat(LPFORMATETC)
430 * Render the clipboard data. Note that this call will delegate to the
431 * source data object.
432 * Note: This function assumes it is passed an HGLOBAL format to render.
434 static HRESULT OLEClipbrd_RenderFormat(IDataObject *pIDataObject, LPFORMATETC pFormatetc)
439 char szFmtName[MAX_CLIPFORMAT_NAME];
440 ILockBytes *ptrILockBytes = 0;
441 HGLOBAL hStorage = 0;
443 if (!GetClipboardFormatNameA(pFormatetc->cfFormat, szFmtName, MAX_CLIPFORMAT_NAME))
446 /* If embed source */
447 if (!strcmp(szFmtName, CF_EMBEDSOURCE))
449 memset(&std, 0, sizeof(STGMEDIUM));
450 std.tymed = pFormatetc->tymed = TYMED_ISTORAGE;
452 hStorage = GlobalAlloc(GMEM_SHARE|GMEM_MOVEABLE, 0);
453 if (hStorage == NULL)
454 HANDLE_ERROR( E_OUTOFMEMORY );
455 hr = CreateILockBytesOnHGlobal(hStorage, FALSE, &ptrILockBytes);
456 hr = StgCreateDocfileOnILockBytes(ptrILockBytes, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &std.u.pstg);
458 if (FAILED(hr = IDataObject_GetDataHere(theOleClipboard->pIDataObjectSrc, pFormatetc, &std)))
460 WARN("() : IDataObject_GetDataHere failed to render clipboard data! (%x)\n", hr);
461 GlobalFree(hStorage);
465 if (1) /* check whether the presentation data is already -not- present */
469 METAFILEPICT *mfp = 0;
471 fmt2.cfFormat = CF_METAFILEPICT;
473 fmt2.dwAspect = DVASPECT_CONTENT;
475 fmt2.tymed = TYMED_MFPICT;
477 memset(&std2, 0, sizeof(STGMEDIUM));
478 std2.tymed = TYMED_MFPICT;
480 /* Get the metafile picture out of it */
482 if (SUCCEEDED(hr = IDataObject_GetData(theOleClipboard->pIDataObjectSrc, &fmt2, &std2)))
484 mfp = GlobalLock(std2.u.hGlobal);
489 OLECHAR name[]={ 2, 'O', 'l', 'e', 'P', 'r', 'e', 's', '0', '0', '0', 0};
490 IStream *pStream = 0;
492 PresentationDataHeader pdh;
496 CHAR strOleTypeName[51];
497 BYTE OlePresStreamHeader [] =
499 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00,
500 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
501 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
502 0x00, 0x00, 0x00, 0x00
505 nSize = GetMetaFileBitsEx(mfp->hMF, 0, NULL);
507 memset(&pdh, 0, sizeof(PresentationDataHeader));
508 memcpy(&pdh, OlePresStreamHeader, sizeof(OlePresStreamHeader));
510 pdh.dwObjectExtentX = mfp->xExt;
511 pdh.dwObjectExtentY = mfp->yExt;
514 hr = IStorage_CreateStream(std.u.pstg, name, STGM_CREATE|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, 0, &pStream);
516 hr = IStream_Write(pStream, &pdh, sizeof(PresentationDataHeader), NULL);
518 mfBits = HeapAlloc(GetProcessHeap(), 0, nSize);
519 nSize = GetMetaFileBitsEx(mfp->hMF, nSize, mfBits);
521 hr = IStream_Write(pStream, mfBits, nSize, NULL);
523 IStream_Release(pStream);
525 HeapFree(GetProcessHeap(), 0, mfBits);
527 GlobalUnlock(std2.u.hGlobal);
529 ReadClassStg(std.u.pstg, &clsID);
530 ProgIDFromCLSID(&clsID, &strProgID);
532 WideCharToMultiByte( CP_ACP, 0, strProgID, -1, strOleTypeName, sizeof(strOleTypeName), NULL, NULL );
533 OLECONVERT_CreateOleStream(std.u.pstg);
534 OLECONVERT_CreateCompObjStream(std.u.pstg, strOleTypeName);
540 if (FAILED(hr = IDataObject_GetData(pIDataObject, pFormatetc, &std)))
542 WARN("() : IDataObject_GetData failed to render clipboard data! (%x)\n", hr);
543 GlobalFree(hStorage);
547 /* To put a copy back on the clipboard */
549 hStorage = std.u.hGlobal;
553 * Put a copy of the rendered data back on the clipboard
556 if ( !(hDup = OLEClipbrd_GlobalDupMem(hStorage)) )
557 HANDLE_ERROR( E_OUTOFMEMORY );
559 if ( !SetClipboardData( pFormatetc->cfFormat, hDup ) )
562 WARN("() : Failed to set rendered clipboard data into clipboard!\n");
567 ReleaseStgMedium(&std);
573 /***********************************************************************
574 * OLEClipbrd_WndProc(HWND, unsigned, WORD, LONG)
575 * Processes messages sent to the OLE clipboard window.
576 * Note that we will intercept messages in our WndProc only when data
577 * has been placed in the clipboard via OleSetClipboard().
578 * i.e. Only when OLE owns the windows clipboard.
580 static LRESULT CALLBACK OLEClipbrd_WndProc
581 (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
587 * We receive this message to allow us to handle delayed rendering of
588 * a specific clipboard format when an application requests data in
589 * that format by calling GetClipboardData.
590 * (Recall that in OleSetClipboard, we used SetClipboardData to
591 * make all HGLOBAL formats supported by the source IDataObject
592 * available using delayed rendering)
593 * On receiving this message we must actually render the data in the
594 * specified format and place it on the clipboard by calling the
595 * SetClipboardData function.
597 case WM_RENDERFORMAT:
601 ZeroMemory( &rgelt, sizeof(FORMATETC));
604 * Initialize FORMATETC to a Windows clipboard friendly format
606 rgelt.cfFormat = (UINT) wParam;
607 rgelt.dwAspect = DVASPECT_CONTENT;
609 rgelt.tymed = TYMED_HGLOBAL;
611 TRACE("(): WM_RENDERFORMAT(cfFormat=%d)\n", rgelt.cfFormat);
614 * Render the clipboard data.
615 * (We must have a source data object or we wouldn't be in this WndProc)
617 OLEClipbrd_RenderFormat( (IDataObject*)&(theOleClipboard->lpvtbl), &rgelt );
623 * WM_RENDERALLFORMATS
624 * Sent before the clipboard owner window is destroyed.
625 * We should receive this message only when OleUninitialize is called
626 * while we have an IDataObject in the clipboard.
627 * For the content of the clipboard to remain available to other
628 * applications, we must render data in all the formats the source IDataObject
629 * is capable of generating, and place the data on the clipboard by calling
632 case WM_RENDERALLFORMATS:
634 IEnumFORMATETC* penumFormatetc = NULL;
637 TRACE("(): WM_RENDERALLFORMATS\n");
640 * Render all HGLOBAL formats supported by the source into
641 * the windows clipboard.
643 if ( FAILED( IDataObject_EnumFormatEtc( (IDataObject*)&(theOleClipboard->lpvtbl),
644 DATADIR_GET, &penumFormatetc) ) )
646 WARN("(): WM_RENDERALLFORMATS failed to retrieve EnumFormatEtc!\n");
650 while ( S_OK == IEnumFORMATETC_Next(penumFormatetc, 1, &rgelt, NULL) )
652 if ( rgelt.tymed == TYMED_HGLOBAL )
655 * Render the clipboard data.
657 if ( FAILED(OLEClipbrd_RenderFormat( (IDataObject*)&(theOleClipboard->lpvtbl), &rgelt )) )
660 TRACE("(): WM_RENDERALLFORMATS(cfFormat=%d)\n", rgelt.cfFormat);
664 IEnumFORMATETC_Release(penumFormatetc);
670 * WM_DESTROYCLIPBOARD
671 * This is sent by EmptyClipboard before the clipboard is emptied.
672 * We should release any IDataObject we are holding onto when we receive
673 * this message, since it indicates that the OLE clipboard should be empty
674 * from this point on.
676 case WM_DESTROYCLIPBOARD:
678 TRACE("(): WM_DESTROYCLIPBOARD\n");
680 * Release the data object we are holding on to
682 if ( theOleClipboard->pIDataObjectSrc )
684 IDataObject_Release(theOleClipboard->pIDataObjectSrc);
685 theOleClipboard->pIDataObjectSrc = NULL;
691 case WM_ASKCBFORMATNAME:
692 case WM_CHANGECBCHAIN:
693 case WM_DRAWCLIPBOARD:
694 case WM_SIZECLIPBOARD:
695 case WM_HSCROLLCLIPBOARD:
696 case WM_VSCROLLCLIPBOARD:
697 case WM_PAINTCLIPBOARD:
700 return DefWindowProcA(hWnd, message, wParam, lParam);
707 /*---------------------------------------------------------------------*
708 * Implementation of the internal IDataObject interface exposed by
710 *---------------------------------------------------------------------*/
713 /************************************************************************
714 * OLEClipbrd_IDataObject_QueryInterface (IUnknown)
716 * See Windows documentation for more details on IUnknown methods.
718 static HRESULT WINAPI OLEClipbrd_IDataObject_QueryInterface(
723 ole_clipbrd *This = impl_from_IDataObject(iface);
724 TRACE("(%p)->(IID:%s, %p)\n", This, debugstr_guid(riid), ppvObject);
726 if ( (This==0) || (ppvObject==0) )
731 if (IsEqualIID(&IID_IUnknown, riid) ||
732 IsEqualIID(&IID_IDataObject, riid))
738 WARN( "() : asking for unsupported interface %s\n", debugstr_guid(riid));
739 return E_NOINTERFACE;
742 IUnknown_AddRef((IUnknown*)*ppvObject);
747 /************************************************************************
748 * OLEClipbrd_IDataObject_AddRef (IUnknown)
750 * See Windows documentation for more details on IUnknown methods.
752 static ULONG WINAPI OLEClipbrd_IDataObject_AddRef(
755 ole_clipbrd *This = impl_from_IDataObject(iface);
757 TRACE("(%p)->(count=%u)\n",This, This->ref);
759 return InterlockedIncrement(&This->ref);
762 /***********************************************************************
763 * OLEClipbrd_DestroyWindow(HWND)
764 * Destroy the clipboard window and unregister its class
766 static void OLEClipbrd_DestroyWindow(HWND hwnd)
769 UnregisterClassA( OLEClipbrd_WNDCLASS, 0 );
772 static void OLEClipbrd_Destroy(ole_clipbrd* This)
778 theOleClipboard = NULL;
780 if ( This->hWndClipboard )
781 OLEClipbrd_DestroyWindow(This->hWndClipboard);
783 HeapFree(GetProcessHeap(), 0, This);
786 /************************************************************************
787 * OLEClipbrd_IDataObject_Release (IUnknown)
789 * See Windows documentation for more details on IUnknown methods.
791 static ULONG WINAPI OLEClipbrd_IDataObject_Release(
794 ole_clipbrd *This = impl_from_IDataObject(iface);
797 TRACE("(%p)->(count=%u)\n",This, This->ref);
799 ref = InterlockedDecrement(&This->ref);
803 OLEClipbrd_Destroy(This);
810 /************************************************************************
811 * OLEClipbrd_IDataObject_GetData (IDataObject)
813 * The OLE Clipboard's implementation of this method delegates to
814 * a data source if there is one or wraps around the windows clipboard
816 * See Windows documentation for more details on IDataObject methods.
818 static HRESULT WINAPI OLEClipbrd_IDataObject_GetData(
820 LPFORMATETC pformatetcIn,
825 ole_clipbrd *This = impl_from_IDataObject(iface);
827 TRACE("(%p,%p,%p)\n", iface, pformatetcIn, pmedium);
829 if ( !pformatetcIn || !pmedium )
833 * If we have a data source placed on the clipboard (via OleSetClipboard)
834 * simply delegate to the source object's QueryGetData
835 * NOTE: This code assumes that the IDataObject is in the same address space!
836 * We will need to add marshalling support when Wine handles multiple processes.
838 if ( This->pIDataObjectSrc )
840 return IDataObject_GetData(This->pIDataObjectSrc, pformatetcIn, pmedium);
843 if ( pformatetcIn->lindex != -1 )
844 return DV_E_FORMATETC;
846 if ( (pformatetcIn->tymed & TYMED_HGLOBAL) != TYMED_HGLOBAL )
849 if ( pformatetcIn->dwAspect != DVASPECT_CONTENT )
850 return DV_E_DVASPECT;
854 * Otherwise, get the data from the windows clipboard using GetClipboardData
856 if ( !OpenClipboard(theOleClipboard->hWndClipboard)) return CLIPBRD_E_CANT_OPEN;
858 hData = GetClipboardData(pformatetcIn->cfFormat);
860 /* Must make a copy of global handle returned by GetClipboardData; it
861 * is not valid after we call CloseClipboard
862 * Application is responsible for freeing the memory (Forte Agent does this)
864 src = GlobalLock(hData);
870 size = GlobalSize(hData);
871 hDest = GlobalAlloc(GHND, size);
872 dest = GlobalLock(hDest);
873 memcpy(dest, src, size);
880 * Return the clipboard data in the storage medium structure
882 pmedium->tymed = (hData == 0) ? TYMED_NULL : TYMED_HGLOBAL;
883 pmedium->u.hGlobal = hData;
884 pmedium->pUnkForRelease = NULL;
886 if ( !CloseClipboard() ) return CLIPBRD_E_CANT_CLOSE;
888 return (hData == 0) ? DV_E_FORMATETC : S_OK;
891 static HRESULT WINAPI OLEClipbrd_IDataObject_GetDataHere(
893 LPFORMATETC pformatetc,
900 /************************************************************************
901 * OLEClipbrd_IDataObject_QueryGetData (IDataObject)
903 * The OLE Clipboard's implementation of this method delegates to
904 * a data source if there is one or wraps around the windows clipboard
905 * function IsClipboardFormatAvailable() otherwise.
907 * See Windows documentation for more details on IDataObject methods.
909 static HRESULT WINAPI OLEClipbrd_IDataObject_QueryGetData(
911 LPFORMATETC pformatetc)
913 TRACE("(%p, %p)\n", iface, pformatetc);
918 if ( pformatetc->dwAspect != DVASPECT_CONTENT )
919 return DV_E_FORMATETC;
921 if ( pformatetc->lindex != -1 )
922 return DV_E_FORMATETC;
925 * Delegate to the Windows clipboard function IsClipboardFormatAvailable
927 return (IsClipboardFormatAvailable(pformatetc->cfFormat)) ? S_OK : DV_E_CLIPFORMAT;
930 /************************************************************************
931 * OLEClipbrd_IDataObject_GetCanonicalFormatEtc (IDataObject)
933 * See Windows documentation for more details on IDataObject methods.
935 static HRESULT WINAPI OLEClipbrd_IDataObject_GetCanonicalFormatEtc(
937 LPFORMATETC pformatectIn,
938 LPFORMATETC pformatetcOut)
940 TRACE("(%p, %p, %p)\n", iface, pformatectIn, pformatetcOut);
942 if ( !pformatectIn || !pformatetcOut )
945 *pformatetcOut = *pformatectIn;
946 return DATA_S_SAMEFORMATETC;
949 /************************************************************************
950 * OLEClipbrd_IDataObject_SetData (IDataObject)
952 * The OLE Clipboard's does not implement this method
954 * See Windows documentation for more details on IDataObject methods.
956 static HRESULT WINAPI OLEClipbrd_IDataObject_SetData(
958 LPFORMATETC pformatetc,
966 /************************************************************************
967 * OLEClipbrd_IDataObject_EnumFormatEtc (IDataObject)
969 * See Windows documentation for more details on IDataObject methods.
971 static HRESULT WINAPI OLEClipbrd_IDataObject_EnumFormatEtc(
974 IEnumFORMATETC** enum_fmt)
977 ole_clipbrd *This = impl_from_IDataObject(iface);
979 ole_priv_data *data = NULL;
981 TRACE("(%p, %x, %p)\n", iface, dwDirection, enum_fmt);
985 if ( dwDirection != DATADIR_GET ) return E_NOTIMPL;
986 if ( !OpenClipboard(This->hWndClipboard) ) return CLIPBRD_E_CANT_OPEN;
988 handle = GetClipboardData( ole_priv_data_clipboard_format );
991 ole_priv_data *src = GlobalLock(handle);
994 /* FIXME: sanity check on size */
995 data = HeapAlloc(GetProcessHeap(), 0, src->size);
998 GlobalUnlock(handle);
1002 memcpy(data, src, src->size);
1003 GlobalUnlock(handle);
1007 if(!data) hr = create_empty_priv_data(&data);
1008 if(FAILED(hr)) goto end;
1010 hr = enum_fmtetc_construct( data, 0, enum_fmt );
1013 if ( !CloseClipboard() ) hr = CLIPBRD_E_CANT_CLOSE;
1017 /************************************************************************
1018 * OLEClipbrd_IDataObject_DAdvise (IDataObject)
1020 * The OLE Clipboard's does not implement this method
1022 * See Windows documentation for more details on IDataObject methods.
1024 static HRESULT WINAPI OLEClipbrd_IDataObject_DAdvise(
1026 FORMATETC* pformatetc,
1028 IAdviseSink* pAdvSink,
1029 DWORD* pdwConnection)
1035 /************************************************************************
1036 * OLEClipbrd_IDataObject_DUnadvise (IDataObject)
1038 * The OLE Clipboard's does not implement this method
1040 * See Windows documentation for more details on IDataObject methods.
1042 static HRESULT WINAPI OLEClipbrd_IDataObject_DUnadvise(
1050 /************************************************************************
1051 * OLEClipbrd_IDataObject_EnumDAdvise (IDataObject)
1053 * The OLE Clipboard does not implement this method
1055 * See Windows documentation for more details on IDataObject methods.
1057 static HRESULT WINAPI OLEClipbrd_IDataObject_EnumDAdvise(
1059 IEnumSTATDATA** ppenumAdvise)
1065 static const IDataObjectVtbl OLEClipbrd_IDataObject_VTable =
1067 OLEClipbrd_IDataObject_QueryInterface,
1068 OLEClipbrd_IDataObject_AddRef,
1069 OLEClipbrd_IDataObject_Release,
1070 OLEClipbrd_IDataObject_GetData,
1071 OLEClipbrd_IDataObject_GetDataHere,
1072 OLEClipbrd_IDataObject_QueryGetData,
1073 OLEClipbrd_IDataObject_GetCanonicalFormatEtc,
1074 OLEClipbrd_IDataObject_SetData,
1075 OLEClipbrd_IDataObject_EnumFormatEtc,
1076 OLEClipbrd_IDataObject_DAdvise,
1077 OLEClipbrd_IDataObject_DUnadvise,
1078 OLEClipbrd_IDataObject_EnumDAdvise
1081 /*---------------------------------------------------------------------*
1082 * Internal implementation methods for the OLE clipboard
1083 *---------------------------------------------------------------------*/
1085 /*********************************************************
1086 * Construct the OLEClipbrd class.
1088 static ole_clipbrd* OLEClipbrd_Construct(void)
1092 This = HeapAlloc( GetProcessHeap(), 0, sizeof(*This) );
1093 if (!This) return NULL;
1095 This->lpvtbl = &OLEClipbrd_IDataObject_VTable;
1098 This->hWndClipboard = NULL;
1099 This->pIDataObjectSrc = NULL;
1101 theOleClipboard = This;
1105 static void register_clipboard_formats(void)
1107 static const WCHAR DataObjectW[] = { 'D','a','t','a','O','b','j','e','c','t',0 };
1108 static const WCHAR OlePrivateDataW[] = { 'O','l','e',' ','P','r','i','v','a','t','e',' ','D','a','t','a',0 };
1110 if(!dataobject_clipboard_format)
1111 dataobject_clipboard_format = RegisterClipboardFormatW(DataObjectW);
1112 if(!ole_priv_data_clipboard_format)
1113 ole_priv_data_clipboard_format = RegisterClipboardFormatW(OlePrivateDataW);
1116 /***********************************************************************
1117 * OLEClipbrd_Initialize()
1118 * Initializes the OLE clipboard.
1120 void OLEClipbrd_Initialize(void)
1122 register_clipboard_formats();
1124 if ( !theOleClipboard )
1127 theOleClipboard = OLEClipbrd_Construct();
1132 /***********************************************************************
1133 * OLEClipbrd_UnInitialize()
1134 * Un-Initializes the OLE clipboard
1136 void OLEClipbrd_UnInitialize(void)
1140 * Destroy the clipboard if no one holds a reference to us.
1141 * Note that the clipboard was created with a reference count of 1.
1143 if ( theOleClipboard && (theOleClipboard->ref <= 1) )
1145 OLEClipbrd_Destroy( theOleClipboard );
1149 WARN( "() : OLEClipbrd_UnInitialize called while client holds an IDataObject reference!\n");
1153 /***********************************************************************
1154 * OLEClipbrd_CreateWindow()
1155 * Create the clipboard window
1157 static HWND OLEClipbrd_CreateWindow(void)
1163 * Register the clipboard window class if necessary
1165 ZeroMemory( &wcex, sizeof(WNDCLASSEXA));
1167 wcex.cbSize = sizeof(WNDCLASSEXA);
1168 /* Windows creates this class with a style mask of 0
1169 * We don't bother doing this since the FindClassByAtom code
1170 * would have to be changed to deal with this idiosyncrasy. */
1171 wcex.style = CS_GLOBALCLASS;
1172 wcex.lpfnWndProc = OLEClipbrd_WndProc;
1174 wcex.lpszClassName = OLEClipbrd_WNDCLASS;
1176 RegisterClassExA(&wcex);
1179 * Create a hidden window to receive OLE clipboard messages
1183 * If we need to store state info we can store it here.
1184 * For now we don't need this functionality.
1185 * ClipboardWindowInfo clipboardInfo;
1186 * ZeroMemory( &trackerInfo, sizeof(ClipboardWindowInfo));
1189 hwnd = CreateWindowA(OLEClipbrd_WNDCLASS,
1191 WS_POPUP | WS_CLIPSIBLINGS | WS_OVERLAPPED,
1192 CW_USEDEFAULT, CW_USEDEFAULT,
1193 CW_USEDEFAULT, CW_USEDEFAULT,
1197 0 /*(LPVOID)&clipboardInfo */);
1202 static inline BOOL is_format_in_list(ole_priv_data_entry *entries, DWORD num, UINT cf)
1205 for(i = 0; i < num; i++)
1206 if(entries[i].fmtetc.cfFormat == cf)
1212 /*********************************************************************
1213 * set_clipboard_formats
1215 * Enumerate all HGLOBAL formats supported by the source and make
1216 * those formats available using delayed rendering using SetClipboardData.
1218 * TODO: We need to additionally handle TYMED_IStorage and
1219 * TYMED_IStream data by copying into global memory.
1221 static HRESULT set_clipboard_formats(IDataObject *data)
1225 IEnumFORMATETC *enum_fmt;
1226 HGLOBAL priv_data_handle;
1227 DWORD target_offset;
1228 ole_priv_data *priv_data;
1229 DWORD count = 0, needed = sizeof(*priv_data), idx;
1231 hr = IDataObject_EnumFormatEtc(data, DATADIR_GET, &enum_fmt);
1232 if(FAILED(hr)) return hr;
1234 while(IEnumFORMATETC_Next(enum_fmt, 1, &fmt, NULL) == S_OK)
1237 needed += sizeof(priv_data->entries[0]);
1240 needed += fmt.ptd->tdSize;
1241 CoTaskMemFree(fmt.ptd);
1245 /* Windows pads the list with two empty ole_priv_data_entries, one
1246 * after the entries array and one after the target device data.
1247 * Allocating with zero init to zero these pads. */
1249 needed += sizeof(priv_data->entries[0]); /* initialisation of needed includes one of these. */
1250 priv_data_handle = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE | GMEM_ZEROINIT, needed);
1251 priv_data = GlobalLock(priv_data_handle);
1253 priv_data->unk1 = 0;
1254 priv_data->size = needed;
1255 priv_data->unk2 = 1;
1256 priv_data->count = count;
1257 priv_data->unk3[0] = 0;
1258 priv_data->unk3[1] = 0;
1260 IEnumFORMATETC_Reset(enum_fmt);
1263 target_offset = FIELD_OFFSET(ole_priv_data, entries[count + 1]); /* count entries + one pad. */
1265 while(IEnumFORMATETC_Next(enum_fmt, 1, &fmt, NULL) == S_OK)
1267 if (fmt.tymed == TYMED_HGLOBAL)
1270 TRACE("(cfFormat=%d:%s)\n", fmt.cfFormat,
1271 GetClipboardFormatNameA(fmt.cfFormat, fmt_name, sizeof(fmt_name)-1) ? fmt_name : "");
1273 SetClipboardData(fmt.cfFormat, NULL);
1276 priv_data->entries[idx].fmtetc = fmt;
1279 memcpy((char*)priv_data + target_offset, fmt.ptd, fmt.ptd->tdSize);
1280 priv_data->entries[idx].fmtetc.ptd = (DVTARGETDEVICE*)target_offset;
1281 target_offset += fmt.ptd->tdSize;
1282 CoTaskMemFree(fmt.ptd);
1285 priv_data->entries[idx].first_use = !is_format_in_list(priv_data->entries, idx, fmt.cfFormat);
1286 priv_data->entries[idx].unk[0] = 0;
1287 priv_data->entries[idx].unk[1] = 0;
1292 IEnumFORMATETC_Release(enum_fmt);
1294 GlobalUnlock(priv_data_handle);
1295 SetClipboardData(ole_priv_data_clipboard_format, priv_data_handle);
1300 /*********************************************************************
1301 * set_dataobject_format
1303 * Windows creates a 'DataObject' clipboard format that contains the
1304 * clipboard window's HWND or NULL if the Ole clipboard has been flushed.
1306 static HRESULT set_dataobject_format(HWND hwnd)
1308 HGLOBAL h = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE, sizeof(hwnd));
1311 if(!h) return E_OUTOFMEMORY;
1313 data = GlobalLock(h);
1317 if(!SetClipboardData(dataobject_clipboard_format, h))
1320 return CLIPBRD_E_CANT_SET;
1326 /*---------------------------------------------------------------------*
1327 * Win32 OLE clipboard API
1328 *---------------------------------------------------------------------*/
1330 /***********************************************************************
1331 * OleSetClipboard [OLE32.@]
1332 * Places a pointer to the specified data object onto the clipboard,
1333 * making the data object accessible to the OleGetClipboard function.
1337 * S_OK IDataObject pointer placed on the clipboard
1338 * CLIPBRD_E_CANT_OPEN OpenClipboard failed
1339 * CLIPBRD_E_CANT_EMPTY EmptyClipboard failed
1340 * CLIPBRD_E_CANT_CLOSE CloseClipboard failed
1341 * CLIPBRD_E_CANT_SET SetClipboard failed
1344 HRESULT WINAPI OleSetClipboard(IDataObject* pDataObj)
1347 struct oletls *info = COM_CurrentInfo();
1349 TRACE("(%p)\n", pDataObj);
1352 WARN("Could not allocate tls\n");
1354 if(!info->ole_inits)
1355 return CO_E_NOTINITIALIZED;
1357 OLEClipbrd_Initialize();
1360 * If the Ole clipboard window hasn't been created yet, create it now.
1362 if ( !theOleClipboard->hWndClipboard )
1363 theOleClipboard->hWndClipboard = OLEClipbrd_CreateWindow();
1365 if ( !theOleClipboard->hWndClipboard ) return E_FAIL;
1367 if ( !OpenClipboard(theOleClipboard->hWndClipboard) ) return CLIPBRD_E_CANT_OPEN;
1370 * Empty the current clipboard and make our window the clipboard owner
1371 * NOTE: This will trigger a WM_DESTROYCLIPBOARD message
1373 if ( !EmptyClipboard() )
1375 hr = CLIPBRD_E_CANT_EMPTY;
1380 * If we are already holding on to an IDataObject first release that.
1382 if ( theOleClipboard->pIDataObjectSrc )
1384 IDataObject_Release(theOleClipboard->pIDataObjectSrc);
1385 theOleClipboard->pIDataObjectSrc = NULL;
1388 /* A NULL value indicates that the clipboard should be emptied. */
1389 theOleClipboard->pIDataObjectSrc = pDataObj;
1392 IDataObject_AddRef(theOleClipboard->pIDataObjectSrc);
1393 hr = set_clipboard_formats(pDataObj);
1394 if(FAILED(hr)) goto end;
1397 hr = set_dataobject_format(theOleClipboard->hWndClipboard);
1401 if ( !CloseClipboard() ) hr = CLIPBRD_E_CANT_CLOSE;
1405 if (theOleClipboard->pIDataObjectSrc)
1407 IDataObject_Release(theOleClipboard->pIDataObjectSrc);
1408 theOleClipboard->pIDataObjectSrc = NULL;
1416 /***********************************************************************
1417 * OleGetClipboard [OLE32.@]
1418 * Returns a pointer to our internal IDataObject which represents the conceptual
1419 * state of the Windows clipboard. If the current clipboard already contains
1420 * an IDataObject, our internal IDataObject will delegate to this object.
1422 HRESULT WINAPI OleGetClipboard(IDataObject** ppDataObj)
1428 * Make sure we have a clipboard object
1430 OLEClipbrd_Initialize();
1432 if (!theOleClipboard)
1433 return E_OUTOFMEMORY;
1435 /* Return a reference counted IDataObject */
1436 hr = IDataObject_QueryInterface( (IDataObject*)&(theOleClipboard->lpvtbl),
1437 &IID_IDataObject, (void**)ppDataObj);
1441 /******************************************************************************
1442 * OleFlushClipboard [OLE32.@]
1443 * Renders the data from the source IDataObject into the windows clipboard
1445 * TODO: OleFlushClipboard needs to additionally handle TYMED_IStorage media
1446 * by copying the storage into global memory. Subsequently the default
1447 * data object exposed through OleGetClipboard must convert this TYMED_HGLOBAL
1448 * back to TYMED_IStorage.
1450 HRESULT WINAPI OleFlushClipboard(void)
1452 IEnumFORMATETC* penumFormatetc = NULL;
1458 OLEClipbrd_Initialize();
1461 * Already flushed or no source DataObject? Nothing to do.
1463 if (!theOleClipboard->pIDataObjectSrc)
1466 if (!OpenClipboard(theOleClipboard->hWndClipboard))
1467 return CLIPBRD_E_CANT_OPEN;
1470 * Render all HGLOBAL formats supported by the source into
1471 * the windows clipboard.
1473 if ( FAILED( hr = IDataObject_EnumFormatEtc( theOleClipboard->pIDataObjectSrc,
1479 while ( S_OK == IEnumFORMATETC_Next(penumFormatetc, 1, &rgelt, NULL) )
1481 if ( rgelt.tymed == TYMED_HGLOBAL )
1484 TRACE("(cfFormat=%d:%s)\n", rgelt.cfFormat,
1485 GetClipboardFormatNameA(rgelt.cfFormat, szFmtName, sizeof(szFmtName)-1)
1488 if ( FAILED(OLEClipbrd_RenderFormat( theOleClipboard->pIDataObjectSrc, &rgelt )) )
1493 IEnumFORMATETC_Release(penumFormatetc);
1495 hr = set_dataobject_format(NULL);
1497 IDataObject_Release(theOleClipboard->pIDataObjectSrc);
1498 theOleClipboard->pIDataObjectSrc = NULL;
1502 if ( !CloseClipboard() ) hr = CLIPBRD_E_CANT_CLOSE;
1508 /***********************************************************************
1509 * OleIsCurrentClipboard [OLE32.@]
1511 HRESULT WINAPI OleIsCurrentClipboard(IDataObject *pDataObject)
1515 * Make sure we have a clipboard object
1517 OLEClipbrd_Initialize();
1519 if (!theOleClipboard)
1520 return E_OUTOFMEMORY;
1522 if (pDataObject == NULL)
1525 return (pDataObject == theOleClipboard->pIDataObjectSrc) ? S_OK : S_FALSE;