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))
190 else if(IsEqualIID(riid, &IID_IEnumFORMATETC))
197 IEnumFORMATETC_AddRef((IEnumFORMATETC*)*ppvObj);
198 TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
202 TRACE("-- Interface: E_NOINTERFACE\n");
203 return E_NOINTERFACE;
206 /************************************************************************
207 * OLEClipbrd_IEnumFORMATETC_AddRef (IUnknown)
209 * Since enumerating formats only makes sense when our data object is around,
210 * we insure that it stays as long as we stay by calling our parents IUnknown
211 * for AddRef and Release. But since we are not controlled by the lifetime of
212 * the outer object, we still keep our own reference count in order to
215 static ULONG WINAPI OLEClipbrd_IEnumFORMATETC_AddRef(LPENUMFORMATETC iface)
217 IEnumFORMATETCImpl *This = (IEnumFORMATETCImpl *)iface;
218 TRACE("(%p)->(count=%u)\n",This, This->ref);
220 if (This->pUnkDataObj)
221 IUnknown_AddRef(This->pUnkDataObj);
223 return InterlockedIncrement(&This->ref);
226 /************************************************************************
227 * OLEClipbrd_IEnumFORMATETC_Release (IUnknown)
229 * See Windows documentation for more details on IUnknown methods.
231 static ULONG WINAPI OLEClipbrd_IEnumFORMATETC_Release(LPENUMFORMATETC iface)
233 IEnumFORMATETCImpl *This = (IEnumFORMATETCImpl *)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 if (SUCCEEDED(CoGetMalloc(MEMCTX_TASK, &pIMalloc)))
248 IMalloc_Free(pIMalloc, This->pFmt);
249 IMalloc_Release(pIMalloc);
252 HeapFree(GetProcessHeap(),0,This);
257 /************************************************************************
258 * OLEClipbrd_IEnumFORMATETC_Next (IEnumFORMATETC)
260 * Standard enumerator members for IEnumFORMATETC
262 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Next
263 (LPENUMFORMATETC iface, ULONG celt, FORMATETC *rgelt, ULONG *pceltFethed)
265 IEnumFORMATETCImpl *This = (IEnumFORMATETCImpl *)iface;
267 HRESULT hres = S_FALSE;
269 TRACE("(%p)->(pos=%u)\n", This, This->posFmt);
271 if (This->posFmt < This->countFmt)
273 cfetch = This->countFmt - This->posFmt;
280 memcpy(rgelt, &This->pFmt[This->posFmt], cfetch * sizeof(FORMATETC));
281 This->posFmt += cfetch;
290 *pceltFethed = cfetch;
296 /************************************************************************
297 * OLEClipbrd_IEnumFORMATETC_Skip (IEnumFORMATETC)
299 * Standard enumerator members for IEnumFORMATETC
301 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Skip(LPENUMFORMATETC iface, ULONG celt)
303 IEnumFORMATETCImpl *This = (IEnumFORMATETCImpl *)iface;
304 TRACE("(%p)->(num=%u)\n", This, celt);
306 This->posFmt += celt;
307 if (This->posFmt > This->countFmt)
309 This->posFmt = This->countFmt;
315 /************************************************************************
316 * OLEClipbrd_IEnumFORMATETC_Reset (IEnumFORMATETC)
318 * Standard enumerator members for IEnumFORMATETC
320 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Reset(LPENUMFORMATETC iface)
322 IEnumFORMATETCImpl *This = (IEnumFORMATETCImpl *)iface;
323 TRACE("(%p)->()\n", This);
329 static LPENUMFORMATETC OLEClipbrd_IEnumFORMATETC_Construct(UINT cfmt, const FORMATETC afmt[],
330 LPUNKNOWN pUnkDataObj);
332 /************************************************************************
333 * OLEClipbrd_IEnumFORMATETC_Clone (IEnumFORMATETC)
335 * Standard enumerator members for IEnumFORMATETC
337 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Clone
338 (LPENUMFORMATETC iface, LPENUMFORMATETC* ppenum)
340 IEnumFORMATETCImpl *This = (IEnumFORMATETCImpl *)iface;
343 TRACE("(%p)->(ppenum=%p)\n", This, ppenum);
348 *ppenum = OLEClipbrd_IEnumFORMATETC_Construct(This->countFmt,
352 if (FAILED( hr = IEnumFORMATETC_AddRef(*ppenum)))
355 return (*ppenum) ? S_OK : E_OUTOFMEMORY;
358 static const IEnumFORMATETCVtbl efvt =
360 OLEClipbrd_IEnumFORMATETC_QueryInterface,
361 OLEClipbrd_IEnumFORMATETC_AddRef,
362 OLEClipbrd_IEnumFORMATETC_Release,
363 OLEClipbrd_IEnumFORMATETC_Next,
364 OLEClipbrd_IEnumFORMATETC_Skip,
365 OLEClipbrd_IEnumFORMATETC_Reset,
366 OLEClipbrd_IEnumFORMATETC_Clone
369 /************************************************************************
370 * OLEClipbrd_IEnumFORMATETC_Construct (UINT, const FORMATETC, LPUNKNOWN)
372 * Creates an IEnumFORMATETC enumerator from an array of FORMATETC
373 * Structures. pUnkOuter is the outer unknown for reference counting only.
374 * NOTE: this does not AddRef the interface.
377 static LPENUMFORMATETC OLEClipbrd_IEnumFORMATETC_Construct(UINT cfmt, const FORMATETC afmt[],
378 LPUNKNOWN pUnkDataObj)
380 IEnumFORMATETCImpl* ef;
381 DWORD size=cfmt * sizeof(FORMATETC);
384 ef = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IEnumFORMATETCImpl));
390 ef->pUnkDataObj = pUnkDataObj;
394 if (FAILED(CoGetMalloc(MEMCTX_TASK, &pIMalloc))) {
395 HeapFree(GetProcessHeap(), 0, ef);
398 ef->pFmt = IMalloc_Alloc(pIMalloc, size);
399 IMalloc_Release(pIMalloc);
402 memcpy(ef->pFmt, afmt, size);
404 TRACE("(%p)->()\n",ef);
405 return (LPENUMFORMATETC)ef;
408 /***********************************************************************
409 * OLEClipbrd_GlobalDupMem( HGLOBAL )
410 * Helper method to duplicate an HGLOBAL chunk of memory
412 static HGLOBAL OLEClipbrd_GlobalDupMem( HGLOBAL hGlobalSrc )
415 PVOID pGlobalSrc, pGlobalDest;
421 cBytes = GlobalSize(hGlobalSrc);
425 hGlobalDest = GlobalAlloc( GMEM_DDESHARE|GMEM_MOVEABLE,
430 pGlobalSrc = GlobalLock(hGlobalSrc);
431 pGlobalDest = GlobalLock(hGlobalDest);
432 if ( !pGlobalSrc || !pGlobalDest )
434 GlobalFree(hGlobalDest);
438 memcpy(pGlobalDest, pGlobalSrc, cBytes);
440 GlobalUnlock(hGlobalSrc);
441 GlobalUnlock(hGlobalDest);
446 #define MAX_CLIPFORMAT_NAME 80
448 /***********************************************************************
449 * OLEClipbrd_RenderFormat(LPFORMATETC)
450 * Render the clipboard data. Note that this call will delegate to the
451 * source data object.
452 * Note: This function assumes it is passed an HGLOBAL format to render.
454 static HRESULT OLEClipbrd_RenderFormat(IDataObject *pIDataObject, LPFORMATETC pFormatetc)
459 char szFmtName[MAX_CLIPFORMAT_NAME];
460 ILockBytes *ptrILockBytes = 0;
461 HGLOBAL hStorage = 0;
463 if (!GetClipboardFormatNameA(pFormatetc->cfFormat, szFmtName, MAX_CLIPFORMAT_NAME))
466 /* If embed source */
467 if (!strcmp(szFmtName, CF_EMBEDSOURCE))
469 memset(&std, 0, sizeof(STGMEDIUM));
470 std.tymed = pFormatetc->tymed = TYMED_ISTORAGE;
472 hStorage = GlobalAlloc(GMEM_SHARE|GMEM_MOVEABLE, 0);
473 if (hStorage == NULL)
474 HANDLE_ERROR( E_OUTOFMEMORY );
475 hr = CreateILockBytesOnHGlobal(hStorage, FALSE, &ptrILockBytes);
476 hr = StgCreateDocfileOnILockBytes(ptrILockBytes, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &std.u.pstg);
478 if (FAILED(hr = IDataObject_GetDataHere(theOleClipboard->pIDataObjectSrc, pFormatetc, &std)))
480 WARN("() : IDataObject_GetDataHere failed to render clipboard data! (%x)\n", hr);
481 GlobalFree(hStorage);
485 if (1) /* check whether the presentation data is already -not- present */
489 METAFILEPICT *mfp = 0;
491 fmt2.cfFormat = CF_METAFILEPICT;
493 fmt2.dwAspect = DVASPECT_CONTENT;
495 fmt2.tymed = TYMED_MFPICT;
497 memset(&std2, 0, sizeof(STGMEDIUM));
498 std2.tymed = TYMED_MFPICT;
500 /* Get the metafile picture out of it */
502 if (SUCCEEDED(hr = IDataObject_GetData(theOleClipboard->pIDataObjectSrc, &fmt2, &std2)))
504 mfp = GlobalLock(std2.u.hGlobal);
509 OLECHAR name[]={ 2, 'O', 'l', 'e', 'P', 'r', 'e', 's', '0', '0', '0', 0};
510 IStream *pStream = 0;
512 PresentationDataHeader pdh;
516 CHAR strOleTypeName[51];
517 BYTE OlePresStreamHeader [] =
519 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00,
520 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
521 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
522 0x00, 0x00, 0x00, 0x00
525 nSize = GetMetaFileBitsEx(mfp->hMF, 0, NULL);
527 memset(&pdh, 0, sizeof(PresentationDataHeader));
528 memcpy(&pdh, OlePresStreamHeader, sizeof(OlePresStreamHeader));
530 pdh.dwObjectExtentX = mfp->xExt;
531 pdh.dwObjectExtentY = mfp->yExt;
534 hr = IStorage_CreateStream(std.u.pstg, name, STGM_CREATE|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, 0, &pStream);
536 hr = IStream_Write(pStream, &pdh, sizeof(PresentationDataHeader), NULL);
538 mfBits = HeapAlloc(GetProcessHeap(), 0, nSize);
539 nSize = GetMetaFileBitsEx(mfp->hMF, nSize, mfBits);
541 hr = IStream_Write(pStream, mfBits, nSize, NULL);
543 IStream_Release(pStream);
545 HeapFree(GetProcessHeap(), 0, mfBits);
547 GlobalUnlock(std2.u.hGlobal);
549 ReadClassStg(std.u.pstg, &clsID);
550 ProgIDFromCLSID(&clsID, &strProgID);
552 WideCharToMultiByte( CP_ACP, 0, strProgID, -1, strOleTypeName, sizeof(strOleTypeName), NULL, NULL );
553 OLECONVERT_CreateOleStream(std.u.pstg);
554 OLECONVERT_CreateCompObjStream(std.u.pstg, strOleTypeName);
560 if (FAILED(hr = IDataObject_GetData(pIDataObject, pFormatetc, &std)))
562 WARN("() : IDataObject_GetData failed to render clipboard data! (%x)\n", hr);
563 GlobalFree(hStorage);
567 /* To put a copy back on the clipboard */
569 hStorage = std.u.hGlobal;
573 * Put a copy of the rendered data back on the clipboard
576 if ( !(hDup = OLEClipbrd_GlobalDupMem(hStorage)) )
577 HANDLE_ERROR( E_OUTOFMEMORY );
579 if ( !SetClipboardData( pFormatetc->cfFormat, hDup ) )
582 WARN("() : Failed to set rendered clipboard data into clipboard!\n");
587 ReleaseStgMedium(&std);
593 /***********************************************************************
594 * OLEClipbrd_WndProc(HWND, unsigned, WORD, LONG)
595 * Processes messages sent to the OLE clipboard window.
596 * Note that we will intercept messages in our WndProc only when data
597 * has been placed in the clipboard via OleSetClipboard().
598 * i.e. Only when OLE owns the windows clipboard.
600 static LRESULT CALLBACK OLEClipbrd_WndProc
601 (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
607 * We receive this message to allow us to handle delayed rendering of
608 * a specific clipboard format when an application requests data in
609 * that format by calling GetClipboardData.
610 * (Recall that in OleSetClipboard, we used SetClipboardData to
611 * make all HGLOBAL formats supported by the source IDataObject
612 * available using delayed rendering)
613 * On receiving this message we must actually render the data in the
614 * specified format and place it on the clipboard by calling the
615 * SetClipboardData function.
617 case WM_RENDERFORMAT:
621 ZeroMemory( &rgelt, sizeof(FORMATETC));
624 * Initialize FORMATETC to a Windows clipboard friendly format
626 rgelt.cfFormat = (UINT) wParam;
627 rgelt.dwAspect = DVASPECT_CONTENT;
629 rgelt.tymed = TYMED_HGLOBAL;
631 TRACE("(): WM_RENDERFORMAT(cfFormat=%d)\n", rgelt.cfFormat);
634 * Render the clipboard data.
635 * (We must have a source data object or we wouldn't be in this WndProc)
637 OLEClipbrd_RenderFormat( (IDataObject*)&(theOleClipboard->lpvtbl), &rgelt );
643 * WM_RENDERALLFORMATS
644 * Sent before the clipboard owner window is destroyed.
645 * We should receive this message only when OleUninitialize is called
646 * while we have an IDataObject in the clipboard.
647 * For the content of the clipboard to remain available to other
648 * applications, we must render data in all the formats the source IDataObject
649 * is capable of generating, and place the data on the clipboard by calling
652 case WM_RENDERALLFORMATS:
654 IEnumFORMATETC* penumFormatetc = NULL;
657 TRACE("(): WM_RENDERALLFORMATS\n");
660 * Render all HGLOBAL formats supported by the source into
661 * the windows clipboard.
663 if ( FAILED( IDataObject_EnumFormatEtc( (IDataObject*)&(theOleClipboard->lpvtbl),
664 DATADIR_GET, &penumFormatetc) ) )
666 WARN("(): WM_RENDERALLFORMATS failed to retrieve EnumFormatEtc!\n");
670 while ( S_OK == IEnumFORMATETC_Next(penumFormatetc, 1, &rgelt, NULL) )
672 if ( rgelt.tymed == TYMED_HGLOBAL )
675 * Render the clipboard data.
677 if ( FAILED(OLEClipbrd_RenderFormat( (IDataObject*)&(theOleClipboard->lpvtbl), &rgelt )) )
680 TRACE("(): WM_RENDERALLFORMATS(cfFormat=%d)\n", rgelt.cfFormat);
684 IEnumFORMATETC_Release(penumFormatetc);
690 * WM_DESTROYCLIPBOARD
691 * This is sent by EmptyClipboard before the clipboard is emptied.
692 * We should release any IDataObject we are holding onto when we receive
693 * this message, since it indicates that the OLE clipboard should be empty
694 * from this point on.
696 case WM_DESTROYCLIPBOARD:
698 TRACE("(): WM_DESTROYCLIPBOARD\n");
700 * Release the data object we are holding on to
702 if ( theOleClipboard->pIDataObjectSrc )
704 IDataObject_Release(theOleClipboard->pIDataObjectSrc);
705 theOleClipboard->pIDataObjectSrc = NULL;
711 case WM_ASKCBFORMATNAME:
712 case WM_CHANGECBCHAIN:
713 case WM_DRAWCLIPBOARD:
714 case WM_SIZECLIPBOARD:
715 case WM_HSCROLLCLIPBOARD:
716 case WM_VSCROLLCLIPBOARD:
717 case WM_PAINTCLIPBOARD:
720 return DefWindowProcA(hWnd, message, wParam, lParam);
727 /*---------------------------------------------------------------------*
728 * Implementation of the internal IDataObject interface exposed by
730 *---------------------------------------------------------------------*/
733 /************************************************************************
734 * OLEClipbrd_IDataObject_QueryInterface (IUnknown)
736 * See Windows documentation for more details on IUnknown methods.
738 static HRESULT WINAPI OLEClipbrd_IDataObject_QueryInterface(
743 ole_clipbrd *This = impl_from_IDataObject(iface);
744 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObject);
747 * Perform a sanity check on the parameters.
749 if ( (This==0) || (ppvObject==0) )
753 * Initialize the return parameter.
758 * Compare the riid with the interface IDs implemented by this object.
760 if (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0)
764 else if (memcmp(&IID_IDataObject, riid, sizeof(IID_IDataObject)) == 0)
766 *ppvObject = &This->lpvtbl;
768 else /* We only support IUnknown and IDataObject */
770 WARN( "() : asking for unsupported interface %s\n", debugstr_guid(riid));
771 return E_NOINTERFACE;
775 * Query Interface always increases the reference count by one when it is
778 IUnknown_AddRef((IUnknown*)*ppvObject);
783 /************************************************************************
784 * OLEClipbrd_IDataObject_AddRef (IUnknown)
786 * See Windows documentation for more details on IUnknown methods.
788 static ULONG WINAPI OLEClipbrd_IDataObject_AddRef(
791 ole_clipbrd *This = impl_from_IDataObject(iface);
793 TRACE("(%p)->(count=%u)\n",This, This->ref);
795 return InterlockedIncrement(&This->ref);
798 /***********************************************************************
799 * OLEClipbrd_DestroyWindow(HWND)
800 * Destroy the clipboard window and unregister its class
802 static void OLEClipbrd_DestroyWindow(HWND hwnd)
805 UnregisterClassA( OLEClipbrd_WNDCLASS, 0 );
808 static void OLEClipbrd_Destroy(ole_clipbrd* This)
814 theOleClipboard = NULL;
816 if ( This->hWndClipboard )
817 OLEClipbrd_DestroyWindow(This->hWndClipboard);
819 HeapFree(GetProcessHeap(), 0, This);
822 /************************************************************************
823 * OLEClipbrd_IDataObject_Release (IUnknown)
825 * See Windows documentation for more details on IUnknown methods.
827 static ULONG WINAPI OLEClipbrd_IDataObject_Release(
830 ole_clipbrd *This = impl_from_IDataObject(iface);
833 TRACE("(%p)->(count=%u)\n",This, This->ref);
835 ref = InterlockedDecrement(&This->ref);
839 OLEClipbrd_Destroy(This);
846 /************************************************************************
847 * OLEClipbrd_IDataObject_GetData (IDataObject)
849 * The OLE Clipboard's implementation of this method delegates to
850 * a data source if there is one or wraps around the windows clipboard
852 * See Windows documentation for more details on IDataObject methods.
854 static HRESULT WINAPI OLEClipbrd_IDataObject_GetData(
856 LPFORMATETC pformatetcIn,
860 BOOL bClipboardOpen = FALSE;
863 ole_clipbrd *This = impl_from_IDataObject(iface);
865 TRACE("(%p,%p,%p)\n", iface, pformatetcIn, pmedium);
867 if ( !pformatetcIn || !pmedium )
871 * If we have a data source placed on the clipboard (via OleSetClipboard)
872 * simply delegate to the source object's QueryGetData
873 * NOTE: This code assumes that the IDataObject is in the same address space!
874 * We will need to add marshalling support when Wine handles multiple processes.
876 if ( This->pIDataObjectSrc )
878 return IDataObject_GetData(This->pIDataObjectSrc, pformatetcIn, pmedium);
881 if ( pformatetcIn->lindex != -1 )
882 return DV_E_FORMATETC;
884 if ( (pformatetcIn->tymed & TYMED_HGLOBAL) != TYMED_HGLOBAL )
887 if ( pformatetcIn->dwAspect != DVASPECT_CONTENT )
888 return DV_E_DVASPECT;
892 * Otherwise, get the data from the windows clipboard using GetClipboardData
894 if ( !(bClipboardOpen = OpenClipboard(theOleClipboard->hWndClipboard)) )
895 HANDLE_ERROR( CLIPBRD_E_CANT_OPEN );
897 hData = GetClipboardData(pformatetcIn->cfFormat);
899 /* Must make a copy of global handle returned by GetClipboardData; it
900 * is not valid after we call CloseClipboard
901 * Application is responsible for freeing the memory (Forte Agent does this)
903 src = GlobalLock(hData);
909 size = GlobalSize(hData);
910 hDest = GlobalAlloc(GHND, size);
911 dest = GlobalLock(hDest);
912 memcpy(dest, src, size);
919 * Return the clipboard data in the storage medium structure
921 pmedium->tymed = (hData == 0) ? TYMED_NULL : TYMED_HGLOBAL;
922 pmedium->u.hGlobal = hData;
923 pmedium->pUnkForRelease = NULL;
929 * Close Windows clipboard
931 if ( bClipboardOpen && !CloseClipboard() )
932 hr = CLIPBRD_E_CANT_CLOSE;
936 return (hData == 0) ? DV_E_FORMATETC : S_OK;
939 static HRESULT WINAPI OLEClipbrd_IDataObject_GetDataHere(
941 LPFORMATETC pformatetc,
948 /************************************************************************
949 * OLEClipbrd_IDataObject_QueryGetData (IDataObject)
951 * The OLE Clipboard's implementation of this method delegates to
952 * a data source if there is one or wraps around the windows clipboard
953 * function IsClipboardFormatAvailable() otherwise.
955 * See Windows documentation for more details on IDataObject methods.
957 static HRESULT WINAPI OLEClipbrd_IDataObject_QueryGetData(
959 LPFORMATETC pformatetc)
961 TRACE("(%p, %p)\n", iface, pformatetc);
966 if ( pformatetc->dwAspect != DVASPECT_CONTENT )
967 return DV_E_FORMATETC;
969 if ( pformatetc->lindex != -1 )
970 return DV_E_FORMATETC;
973 * Delegate to the Windows clipboard function IsClipboardFormatAvailable
975 return (IsClipboardFormatAvailable(pformatetc->cfFormat)) ? S_OK : DV_E_CLIPFORMAT;
978 /************************************************************************
979 * OLEClipbrd_IDataObject_GetCanonicalFormatEtc (IDataObject)
981 * See Windows documentation for more details on IDataObject methods.
983 static HRESULT WINAPI OLEClipbrd_IDataObject_GetCanonicalFormatEtc(
985 LPFORMATETC pformatectIn,
986 LPFORMATETC pformatetcOut)
988 TRACE("(%p, %p, %p)\n", iface, pformatectIn, pformatetcOut);
990 if ( !pformatectIn || !pformatetcOut )
993 *pformatetcOut = *pformatectIn;
994 return DATA_S_SAMEFORMATETC;
997 /************************************************************************
998 * OLEClipbrd_IDataObject_SetData (IDataObject)
1000 * The OLE Clipboard's does not implement this method
1002 * See Windows documentation for more details on IDataObject methods.
1004 static HRESULT WINAPI OLEClipbrd_IDataObject_SetData(
1006 LPFORMATETC pformatetc,
1014 /************************************************************************
1015 * OLEClipbrd_IDataObject_EnumFormatEtc (IDataObject)
1017 * See Windows documentation for more details on IDataObject methods.
1019 static HRESULT WINAPI OLEClipbrd_IDataObject_EnumFormatEtc(
1022 IEnumFORMATETC** ppenumFormatEtc)
1025 FORMATETC *afmt = NULL;
1028 BOOL bClipboardOpen;
1029 ole_clipbrd *This = impl_from_IDataObject(iface);
1031 TRACE("(%p, %x, %p)\n", iface, dwDirection, ppenumFormatEtc);
1034 * If we have a data source placed on the clipboard (via OleSetClipboard)
1035 * simply delegate to the source object's EnumFormatEtc
1037 if ( This->pIDataObjectSrc )
1039 return IDataObject_EnumFormatEtc(This->pIDataObjectSrc,
1040 dwDirection, ppenumFormatEtc);
1044 * Otherwise we must provide our own enumerator which wraps around the
1045 * Windows clipboard function EnumClipboardFormats
1047 if ( !ppenumFormatEtc )
1048 return E_INVALIDARG;
1050 if ( dwDirection != DATADIR_GET ) /* IDataObject_SetData not implemented */
1054 * Store all current clipboard formats in an array of FORMATETC's,
1055 * and create an IEnumFORMATETC enumerator from this list.
1057 cfmt = CountClipboardFormats();
1058 afmt = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1059 sizeof(FORMATETC) * cfmt);
1061 * Open the Windows clipboard, associating it with our hidden window
1063 if ( !(bClipboardOpen = OpenClipboard(This->hWndClipboard)) )
1064 HANDLE_ERROR( CLIPBRD_E_CANT_OPEN );
1067 * Store all current clipboard formats in an array of FORMATETC's
1068 * TODO: Handle TYMED_IStorage media which were put on the clipboard
1069 * by copying the storage into global memory. We must convert this
1070 * TYMED_HGLOBAL back to TYMED_IStorage.
1072 for (i = 0, format = 0; i < cfmt; i++)
1074 format = EnumClipboardFormats(format);
1075 if (!format) /* Failed! */
1077 ERR("EnumClipboardFormats failed to return format!\n");
1078 HANDLE_ERROR( E_FAIL );
1081 /* Init the FORMATETC struct */
1082 afmt[i].cfFormat = format;
1084 afmt[i].dwAspect = DVASPECT_CONTENT;
1085 afmt[i].lindex = -1;
1086 afmt[i].tymed = TYMED_HGLOBAL;
1090 * Create an EnumFORMATETC enumerator and return an
1091 * EnumFORMATETC after bumping up its ref count
1093 *ppenumFormatEtc = OLEClipbrd_IEnumFORMATETC_Construct( cfmt, afmt, (LPUNKNOWN)iface);
1094 if (!(*ppenumFormatEtc))
1095 HANDLE_ERROR( E_OUTOFMEMORY );
1097 if (FAILED( hr = IEnumFORMATETC_AddRef(*ppenumFormatEtc)))
1104 * Free the array of FORMATETC's
1106 HeapFree(GetProcessHeap(), 0, afmt);
1109 * Close Windows clipboard
1111 if ( bClipboardOpen && !CloseClipboard() )
1112 hr = CLIPBRD_E_CANT_CLOSE;
1117 /************************************************************************
1118 * OLEClipbrd_IDataObject_DAdvise (IDataObject)
1120 * The OLE Clipboard's does not implement this method
1122 * See Windows documentation for more details on IDataObject methods.
1124 static HRESULT WINAPI OLEClipbrd_IDataObject_DAdvise(
1126 FORMATETC* pformatetc,
1128 IAdviseSink* pAdvSink,
1129 DWORD* pdwConnection)
1135 /************************************************************************
1136 * OLEClipbrd_IDataObject_DUnadvise (IDataObject)
1138 * The OLE Clipboard's does not implement this method
1140 * See Windows documentation for more details on IDataObject methods.
1142 static HRESULT WINAPI OLEClipbrd_IDataObject_DUnadvise(
1150 /************************************************************************
1151 * OLEClipbrd_IDataObject_EnumDAdvise (IDataObject)
1153 * The OLE Clipboard does not implement this method
1155 * See Windows documentation for more details on IDataObject methods.
1157 static HRESULT WINAPI OLEClipbrd_IDataObject_EnumDAdvise(
1159 IEnumSTATDATA** ppenumAdvise)
1165 static const IDataObjectVtbl OLEClipbrd_IDataObject_VTable =
1167 OLEClipbrd_IDataObject_QueryInterface,
1168 OLEClipbrd_IDataObject_AddRef,
1169 OLEClipbrd_IDataObject_Release,
1170 OLEClipbrd_IDataObject_GetData,
1171 OLEClipbrd_IDataObject_GetDataHere,
1172 OLEClipbrd_IDataObject_QueryGetData,
1173 OLEClipbrd_IDataObject_GetCanonicalFormatEtc,
1174 OLEClipbrd_IDataObject_SetData,
1175 OLEClipbrd_IDataObject_EnumFormatEtc,
1176 OLEClipbrd_IDataObject_DAdvise,
1177 OLEClipbrd_IDataObject_DUnadvise,
1178 OLEClipbrd_IDataObject_EnumDAdvise
1181 /*---------------------------------------------------------------------*
1182 * Internal implementation methods for the OLE clipboard
1183 *---------------------------------------------------------------------*/
1185 /*********************************************************
1186 * Construct the OLEClipbrd class.
1188 static ole_clipbrd* OLEClipbrd_Construct(void)
1192 This = HeapAlloc( GetProcessHeap(), 0, sizeof(*This) );
1193 if (!This) return NULL;
1195 This->lpvtbl = &OLEClipbrd_IDataObject_VTable;
1198 This->hWndClipboard = NULL;
1199 This->pIDataObjectSrc = NULL;
1201 theOleClipboard = This;
1205 /***********************************************************************
1206 * OLEClipbrd_Initialize()
1207 * Initializes the OLE clipboard.
1209 void OLEClipbrd_Initialize(void)
1212 * Create the clipboard if necessary
1214 if ( !theOleClipboard )
1217 theOleClipboard = OLEClipbrd_Construct();
1222 /***********************************************************************
1223 * OLEClipbrd_UnInitialize()
1224 * Un-Initializes the OLE clipboard
1226 void OLEClipbrd_UnInitialize(void)
1230 * Destroy the clipboard if no one holds a reference to us.
1231 * Note that the clipboard was created with a reference count of 1.
1233 if ( theOleClipboard && (theOleClipboard->ref <= 1) )
1235 OLEClipbrd_Destroy( theOleClipboard );
1239 WARN( "() : OLEClipbrd_UnInitialize called while client holds an IDataObject reference!\n");
1243 /***********************************************************************
1244 * OLEClipbrd_CreateWindow()
1245 * Create the clipboard window
1247 static HWND OLEClipbrd_CreateWindow(void)
1253 * Register the clipboard window class if necessary
1255 ZeroMemory( &wcex, sizeof(WNDCLASSEXA));
1257 wcex.cbSize = sizeof(WNDCLASSEXA);
1258 /* Windows creates this class with a style mask of 0
1259 * We don't bother doing this since the FindClassByAtom code
1260 * would have to be changed to deal with this idiosyncrasy. */
1261 wcex.style = CS_GLOBALCLASS;
1262 wcex.lpfnWndProc = OLEClipbrd_WndProc;
1264 wcex.lpszClassName = OLEClipbrd_WNDCLASS;
1266 RegisterClassExA(&wcex);
1269 * Create a hidden window to receive OLE clipboard messages
1273 * If we need to store state info we can store it here.
1274 * For now we don't need this functionality.
1275 * ClipboardWindowInfo clipboardInfo;
1276 * ZeroMemory( &trackerInfo, sizeof(ClipboardWindowInfo));
1279 hwnd = CreateWindowA(OLEClipbrd_WNDCLASS,
1281 WS_POPUP | WS_CLIPSIBLINGS | WS_OVERLAPPED,
1282 CW_USEDEFAULT, CW_USEDEFAULT,
1283 CW_USEDEFAULT, CW_USEDEFAULT,
1287 0 /*(LPVOID)&clipboardInfo */);
1292 /*---------------------------------------------------------------------*
1293 * Win32 OLE clipboard API
1294 *---------------------------------------------------------------------*/
1296 /***********************************************************************
1297 * OleSetClipboard [OLE32.@]
1298 * Places a pointer to the specified data object onto the clipboard,
1299 * making the data object accessible to the OleGetClipboard function.
1303 * S_OK IDataObject pointer placed on the clipboard
1304 * CLIPBRD_E_CANT_OPEN OpenClipboard failed
1305 * CLIPBRD_E_CANT_EMPTY EmptyClipboard failed
1306 * CLIPBRD_E_CANT_CLOSE CloseClipboard failed
1307 * CLIPBRD_E_CANT_SET SetClipboard failed
1310 HRESULT WINAPI OleSetClipboard(IDataObject* pDataObj)
1313 IEnumFORMATETC* penumFormatetc = NULL;
1315 BOOL bClipboardOpen = FALSE;
1316 struct oletls *info = COM_CurrentInfo();
1318 HGLOBAL hDataObject = 0;
1319 OLEClipbrd **ppDataObject;
1322 TRACE("(%p)\n", pDataObj);
1325 WARN("Could not allocate tls\n");
1327 if(!info->ole_inits)
1328 return CO_E_NOTINITIALIZED;
1331 * Make sure we have a clipboard object
1333 OLEClipbrd_Initialize();
1336 * If the Ole clipboard window hasn't been created yet, create it now.
1338 if ( !theOleClipboard->hWndClipboard )
1339 theOleClipboard->hWndClipboard = OLEClipbrd_CreateWindow();
1341 if ( !theOleClipboard->hWndClipboard ) /* sanity check */
1342 HANDLE_ERROR( E_FAIL );
1345 * Open the Windows clipboard, associating it with our hidden window
1347 if ( !(bClipboardOpen = OpenClipboard(theOleClipboard->hWndClipboard)) )
1348 HANDLE_ERROR( CLIPBRD_E_CANT_OPEN );
1351 * Empty the current clipboard and make our window the clipboard owner
1352 * NOTE: This will trigger a WM_DESTROYCLIPBOARD message
1354 if ( !EmptyClipboard() )
1355 HANDLE_ERROR( CLIPBRD_E_CANT_EMPTY );
1358 * If we are already holding on to an IDataObject first release that.
1360 if ( theOleClipboard->pIDataObjectSrc )
1362 IDataObject_Release(theOleClipboard->pIDataObjectSrc);
1363 theOleClipboard->pIDataObjectSrc = NULL;
1367 * AddRef the data object passed in and save its pointer.
1368 * A NULL value indicates that the clipboard should be emptied.
1370 theOleClipboard->pIDataObjectSrc = pDataObj;
1373 IDataObject_AddRef(theOleClipboard->pIDataObjectSrc);
1377 * Enumerate all HGLOBAL formats supported by the source and make
1378 * those formats available using delayed rendering using SetClipboardData.
1379 * Only global memory based data items may be made available to non-OLE
1380 * applications via the standard Windows clipboard API. Data based on other
1381 * mediums(non TYMED_HGLOBAL) can only be accessed via the Ole Clipboard API.
1383 * TODO: Do we need to additionally handle TYMED_IStorage media by copying
1384 * the storage into global memory?
1388 if ( FAILED(hr = IDataObject_EnumFormatEtc( pDataObj,
1395 while ( S_OK == IEnumFORMATETC_Next(penumFormatetc, 1, &rgelt, NULL) )
1397 if ( rgelt.tymed == TYMED_HGLOBAL )
1400 TRACE("(cfFormat=%d:%s)\n", rgelt.cfFormat,
1401 GetClipboardFormatNameA(rgelt.cfFormat, szFmtName, sizeof(szFmtName)-1)
1404 SetClipboardData( rgelt.cfFormat, NULL);
1407 IEnumFORMATETC_Release(penumFormatetc);
1411 * Windows additionally creates a new "DataObject" clipboard format
1412 * and stores in on the clipboard. We could possibly store a pointer
1413 * to our internal IDataObject interface on the clipboard. I'm not
1414 * sure what the use of this is though.
1415 * Enable the code below for this functionality.
1418 theOleClipboard->cfDataObj = RegisterClipboardFormatA("DataObject");
1419 hDataObject = GlobalAlloc( GMEM_DDESHARE|GMEM_MOVEABLE|GMEM_ZEROINIT,
1420 sizeof(OLEClipbrd *));
1422 HANDLE_ERROR( E_OUTOFMEMORY );
1424 ppDataObject = GlobalLock(hDataObject);
1425 *ppDataObject = theOleClipboard;
1426 GlobalUnlock(hDataObject);
1428 if ( !SetClipboardData( theOleClipboard->cfDataObj, hDataObject ) )
1429 HANDLE_ERROR( CLIPBRD_E_CANT_SET );
1437 * Close Windows clipboard (It remains associated with our window)
1439 if ( bClipboardOpen && !CloseClipboard() )
1440 hr = CLIPBRD_E_CANT_CLOSE;
1443 * Release the source IDataObject if something failed
1447 if (theOleClipboard->pIDataObjectSrc)
1449 IDataObject_Release(theOleClipboard->pIDataObjectSrc);
1450 theOleClipboard->pIDataObjectSrc = NULL;
1458 /***********************************************************************
1459 * OleGetClipboard [OLE32.@]
1460 * Returns a pointer to our internal IDataObject which represents the conceptual
1461 * state of the Windows clipboard. If the current clipboard already contains
1462 * an IDataObject, our internal IDataObject will delegate to this object.
1464 HRESULT WINAPI OleGetClipboard(IDataObject** ppDataObj)
1470 * Make sure we have a clipboard object
1472 OLEClipbrd_Initialize();
1474 if (!theOleClipboard)
1475 return E_OUTOFMEMORY;
1477 /* Return a reference counted IDataObject */
1478 hr = IDataObject_QueryInterface( (IDataObject*)&(theOleClipboard->lpvtbl),
1479 &IID_IDataObject, (void**)ppDataObj);
1483 /******************************************************************************
1484 * OleFlushClipboard [OLE32.@]
1485 * Renders the data from the source IDataObject into the windows clipboard
1487 * TODO: OleFlushClipboard needs to additionally handle TYMED_IStorage media
1488 * by copying the storage into global memory. Subsequently the default
1489 * data object exposed through OleGetClipboard must convert this TYMED_HGLOBAL
1490 * back to TYMED_IStorage.
1492 HRESULT WINAPI OleFlushClipboard(void)
1494 IEnumFORMATETC* penumFormatetc = NULL;
1497 BOOL bClipboardOpen = FALSE;
1498 IDataObject* pIDataObjectSrc = NULL;
1503 * Make sure we have a clipboard object
1505 OLEClipbrd_Initialize();
1508 * Already flushed or no source DataObject? Nothing to do.
1510 if (!theOleClipboard->pIDataObjectSrc)
1514 * Addref and save the source data object we are holding on to temporarily,
1515 * since it will be released when we empty the clipboard.
1517 pIDataObjectSrc = theOleClipboard->pIDataObjectSrc;
1518 IDataObject_AddRef(pIDataObjectSrc);
1521 * Open the Windows clipboard
1523 if ( !(bClipboardOpen = OpenClipboard(theOleClipboard->hWndClipboard)) )
1524 HANDLE_ERROR( CLIPBRD_E_CANT_OPEN );
1527 * Empty the current clipboard
1529 if ( !EmptyClipboard() )
1530 HANDLE_ERROR( CLIPBRD_E_CANT_EMPTY );
1533 * Render all HGLOBAL formats supported by the source into
1534 * the windows clipboard.
1536 if ( FAILED( hr = IDataObject_EnumFormatEtc( pIDataObjectSrc,
1543 while ( S_OK == IEnumFORMATETC_Next(penumFormatetc, 1, &rgelt, NULL) )
1545 if ( rgelt.tymed == TYMED_HGLOBAL )
1548 TRACE("(cfFormat=%d:%s)\n", rgelt.cfFormat,
1549 GetClipboardFormatNameA(rgelt.cfFormat, szFmtName, sizeof(szFmtName)-1)
1553 * Render the clipboard data
1555 if ( FAILED(OLEClipbrd_RenderFormat( pIDataObjectSrc, &rgelt )) )
1560 IEnumFORMATETC_Release(penumFormatetc);
1563 * Release the source data object we are holding on to
1565 IDataObject_Release(pIDataObjectSrc);
1570 * Close Windows clipboard (It remains associated with our window)
1572 if ( bClipboardOpen && !CloseClipboard() )
1573 hr = CLIPBRD_E_CANT_CLOSE;
1579 /***********************************************************************
1580 * OleIsCurrentClipboard [OLE32.@]
1582 HRESULT WINAPI OleIsCurrentClipboard(IDataObject *pDataObject)
1586 * Make sure we have a clipboard object
1588 OLEClipbrd_Initialize();
1590 if (!theOleClipboard)
1591 return E_OUTOFMEMORY;
1593 if (pDataObject == NULL)
1596 return (pDataObject == theOleClipboard->pIDataObjectSrc) ? S_OK : S_FALSE;