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 /*---------------------------------------------------------------------*
150 * Implementation of the internal IEnumFORMATETC interface returned by
151 * the OLE clipboard's IDataObject.
152 *---------------------------------------------------------------------*/
154 typedef struct enum_fmtetc
156 const IEnumFORMATETCVtbl *lpVtbl;
159 UINT pos; /* current enumerator position */
160 UINT countFmt; /* number of EnumFORMATETC's in array */
161 LPFORMATETC pFmt; /* array of EnumFORMATETC's */
165 * IUnknown implementation of the parent data object.
167 IUnknown* pUnkDataObj;
171 static inline enum_fmtetc *impl_from_IEnumFORMATETC(IEnumFORMATETC *iface)
173 return (enum_fmtetc*)((char*)iface - FIELD_OFFSET(enum_fmtetc, lpVtbl));
176 /************************************************************************
177 * OLEClipbrd_IEnumFORMATETC_QueryInterface (IUnknown)
179 * See Windows documentation for more details on IUnknown methods.
181 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_QueryInterface
182 (LPENUMFORMATETC iface, REFIID riid, LPVOID* ppvObj)
184 enum_fmtetc *This = impl_from_IEnumFORMATETC(iface);
186 TRACE("(%p)->(IID: %s, %p)\n", This, debugstr_guid(riid), ppvObj);
190 if(IsEqualIID(riid, &IID_IUnknown) ||
191 IsEqualIID(riid, &IID_IEnumFORMATETC))
198 IEnumFORMATETC_AddRef((IEnumFORMATETC*)*ppvObj);
199 TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
203 TRACE("-- Interface: E_NOINTERFACE\n");
204 return E_NOINTERFACE;
207 /************************************************************************
208 * OLEClipbrd_IEnumFORMATETC_AddRef (IUnknown)
210 * Since enumerating formats only makes sense when our data object is around,
211 * we insure that it stays as long as we stay by calling our parents IUnknown
212 * for AddRef and Release. But since we are not controlled by the lifetime of
213 * the outer object, we still keep our own reference count in order to
216 static ULONG WINAPI OLEClipbrd_IEnumFORMATETC_AddRef(LPENUMFORMATETC iface)
218 enum_fmtetc *This = impl_from_IEnumFORMATETC(iface);
219 TRACE("(%p)->(count=%u)\n",This, This->ref);
221 if (This->pUnkDataObj)
222 IUnknown_AddRef(This->pUnkDataObj);
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 if (This->pUnkDataObj)
240 IUnknown_Release(This->pUnkDataObj); /* Release parent data object */
242 ref = InterlockedDecrement(&This->ref);
245 TRACE("() - destroying IEnumFORMATETC(%p)\n",This);
246 HeapFree(GetProcessHeap(), 0, This->pFmt);
247 HeapFree(GetProcessHeap(),0,This);
252 /************************************************************************
253 * OLEClipbrd_IEnumFORMATETC_Next (IEnumFORMATETC)
255 * Standard enumerator members for IEnumFORMATETC
257 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Next
258 (LPENUMFORMATETC iface, ULONG celt, FORMATETC *rgelt, ULONG *pceltFethed)
260 enum_fmtetc *This = impl_from_IEnumFORMATETC(iface);
262 HRESULT hres = S_FALSE;
264 TRACE("(%p)->(pos=%u)\n", This, This->pos);
266 if (This->pos < This->countFmt)
268 cfetch = This->countFmt - This->pos;
275 memcpy(rgelt, &This->pFmt[This->pos], cfetch * sizeof(FORMATETC));
285 *pceltFethed = cfetch;
291 /************************************************************************
292 * OLEClipbrd_IEnumFORMATETC_Skip (IEnumFORMATETC)
294 * Standard enumerator members for IEnumFORMATETC
296 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Skip(LPENUMFORMATETC iface, ULONG celt)
298 enum_fmtetc *This = impl_from_IEnumFORMATETC(iface);
299 TRACE("(%p)->(num=%u)\n", This, celt);
302 if (This->pos > This->countFmt)
304 This->pos = This->countFmt;
310 /************************************************************************
311 * OLEClipbrd_IEnumFORMATETC_Reset (IEnumFORMATETC)
313 * Standard enumerator members for IEnumFORMATETC
315 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Reset(LPENUMFORMATETC iface)
317 enum_fmtetc *This = impl_from_IEnumFORMATETC(iface);
318 TRACE("(%p)->()\n", This);
324 static LPENUMFORMATETC OLEClipbrd_IEnumFORMATETC_Construct(UINT cfmt, const FORMATETC afmt[],
325 LPUNKNOWN pUnkDataObj);
327 /************************************************************************
328 * OLEClipbrd_IEnumFORMATETC_Clone (IEnumFORMATETC)
330 * Standard enumerator members for IEnumFORMATETC
332 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Clone
333 (LPENUMFORMATETC iface, LPENUMFORMATETC* ppenum)
335 enum_fmtetc *This = impl_from_IEnumFORMATETC(iface);
338 TRACE("(%p)->(ppenum=%p)\n", This, ppenum);
343 *ppenum = OLEClipbrd_IEnumFORMATETC_Construct(This->countFmt,
347 /* FIXME: This is wrong! */
348 if (FAILED( hr = IEnumFORMATETC_AddRef(*ppenum)))
351 return (*ppenum) ? S_OK : E_OUTOFMEMORY;
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 * OLEClipbrd_IEnumFORMATETC_Construct (UINT, const FORMATETC, LPUNKNOWN)
368 * Creates an IEnumFORMATETC enumerator from an array of FORMATETC
369 * Structures. pUnkOuter is the outer unknown for reference counting only.
370 * NOTE: this does not AddRef the interface.
373 static LPENUMFORMATETC OLEClipbrd_IEnumFORMATETC_Construct(UINT cfmt, const FORMATETC afmt[],
374 LPUNKNOWN pUnkDataObj)
377 DWORD size=cfmt * sizeof(FORMATETC);
379 ef = HeapAlloc(GetProcessHeap(), 0, sizeof(*ef));
385 ef->pUnkDataObj = pUnkDataObj;
389 ef->pFmt = HeapAlloc(GetProcessHeap(), 0, size);
391 memcpy(ef->pFmt, afmt, size);
394 HeapFree(GetProcessHeap(), 0, ef);
398 TRACE("(%p)->()\n",ef);
399 return (LPENUMFORMATETC)ef;
402 /***********************************************************************
403 * OLEClipbrd_GlobalDupMem( HGLOBAL )
404 * Helper method to duplicate an HGLOBAL chunk of memory
406 static HGLOBAL OLEClipbrd_GlobalDupMem( HGLOBAL hGlobalSrc )
409 PVOID pGlobalSrc, pGlobalDest;
415 cBytes = GlobalSize(hGlobalSrc);
419 hGlobalDest = GlobalAlloc( GMEM_DDESHARE|GMEM_MOVEABLE,
424 pGlobalSrc = GlobalLock(hGlobalSrc);
425 pGlobalDest = GlobalLock(hGlobalDest);
426 if ( !pGlobalSrc || !pGlobalDest )
428 GlobalFree(hGlobalDest);
432 memcpy(pGlobalDest, pGlobalSrc, cBytes);
434 GlobalUnlock(hGlobalSrc);
435 GlobalUnlock(hGlobalDest);
440 #define MAX_CLIPFORMAT_NAME 80
442 /***********************************************************************
443 * OLEClipbrd_RenderFormat(LPFORMATETC)
444 * Render the clipboard data. Note that this call will delegate to the
445 * source data object.
446 * Note: This function assumes it is passed an HGLOBAL format to render.
448 static HRESULT OLEClipbrd_RenderFormat(IDataObject *pIDataObject, LPFORMATETC pFormatetc)
453 char szFmtName[MAX_CLIPFORMAT_NAME];
454 ILockBytes *ptrILockBytes = 0;
455 HGLOBAL hStorage = 0;
457 if (!GetClipboardFormatNameA(pFormatetc->cfFormat, szFmtName, MAX_CLIPFORMAT_NAME))
460 /* If embed source */
461 if (!strcmp(szFmtName, CF_EMBEDSOURCE))
463 memset(&std, 0, sizeof(STGMEDIUM));
464 std.tymed = pFormatetc->tymed = TYMED_ISTORAGE;
466 hStorage = GlobalAlloc(GMEM_SHARE|GMEM_MOVEABLE, 0);
467 if (hStorage == NULL)
468 HANDLE_ERROR( E_OUTOFMEMORY );
469 hr = CreateILockBytesOnHGlobal(hStorage, FALSE, &ptrILockBytes);
470 hr = StgCreateDocfileOnILockBytes(ptrILockBytes, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &std.u.pstg);
472 if (FAILED(hr = IDataObject_GetDataHere(theOleClipboard->pIDataObjectSrc, pFormatetc, &std)))
474 WARN("() : IDataObject_GetDataHere failed to render clipboard data! (%x)\n", hr);
475 GlobalFree(hStorage);
479 if (1) /* check whether the presentation data is already -not- present */
483 METAFILEPICT *mfp = 0;
485 fmt2.cfFormat = CF_METAFILEPICT;
487 fmt2.dwAspect = DVASPECT_CONTENT;
489 fmt2.tymed = TYMED_MFPICT;
491 memset(&std2, 0, sizeof(STGMEDIUM));
492 std2.tymed = TYMED_MFPICT;
494 /* Get the metafile picture out of it */
496 if (SUCCEEDED(hr = IDataObject_GetData(theOleClipboard->pIDataObjectSrc, &fmt2, &std2)))
498 mfp = GlobalLock(std2.u.hGlobal);
503 OLECHAR name[]={ 2, 'O', 'l', 'e', 'P', 'r', 'e', 's', '0', '0', '0', 0};
504 IStream *pStream = 0;
506 PresentationDataHeader pdh;
510 CHAR strOleTypeName[51];
511 BYTE OlePresStreamHeader [] =
513 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00,
514 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
515 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
516 0x00, 0x00, 0x00, 0x00
519 nSize = GetMetaFileBitsEx(mfp->hMF, 0, NULL);
521 memset(&pdh, 0, sizeof(PresentationDataHeader));
522 memcpy(&pdh, OlePresStreamHeader, sizeof(OlePresStreamHeader));
524 pdh.dwObjectExtentX = mfp->xExt;
525 pdh.dwObjectExtentY = mfp->yExt;
528 hr = IStorage_CreateStream(std.u.pstg, name, STGM_CREATE|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, 0, &pStream);
530 hr = IStream_Write(pStream, &pdh, sizeof(PresentationDataHeader), NULL);
532 mfBits = HeapAlloc(GetProcessHeap(), 0, nSize);
533 nSize = GetMetaFileBitsEx(mfp->hMF, nSize, mfBits);
535 hr = IStream_Write(pStream, mfBits, nSize, NULL);
537 IStream_Release(pStream);
539 HeapFree(GetProcessHeap(), 0, mfBits);
541 GlobalUnlock(std2.u.hGlobal);
543 ReadClassStg(std.u.pstg, &clsID);
544 ProgIDFromCLSID(&clsID, &strProgID);
546 WideCharToMultiByte( CP_ACP, 0, strProgID, -1, strOleTypeName, sizeof(strOleTypeName), NULL, NULL );
547 OLECONVERT_CreateOleStream(std.u.pstg);
548 OLECONVERT_CreateCompObjStream(std.u.pstg, strOleTypeName);
554 if (FAILED(hr = IDataObject_GetData(pIDataObject, pFormatetc, &std)))
556 WARN("() : IDataObject_GetData failed to render clipboard data! (%x)\n", hr);
557 GlobalFree(hStorage);
561 /* To put a copy back on the clipboard */
563 hStorage = std.u.hGlobal;
567 * Put a copy of the rendered data back on the clipboard
570 if ( !(hDup = OLEClipbrd_GlobalDupMem(hStorage)) )
571 HANDLE_ERROR( E_OUTOFMEMORY );
573 if ( !SetClipboardData( pFormatetc->cfFormat, hDup ) )
576 WARN("() : Failed to set rendered clipboard data into clipboard!\n");
581 ReleaseStgMedium(&std);
587 /***********************************************************************
588 * OLEClipbrd_WndProc(HWND, unsigned, WORD, LONG)
589 * Processes messages sent to the OLE clipboard window.
590 * Note that we will intercept messages in our WndProc only when data
591 * has been placed in the clipboard via OleSetClipboard().
592 * i.e. Only when OLE owns the windows clipboard.
594 static LRESULT CALLBACK OLEClipbrd_WndProc
595 (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
601 * We receive this message to allow us to handle delayed rendering of
602 * a specific clipboard format when an application requests data in
603 * that format by calling GetClipboardData.
604 * (Recall that in OleSetClipboard, we used SetClipboardData to
605 * make all HGLOBAL formats supported by the source IDataObject
606 * available using delayed rendering)
607 * On receiving this message we must actually render the data in the
608 * specified format and place it on the clipboard by calling the
609 * SetClipboardData function.
611 case WM_RENDERFORMAT:
615 ZeroMemory( &rgelt, sizeof(FORMATETC));
618 * Initialize FORMATETC to a Windows clipboard friendly format
620 rgelt.cfFormat = (UINT) wParam;
621 rgelt.dwAspect = DVASPECT_CONTENT;
623 rgelt.tymed = TYMED_HGLOBAL;
625 TRACE("(): WM_RENDERFORMAT(cfFormat=%d)\n", rgelt.cfFormat);
628 * Render the clipboard data.
629 * (We must have a source data object or we wouldn't be in this WndProc)
631 OLEClipbrd_RenderFormat( (IDataObject*)&(theOleClipboard->lpvtbl), &rgelt );
637 * WM_RENDERALLFORMATS
638 * Sent before the clipboard owner window is destroyed.
639 * We should receive this message only when OleUninitialize is called
640 * while we have an IDataObject in the clipboard.
641 * For the content of the clipboard to remain available to other
642 * applications, we must render data in all the formats the source IDataObject
643 * is capable of generating, and place the data on the clipboard by calling
646 case WM_RENDERALLFORMATS:
648 IEnumFORMATETC* penumFormatetc = NULL;
651 TRACE("(): WM_RENDERALLFORMATS\n");
654 * Render all HGLOBAL formats supported by the source into
655 * the windows clipboard.
657 if ( FAILED( IDataObject_EnumFormatEtc( (IDataObject*)&(theOleClipboard->lpvtbl),
658 DATADIR_GET, &penumFormatetc) ) )
660 WARN("(): WM_RENDERALLFORMATS failed to retrieve EnumFormatEtc!\n");
664 while ( S_OK == IEnumFORMATETC_Next(penumFormatetc, 1, &rgelt, NULL) )
666 if ( rgelt.tymed == TYMED_HGLOBAL )
669 * Render the clipboard data.
671 if ( FAILED(OLEClipbrd_RenderFormat( (IDataObject*)&(theOleClipboard->lpvtbl), &rgelt )) )
674 TRACE("(): WM_RENDERALLFORMATS(cfFormat=%d)\n", rgelt.cfFormat);
678 IEnumFORMATETC_Release(penumFormatetc);
684 * WM_DESTROYCLIPBOARD
685 * This is sent by EmptyClipboard before the clipboard is emptied.
686 * We should release any IDataObject we are holding onto when we receive
687 * this message, since it indicates that the OLE clipboard should be empty
688 * from this point on.
690 case WM_DESTROYCLIPBOARD:
692 TRACE("(): WM_DESTROYCLIPBOARD\n");
694 * Release the data object we are holding on to
696 if ( theOleClipboard->pIDataObjectSrc )
698 IDataObject_Release(theOleClipboard->pIDataObjectSrc);
699 theOleClipboard->pIDataObjectSrc = NULL;
705 case WM_ASKCBFORMATNAME:
706 case WM_CHANGECBCHAIN:
707 case WM_DRAWCLIPBOARD:
708 case WM_SIZECLIPBOARD:
709 case WM_HSCROLLCLIPBOARD:
710 case WM_VSCROLLCLIPBOARD:
711 case WM_PAINTCLIPBOARD:
714 return DefWindowProcA(hWnd, message, wParam, lParam);
721 /*---------------------------------------------------------------------*
722 * Implementation of the internal IDataObject interface exposed by
724 *---------------------------------------------------------------------*/
727 /************************************************************************
728 * OLEClipbrd_IDataObject_QueryInterface (IUnknown)
730 * See Windows documentation for more details on IUnknown methods.
732 static HRESULT WINAPI OLEClipbrd_IDataObject_QueryInterface(
737 ole_clipbrd *This = impl_from_IDataObject(iface);
738 TRACE("(%p)->(IID:%s, %p)\n", This, debugstr_guid(riid), ppvObject);
740 if ( (This==0) || (ppvObject==0) )
745 if (IsEqualIID(&IID_IUnknown, riid) ||
746 IsEqualIID(&IID_IDataObject, riid))
752 WARN( "() : asking for unsupported interface %s\n", debugstr_guid(riid));
753 return E_NOINTERFACE;
756 IUnknown_AddRef((IUnknown*)*ppvObject);
761 /************************************************************************
762 * OLEClipbrd_IDataObject_AddRef (IUnknown)
764 * See Windows documentation for more details on IUnknown methods.
766 static ULONG WINAPI OLEClipbrd_IDataObject_AddRef(
769 ole_clipbrd *This = impl_from_IDataObject(iface);
771 TRACE("(%p)->(count=%u)\n",This, This->ref);
773 return InterlockedIncrement(&This->ref);
776 /***********************************************************************
777 * OLEClipbrd_DestroyWindow(HWND)
778 * Destroy the clipboard window and unregister its class
780 static void OLEClipbrd_DestroyWindow(HWND hwnd)
783 UnregisterClassA( OLEClipbrd_WNDCLASS, 0 );
786 static void OLEClipbrd_Destroy(ole_clipbrd* This)
792 theOleClipboard = NULL;
794 if ( This->hWndClipboard )
795 OLEClipbrd_DestroyWindow(This->hWndClipboard);
797 HeapFree(GetProcessHeap(), 0, This);
800 /************************************************************************
801 * OLEClipbrd_IDataObject_Release (IUnknown)
803 * See Windows documentation for more details on IUnknown methods.
805 static ULONG WINAPI OLEClipbrd_IDataObject_Release(
808 ole_clipbrd *This = impl_from_IDataObject(iface);
811 TRACE("(%p)->(count=%u)\n",This, This->ref);
813 ref = InterlockedDecrement(&This->ref);
817 OLEClipbrd_Destroy(This);
824 /************************************************************************
825 * OLEClipbrd_IDataObject_GetData (IDataObject)
827 * The OLE Clipboard's implementation of this method delegates to
828 * a data source if there is one or wraps around the windows clipboard
830 * See Windows documentation for more details on IDataObject methods.
832 static HRESULT WINAPI OLEClipbrd_IDataObject_GetData(
834 LPFORMATETC pformatetcIn,
838 BOOL bClipboardOpen = FALSE;
841 ole_clipbrd *This = impl_from_IDataObject(iface);
843 TRACE("(%p,%p,%p)\n", iface, pformatetcIn, pmedium);
845 if ( !pformatetcIn || !pmedium )
849 * If we have a data source placed on the clipboard (via OleSetClipboard)
850 * simply delegate to the source object's QueryGetData
851 * NOTE: This code assumes that the IDataObject is in the same address space!
852 * We will need to add marshalling support when Wine handles multiple processes.
854 if ( This->pIDataObjectSrc )
856 return IDataObject_GetData(This->pIDataObjectSrc, pformatetcIn, pmedium);
859 if ( pformatetcIn->lindex != -1 )
860 return DV_E_FORMATETC;
862 if ( (pformatetcIn->tymed & TYMED_HGLOBAL) != TYMED_HGLOBAL )
865 if ( pformatetcIn->dwAspect != DVASPECT_CONTENT )
866 return DV_E_DVASPECT;
870 * Otherwise, get the data from the windows clipboard using GetClipboardData
872 if ( !(bClipboardOpen = OpenClipboard(theOleClipboard->hWndClipboard)) )
873 HANDLE_ERROR( CLIPBRD_E_CANT_OPEN );
875 hData = GetClipboardData(pformatetcIn->cfFormat);
877 /* Must make a copy of global handle returned by GetClipboardData; it
878 * is not valid after we call CloseClipboard
879 * Application is responsible for freeing the memory (Forte Agent does this)
881 src = GlobalLock(hData);
887 size = GlobalSize(hData);
888 hDest = GlobalAlloc(GHND, size);
889 dest = GlobalLock(hDest);
890 memcpy(dest, src, size);
897 * Return the clipboard data in the storage medium structure
899 pmedium->tymed = (hData == 0) ? TYMED_NULL : TYMED_HGLOBAL;
900 pmedium->u.hGlobal = hData;
901 pmedium->pUnkForRelease = NULL;
907 * Close Windows clipboard
909 if ( bClipboardOpen && !CloseClipboard() )
910 hr = CLIPBRD_E_CANT_CLOSE;
914 return (hData == 0) ? DV_E_FORMATETC : S_OK;
917 static HRESULT WINAPI OLEClipbrd_IDataObject_GetDataHere(
919 LPFORMATETC pformatetc,
926 /************************************************************************
927 * OLEClipbrd_IDataObject_QueryGetData (IDataObject)
929 * The OLE Clipboard's implementation of this method delegates to
930 * a data source if there is one or wraps around the windows clipboard
931 * function IsClipboardFormatAvailable() otherwise.
933 * See Windows documentation for more details on IDataObject methods.
935 static HRESULT WINAPI OLEClipbrd_IDataObject_QueryGetData(
937 LPFORMATETC pformatetc)
939 TRACE("(%p, %p)\n", iface, pformatetc);
944 if ( pformatetc->dwAspect != DVASPECT_CONTENT )
945 return DV_E_FORMATETC;
947 if ( pformatetc->lindex != -1 )
948 return DV_E_FORMATETC;
951 * Delegate to the Windows clipboard function IsClipboardFormatAvailable
953 return (IsClipboardFormatAvailable(pformatetc->cfFormat)) ? S_OK : DV_E_CLIPFORMAT;
956 /************************************************************************
957 * OLEClipbrd_IDataObject_GetCanonicalFormatEtc (IDataObject)
959 * See Windows documentation for more details on IDataObject methods.
961 static HRESULT WINAPI OLEClipbrd_IDataObject_GetCanonicalFormatEtc(
963 LPFORMATETC pformatectIn,
964 LPFORMATETC pformatetcOut)
966 TRACE("(%p, %p, %p)\n", iface, pformatectIn, pformatetcOut);
968 if ( !pformatectIn || !pformatetcOut )
971 *pformatetcOut = *pformatectIn;
972 return DATA_S_SAMEFORMATETC;
975 /************************************************************************
976 * OLEClipbrd_IDataObject_SetData (IDataObject)
978 * The OLE Clipboard's does not implement this method
980 * See Windows documentation for more details on IDataObject methods.
982 static HRESULT WINAPI OLEClipbrd_IDataObject_SetData(
984 LPFORMATETC pformatetc,
992 /************************************************************************
993 * OLEClipbrd_IDataObject_EnumFormatEtc (IDataObject)
995 * See Windows documentation for more details on IDataObject methods.
997 static HRESULT WINAPI OLEClipbrd_IDataObject_EnumFormatEtc(
1000 IEnumFORMATETC** ppenumFormatEtc)
1003 FORMATETC *afmt = NULL;
1006 BOOL bClipboardOpen;
1007 ole_clipbrd *This = impl_from_IDataObject(iface);
1009 TRACE("(%p, %x, %p)\n", iface, dwDirection, ppenumFormatEtc);
1012 * If we have a data source placed on the clipboard (via OleSetClipboard)
1013 * simply delegate to the source object's EnumFormatEtc
1015 if ( This->pIDataObjectSrc )
1017 return IDataObject_EnumFormatEtc(This->pIDataObjectSrc,
1018 dwDirection, ppenumFormatEtc);
1022 * Otherwise we must provide our own enumerator which wraps around the
1023 * Windows clipboard function EnumClipboardFormats
1025 if ( !ppenumFormatEtc )
1026 return E_INVALIDARG;
1028 if ( dwDirection != DATADIR_GET ) /* IDataObject_SetData not implemented */
1032 * Store all current clipboard formats in an array of FORMATETC's,
1033 * and create an IEnumFORMATETC enumerator from this list.
1035 cfmt = CountClipboardFormats();
1036 afmt = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1037 sizeof(FORMATETC) * cfmt);
1039 * Open the Windows clipboard, associating it with our hidden window
1041 if ( !(bClipboardOpen = OpenClipboard(This->hWndClipboard)) )
1042 HANDLE_ERROR( CLIPBRD_E_CANT_OPEN );
1045 * Store all current clipboard formats in an array of FORMATETC's
1046 * TODO: Handle TYMED_IStorage media which were put on the clipboard
1047 * by copying the storage into global memory. We must convert this
1048 * TYMED_HGLOBAL back to TYMED_IStorage.
1050 for (i = 0, format = 0; i < cfmt; i++)
1052 format = EnumClipboardFormats(format);
1053 if (!format) /* Failed! */
1055 ERR("EnumClipboardFormats failed to return format!\n");
1056 HANDLE_ERROR( E_FAIL );
1059 /* Init the FORMATETC struct */
1060 afmt[i].cfFormat = format;
1062 afmt[i].dwAspect = DVASPECT_CONTENT;
1063 afmt[i].lindex = -1;
1064 afmt[i].tymed = TYMED_HGLOBAL;
1068 * Create an EnumFORMATETC enumerator and return an
1069 * EnumFORMATETC after bumping up its ref count
1071 *ppenumFormatEtc = OLEClipbrd_IEnumFORMATETC_Construct( cfmt, afmt, (LPUNKNOWN)iface);
1072 if (!(*ppenumFormatEtc))
1073 HANDLE_ERROR( E_OUTOFMEMORY );
1075 if (FAILED( hr = IEnumFORMATETC_AddRef(*ppenumFormatEtc)))
1082 * Free the array of FORMATETC's
1084 HeapFree(GetProcessHeap(), 0, afmt);
1087 * Close Windows clipboard
1089 if ( bClipboardOpen && !CloseClipboard() )
1090 hr = CLIPBRD_E_CANT_CLOSE;
1095 /************************************************************************
1096 * OLEClipbrd_IDataObject_DAdvise (IDataObject)
1098 * The OLE Clipboard's does not implement this method
1100 * See Windows documentation for more details on IDataObject methods.
1102 static HRESULT WINAPI OLEClipbrd_IDataObject_DAdvise(
1104 FORMATETC* pformatetc,
1106 IAdviseSink* pAdvSink,
1107 DWORD* pdwConnection)
1113 /************************************************************************
1114 * OLEClipbrd_IDataObject_DUnadvise (IDataObject)
1116 * The OLE Clipboard's does not implement this method
1118 * See Windows documentation for more details on IDataObject methods.
1120 static HRESULT WINAPI OLEClipbrd_IDataObject_DUnadvise(
1128 /************************************************************************
1129 * OLEClipbrd_IDataObject_EnumDAdvise (IDataObject)
1131 * The OLE Clipboard does not implement this method
1133 * See Windows documentation for more details on IDataObject methods.
1135 static HRESULT WINAPI OLEClipbrd_IDataObject_EnumDAdvise(
1137 IEnumSTATDATA** ppenumAdvise)
1143 static const IDataObjectVtbl OLEClipbrd_IDataObject_VTable =
1145 OLEClipbrd_IDataObject_QueryInterface,
1146 OLEClipbrd_IDataObject_AddRef,
1147 OLEClipbrd_IDataObject_Release,
1148 OLEClipbrd_IDataObject_GetData,
1149 OLEClipbrd_IDataObject_GetDataHere,
1150 OLEClipbrd_IDataObject_QueryGetData,
1151 OLEClipbrd_IDataObject_GetCanonicalFormatEtc,
1152 OLEClipbrd_IDataObject_SetData,
1153 OLEClipbrd_IDataObject_EnumFormatEtc,
1154 OLEClipbrd_IDataObject_DAdvise,
1155 OLEClipbrd_IDataObject_DUnadvise,
1156 OLEClipbrd_IDataObject_EnumDAdvise
1159 /*---------------------------------------------------------------------*
1160 * Internal implementation methods for the OLE clipboard
1161 *---------------------------------------------------------------------*/
1163 /*********************************************************
1164 * Construct the OLEClipbrd class.
1166 static ole_clipbrd* OLEClipbrd_Construct(void)
1170 This = HeapAlloc( GetProcessHeap(), 0, sizeof(*This) );
1171 if (!This) return NULL;
1173 This->lpvtbl = &OLEClipbrd_IDataObject_VTable;
1176 This->hWndClipboard = NULL;
1177 This->pIDataObjectSrc = NULL;
1179 theOleClipboard = This;
1183 static void register_clipboard_formats(void)
1185 static const WCHAR DataObjectW[] = { 'D','a','t','a','O','b','j','e','c','t',0 };
1186 static const WCHAR OlePrivateDataW[] = { 'O','l','e',' ','P','r','i','v','a','t','e',' ','D','a','t','a',0 };
1188 if(!dataobject_clipboard_format)
1189 dataobject_clipboard_format = RegisterClipboardFormatW(DataObjectW);
1190 if(!ole_priv_data_clipboard_format)
1191 ole_priv_data_clipboard_format = RegisterClipboardFormatW(OlePrivateDataW);
1194 /***********************************************************************
1195 * OLEClipbrd_Initialize()
1196 * Initializes the OLE clipboard.
1198 void OLEClipbrd_Initialize(void)
1200 register_clipboard_formats();
1202 if ( !theOleClipboard )
1205 theOleClipboard = OLEClipbrd_Construct();
1210 /***********************************************************************
1211 * OLEClipbrd_UnInitialize()
1212 * Un-Initializes the OLE clipboard
1214 void OLEClipbrd_UnInitialize(void)
1218 * Destroy the clipboard if no one holds a reference to us.
1219 * Note that the clipboard was created with a reference count of 1.
1221 if ( theOleClipboard && (theOleClipboard->ref <= 1) )
1223 OLEClipbrd_Destroy( theOleClipboard );
1227 WARN( "() : OLEClipbrd_UnInitialize called while client holds an IDataObject reference!\n");
1231 /***********************************************************************
1232 * OLEClipbrd_CreateWindow()
1233 * Create the clipboard window
1235 static HWND OLEClipbrd_CreateWindow(void)
1241 * Register the clipboard window class if necessary
1243 ZeroMemory( &wcex, sizeof(WNDCLASSEXA));
1245 wcex.cbSize = sizeof(WNDCLASSEXA);
1246 /* Windows creates this class with a style mask of 0
1247 * We don't bother doing this since the FindClassByAtom code
1248 * would have to be changed to deal with this idiosyncrasy. */
1249 wcex.style = CS_GLOBALCLASS;
1250 wcex.lpfnWndProc = OLEClipbrd_WndProc;
1252 wcex.lpszClassName = OLEClipbrd_WNDCLASS;
1254 RegisterClassExA(&wcex);
1257 * Create a hidden window to receive OLE clipboard messages
1261 * If we need to store state info we can store it here.
1262 * For now we don't need this functionality.
1263 * ClipboardWindowInfo clipboardInfo;
1264 * ZeroMemory( &trackerInfo, sizeof(ClipboardWindowInfo));
1267 hwnd = CreateWindowA(OLEClipbrd_WNDCLASS,
1269 WS_POPUP | WS_CLIPSIBLINGS | WS_OVERLAPPED,
1270 CW_USEDEFAULT, CW_USEDEFAULT,
1271 CW_USEDEFAULT, CW_USEDEFAULT,
1275 0 /*(LPVOID)&clipboardInfo */);
1280 static inline BOOL is_format_in_list(ole_priv_data_entry *entries, DWORD num, UINT cf)
1283 for(i = 0; i < num; i++)
1284 if(entries[i].fmtetc.cfFormat == cf)
1290 /*********************************************************************
1291 * set_clipboard_formats
1293 * Enumerate all HGLOBAL formats supported by the source and make
1294 * those formats available using delayed rendering using SetClipboardData.
1296 * TODO: We need to additionally handle TYMED_IStorage and
1297 * TYMED_IStream data by copying into global memory.
1299 static HRESULT set_clipboard_formats(IDataObject *data)
1303 IEnumFORMATETC *enum_fmt;
1304 HGLOBAL priv_data_handle;
1305 DWORD target_offset;
1306 ole_priv_data *priv_data;
1307 DWORD count = 0, needed = sizeof(*priv_data), idx;
1309 hr = IDataObject_EnumFormatEtc(data, DATADIR_GET, &enum_fmt);
1310 if(FAILED(hr)) return hr;
1312 while(IEnumFORMATETC_Next(enum_fmt, 1, &fmt, NULL) == S_OK)
1315 needed += sizeof(priv_data->entries[0]);
1318 needed += fmt.ptd->tdSize;
1319 CoTaskMemFree(fmt.ptd);
1323 /* Windows pads the list with two empty ole_priv_data_entries, one
1324 * after the entries array and one after the target device data.
1325 * Allocating with zero init to zero these pads. */
1327 needed += sizeof(priv_data->entries[0]); /* initialisation of needed includes one of these. */
1328 priv_data_handle = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE | GMEM_ZEROINIT, needed);
1329 priv_data = GlobalLock(priv_data_handle);
1331 priv_data->unk1 = 0;
1332 priv_data->size = needed;
1333 priv_data->unk2 = 1;
1334 priv_data->count = count;
1335 priv_data->unk3[0] = 0;
1336 priv_data->unk3[1] = 0;
1338 IEnumFORMATETC_Reset(enum_fmt);
1341 target_offset = FIELD_OFFSET(ole_priv_data, entries[count + 1]); /* count entries + one pad. */
1343 while(IEnumFORMATETC_Next(enum_fmt, 1, &fmt, NULL) == S_OK)
1345 if (fmt.tymed == TYMED_HGLOBAL)
1348 TRACE("(cfFormat=%d:%s)\n", fmt.cfFormat,
1349 GetClipboardFormatNameA(fmt.cfFormat, fmt_name, sizeof(fmt_name)-1) ? fmt_name : "");
1351 SetClipboardData(fmt.cfFormat, NULL);
1354 priv_data->entries[idx].fmtetc = fmt;
1357 memcpy((char*)priv_data + target_offset, fmt.ptd, fmt.ptd->tdSize);
1358 priv_data->entries[idx].fmtetc.ptd = (DVTARGETDEVICE*)target_offset;
1359 target_offset += fmt.ptd->tdSize;
1360 CoTaskMemFree(fmt.ptd);
1363 priv_data->entries[idx].first_use = !is_format_in_list(priv_data->entries, idx, fmt.cfFormat);
1364 priv_data->entries[idx].unk[0] = 0;
1365 priv_data->entries[idx].unk[1] = 0;
1370 IEnumFORMATETC_Release(enum_fmt);
1372 GlobalUnlock(priv_data_handle);
1373 SetClipboardData(ole_priv_data_clipboard_format, priv_data_handle);
1378 /*********************************************************************
1379 * set_dataobject_format
1381 * Windows creates a 'DataObject' clipboard format that contains the
1382 * clipboard window's HWND or NULL if the Ole clipboard has been flushed.
1384 static HRESULT set_dataobject_format(HWND hwnd)
1386 HGLOBAL h = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE, sizeof(hwnd));
1389 if(!h) return E_OUTOFMEMORY;
1391 data = GlobalLock(h);
1395 if(!SetClipboardData(dataobject_clipboard_format, h))
1398 return CLIPBRD_E_CANT_SET;
1404 /*---------------------------------------------------------------------*
1405 * Win32 OLE clipboard API
1406 *---------------------------------------------------------------------*/
1408 /***********************************************************************
1409 * OleSetClipboard [OLE32.@]
1410 * Places a pointer to the specified data object onto the clipboard,
1411 * making the data object accessible to the OleGetClipboard function.
1415 * S_OK IDataObject pointer placed on the clipboard
1416 * CLIPBRD_E_CANT_OPEN OpenClipboard failed
1417 * CLIPBRD_E_CANT_EMPTY EmptyClipboard failed
1418 * CLIPBRD_E_CANT_CLOSE CloseClipboard failed
1419 * CLIPBRD_E_CANT_SET SetClipboard failed
1422 HRESULT WINAPI OleSetClipboard(IDataObject* pDataObj)
1425 BOOL bClipboardOpen = FALSE;
1426 struct oletls *info = COM_CurrentInfo();
1428 TRACE("(%p)\n", pDataObj);
1431 WARN("Could not allocate tls\n");
1433 if(!info->ole_inits)
1434 return CO_E_NOTINITIALIZED;
1437 * Make sure we have a clipboard object
1439 OLEClipbrd_Initialize();
1442 * If the Ole clipboard window hasn't been created yet, create it now.
1444 if ( !theOleClipboard->hWndClipboard )
1445 theOleClipboard->hWndClipboard = OLEClipbrd_CreateWindow();
1447 if ( !theOleClipboard->hWndClipboard ) /* sanity check */
1448 HANDLE_ERROR( E_FAIL );
1451 * Open the Windows clipboard, associating it with our hidden window
1453 if ( !(bClipboardOpen = OpenClipboard(theOleClipboard->hWndClipboard)) )
1454 HANDLE_ERROR( CLIPBRD_E_CANT_OPEN );
1457 * Empty the current clipboard and make our window the clipboard owner
1458 * NOTE: This will trigger a WM_DESTROYCLIPBOARD message
1460 if ( !EmptyClipboard() )
1461 HANDLE_ERROR( CLIPBRD_E_CANT_EMPTY );
1464 * If we are already holding on to an IDataObject first release that.
1466 if ( theOleClipboard->pIDataObjectSrc )
1468 IDataObject_Release(theOleClipboard->pIDataObjectSrc);
1469 theOleClipboard->pIDataObjectSrc = NULL;
1472 /* A NULL value indicates that the clipboard should be emptied. */
1473 theOleClipboard->pIDataObjectSrc = pDataObj;
1476 IDataObject_AddRef(theOleClipboard->pIDataObjectSrc);
1477 hr = set_clipboard_formats(pDataObj);
1478 if(FAILED(hr)) goto CLEANUP;
1481 hr = set_dataobject_format(theOleClipboard->hWndClipboard);
1486 * Close Windows clipboard (It remains associated with our window)
1488 if ( bClipboardOpen && !CloseClipboard() )
1489 hr = CLIPBRD_E_CANT_CLOSE;
1492 * Release the source IDataObject if something failed
1496 if (theOleClipboard->pIDataObjectSrc)
1498 IDataObject_Release(theOleClipboard->pIDataObjectSrc);
1499 theOleClipboard->pIDataObjectSrc = NULL;
1507 /***********************************************************************
1508 * OleGetClipboard [OLE32.@]
1509 * Returns a pointer to our internal IDataObject which represents the conceptual
1510 * state of the Windows clipboard. If the current clipboard already contains
1511 * an IDataObject, our internal IDataObject will delegate to this object.
1513 HRESULT WINAPI OleGetClipboard(IDataObject** ppDataObj)
1519 * Make sure we have a clipboard object
1521 OLEClipbrd_Initialize();
1523 if (!theOleClipboard)
1524 return E_OUTOFMEMORY;
1526 /* Return a reference counted IDataObject */
1527 hr = IDataObject_QueryInterface( (IDataObject*)&(theOleClipboard->lpvtbl),
1528 &IID_IDataObject, (void**)ppDataObj);
1532 /******************************************************************************
1533 * OleFlushClipboard [OLE32.@]
1534 * Renders the data from the source IDataObject into the windows clipboard
1536 * TODO: OleFlushClipboard needs to additionally handle TYMED_IStorage media
1537 * by copying the storage into global memory. Subsequently the default
1538 * data object exposed through OleGetClipboard must convert this TYMED_HGLOBAL
1539 * back to TYMED_IStorage.
1541 HRESULT WINAPI OleFlushClipboard(void)
1543 IEnumFORMATETC* penumFormatetc = NULL;
1546 BOOL bClipboardOpen = FALSE;
1550 OLEClipbrd_Initialize();
1553 * Already flushed or no source DataObject? Nothing to do.
1555 if (!theOleClipboard->pIDataObjectSrc)
1558 if ( !(bClipboardOpen = OpenClipboard(theOleClipboard->hWndClipboard)) )
1559 HANDLE_ERROR( CLIPBRD_E_CANT_OPEN );
1562 * Render all HGLOBAL formats supported by the source into
1563 * the windows clipboard.
1565 if ( FAILED( hr = IDataObject_EnumFormatEtc( theOleClipboard->pIDataObjectSrc,
1572 while ( S_OK == IEnumFORMATETC_Next(penumFormatetc, 1, &rgelt, NULL) )
1574 if ( rgelt.tymed == TYMED_HGLOBAL )
1577 TRACE("(cfFormat=%d:%s)\n", rgelt.cfFormat,
1578 GetClipboardFormatNameA(rgelt.cfFormat, szFmtName, sizeof(szFmtName)-1)
1581 if ( FAILED(OLEClipbrd_RenderFormat( theOleClipboard->pIDataObjectSrc, &rgelt )) )
1586 IEnumFORMATETC_Release(penumFormatetc);
1588 hr = set_dataobject_format(NULL);
1590 IDataObject_Release(theOleClipboard->pIDataObjectSrc);
1591 theOleClipboard->pIDataObjectSrc = NULL;
1595 if ( bClipboardOpen && !CloseClipboard() )
1596 hr = CLIPBRD_E_CANT_CLOSE;
1602 /***********************************************************************
1603 * OleIsCurrentClipboard [OLE32.@]
1605 HRESULT WINAPI OleIsCurrentClipboard(IDataObject *pDataObject)
1609 * Make sure we have a clipboard object
1611 OLEClipbrd_Initialize();
1613 if (!theOleClipboard)
1614 return E_OUTOFMEMORY;
1616 if (pDataObject == NULL)
1619 return (pDataObject == theOleClipboard->pIDataObjectSrc) ? S_OK : S_FALSE;