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 */
164 static inline enum_fmtetc
*impl_from_IEnumFORMATETC(IEnumFORMATETC
*iface
)
166 return (enum_fmtetc
*)((char*)iface
- FIELD_OFFSET(enum_fmtetc
, lpVtbl
));
169 /************************************************************************
170 * OLEClipbrd_IEnumFORMATETC_QueryInterface (IUnknown)
172 * See Windows documentation for more details on IUnknown methods.
174 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_QueryInterface
175 (LPENUMFORMATETC iface
, REFIID riid
, LPVOID
* ppvObj
)
177 enum_fmtetc
*This
= impl_from_IEnumFORMATETC(iface
);
179 TRACE("(%p)->(IID: %s, %p)\n", This
, debugstr_guid(riid
), ppvObj
);
183 if(IsEqualIID(riid
, &IID_IUnknown
) ||
184 IsEqualIID(riid
, &IID_IEnumFORMATETC
))
191 IEnumFORMATETC_AddRef((IEnumFORMATETC
*)*ppvObj
);
192 TRACE("-- Interface: (%p)->(%p)\n",ppvObj
,*ppvObj
);
196 TRACE("-- Interface: E_NOINTERFACE\n");
197 return E_NOINTERFACE
;
200 /************************************************************************
201 * OLEClipbrd_IEnumFORMATETC_AddRef (IUnknown)
204 static ULONG WINAPI
OLEClipbrd_IEnumFORMATETC_AddRef(LPENUMFORMATETC iface
)
206 enum_fmtetc
*This
= impl_from_IEnumFORMATETC(iface
);
207 TRACE("(%p)->(count=%u)\n",This
, This
->ref
);
209 return InterlockedIncrement(&This
->ref
);
212 /************************************************************************
213 * OLEClipbrd_IEnumFORMATETC_Release (IUnknown)
215 * See Windows documentation for more details on IUnknown methods.
217 static ULONG WINAPI
OLEClipbrd_IEnumFORMATETC_Release(LPENUMFORMATETC iface
)
219 enum_fmtetc
*This
= impl_from_IEnumFORMATETC(iface
);
222 TRACE("(%p)->(count=%u)\n",This
, This
->ref
);
224 ref
= InterlockedDecrement(&This
->ref
);
227 TRACE("() - destroying IEnumFORMATETC(%p)\n",This
);
228 HeapFree(GetProcessHeap(), 0, This
->pFmt
);
229 HeapFree(GetProcessHeap(),0,This
);
234 /************************************************************************
235 * OLEClipbrd_IEnumFORMATETC_Next (IEnumFORMATETC)
237 * Standard enumerator members for IEnumFORMATETC
239 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Next
240 (LPENUMFORMATETC iface
, ULONG celt
, FORMATETC
*rgelt
, ULONG
*pceltFethed
)
242 enum_fmtetc
*This
= impl_from_IEnumFORMATETC(iface
);
244 HRESULT hres
= S_FALSE
;
246 TRACE("(%p)->(pos=%u)\n", This
, This
->pos
);
248 if (This
->pos
< This
->countFmt
)
250 cfetch
= This
->countFmt
- This
->pos
;
257 memcpy(rgelt
, &This
->pFmt
[This
->pos
], cfetch
* sizeof(FORMATETC
));
267 *pceltFethed
= cfetch
;
273 /************************************************************************
274 * OLEClipbrd_IEnumFORMATETC_Skip (IEnumFORMATETC)
276 * Standard enumerator members for IEnumFORMATETC
278 static HRESULT WINAPI
OLEClipbrd_IEnumFORMATETC_Skip(LPENUMFORMATETC iface
, ULONG celt
)
280 enum_fmtetc
*This
= impl_from_IEnumFORMATETC(iface
);
281 TRACE("(%p)->(num=%u)\n", This
, celt
);
284 if (This
->pos
> This
->countFmt
)
286 This
->pos
= This
->countFmt
;
292 /************************************************************************
293 * OLEClipbrd_IEnumFORMATETC_Reset (IEnumFORMATETC)
295 * Standard enumerator members for IEnumFORMATETC
297 static HRESULT WINAPI
OLEClipbrd_IEnumFORMATETC_Reset(LPENUMFORMATETC iface
)
299 enum_fmtetc
*This
= impl_from_IEnumFORMATETC(iface
);
300 TRACE("(%p)->()\n", This
);
306 static HRESULT
enum_fmtetc_construct(UINT cfmt
, const FORMATETC afmt
[], IEnumFORMATETC
**obj
);
308 /************************************************************************
309 * OLEClipbrd_IEnumFORMATETC_Clone (IEnumFORMATETC)
311 * Standard enumerator members for IEnumFORMATETC
313 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Clone
314 (LPENUMFORMATETC iface
, LPENUMFORMATETC
* ppenum
)
316 enum_fmtetc
*This
= impl_from_IEnumFORMATETC(iface
);
319 TRACE("(%p)->(ppenum=%p)\n", This
, ppenum
);
324 hr
= enum_fmtetc_construct(This
->countFmt
, This
->pFmt
, ppenum
);
329 static const IEnumFORMATETCVtbl efvt
=
331 OLEClipbrd_IEnumFORMATETC_QueryInterface
,
332 OLEClipbrd_IEnumFORMATETC_AddRef
,
333 OLEClipbrd_IEnumFORMATETC_Release
,
334 OLEClipbrd_IEnumFORMATETC_Next
,
335 OLEClipbrd_IEnumFORMATETC_Skip
,
336 OLEClipbrd_IEnumFORMATETC_Reset
,
337 OLEClipbrd_IEnumFORMATETC_Clone
340 /************************************************************************
341 * enum_fmtetc_construct
343 * Creates an IEnumFORMATETC enumerator from an array of FORMATETC
346 static HRESULT
enum_fmtetc_construct(UINT cfmt
, const FORMATETC afmt
[], IEnumFORMATETC
**obj
)
349 DWORD size
=cfmt
* sizeof(FORMATETC
);
352 ef
= HeapAlloc(GetProcessHeap(), 0, sizeof(*ef
));
353 if (!ef
) return E_OUTOFMEMORY
;
360 ef
->pFmt
= HeapAlloc(GetProcessHeap(), 0, size
);
362 memcpy(ef
->pFmt
, afmt
, size
);
365 HeapFree(GetProcessHeap(), 0, ef
);
366 return E_OUTOFMEMORY
;
369 TRACE("(%p)->()\n",ef
);
370 *obj
= (IEnumFORMATETC
*)ef
;
374 /***********************************************************************
375 * OLEClipbrd_GlobalDupMem( HGLOBAL )
376 * Helper method to duplicate an HGLOBAL chunk of memory
378 static HGLOBAL
OLEClipbrd_GlobalDupMem( HGLOBAL hGlobalSrc
)
381 PVOID pGlobalSrc
, pGlobalDest
;
387 cBytes
= GlobalSize(hGlobalSrc
);
391 hGlobalDest
= GlobalAlloc( GMEM_DDESHARE
|GMEM_MOVEABLE
,
396 pGlobalSrc
= GlobalLock(hGlobalSrc
);
397 pGlobalDest
= GlobalLock(hGlobalDest
);
398 if ( !pGlobalSrc
|| !pGlobalDest
)
400 GlobalFree(hGlobalDest
);
404 memcpy(pGlobalDest
, pGlobalSrc
, cBytes
);
406 GlobalUnlock(hGlobalSrc
);
407 GlobalUnlock(hGlobalDest
);
412 #define MAX_CLIPFORMAT_NAME 80
414 /***********************************************************************
415 * OLEClipbrd_RenderFormat(LPFORMATETC)
416 * Render the clipboard data. Note that this call will delegate to the
417 * source data object.
418 * Note: This function assumes it is passed an HGLOBAL format to render.
420 static HRESULT
OLEClipbrd_RenderFormat(IDataObject
*pIDataObject
, LPFORMATETC pFormatetc
)
425 char szFmtName
[MAX_CLIPFORMAT_NAME
];
426 ILockBytes
*ptrILockBytes
= 0;
427 HGLOBAL hStorage
= 0;
429 if (!GetClipboardFormatNameA(pFormatetc
->cfFormat
, szFmtName
, MAX_CLIPFORMAT_NAME
))
432 /* If embed source */
433 if (!strcmp(szFmtName
, CF_EMBEDSOURCE
))
435 memset(&std
, 0, sizeof(STGMEDIUM
));
436 std
.tymed
= pFormatetc
->tymed
= TYMED_ISTORAGE
;
438 hStorage
= GlobalAlloc(GMEM_SHARE
|GMEM_MOVEABLE
, 0);
439 if (hStorage
== NULL
)
440 HANDLE_ERROR( E_OUTOFMEMORY
);
441 hr
= CreateILockBytesOnHGlobal(hStorage
, FALSE
, &ptrILockBytes
);
442 hr
= StgCreateDocfileOnILockBytes(ptrILockBytes
, STGM_SHARE_EXCLUSIVE
|STGM_READWRITE
, 0, &std
.u
.pstg
);
444 if (FAILED(hr
= IDataObject_GetDataHere(theOleClipboard
->pIDataObjectSrc
, pFormatetc
, &std
)))
446 WARN("() : IDataObject_GetDataHere failed to render clipboard data! (%x)\n", hr
);
447 GlobalFree(hStorage
);
451 if (1) /* check whether the presentation data is already -not- present */
455 METAFILEPICT
*mfp
= 0;
457 fmt2
.cfFormat
= CF_METAFILEPICT
;
459 fmt2
.dwAspect
= DVASPECT_CONTENT
;
461 fmt2
.tymed
= TYMED_MFPICT
;
463 memset(&std2
, 0, sizeof(STGMEDIUM
));
464 std2
.tymed
= TYMED_MFPICT
;
466 /* Get the metafile picture out of it */
468 if (SUCCEEDED(hr
= IDataObject_GetData(theOleClipboard
->pIDataObjectSrc
, &fmt2
, &std2
)))
470 mfp
= GlobalLock(std2
.u
.hGlobal
);
475 OLECHAR name
[]={ 2, 'O', 'l', 'e', 'P', 'r', 'e', 's', '0', '0', '0', 0};
476 IStream
*pStream
= 0;
478 PresentationDataHeader pdh
;
482 CHAR strOleTypeName
[51];
483 BYTE OlePresStreamHeader
[] =
485 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00,
486 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
487 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
488 0x00, 0x00, 0x00, 0x00
491 nSize
= GetMetaFileBitsEx(mfp
->hMF
, 0, NULL
);
493 memset(&pdh
, 0, sizeof(PresentationDataHeader
));
494 memcpy(&pdh
, OlePresStreamHeader
, sizeof(OlePresStreamHeader
));
496 pdh
.dwObjectExtentX
= mfp
->xExt
;
497 pdh
.dwObjectExtentY
= mfp
->yExt
;
500 hr
= IStorage_CreateStream(std
.u
.pstg
, name
, STGM_CREATE
|STGM_SHARE_EXCLUSIVE
|STGM_READWRITE
, 0, 0, &pStream
);
502 hr
= IStream_Write(pStream
, &pdh
, sizeof(PresentationDataHeader
), NULL
);
504 mfBits
= HeapAlloc(GetProcessHeap(), 0, nSize
);
505 nSize
= GetMetaFileBitsEx(mfp
->hMF
, nSize
, mfBits
);
507 hr
= IStream_Write(pStream
, mfBits
, nSize
, NULL
);
509 IStream_Release(pStream
);
511 HeapFree(GetProcessHeap(), 0, mfBits
);
513 GlobalUnlock(std2
.u
.hGlobal
);
515 ReadClassStg(std
.u
.pstg
, &clsID
);
516 ProgIDFromCLSID(&clsID
, &strProgID
);
518 WideCharToMultiByte( CP_ACP
, 0, strProgID
, -1, strOleTypeName
, sizeof(strOleTypeName
), NULL
, NULL
);
519 OLECONVERT_CreateOleStream(std
.u
.pstg
);
520 OLECONVERT_CreateCompObjStream(std
.u
.pstg
, strOleTypeName
);
526 if (FAILED(hr
= IDataObject_GetData(pIDataObject
, pFormatetc
, &std
)))
528 WARN("() : IDataObject_GetData failed to render clipboard data! (%x)\n", hr
);
529 GlobalFree(hStorage
);
533 /* To put a copy back on the clipboard */
535 hStorage
= std
.u
.hGlobal
;
539 * Put a copy of the rendered data back on the clipboard
542 if ( !(hDup
= OLEClipbrd_GlobalDupMem(hStorage
)) )
543 HANDLE_ERROR( E_OUTOFMEMORY
);
545 if ( !SetClipboardData( pFormatetc
->cfFormat
, hDup
) )
548 WARN("() : Failed to set rendered clipboard data into clipboard!\n");
553 ReleaseStgMedium(&std
);
559 /***********************************************************************
560 * OLEClipbrd_WndProc(HWND, unsigned, WORD, LONG)
561 * Processes messages sent to the OLE clipboard window.
562 * Note that we will intercept messages in our WndProc only when data
563 * has been placed in the clipboard via OleSetClipboard().
564 * i.e. Only when OLE owns the windows clipboard.
566 static LRESULT CALLBACK OLEClipbrd_WndProc
567 (HWND hWnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
573 * We receive this message to allow us to handle delayed rendering of
574 * a specific clipboard format when an application requests data in
575 * that format by calling GetClipboardData.
576 * (Recall that in OleSetClipboard, we used SetClipboardData to
577 * make all HGLOBAL formats supported by the source IDataObject
578 * available using delayed rendering)
579 * On receiving this message we must actually render the data in the
580 * specified format and place it on the clipboard by calling the
581 * SetClipboardData function.
583 case WM_RENDERFORMAT
:
587 ZeroMemory( &rgelt
, sizeof(FORMATETC
));
590 * Initialize FORMATETC to a Windows clipboard friendly format
592 rgelt
.cfFormat
= (UINT
) wParam
;
593 rgelt
.dwAspect
= DVASPECT_CONTENT
;
595 rgelt
.tymed
= TYMED_HGLOBAL
;
597 TRACE("(): WM_RENDERFORMAT(cfFormat=%d)\n", rgelt
.cfFormat
);
600 * Render the clipboard data.
601 * (We must have a source data object or we wouldn't be in this WndProc)
603 OLEClipbrd_RenderFormat( (IDataObject
*)&(theOleClipboard
->lpvtbl
), &rgelt
);
609 * WM_RENDERALLFORMATS
610 * Sent before the clipboard owner window is destroyed.
611 * We should receive this message only when OleUninitialize is called
612 * while we have an IDataObject in the clipboard.
613 * For the content of the clipboard to remain available to other
614 * applications, we must render data in all the formats the source IDataObject
615 * is capable of generating, and place the data on the clipboard by calling
618 case WM_RENDERALLFORMATS
:
620 IEnumFORMATETC
* penumFormatetc
= NULL
;
623 TRACE("(): WM_RENDERALLFORMATS\n");
626 * Render all HGLOBAL formats supported by the source into
627 * the windows clipboard.
629 if ( FAILED( IDataObject_EnumFormatEtc( (IDataObject
*)&(theOleClipboard
->lpvtbl
),
630 DATADIR_GET
, &penumFormatetc
) ) )
632 WARN("(): WM_RENDERALLFORMATS failed to retrieve EnumFormatEtc!\n");
636 while ( S_OK
== IEnumFORMATETC_Next(penumFormatetc
, 1, &rgelt
, NULL
) )
638 if ( rgelt
.tymed
== TYMED_HGLOBAL
)
641 * Render the clipboard data.
643 if ( FAILED(OLEClipbrd_RenderFormat( (IDataObject
*)&(theOleClipboard
->lpvtbl
), &rgelt
)) )
646 TRACE("(): WM_RENDERALLFORMATS(cfFormat=%d)\n", rgelt
.cfFormat
);
650 IEnumFORMATETC_Release(penumFormatetc
);
656 * WM_DESTROYCLIPBOARD
657 * This is sent by EmptyClipboard before the clipboard is emptied.
658 * We should release any IDataObject we are holding onto when we receive
659 * this message, since it indicates that the OLE clipboard should be empty
660 * from this point on.
662 case WM_DESTROYCLIPBOARD
:
664 TRACE("(): WM_DESTROYCLIPBOARD\n");
666 * Release the data object we are holding on to
668 if ( theOleClipboard
->pIDataObjectSrc
)
670 IDataObject_Release(theOleClipboard
->pIDataObjectSrc
);
671 theOleClipboard
->pIDataObjectSrc
= NULL
;
677 case WM_ASKCBFORMATNAME:
678 case WM_CHANGECBCHAIN:
679 case WM_DRAWCLIPBOARD:
680 case WM_SIZECLIPBOARD:
681 case WM_HSCROLLCLIPBOARD:
682 case WM_VSCROLLCLIPBOARD:
683 case WM_PAINTCLIPBOARD:
686 return DefWindowProcA(hWnd
, message
, wParam
, lParam
);
693 /*---------------------------------------------------------------------*
694 * Implementation of the internal IDataObject interface exposed by
696 *---------------------------------------------------------------------*/
699 /************************************************************************
700 * OLEClipbrd_IDataObject_QueryInterface (IUnknown)
702 * See Windows documentation for more details on IUnknown methods.
704 static HRESULT WINAPI
OLEClipbrd_IDataObject_QueryInterface(
709 ole_clipbrd
*This
= impl_from_IDataObject(iface
);
710 TRACE("(%p)->(IID:%s, %p)\n", This
, debugstr_guid(riid
), ppvObject
);
712 if ( (This
==0) || (ppvObject
==0) )
717 if (IsEqualIID(&IID_IUnknown
, riid
) ||
718 IsEqualIID(&IID_IDataObject
, riid
))
724 WARN( "() : asking for unsupported interface %s\n", debugstr_guid(riid
));
725 return E_NOINTERFACE
;
728 IUnknown_AddRef((IUnknown
*)*ppvObject
);
733 /************************************************************************
734 * OLEClipbrd_IDataObject_AddRef (IUnknown)
736 * See Windows documentation for more details on IUnknown methods.
738 static ULONG WINAPI
OLEClipbrd_IDataObject_AddRef(
741 ole_clipbrd
*This
= impl_from_IDataObject(iface
);
743 TRACE("(%p)->(count=%u)\n",This
, This
->ref
);
745 return InterlockedIncrement(&This
->ref
);
748 /***********************************************************************
749 * OLEClipbrd_DestroyWindow(HWND)
750 * Destroy the clipboard window and unregister its class
752 static void OLEClipbrd_DestroyWindow(HWND hwnd
)
755 UnregisterClassA( OLEClipbrd_WNDCLASS
, 0 );
758 static void OLEClipbrd_Destroy(ole_clipbrd
* This
)
764 theOleClipboard
= NULL
;
766 if ( This
->hWndClipboard
)
767 OLEClipbrd_DestroyWindow(This
->hWndClipboard
);
769 HeapFree(GetProcessHeap(), 0, This
);
772 /************************************************************************
773 * OLEClipbrd_IDataObject_Release (IUnknown)
775 * See Windows documentation for more details on IUnknown methods.
777 static ULONG WINAPI
OLEClipbrd_IDataObject_Release(
780 ole_clipbrd
*This
= impl_from_IDataObject(iface
);
783 TRACE("(%p)->(count=%u)\n",This
, This
->ref
);
785 ref
= InterlockedDecrement(&This
->ref
);
789 OLEClipbrd_Destroy(This
);
796 /************************************************************************
797 * OLEClipbrd_IDataObject_GetData (IDataObject)
799 * The OLE Clipboard's implementation of this method delegates to
800 * a data source if there is one or wraps around the windows clipboard
802 * See Windows documentation for more details on IDataObject methods.
804 static HRESULT WINAPI
OLEClipbrd_IDataObject_GetData(
806 LPFORMATETC pformatetcIn
,
810 BOOL bClipboardOpen
= FALSE
;
813 ole_clipbrd
*This
= impl_from_IDataObject(iface
);
815 TRACE("(%p,%p,%p)\n", iface
, pformatetcIn
, pmedium
);
817 if ( !pformatetcIn
|| !pmedium
)
821 * If we have a data source placed on the clipboard (via OleSetClipboard)
822 * simply delegate to the source object's QueryGetData
823 * NOTE: This code assumes that the IDataObject is in the same address space!
824 * We will need to add marshalling support when Wine handles multiple processes.
826 if ( This
->pIDataObjectSrc
)
828 return IDataObject_GetData(This
->pIDataObjectSrc
, pformatetcIn
, pmedium
);
831 if ( pformatetcIn
->lindex
!= -1 )
832 return DV_E_FORMATETC
;
834 if ( (pformatetcIn
->tymed
& TYMED_HGLOBAL
) != TYMED_HGLOBAL
)
837 if ( pformatetcIn->dwAspect != DVASPECT_CONTENT )
838 return DV_E_DVASPECT;
842 * Otherwise, get the data from the windows clipboard using GetClipboardData
844 if ( !(bClipboardOpen
= OpenClipboard(theOleClipboard
->hWndClipboard
)) )
845 HANDLE_ERROR( CLIPBRD_E_CANT_OPEN
);
847 hData
= GetClipboardData(pformatetcIn
->cfFormat
);
849 /* Must make a copy of global handle returned by GetClipboardData; it
850 * is not valid after we call CloseClipboard
851 * Application is responsible for freeing the memory (Forte Agent does this)
853 src
= GlobalLock(hData
);
859 size
= GlobalSize(hData
);
860 hDest
= GlobalAlloc(GHND
, size
);
861 dest
= GlobalLock(hDest
);
862 memcpy(dest
, src
, size
);
869 * Return the clipboard data in the storage medium structure
871 pmedium
->tymed
= (hData
== 0) ? TYMED_NULL
: TYMED_HGLOBAL
;
872 pmedium
->u
.hGlobal
= hData
;
873 pmedium
->pUnkForRelease
= NULL
;
879 * Close Windows clipboard
881 if ( bClipboardOpen
&& !CloseClipboard() )
882 hr
= CLIPBRD_E_CANT_CLOSE
;
886 return (hData
== 0) ? DV_E_FORMATETC
: S_OK
;
889 static HRESULT WINAPI
OLEClipbrd_IDataObject_GetDataHere(
891 LPFORMATETC pformatetc
,
898 /************************************************************************
899 * OLEClipbrd_IDataObject_QueryGetData (IDataObject)
901 * The OLE Clipboard's implementation of this method delegates to
902 * a data source if there is one or wraps around the windows clipboard
903 * function IsClipboardFormatAvailable() otherwise.
905 * See Windows documentation for more details on IDataObject methods.
907 static HRESULT WINAPI
OLEClipbrd_IDataObject_QueryGetData(
909 LPFORMATETC pformatetc
)
911 TRACE("(%p, %p)\n", iface
, pformatetc
);
916 if ( pformatetc
->dwAspect
!= DVASPECT_CONTENT
)
917 return DV_E_FORMATETC
;
919 if ( pformatetc
->lindex
!= -1 )
920 return DV_E_FORMATETC
;
923 * Delegate to the Windows clipboard function IsClipboardFormatAvailable
925 return (IsClipboardFormatAvailable(pformatetc
->cfFormat
)) ? S_OK
: DV_E_CLIPFORMAT
;
928 /************************************************************************
929 * OLEClipbrd_IDataObject_GetCanonicalFormatEtc (IDataObject)
931 * See Windows documentation for more details on IDataObject methods.
933 static HRESULT WINAPI
OLEClipbrd_IDataObject_GetCanonicalFormatEtc(
935 LPFORMATETC pformatectIn
,
936 LPFORMATETC pformatetcOut
)
938 TRACE("(%p, %p, %p)\n", iface
, pformatectIn
, pformatetcOut
);
940 if ( !pformatectIn
|| !pformatetcOut
)
943 *pformatetcOut
= *pformatectIn
;
944 return DATA_S_SAMEFORMATETC
;
947 /************************************************************************
948 * OLEClipbrd_IDataObject_SetData (IDataObject)
950 * The OLE Clipboard's does not implement this method
952 * See Windows documentation for more details on IDataObject methods.
954 static HRESULT WINAPI
OLEClipbrd_IDataObject_SetData(
956 LPFORMATETC pformatetc
,
964 /************************************************************************
965 * OLEClipbrd_IDataObject_EnumFormatEtc (IDataObject)
967 * See Windows documentation for more details on IDataObject methods.
969 static HRESULT WINAPI
OLEClipbrd_IDataObject_EnumFormatEtc(
972 IEnumFORMATETC
** ppenumFormatEtc
)
975 FORMATETC
*afmt
= NULL
;
979 ole_clipbrd
*This
= impl_from_IDataObject(iface
);
981 TRACE("(%p, %x, %p)\n", iface
, dwDirection
, ppenumFormatEtc
);
984 * If we have a data source placed on the clipboard (via OleSetClipboard)
985 * simply delegate to the source object's EnumFormatEtc
987 if ( This
->pIDataObjectSrc
)
989 return IDataObject_EnumFormatEtc(This
->pIDataObjectSrc
,
990 dwDirection
, ppenumFormatEtc
);
994 * Otherwise we must provide our own enumerator which wraps around the
995 * Windows clipboard function EnumClipboardFormats
997 if ( !ppenumFormatEtc
)
1000 if ( dwDirection
!= DATADIR_GET
) /* IDataObject_SetData not implemented */
1004 * Store all current clipboard formats in an array of FORMATETC's,
1005 * and create an IEnumFORMATETC enumerator from this list.
1007 cfmt
= CountClipboardFormats();
1008 afmt
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
1009 sizeof(FORMATETC
) * cfmt
);
1011 * Open the Windows clipboard, associating it with our hidden window
1013 if ( !(bClipboardOpen
= OpenClipboard(This
->hWndClipboard
)) )
1014 HANDLE_ERROR( CLIPBRD_E_CANT_OPEN
);
1017 * Store all current clipboard formats in an array of FORMATETC's
1018 * TODO: Handle TYMED_IStorage media which were put on the clipboard
1019 * by copying the storage into global memory. We must convert this
1020 * TYMED_HGLOBAL back to TYMED_IStorage.
1022 for (i
= 0, format
= 0; i
< cfmt
; i
++)
1024 format
= EnumClipboardFormats(format
);
1025 if (!format
) /* Failed! */
1027 ERR("EnumClipboardFormats failed to return format!\n");
1028 HANDLE_ERROR( E_FAIL
);
1031 /* Init the FORMATETC struct */
1032 afmt
[i
].cfFormat
= format
;
1034 afmt
[i
].dwAspect
= DVASPECT_CONTENT
;
1035 afmt
[i
].lindex
= -1;
1036 afmt
[i
].tymed
= TYMED_HGLOBAL
;
1039 hr
= enum_fmtetc_construct( cfmt
, afmt
, ppenumFormatEtc
);
1045 * Free the array of FORMATETC's
1047 HeapFree(GetProcessHeap(), 0, afmt
);
1050 * Close Windows clipboard
1052 if ( bClipboardOpen
&& !CloseClipboard() )
1053 hr
= CLIPBRD_E_CANT_CLOSE
;
1058 /************************************************************************
1059 * OLEClipbrd_IDataObject_DAdvise (IDataObject)
1061 * The OLE Clipboard's does not implement this method
1063 * See Windows documentation for more details on IDataObject methods.
1065 static HRESULT WINAPI
OLEClipbrd_IDataObject_DAdvise(
1067 FORMATETC
* pformatetc
,
1069 IAdviseSink
* pAdvSink
,
1070 DWORD
* pdwConnection
)
1076 /************************************************************************
1077 * OLEClipbrd_IDataObject_DUnadvise (IDataObject)
1079 * The OLE Clipboard's does not implement this method
1081 * See Windows documentation for more details on IDataObject methods.
1083 static HRESULT WINAPI
OLEClipbrd_IDataObject_DUnadvise(
1091 /************************************************************************
1092 * OLEClipbrd_IDataObject_EnumDAdvise (IDataObject)
1094 * The OLE Clipboard does not implement this method
1096 * See Windows documentation for more details on IDataObject methods.
1098 static HRESULT WINAPI
OLEClipbrd_IDataObject_EnumDAdvise(
1100 IEnumSTATDATA
** ppenumAdvise
)
1106 static const IDataObjectVtbl OLEClipbrd_IDataObject_VTable
=
1108 OLEClipbrd_IDataObject_QueryInterface
,
1109 OLEClipbrd_IDataObject_AddRef
,
1110 OLEClipbrd_IDataObject_Release
,
1111 OLEClipbrd_IDataObject_GetData
,
1112 OLEClipbrd_IDataObject_GetDataHere
,
1113 OLEClipbrd_IDataObject_QueryGetData
,
1114 OLEClipbrd_IDataObject_GetCanonicalFormatEtc
,
1115 OLEClipbrd_IDataObject_SetData
,
1116 OLEClipbrd_IDataObject_EnumFormatEtc
,
1117 OLEClipbrd_IDataObject_DAdvise
,
1118 OLEClipbrd_IDataObject_DUnadvise
,
1119 OLEClipbrd_IDataObject_EnumDAdvise
1122 /*---------------------------------------------------------------------*
1123 * Internal implementation methods for the OLE clipboard
1124 *---------------------------------------------------------------------*/
1126 /*********************************************************
1127 * Construct the OLEClipbrd class.
1129 static ole_clipbrd
* OLEClipbrd_Construct(void)
1133 This
= HeapAlloc( GetProcessHeap(), 0, sizeof(*This
) );
1134 if (!This
) return NULL
;
1136 This
->lpvtbl
= &OLEClipbrd_IDataObject_VTable
;
1139 This
->hWndClipboard
= NULL
;
1140 This
->pIDataObjectSrc
= NULL
;
1142 theOleClipboard
= This
;
1146 static void register_clipboard_formats(void)
1148 static const WCHAR DataObjectW
[] = { 'D','a','t','a','O','b','j','e','c','t',0 };
1149 static const WCHAR OlePrivateDataW
[] = { 'O','l','e',' ','P','r','i','v','a','t','e',' ','D','a','t','a',0 };
1151 if(!dataobject_clipboard_format
)
1152 dataobject_clipboard_format
= RegisterClipboardFormatW(DataObjectW
);
1153 if(!ole_priv_data_clipboard_format
)
1154 ole_priv_data_clipboard_format
= RegisterClipboardFormatW(OlePrivateDataW
);
1157 /***********************************************************************
1158 * OLEClipbrd_Initialize()
1159 * Initializes the OLE clipboard.
1161 void OLEClipbrd_Initialize(void)
1163 register_clipboard_formats();
1165 if ( !theOleClipboard
)
1168 theOleClipboard
= OLEClipbrd_Construct();
1173 /***********************************************************************
1174 * OLEClipbrd_UnInitialize()
1175 * Un-Initializes the OLE clipboard
1177 void OLEClipbrd_UnInitialize(void)
1181 * Destroy the clipboard if no one holds a reference to us.
1182 * Note that the clipboard was created with a reference count of 1.
1184 if ( theOleClipboard
&& (theOleClipboard
->ref
<= 1) )
1186 OLEClipbrd_Destroy( theOleClipboard
);
1190 WARN( "() : OLEClipbrd_UnInitialize called while client holds an IDataObject reference!\n");
1194 /***********************************************************************
1195 * OLEClipbrd_CreateWindow()
1196 * Create the clipboard window
1198 static HWND
OLEClipbrd_CreateWindow(void)
1204 * Register the clipboard window class if necessary
1206 ZeroMemory( &wcex
, sizeof(WNDCLASSEXA
));
1208 wcex
.cbSize
= sizeof(WNDCLASSEXA
);
1209 /* Windows creates this class with a style mask of 0
1210 * We don't bother doing this since the FindClassByAtom code
1211 * would have to be changed to deal with this idiosyncrasy. */
1212 wcex
.style
= CS_GLOBALCLASS
;
1213 wcex
.lpfnWndProc
= OLEClipbrd_WndProc
;
1215 wcex
.lpszClassName
= OLEClipbrd_WNDCLASS
;
1217 RegisterClassExA(&wcex
);
1220 * Create a hidden window to receive OLE clipboard messages
1224 * If we need to store state info we can store it here.
1225 * For now we don't need this functionality.
1226 * ClipboardWindowInfo clipboardInfo;
1227 * ZeroMemory( &trackerInfo, sizeof(ClipboardWindowInfo));
1230 hwnd
= CreateWindowA(OLEClipbrd_WNDCLASS
,
1232 WS_POPUP
| WS_CLIPSIBLINGS
| WS_OVERLAPPED
,
1233 CW_USEDEFAULT
, CW_USEDEFAULT
,
1234 CW_USEDEFAULT
, CW_USEDEFAULT
,
1238 0 /*(LPVOID)&clipboardInfo */);
1243 static inline BOOL
is_format_in_list(ole_priv_data_entry
*entries
, DWORD num
, UINT cf
)
1246 for(i
= 0; i
< num
; i
++)
1247 if(entries
[i
].fmtetc
.cfFormat
== cf
)
1253 /*********************************************************************
1254 * set_clipboard_formats
1256 * Enumerate all HGLOBAL formats supported by the source and make
1257 * those formats available using delayed rendering using SetClipboardData.
1259 * TODO: We need to additionally handle TYMED_IStorage and
1260 * TYMED_IStream data by copying into global memory.
1262 static HRESULT
set_clipboard_formats(IDataObject
*data
)
1266 IEnumFORMATETC
*enum_fmt
;
1267 HGLOBAL priv_data_handle
;
1268 DWORD target_offset
;
1269 ole_priv_data
*priv_data
;
1270 DWORD count
= 0, needed
= sizeof(*priv_data
), idx
;
1272 hr
= IDataObject_EnumFormatEtc(data
, DATADIR_GET
, &enum_fmt
);
1273 if(FAILED(hr
)) return hr
;
1275 while(IEnumFORMATETC_Next(enum_fmt
, 1, &fmt
, NULL
) == S_OK
)
1278 needed
+= sizeof(priv_data
->entries
[0]);
1281 needed
+= fmt
.ptd
->tdSize
;
1282 CoTaskMemFree(fmt
.ptd
);
1286 /* Windows pads the list with two empty ole_priv_data_entries, one
1287 * after the entries array and one after the target device data.
1288 * Allocating with zero init to zero these pads. */
1290 needed
+= sizeof(priv_data
->entries
[0]); /* initialisation of needed includes one of these. */
1291 priv_data_handle
= GlobalAlloc(GMEM_DDESHARE
| GMEM_MOVEABLE
| GMEM_ZEROINIT
, needed
);
1292 priv_data
= GlobalLock(priv_data_handle
);
1294 priv_data
->unk1
= 0;
1295 priv_data
->size
= needed
;
1296 priv_data
->unk2
= 1;
1297 priv_data
->count
= count
;
1298 priv_data
->unk3
[0] = 0;
1299 priv_data
->unk3
[1] = 0;
1301 IEnumFORMATETC_Reset(enum_fmt
);
1304 target_offset
= FIELD_OFFSET(ole_priv_data
, entries
[count
+ 1]); /* count entries + one pad. */
1306 while(IEnumFORMATETC_Next(enum_fmt
, 1, &fmt
, NULL
) == S_OK
)
1308 if (fmt
.tymed
== TYMED_HGLOBAL
)
1311 TRACE("(cfFormat=%d:%s)\n", fmt
.cfFormat
,
1312 GetClipboardFormatNameA(fmt
.cfFormat
, fmt_name
, sizeof(fmt_name
)-1) ? fmt_name
: "");
1314 SetClipboardData(fmt
.cfFormat
, NULL
);
1317 priv_data
->entries
[idx
].fmtetc
= fmt
;
1320 memcpy((char*)priv_data
+ target_offset
, fmt
.ptd
, fmt
.ptd
->tdSize
);
1321 priv_data
->entries
[idx
].fmtetc
.ptd
= (DVTARGETDEVICE
*)target_offset
;
1322 target_offset
+= fmt
.ptd
->tdSize
;
1323 CoTaskMemFree(fmt
.ptd
);
1326 priv_data
->entries
[idx
].first_use
= !is_format_in_list(priv_data
->entries
, idx
, fmt
.cfFormat
);
1327 priv_data
->entries
[idx
].unk
[0] = 0;
1328 priv_data
->entries
[idx
].unk
[1] = 0;
1333 IEnumFORMATETC_Release(enum_fmt
);
1335 GlobalUnlock(priv_data_handle
);
1336 SetClipboardData(ole_priv_data_clipboard_format
, priv_data_handle
);
1341 /*********************************************************************
1342 * set_dataobject_format
1344 * Windows creates a 'DataObject' clipboard format that contains the
1345 * clipboard window's HWND or NULL if the Ole clipboard has been flushed.
1347 static HRESULT
set_dataobject_format(HWND hwnd
)
1349 HGLOBAL h
= GlobalAlloc(GMEM_DDESHARE
| GMEM_MOVEABLE
, sizeof(hwnd
));
1352 if(!h
) return E_OUTOFMEMORY
;
1354 data
= GlobalLock(h
);
1358 if(!SetClipboardData(dataobject_clipboard_format
, h
))
1361 return CLIPBRD_E_CANT_SET
;
1367 /*---------------------------------------------------------------------*
1368 * Win32 OLE clipboard API
1369 *---------------------------------------------------------------------*/
1371 /***********************************************************************
1372 * OleSetClipboard [OLE32.@]
1373 * Places a pointer to the specified data object onto the clipboard,
1374 * making the data object accessible to the OleGetClipboard function.
1378 * S_OK IDataObject pointer placed on the clipboard
1379 * CLIPBRD_E_CANT_OPEN OpenClipboard failed
1380 * CLIPBRD_E_CANT_EMPTY EmptyClipboard failed
1381 * CLIPBRD_E_CANT_CLOSE CloseClipboard failed
1382 * CLIPBRD_E_CANT_SET SetClipboard failed
1385 HRESULT WINAPI
OleSetClipboard(IDataObject
* pDataObj
)
1388 BOOL bClipboardOpen
= FALSE
;
1389 struct oletls
*info
= COM_CurrentInfo();
1391 TRACE("(%p)\n", pDataObj
);
1394 WARN("Could not allocate tls\n");
1396 if(!info
->ole_inits
)
1397 return CO_E_NOTINITIALIZED
;
1400 * Make sure we have a clipboard object
1402 OLEClipbrd_Initialize();
1405 * If the Ole clipboard window hasn't been created yet, create it now.
1407 if ( !theOleClipboard
->hWndClipboard
)
1408 theOleClipboard
->hWndClipboard
= OLEClipbrd_CreateWindow();
1410 if ( !theOleClipboard
->hWndClipboard
) /* sanity check */
1411 HANDLE_ERROR( E_FAIL
);
1414 * Open the Windows clipboard, associating it with our hidden window
1416 if ( !(bClipboardOpen
= OpenClipboard(theOleClipboard
->hWndClipboard
)) )
1417 HANDLE_ERROR( CLIPBRD_E_CANT_OPEN
);
1420 * Empty the current clipboard and make our window the clipboard owner
1421 * NOTE: This will trigger a WM_DESTROYCLIPBOARD message
1423 if ( !EmptyClipboard() )
1424 HANDLE_ERROR( CLIPBRD_E_CANT_EMPTY
);
1427 * If we are already holding on to an IDataObject first release that.
1429 if ( theOleClipboard
->pIDataObjectSrc
)
1431 IDataObject_Release(theOleClipboard
->pIDataObjectSrc
);
1432 theOleClipboard
->pIDataObjectSrc
= NULL
;
1435 /* A NULL value indicates that the clipboard should be emptied. */
1436 theOleClipboard
->pIDataObjectSrc
= pDataObj
;
1439 IDataObject_AddRef(theOleClipboard
->pIDataObjectSrc
);
1440 hr
= set_clipboard_formats(pDataObj
);
1441 if(FAILED(hr
)) goto CLEANUP
;
1444 hr
= set_dataobject_format(theOleClipboard
->hWndClipboard
);
1449 * Close Windows clipboard (It remains associated with our window)
1451 if ( bClipboardOpen
&& !CloseClipboard() )
1452 hr
= CLIPBRD_E_CANT_CLOSE
;
1455 * Release the source IDataObject if something failed
1459 if (theOleClipboard
->pIDataObjectSrc
)
1461 IDataObject_Release(theOleClipboard
->pIDataObjectSrc
);
1462 theOleClipboard
->pIDataObjectSrc
= NULL
;
1470 /***********************************************************************
1471 * OleGetClipboard [OLE32.@]
1472 * Returns a pointer to our internal IDataObject which represents the conceptual
1473 * state of the Windows clipboard. If the current clipboard already contains
1474 * an IDataObject, our internal IDataObject will delegate to this object.
1476 HRESULT WINAPI
OleGetClipboard(IDataObject
** ppDataObj
)
1482 * Make sure we have a clipboard object
1484 OLEClipbrd_Initialize();
1486 if (!theOleClipboard
)
1487 return E_OUTOFMEMORY
;
1489 /* Return a reference counted IDataObject */
1490 hr
= IDataObject_QueryInterface( (IDataObject
*)&(theOleClipboard
->lpvtbl
),
1491 &IID_IDataObject
, (void**)ppDataObj
);
1495 /******************************************************************************
1496 * OleFlushClipboard [OLE32.@]
1497 * Renders the data from the source IDataObject into the windows clipboard
1499 * TODO: OleFlushClipboard needs to additionally handle TYMED_IStorage media
1500 * by copying the storage into global memory. Subsequently the default
1501 * data object exposed through OleGetClipboard must convert this TYMED_HGLOBAL
1502 * back to TYMED_IStorage.
1504 HRESULT WINAPI
OleFlushClipboard(void)
1506 IEnumFORMATETC
* penumFormatetc
= NULL
;
1509 BOOL bClipboardOpen
= FALSE
;
1513 OLEClipbrd_Initialize();
1516 * Already flushed or no source DataObject? Nothing to do.
1518 if (!theOleClipboard
->pIDataObjectSrc
)
1521 if ( !(bClipboardOpen
= OpenClipboard(theOleClipboard
->hWndClipboard
)) )
1522 HANDLE_ERROR( CLIPBRD_E_CANT_OPEN
);
1525 * Render all HGLOBAL formats supported by the source into
1526 * the windows clipboard.
1528 if ( FAILED( hr
= IDataObject_EnumFormatEtc( theOleClipboard
->pIDataObjectSrc
,
1535 while ( S_OK
== IEnumFORMATETC_Next(penumFormatetc
, 1, &rgelt
, NULL
) )
1537 if ( rgelt
.tymed
== TYMED_HGLOBAL
)
1540 TRACE("(cfFormat=%d:%s)\n", rgelt
.cfFormat
,
1541 GetClipboardFormatNameA(rgelt
.cfFormat
, szFmtName
, sizeof(szFmtName
)-1)
1544 if ( FAILED(OLEClipbrd_RenderFormat( theOleClipboard
->pIDataObjectSrc
, &rgelt
)) )
1549 IEnumFORMATETC_Release(penumFormatetc
);
1551 hr
= set_dataobject_format(NULL
);
1553 IDataObject_Release(theOleClipboard
->pIDataObjectSrc
);
1554 theOleClipboard
->pIDataObjectSrc
= NULL
;
1558 if ( bClipboardOpen
&& !CloseClipboard() )
1559 hr
= CLIPBRD_E_CANT_CLOSE
;
1565 /***********************************************************************
1566 * OleIsCurrentClipboard [OLE32.@]
1568 HRESULT WINAPI
OleIsCurrentClipboard(IDataObject
*pDataObject
)
1572 * Make sure we have a clipboard object
1574 OLEClipbrd_Initialize();
1576 if (!theOleClipboard
)
1577 return E_OUTOFMEMORY
;
1579 if (pDataObject
== NULL
)
1582 return (pDataObject
== theOleClipboard
->pIDataObjectSrc
) ? S_OK
: S_FALSE
;