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 /****************************************************************************
109 * IEnumFORMATETC implementation
110 * DO NOT add any members before the VTables declaration!
114 /* IEnumFORMATETC VTable */
115 const IEnumFORMATETCVtbl *lpVtbl;
117 /* IEnumFORMATETC fields */
118 UINT posFmt; /* current enumerator position */
119 UINT countFmt; /* number of EnumFORMATETC's in array */
120 LPFORMATETC pFmt; /* array of EnumFORMATETC's */
123 * Reference count of this object
128 * IUnknown implementation of the parent data object.
130 IUnknown* pUnkDataObj;
132 } IEnumFORMATETCImpl;
134 typedef struct PresentationDataHeader
137 DWORD dwObjectExtentX;
138 DWORD dwObjectExtentY;
140 } PresentationDataHeader;
143 * The one and only ole_clipbrd object which is created by OLEClipbrd_Initialize()
145 static ole_clipbrd* theOleClipboard;
149 * Name of our registered OLE clipboard window class
151 static const CHAR OLEClipbrd_WNDCLASS[] = "CLIPBRDWNDCLASS";
154 * If we need to store state info we can store it here.
155 * For now we don't need this functionality.
157 typedef struct tagClipboardWindowInfo
159 } ClipboardWindowInfo;
162 /*---------------------------------------------------------------------*
163 * Implementation of the internal IEnumFORMATETC interface returned by
164 * the OLE clipboard's IDataObject.
165 *---------------------------------------------------------------------*/
167 /************************************************************************
168 * OLEClipbrd_IEnumFORMATETC_QueryInterface (IUnknown)
170 * See Windows documentation for more details on IUnknown methods.
172 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_QueryInterface
173 (LPENUMFORMATETC iface, REFIID riid, LPVOID* ppvObj)
175 IEnumFORMATETCImpl *This = (IEnumFORMATETCImpl *)iface;
177 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
180 * Since enumerators are separate objects from the parent data object
181 * we only need to support the IUnknown and IEnumFORMATETC interfaces
186 if(IsEqualIID(riid, &IID_IUnknown) ||
187 IsEqualIID(riid, &IID_IEnumFORMATETC))
194 IEnumFORMATETC_AddRef((IEnumFORMATETC*)*ppvObj);
195 TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
199 TRACE("-- Interface: E_NOINTERFACE\n");
200 return E_NOINTERFACE;
203 /************************************************************************
204 * OLEClipbrd_IEnumFORMATETC_AddRef (IUnknown)
206 * Since enumerating formats only makes sense when our data object is around,
207 * we insure that it stays as long as we stay by calling our parents IUnknown
208 * for AddRef and Release. But since we are not controlled by the lifetime of
209 * the outer object, we still keep our own reference count in order to
212 static ULONG WINAPI OLEClipbrd_IEnumFORMATETC_AddRef(LPENUMFORMATETC iface)
214 IEnumFORMATETCImpl *This = (IEnumFORMATETCImpl *)iface;
215 TRACE("(%p)->(count=%u)\n",This, This->ref);
217 if (This->pUnkDataObj)
218 IUnknown_AddRef(This->pUnkDataObj);
220 return InterlockedIncrement(&This->ref);
223 /************************************************************************
224 * OLEClipbrd_IEnumFORMATETC_Release (IUnknown)
226 * See Windows documentation for more details on IUnknown methods.
228 static ULONG WINAPI OLEClipbrd_IEnumFORMATETC_Release(LPENUMFORMATETC iface)
230 IEnumFORMATETCImpl *This = (IEnumFORMATETCImpl *)iface;
233 TRACE("(%p)->(count=%u)\n",This, This->ref);
235 if (This->pUnkDataObj)
236 IUnknown_Release(This->pUnkDataObj); /* Release parent data object */
238 ref = InterlockedDecrement(&This->ref);
241 TRACE("() - destroying IEnumFORMATETC(%p)\n",This);
242 HeapFree(GetProcessHeap(), 0, This->pFmt);
243 HeapFree(GetProcessHeap(),0,This);
248 /************************************************************************
249 * OLEClipbrd_IEnumFORMATETC_Next (IEnumFORMATETC)
251 * Standard enumerator members for IEnumFORMATETC
253 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Next
254 (LPENUMFORMATETC iface, ULONG celt, FORMATETC *rgelt, ULONG *pceltFethed)
256 IEnumFORMATETCImpl *This = (IEnumFORMATETCImpl *)iface;
258 HRESULT hres = S_FALSE;
260 TRACE("(%p)->(pos=%u)\n", This, This->posFmt);
262 if (This->posFmt < This->countFmt)
264 cfetch = This->countFmt - This->posFmt;
271 memcpy(rgelt, &This->pFmt[This->posFmt], cfetch * sizeof(FORMATETC));
272 This->posFmt += cfetch;
281 *pceltFethed = cfetch;
287 /************************************************************************
288 * OLEClipbrd_IEnumFORMATETC_Skip (IEnumFORMATETC)
290 * Standard enumerator members for IEnumFORMATETC
292 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Skip(LPENUMFORMATETC iface, ULONG celt)
294 IEnumFORMATETCImpl *This = (IEnumFORMATETCImpl *)iface;
295 TRACE("(%p)->(num=%u)\n", This, celt);
297 This->posFmt += celt;
298 if (This->posFmt > This->countFmt)
300 This->posFmt = This->countFmt;
306 /************************************************************************
307 * OLEClipbrd_IEnumFORMATETC_Reset (IEnumFORMATETC)
309 * Standard enumerator members for IEnumFORMATETC
311 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Reset(LPENUMFORMATETC iface)
313 IEnumFORMATETCImpl *This = (IEnumFORMATETCImpl *)iface;
314 TRACE("(%p)->()\n", This);
320 static LPENUMFORMATETC OLEClipbrd_IEnumFORMATETC_Construct(UINT cfmt, const FORMATETC afmt[],
321 LPUNKNOWN pUnkDataObj);
323 /************************************************************************
324 * OLEClipbrd_IEnumFORMATETC_Clone (IEnumFORMATETC)
326 * Standard enumerator members for IEnumFORMATETC
328 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Clone
329 (LPENUMFORMATETC iface, LPENUMFORMATETC* ppenum)
331 IEnumFORMATETCImpl *This = (IEnumFORMATETCImpl *)iface;
334 TRACE("(%p)->(ppenum=%p)\n", This, ppenum);
339 *ppenum = OLEClipbrd_IEnumFORMATETC_Construct(This->countFmt,
343 if (FAILED( hr = IEnumFORMATETC_AddRef(*ppenum)))
346 return (*ppenum) ? S_OK : E_OUTOFMEMORY;
349 static const IEnumFORMATETCVtbl efvt =
351 OLEClipbrd_IEnumFORMATETC_QueryInterface,
352 OLEClipbrd_IEnumFORMATETC_AddRef,
353 OLEClipbrd_IEnumFORMATETC_Release,
354 OLEClipbrd_IEnumFORMATETC_Next,
355 OLEClipbrd_IEnumFORMATETC_Skip,
356 OLEClipbrd_IEnumFORMATETC_Reset,
357 OLEClipbrd_IEnumFORMATETC_Clone
360 /************************************************************************
361 * OLEClipbrd_IEnumFORMATETC_Construct (UINT, const FORMATETC, LPUNKNOWN)
363 * Creates an IEnumFORMATETC enumerator from an array of FORMATETC
364 * Structures. pUnkOuter is the outer unknown for reference counting only.
365 * NOTE: this does not AddRef the interface.
368 static LPENUMFORMATETC OLEClipbrd_IEnumFORMATETC_Construct(UINT cfmt, const FORMATETC afmt[],
369 LPUNKNOWN pUnkDataObj)
371 IEnumFORMATETCImpl* ef;
372 DWORD size=cfmt * sizeof(FORMATETC);
374 ef = HeapAlloc(GetProcessHeap(), 0, sizeof(IEnumFORMATETCImpl));
380 ef->pUnkDataObj = pUnkDataObj;
384 ef->pFmt = HeapAlloc(GetProcessHeap(), 0, size);
386 memcpy(ef->pFmt, afmt, size);
389 HeapFree(GetProcessHeap(), 0, ef);
393 TRACE("(%p)->()\n",ef);
394 return (LPENUMFORMATETC)ef;
397 /***********************************************************************
398 * OLEClipbrd_GlobalDupMem( HGLOBAL )
399 * Helper method to duplicate an HGLOBAL chunk of memory
401 static HGLOBAL OLEClipbrd_GlobalDupMem( HGLOBAL hGlobalSrc )
404 PVOID pGlobalSrc, pGlobalDest;
410 cBytes = GlobalSize(hGlobalSrc);
414 hGlobalDest = GlobalAlloc( GMEM_DDESHARE|GMEM_MOVEABLE,
419 pGlobalSrc = GlobalLock(hGlobalSrc);
420 pGlobalDest = GlobalLock(hGlobalDest);
421 if ( !pGlobalSrc || !pGlobalDest )
423 GlobalFree(hGlobalDest);
427 memcpy(pGlobalDest, pGlobalSrc, cBytes);
429 GlobalUnlock(hGlobalSrc);
430 GlobalUnlock(hGlobalDest);
435 #define MAX_CLIPFORMAT_NAME 80
437 /***********************************************************************
438 * OLEClipbrd_RenderFormat(LPFORMATETC)
439 * Render the clipboard data. Note that this call will delegate to the
440 * source data object.
441 * Note: This function assumes it is passed an HGLOBAL format to render.
443 static HRESULT OLEClipbrd_RenderFormat(IDataObject *pIDataObject, LPFORMATETC pFormatetc)
448 char szFmtName[MAX_CLIPFORMAT_NAME];
449 ILockBytes *ptrILockBytes = 0;
450 HGLOBAL hStorage = 0;
452 if (!GetClipboardFormatNameA(pFormatetc->cfFormat, szFmtName, MAX_CLIPFORMAT_NAME))
455 /* If embed source */
456 if (!strcmp(szFmtName, CF_EMBEDSOURCE))
458 memset(&std, 0, sizeof(STGMEDIUM));
459 std.tymed = pFormatetc->tymed = TYMED_ISTORAGE;
461 hStorage = GlobalAlloc(GMEM_SHARE|GMEM_MOVEABLE, 0);
462 if (hStorage == NULL)
463 HANDLE_ERROR( E_OUTOFMEMORY );
464 hr = CreateILockBytesOnHGlobal(hStorage, FALSE, &ptrILockBytes);
465 hr = StgCreateDocfileOnILockBytes(ptrILockBytes, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &std.u.pstg);
467 if (FAILED(hr = IDataObject_GetDataHere(theOleClipboard->pIDataObjectSrc, pFormatetc, &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->pIDataObjectSrc, &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);
538 ReadClassStg(std.u.pstg, &clsID);
539 ProgIDFromCLSID(&clsID, &strProgID);
541 WideCharToMultiByte( CP_ACP, 0, strProgID, -1, strOleTypeName, sizeof(strOleTypeName), NULL, NULL );
542 OLECONVERT_CreateOleStream(std.u.pstg);
543 OLECONVERT_CreateCompObjStream(std.u.pstg, strOleTypeName);
549 if (FAILED(hr = IDataObject_GetData(pIDataObject, pFormatetc, &std)))
551 WARN("() : IDataObject_GetData failed to render clipboard data! (%x)\n", hr);
552 GlobalFree(hStorage);
556 /* To put a copy back on the clipboard */
558 hStorage = std.u.hGlobal;
562 * Put a copy of the rendered data back on the clipboard
565 if ( !(hDup = OLEClipbrd_GlobalDupMem(hStorage)) )
566 HANDLE_ERROR( E_OUTOFMEMORY );
568 if ( !SetClipboardData( pFormatetc->cfFormat, hDup ) )
571 WARN("() : Failed to set rendered clipboard data into clipboard!\n");
576 ReleaseStgMedium(&std);
582 /***********************************************************************
583 * OLEClipbrd_WndProc(HWND, unsigned, WORD, LONG)
584 * Processes messages sent to the OLE clipboard window.
585 * Note that we will intercept messages in our WndProc only when data
586 * has been placed in the clipboard via OleSetClipboard().
587 * i.e. Only when OLE owns the windows clipboard.
589 static LRESULT CALLBACK OLEClipbrd_WndProc
590 (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
596 * We receive this message to allow us to handle delayed rendering of
597 * a specific clipboard format when an application requests data in
598 * that format by calling GetClipboardData.
599 * (Recall that in OleSetClipboard, we used SetClipboardData to
600 * make all HGLOBAL formats supported by the source IDataObject
601 * available using delayed rendering)
602 * On receiving this message we must actually render the data in the
603 * specified format and place it on the clipboard by calling the
604 * SetClipboardData function.
606 case WM_RENDERFORMAT:
610 ZeroMemory( &rgelt, sizeof(FORMATETC));
613 * Initialize FORMATETC to a Windows clipboard friendly format
615 rgelt.cfFormat = (UINT) wParam;
616 rgelt.dwAspect = DVASPECT_CONTENT;
618 rgelt.tymed = TYMED_HGLOBAL;
620 TRACE("(): WM_RENDERFORMAT(cfFormat=%d)\n", rgelt.cfFormat);
623 * Render the clipboard data.
624 * (We must have a source data object or we wouldn't be in this WndProc)
626 OLEClipbrd_RenderFormat( (IDataObject*)&(theOleClipboard->lpvtbl), &rgelt );
632 * WM_RENDERALLFORMATS
633 * Sent before the clipboard owner window is destroyed.
634 * We should receive this message only when OleUninitialize is called
635 * while we have an IDataObject in the clipboard.
636 * For the content of the clipboard to remain available to other
637 * applications, we must render data in all the formats the source IDataObject
638 * is capable of generating, and place the data on the clipboard by calling
641 case WM_RENDERALLFORMATS:
643 IEnumFORMATETC* penumFormatetc = NULL;
646 TRACE("(): WM_RENDERALLFORMATS\n");
649 * Render all HGLOBAL formats supported by the source into
650 * the windows clipboard.
652 if ( FAILED( IDataObject_EnumFormatEtc( (IDataObject*)&(theOleClipboard->lpvtbl),
653 DATADIR_GET, &penumFormatetc) ) )
655 WARN("(): WM_RENDERALLFORMATS failed to retrieve EnumFormatEtc!\n");
659 while ( S_OK == IEnumFORMATETC_Next(penumFormatetc, 1, &rgelt, NULL) )
661 if ( rgelt.tymed == TYMED_HGLOBAL )
664 * Render the clipboard data.
666 if ( FAILED(OLEClipbrd_RenderFormat( (IDataObject*)&(theOleClipboard->lpvtbl), &rgelt )) )
669 TRACE("(): WM_RENDERALLFORMATS(cfFormat=%d)\n", rgelt.cfFormat);
673 IEnumFORMATETC_Release(penumFormatetc);
679 * WM_DESTROYCLIPBOARD
680 * This is sent by EmptyClipboard before the clipboard is emptied.
681 * We should release any IDataObject we are holding onto when we receive
682 * this message, since it indicates that the OLE clipboard should be empty
683 * from this point on.
685 case WM_DESTROYCLIPBOARD:
687 TRACE("(): WM_DESTROYCLIPBOARD\n");
689 * Release the data object we are holding on to
691 if ( theOleClipboard->pIDataObjectSrc )
693 IDataObject_Release(theOleClipboard->pIDataObjectSrc);
694 theOleClipboard->pIDataObjectSrc = NULL;
700 case WM_ASKCBFORMATNAME:
701 case WM_CHANGECBCHAIN:
702 case WM_DRAWCLIPBOARD:
703 case WM_SIZECLIPBOARD:
704 case WM_HSCROLLCLIPBOARD:
705 case WM_VSCROLLCLIPBOARD:
706 case WM_PAINTCLIPBOARD:
709 return DefWindowProcA(hWnd, message, wParam, lParam);
716 /*---------------------------------------------------------------------*
717 * Implementation of the internal IDataObject interface exposed by
719 *---------------------------------------------------------------------*/
722 /************************************************************************
723 * OLEClipbrd_IDataObject_QueryInterface (IUnknown)
725 * See Windows documentation for more details on IUnknown methods.
727 static HRESULT WINAPI OLEClipbrd_IDataObject_QueryInterface(
732 ole_clipbrd *This = impl_from_IDataObject(iface);
733 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObject);
736 * Perform a sanity check on the parameters.
738 if ( (This==0) || (ppvObject==0) )
742 * Initialize the return parameter.
747 * Compare the riid with the interface IDs implemented by this object.
749 if (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0)
753 else if (memcmp(&IID_IDataObject, riid, sizeof(IID_IDataObject)) == 0)
755 *ppvObject = &This->lpvtbl;
757 else /* We only support IUnknown and IDataObject */
759 WARN( "() : asking for unsupported interface %s\n", debugstr_guid(riid));
760 return E_NOINTERFACE;
764 * Query Interface always increases the reference count by one when it is
767 IUnknown_AddRef((IUnknown*)*ppvObject);
772 /************************************************************************
773 * OLEClipbrd_IDataObject_AddRef (IUnknown)
775 * See Windows documentation for more details on IUnknown methods.
777 static ULONG WINAPI OLEClipbrd_IDataObject_AddRef(
780 ole_clipbrd *This = impl_from_IDataObject(iface);
782 TRACE("(%p)->(count=%u)\n",This, This->ref);
784 return InterlockedIncrement(&This->ref);
787 /***********************************************************************
788 * OLEClipbrd_DestroyWindow(HWND)
789 * Destroy the clipboard window and unregister its class
791 static void OLEClipbrd_DestroyWindow(HWND hwnd)
794 UnregisterClassA( OLEClipbrd_WNDCLASS, 0 );
797 static void OLEClipbrd_Destroy(ole_clipbrd* This)
803 theOleClipboard = NULL;
805 if ( This->hWndClipboard )
806 OLEClipbrd_DestroyWindow(This->hWndClipboard);
808 HeapFree(GetProcessHeap(), 0, This);
811 /************************************************************************
812 * OLEClipbrd_IDataObject_Release (IUnknown)
814 * See Windows documentation for more details on IUnknown methods.
816 static ULONG WINAPI OLEClipbrd_IDataObject_Release(
819 ole_clipbrd *This = impl_from_IDataObject(iface);
822 TRACE("(%p)->(count=%u)\n",This, This->ref);
824 ref = InterlockedDecrement(&This->ref);
828 OLEClipbrd_Destroy(This);
835 /************************************************************************
836 * OLEClipbrd_IDataObject_GetData (IDataObject)
838 * The OLE Clipboard's implementation of this method delegates to
839 * a data source if there is one or wraps around the windows clipboard
841 * See Windows documentation for more details on IDataObject methods.
843 static HRESULT WINAPI OLEClipbrd_IDataObject_GetData(
845 LPFORMATETC pformatetcIn,
849 BOOL bClipboardOpen = FALSE;
852 ole_clipbrd *This = impl_from_IDataObject(iface);
854 TRACE("(%p,%p,%p)\n", iface, pformatetcIn, pmedium);
856 if ( !pformatetcIn || !pmedium )
860 * If we have a data source placed on the clipboard (via OleSetClipboard)
861 * simply delegate to the source object's QueryGetData
862 * NOTE: This code assumes that the IDataObject is in the same address space!
863 * We will need to add marshalling support when Wine handles multiple processes.
865 if ( This->pIDataObjectSrc )
867 return IDataObject_GetData(This->pIDataObjectSrc, pformatetcIn, pmedium);
870 if ( pformatetcIn->lindex != -1 )
871 return DV_E_FORMATETC;
873 if ( (pformatetcIn->tymed & TYMED_HGLOBAL) != TYMED_HGLOBAL )
876 if ( pformatetcIn->dwAspect != DVASPECT_CONTENT )
877 return DV_E_DVASPECT;
881 * Otherwise, get the data from the windows clipboard using GetClipboardData
883 if ( !(bClipboardOpen = OpenClipboard(theOleClipboard->hWndClipboard)) )
884 HANDLE_ERROR( CLIPBRD_E_CANT_OPEN );
886 hData = GetClipboardData(pformatetcIn->cfFormat);
888 /* Must make a copy of global handle returned by GetClipboardData; it
889 * is not valid after we call CloseClipboard
890 * Application is responsible for freeing the memory (Forte Agent does this)
892 src = GlobalLock(hData);
898 size = GlobalSize(hData);
899 hDest = GlobalAlloc(GHND, size);
900 dest = GlobalLock(hDest);
901 memcpy(dest, src, size);
908 * Return the clipboard data in the storage medium structure
910 pmedium->tymed = (hData == 0) ? TYMED_NULL : TYMED_HGLOBAL;
911 pmedium->u.hGlobal = hData;
912 pmedium->pUnkForRelease = NULL;
918 * Close Windows clipboard
920 if ( bClipboardOpen && !CloseClipboard() )
921 hr = CLIPBRD_E_CANT_CLOSE;
925 return (hData == 0) ? DV_E_FORMATETC : S_OK;
928 static HRESULT WINAPI OLEClipbrd_IDataObject_GetDataHere(
930 LPFORMATETC pformatetc,
937 /************************************************************************
938 * OLEClipbrd_IDataObject_QueryGetData (IDataObject)
940 * The OLE Clipboard's implementation of this method delegates to
941 * a data source if there is one or wraps around the windows clipboard
942 * function IsClipboardFormatAvailable() otherwise.
944 * See Windows documentation for more details on IDataObject methods.
946 static HRESULT WINAPI OLEClipbrd_IDataObject_QueryGetData(
948 LPFORMATETC pformatetc)
950 TRACE("(%p, %p)\n", iface, pformatetc);
955 if ( pformatetc->dwAspect != DVASPECT_CONTENT )
956 return DV_E_FORMATETC;
958 if ( pformatetc->lindex != -1 )
959 return DV_E_FORMATETC;
962 * Delegate to the Windows clipboard function IsClipboardFormatAvailable
964 return (IsClipboardFormatAvailable(pformatetc->cfFormat)) ? S_OK : DV_E_CLIPFORMAT;
967 /************************************************************************
968 * OLEClipbrd_IDataObject_GetCanonicalFormatEtc (IDataObject)
970 * See Windows documentation for more details on IDataObject methods.
972 static HRESULT WINAPI OLEClipbrd_IDataObject_GetCanonicalFormatEtc(
974 LPFORMATETC pformatectIn,
975 LPFORMATETC pformatetcOut)
977 TRACE("(%p, %p, %p)\n", iface, pformatectIn, pformatetcOut);
979 if ( !pformatectIn || !pformatetcOut )
982 *pformatetcOut = *pformatectIn;
983 return DATA_S_SAMEFORMATETC;
986 /************************************************************************
987 * OLEClipbrd_IDataObject_SetData (IDataObject)
989 * The OLE Clipboard's does not implement this method
991 * See Windows documentation for more details on IDataObject methods.
993 static HRESULT WINAPI OLEClipbrd_IDataObject_SetData(
995 LPFORMATETC pformatetc,
1003 /************************************************************************
1004 * OLEClipbrd_IDataObject_EnumFormatEtc (IDataObject)
1006 * See Windows documentation for more details on IDataObject methods.
1008 static HRESULT WINAPI OLEClipbrd_IDataObject_EnumFormatEtc(
1011 IEnumFORMATETC** ppenumFormatEtc)
1014 FORMATETC *afmt = NULL;
1017 BOOL bClipboardOpen;
1018 ole_clipbrd *This = impl_from_IDataObject(iface);
1020 TRACE("(%p, %x, %p)\n", iface, dwDirection, ppenumFormatEtc);
1023 * If we have a data source placed on the clipboard (via OleSetClipboard)
1024 * simply delegate to the source object's EnumFormatEtc
1026 if ( This->pIDataObjectSrc )
1028 return IDataObject_EnumFormatEtc(This->pIDataObjectSrc,
1029 dwDirection, ppenumFormatEtc);
1033 * Otherwise we must provide our own enumerator which wraps around the
1034 * Windows clipboard function EnumClipboardFormats
1036 if ( !ppenumFormatEtc )
1037 return E_INVALIDARG;
1039 if ( dwDirection != DATADIR_GET ) /* IDataObject_SetData not implemented */
1043 * Store all current clipboard formats in an array of FORMATETC's,
1044 * and create an IEnumFORMATETC enumerator from this list.
1046 cfmt = CountClipboardFormats();
1047 afmt = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1048 sizeof(FORMATETC) * cfmt);
1050 * Open the Windows clipboard, associating it with our hidden window
1052 if ( !(bClipboardOpen = OpenClipboard(This->hWndClipboard)) )
1053 HANDLE_ERROR( CLIPBRD_E_CANT_OPEN );
1056 * Store all current clipboard formats in an array of FORMATETC's
1057 * TODO: Handle TYMED_IStorage media which were put on the clipboard
1058 * by copying the storage into global memory. We must convert this
1059 * TYMED_HGLOBAL back to TYMED_IStorage.
1061 for (i = 0, format = 0; i < cfmt; i++)
1063 format = EnumClipboardFormats(format);
1064 if (!format) /* Failed! */
1066 ERR("EnumClipboardFormats failed to return format!\n");
1067 HANDLE_ERROR( E_FAIL );
1070 /* Init the FORMATETC struct */
1071 afmt[i].cfFormat = format;
1073 afmt[i].dwAspect = DVASPECT_CONTENT;
1074 afmt[i].lindex = -1;
1075 afmt[i].tymed = TYMED_HGLOBAL;
1079 * Create an EnumFORMATETC enumerator and return an
1080 * EnumFORMATETC after bumping up its ref count
1082 *ppenumFormatEtc = OLEClipbrd_IEnumFORMATETC_Construct( cfmt, afmt, (LPUNKNOWN)iface);
1083 if (!(*ppenumFormatEtc))
1084 HANDLE_ERROR( E_OUTOFMEMORY );
1086 if (FAILED( hr = IEnumFORMATETC_AddRef(*ppenumFormatEtc)))
1093 * Free the array of FORMATETC's
1095 HeapFree(GetProcessHeap(), 0, afmt);
1098 * Close Windows clipboard
1100 if ( bClipboardOpen && !CloseClipboard() )
1101 hr = CLIPBRD_E_CANT_CLOSE;
1106 /************************************************************************
1107 * OLEClipbrd_IDataObject_DAdvise (IDataObject)
1109 * The OLE Clipboard's does not implement this method
1111 * See Windows documentation for more details on IDataObject methods.
1113 static HRESULT WINAPI OLEClipbrd_IDataObject_DAdvise(
1115 FORMATETC* pformatetc,
1117 IAdviseSink* pAdvSink,
1118 DWORD* pdwConnection)
1124 /************************************************************************
1125 * OLEClipbrd_IDataObject_DUnadvise (IDataObject)
1127 * The OLE Clipboard's does not implement this method
1129 * See Windows documentation for more details on IDataObject methods.
1131 static HRESULT WINAPI OLEClipbrd_IDataObject_DUnadvise(
1139 /************************************************************************
1140 * OLEClipbrd_IDataObject_EnumDAdvise (IDataObject)
1142 * The OLE Clipboard does not implement this method
1144 * See Windows documentation for more details on IDataObject methods.
1146 static HRESULT WINAPI OLEClipbrd_IDataObject_EnumDAdvise(
1148 IEnumSTATDATA** ppenumAdvise)
1154 static const IDataObjectVtbl OLEClipbrd_IDataObject_VTable =
1156 OLEClipbrd_IDataObject_QueryInterface,
1157 OLEClipbrd_IDataObject_AddRef,
1158 OLEClipbrd_IDataObject_Release,
1159 OLEClipbrd_IDataObject_GetData,
1160 OLEClipbrd_IDataObject_GetDataHere,
1161 OLEClipbrd_IDataObject_QueryGetData,
1162 OLEClipbrd_IDataObject_GetCanonicalFormatEtc,
1163 OLEClipbrd_IDataObject_SetData,
1164 OLEClipbrd_IDataObject_EnumFormatEtc,
1165 OLEClipbrd_IDataObject_DAdvise,
1166 OLEClipbrd_IDataObject_DUnadvise,
1167 OLEClipbrd_IDataObject_EnumDAdvise
1170 /*---------------------------------------------------------------------*
1171 * Internal implementation methods for the OLE clipboard
1172 *---------------------------------------------------------------------*/
1174 /*********************************************************
1175 * Construct the OLEClipbrd class.
1177 static ole_clipbrd* OLEClipbrd_Construct(void)
1181 This = HeapAlloc( GetProcessHeap(), 0, sizeof(*This) );
1182 if (!This) return NULL;
1184 This->lpvtbl = &OLEClipbrd_IDataObject_VTable;
1187 This->hWndClipboard = NULL;
1188 This->pIDataObjectSrc = NULL;
1190 theOleClipboard = This;
1194 /***********************************************************************
1195 * OLEClipbrd_Initialize()
1196 * Initializes the OLE clipboard.
1198 void OLEClipbrd_Initialize(void)
1201 * Create the clipboard if necessary
1203 if ( !theOleClipboard )
1206 theOleClipboard = OLEClipbrd_Construct();
1211 /***********************************************************************
1212 * OLEClipbrd_UnInitialize()
1213 * Un-Initializes the OLE clipboard
1215 void OLEClipbrd_UnInitialize(void)
1219 * Destroy the clipboard if no one holds a reference to us.
1220 * Note that the clipboard was created with a reference count of 1.
1222 if ( theOleClipboard && (theOleClipboard->ref <= 1) )
1224 OLEClipbrd_Destroy( theOleClipboard );
1228 WARN( "() : OLEClipbrd_UnInitialize called while client holds an IDataObject reference!\n");
1232 /***********************************************************************
1233 * OLEClipbrd_CreateWindow()
1234 * Create the clipboard window
1236 static HWND OLEClipbrd_CreateWindow(void)
1242 * Register the clipboard window class if necessary
1244 ZeroMemory( &wcex, sizeof(WNDCLASSEXA));
1246 wcex.cbSize = sizeof(WNDCLASSEXA);
1247 /* Windows creates this class with a style mask of 0
1248 * We don't bother doing this since the FindClassByAtom code
1249 * would have to be changed to deal with this idiosyncrasy. */
1250 wcex.style = CS_GLOBALCLASS;
1251 wcex.lpfnWndProc = OLEClipbrd_WndProc;
1253 wcex.lpszClassName = OLEClipbrd_WNDCLASS;
1255 RegisterClassExA(&wcex);
1258 * Create a hidden window to receive OLE clipboard messages
1262 * If we need to store state info we can store it here.
1263 * For now we don't need this functionality.
1264 * ClipboardWindowInfo clipboardInfo;
1265 * ZeroMemory( &trackerInfo, sizeof(ClipboardWindowInfo));
1268 hwnd = CreateWindowA(OLEClipbrd_WNDCLASS,
1270 WS_POPUP | WS_CLIPSIBLINGS | WS_OVERLAPPED,
1271 CW_USEDEFAULT, CW_USEDEFAULT,
1272 CW_USEDEFAULT, CW_USEDEFAULT,
1276 0 /*(LPVOID)&clipboardInfo */);
1281 /*---------------------------------------------------------------------*
1282 * Win32 OLE clipboard API
1283 *---------------------------------------------------------------------*/
1285 /***********************************************************************
1286 * OleSetClipboard [OLE32.@]
1287 * Places a pointer to the specified data object onto the clipboard,
1288 * making the data object accessible to the OleGetClipboard function.
1292 * S_OK IDataObject pointer placed on the clipboard
1293 * CLIPBRD_E_CANT_OPEN OpenClipboard failed
1294 * CLIPBRD_E_CANT_EMPTY EmptyClipboard failed
1295 * CLIPBRD_E_CANT_CLOSE CloseClipboard failed
1296 * CLIPBRD_E_CANT_SET SetClipboard failed
1299 HRESULT WINAPI OleSetClipboard(IDataObject* pDataObj)
1302 IEnumFORMATETC* penumFormatetc = NULL;
1304 BOOL bClipboardOpen = FALSE;
1305 struct oletls *info = COM_CurrentInfo();
1307 HGLOBAL hDataObject = 0;
1308 OLEClipbrd **ppDataObject;
1311 TRACE("(%p)\n", pDataObj);
1314 WARN("Could not allocate tls\n");
1316 if(!info->ole_inits)
1317 return CO_E_NOTINITIALIZED;
1320 * Make sure we have a clipboard object
1322 OLEClipbrd_Initialize();
1325 * If the Ole clipboard window hasn't been created yet, create it now.
1327 if ( !theOleClipboard->hWndClipboard )
1328 theOleClipboard->hWndClipboard = OLEClipbrd_CreateWindow();
1330 if ( !theOleClipboard->hWndClipboard ) /* sanity check */
1331 HANDLE_ERROR( E_FAIL );
1334 * Open the Windows clipboard, associating it with our hidden window
1336 if ( !(bClipboardOpen = OpenClipboard(theOleClipboard->hWndClipboard)) )
1337 HANDLE_ERROR( CLIPBRD_E_CANT_OPEN );
1340 * Empty the current clipboard and make our window the clipboard owner
1341 * NOTE: This will trigger a WM_DESTROYCLIPBOARD message
1343 if ( !EmptyClipboard() )
1344 HANDLE_ERROR( CLIPBRD_E_CANT_EMPTY );
1347 * If we are already holding on to an IDataObject first release that.
1349 if ( theOleClipboard->pIDataObjectSrc )
1351 IDataObject_Release(theOleClipboard->pIDataObjectSrc);
1352 theOleClipboard->pIDataObjectSrc = NULL;
1356 * AddRef the data object passed in and save its pointer.
1357 * A NULL value indicates that the clipboard should be emptied.
1359 theOleClipboard->pIDataObjectSrc = pDataObj;
1362 IDataObject_AddRef(theOleClipboard->pIDataObjectSrc);
1366 * Enumerate all HGLOBAL formats supported by the source and make
1367 * those formats available using delayed rendering using SetClipboardData.
1368 * Only global memory based data items may be made available to non-OLE
1369 * applications via the standard Windows clipboard API. Data based on other
1370 * mediums(non TYMED_HGLOBAL) can only be accessed via the Ole Clipboard API.
1372 * TODO: Do we need to additionally handle TYMED_IStorage media by copying
1373 * the storage into global memory?
1377 if ( FAILED(hr = IDataObject_EnumFormatEtc( pDataObj,
1384 while ( S_OK == IEnumFORMATETC_Next(penumFormatetc, 1, &rgelt, NULL) )
1386 if ( rgelt.tymed == TYMED_HGLOBAL )
1389 TRACE("(cfFormat=%d:%s)\n", rgelt.cfFormat,
1390 GetClipboardFormatNameA(rgelt.cfFormat, szFmtName, sizeof(szFmtName)-1)
1393 SetClipboardData( rgelt.cfFormat, NULL);
1396 IEnumFORMATETC_Release(penumFormatetc);
1400 * Windows additionally creates a new "DataObject" clipboard format
1401 * and stores in on the clipboard. We could possibly store a pointer
1402 * to our internal IDataObject interface on the clipboard. I'm not
1403 * sure what the use of this is though.
1404 * Enable the code below for this functionality.
1407 theOleClipboard->cfDataObj = RegisterClipboardFormatA("DataObject");
1408 hDataObject = GlobalAlloc( GMEM_DDESHARE|GMEM_MOVEABLE|GMEM_ZEROINIT,
1409 sizeof(OLEClipbrd *));
1411 HANDLE_ERROR( E_OUTOFMEMORY );
1413 ppDataObject = GlobalLock(hDataObject);
1414 *ppDataObject = theOleClipboard;
1415 GlobalUnlock(hDataObject);
1417 if ( !SetClipboardData( theOleClipboard->cfDataObj, hDataObject ) )
1418 HANDLE_ERROR( CLIPBRD_E_CANT_SET );
1426 * Close Windows clipboard (It remains associated with our window)
1428 if ( bClipboardOpen && !CloseClipboard() )
1429 hr = CLIPBRD_E_CANT_CLOSE;
1432 * Release the source IDataObject if something failed
1436 if (theOleClipboard->pIDataObjectSrc)
1438 IDataObject_Release(theOleClipboard->pIDataObjectSrc);
1439 theOleClipboard->pIDataObjectSrc = NULL;
1447 /***********************************************************************
1448 * OleGetClipboard [OLE32.@]
1449 * Returns a pointer to our internal IDataObject which represents the conceptual
1450 * state of the Windows clipboard. If the current clipboard already contains
1451 * an IDataObject, our internal IDataObject will delegate to this object.
1453 HRESULT WINAPI OleGetClipboard(IDataObject** ppDataObj)
1459 * Make sure we have a clipboard object
1461 OLEClipbrd_Initialize();
1463 if (!theOleClipboard)
1464 return E_OUTOFMEMORY;
1466 /* Return a reference counted IDataObject */
1467 hr = IDataObject_QueryInterface( (IDataObject*)&(theOleClipboard->lpvtbl),
1468 &IID_IDataObject, (void**)ppDataObj);
1472 /******************************************************************************
1473 * OleFlushClipboard [OLE32.@]
1474 * Renders the data from the source IDataObject into the windows clipboard
1476 * TODO: OleFlushClipboard needs to additionally handle TYMED_IStorage media
1477 * by copying the storage into global memory. Subsequently the default
1478 * data object exposed through OleGetClipboard must convert this TYMED_HGLOBAL
1479 * back to TYMED_IStorage.
1481 HRESULT WINAPI OleFlushClipboard(void)
1483 IEnumFORMATETC* penumFormatetc = NULL;
1486 BOOL bClipboardOpen = FALSE;
1487 IDataObject* pIDataObjectSrc = NULL;
1492 * Make sure we have a clipboard object
1494 OLEClipbrd_Initialize();
1497 * Already flushed or no source DataObject? Nothing to do.
1499 if (!theOleClipboard->pIDataObjectSrc)
1503 * Addref and save the source data object we are holding on to temporarily,
1504 * since it will be released when we empty the clipboard.
1506 pIDataObjectSrc = theOleClipboard->pIDataObjectSrc;
1507 IDataObject_AddRef(pIDataObjectSrc);
1510 * Open the Windows clipboard
1512 if ( !(bClipboardOpen = OpenClipboard(theOleClipboard->hWndClipboard)) )
1513 HANDLE_ERROR( CLIPBRD_E_CANT_OPEN );
1516 * Empty the current clipboard
1518 if ( !EmptyClipboard() )
1519 HANDLE_ERROR( CLIPBRD_E_CANT_EMPTY );
1522 * Render all HGLOBAL formats supported by the source into
1523 * the windows clipboard.
1525 if ( FAILED( hr = IDataObject_EnumFormatEtc( pIDataObjectSrc,
1532 while ( S_OK == IEnumFORMATETC_Next(penumFormatetc, 1, &rgelt, NULL) )
1534 if ( rgelt.tymed == TYMED_HGLOBAL )
1537 TRACE("(cfFormat=%d:%s)\n", rgelt.cfFormat,
1538 GetClipboardFormatNameA(rgelt.cfFormat, szFmtName, sizeof(szFmtName)-1)
1542 * Render the clipboard data
1544 if ( FAILED(OLEClipbrd_RenderFormat( pIDataObjectSrc, &rgelt )) )
1549 IEnumFORMATETC_Release(penumFormatetc);
1552 * Release the source data object we are holding on to
1554 IDataObject_Release(pIDataObjectSrc);
1559 * Close Windows clipboard (It remains associated with our window)
1561 if ( bClipboardOpen && !CloseClipboard() )
1562 hr = CLIPBRD_E_CANT_CLOSE;
1568 /***********************************************************************
1569 * OleIsCurrentClipboard [OLE32.@]
1571 HRESULT WINAPI OleIsCurrentClipboard(IDataObject *pDataObject)
1575 * Make sure we have a clipboard object
1577 OLEClipbrd_Initialize();
1579 if (!theOleClipboard)
1580 return E_OUTOFMEMORY;
1582 if (pDataObject == NULL)
1585 return (pDataObject == theOleClipboard->pIDataObjectSrc) ? S_OK : S_FALSE;