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.
67 #define NONAMELESSUNION
68 #define NONAMELESSSTRUCT
77 #include "wine/debug.h"
80 #include "storage32.h"
82 #include "compobj_private.h"
84 WINE_DEFAULT_DEBUG_CHANNEL(ole
);
86 #define HANDLE_ERROR(err) do { hr = err; TRACE("(HRESULT=%x)\n", (HRESULT)err); goto CLEANUP; } while (0)
88 /* Structure of 'Ole Private Data' clipboard format */
92 DWORD first_use
; /* Has this cf been added to the list already */
94 } ole_priv_data_entry
;
99 DWORD size
; /* in bytes of the entire structure */
101 DWORD count
; /* no. of format entries */
103 ole_priv_data_entry entries
[1]; /* array of size count */
104 /* then follows any DVTARGETDEVICE structures referenced in the FORMATETCs */
107 /*****************************************************************************
108 * create_empty_priv_data
110 * Create an empty data structure. The only thing that really matters
111 * here is setting count and size members. This is used by the enumerator as a
112 * convenience when there's an empty list.
114 static HRESULT
create_empty_priv_data(ole_priv_data
**data
)
119 ptr
= HeapAlloc(GetProcessHeap(), 0, sizeof(*ptr
));
120 if(!ptr
) return E_OUTOFMEMORY
;
121 ptr
->size
= sizeof(*ptr
);
127 /****************************************************************************
128 * Consumer snapshot. Represents the state of the ole clipboard
129 * returned by OleGetClipboard().
131 typedef struct snapshot
133 const IDataObjectVtbl
* lpVtbl
;
136 DWORD seq_no
; /* Clipboard sequence number corresponding to this snapshot */
138 IDataObject
*data
; /* If we unmarshal a remote data object we hold a ref here */
141 /****************************************************************************
144 typedef struct ole_clipbrd
146 snapshot
*latest_snapshot
; /* Latest consumer snapshot */
148 HWND window
; /* Hidden clipboard window */
149 IDataObject
*src_data
; /* Source object passed to OleSetClipboard */
150 ole_priv_data
*cached_enum
; /* Cached result from the enumeration of src data object */
151 IStream
*marshal_data
; /* Stream onto which to marshal src_data */
154 static inline snapshot
*impl_from_IDataObject(IDataObject
*iface
)
156 return (snapshot
*)((char*)iface
- FIELD_OFFSET(snapshot
, lpVtbl
));
159 typedef struct PresentationDataHeader
162 DWORD dwObjectExtentX
;
163 DWORD dwObjectExtentY
;
165 } PresentationDataHeader
;
168 * The one and only ole_clipbrd object which is created by OLEClipbrd_Initialize()
170 static ole_clipbrd
* theOleClipboard
;
172 static inline HRESULT
get_ole_clipbrd(ole_clipbrd
**clipbrd
)
174 struct oletls
*info
= COM_CurrentInfo();
178 return CO_E_NOTINITIALIZED
;
179 *clipbrd
= theOleClipboard
;
185 * Name of our registered OLE clipboard window class
187 static const WCHAR clipbrd_wndclass
[] = {'C','L','I','P','B','R','D','W','N','D','C','L','A','S','S',0};
189 static const WCHAR wine_marshal_dataobject
[] = {'W','i','n','e',' ','m','a','r','s','h','a','l',' ','d','a','t','a','o','b','j','e','c','t',0};
191 static UINT dataobject_clipboard_format
;
192 static UINT ole_priv_data_clipboard_format
;
193 static UINT embed_source_clipboard_format
;
195 static inline char *dump_fmtetc(FORMATETC
*fmt
)
197 static char buf
[100];
199 snprintf(buf
, sizeof(buf
), "cf %04x ptd %p aspect %x lindex %d tymed %x",
200 fmt
->cfFormat
, fmt
->ptd
, fmt
->dwAspect
, fmt
->lindex
, fmt
->tymed
);
204 /*---------------------------------------------------------------------*
205 * Implementation of the internal IEnumFORMATETC interface returned by
206 * the OLE clipboard's IDataObject.
207 *---------------------------------------------------------------------*/
209 typedef struct enum_fmtetc
211 const IEnumFORMATETCVtbl
*lpVtbl
;
214 UINT pos
; /* current enumerator position */
218 static inline enum_fmtetc
*impl_from_IEnumFORMATETC(IEnumFORMATETC
*iface
)
220 return (enum_fmtetc
*)((char*)iface
- FIELD_OFFSET(enum_fmtetc
, lpVtbl
));
223 /************************************************************************
224 * OLEClipbrd_IEnumFORMATETC_QueryInterface (IUnknown)
226 * See Windows documentation for more details on IUnknown methods.
228 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_QueryInterface
229 (LPENUMFORMATETC iface
, REFIID riid
, LPVOID
* ppvObj
)
231 enum_fmtetc
*This
= impl_from_IEnumFORMATETC(iface
);
233 TRACE("(%p)->(IID: %s, %p)\n", This
, debugstr_guid(riid
), ppvObj
);
237 if(IsEqualIID(riid
, &IID_IUnknown
) ||
238 IsEqualIID(riid
, &IID_IEnumFORMATETC
))
245 IEnumFORMATETC_AddRef((IEnumFORMATETC
*)*ppvObj
);
246 TRACE("-- Interface: (%p)->(%p)\n",ppvObj
,*ppvObj
);
250 TRACE("-- Interface: E_NOINTERFACE\n");
251 return E_NOINTERFACE
;
254 /************************************************************************
255 * OLEClipbrd_IEnumFORMATETC_AddRef (IUnknown)
258 static ULONG WINAPI
OLEClipbrd_IEnumFORMATETC_AddRef(LPENUMFORMATETC iface
)
260 enum_fmtetc
*This
= impl_from_IEnumFORMATETC(iface
);
261 TRACE("(%p)->(count=%u)\n",This
, This
->ref
);
263 return InterlockedIncrement(&This
->ref
);
266 /************************************************************************
267 * OLEClipbrd_IEnumFORMATETC_Release (IUnknown)
269 * See Windows documentation for more details on IUnknown methods.
271 static ULONG WINAPI
OLEClipbrd_IEnumFORMATETC_Release(LPENUMFORMATETC iface
)
273 enum_fmtetc
*This
= impl_from_IEnumFORMATETC(iface
);
276 TRACE("(%p)->(count=%u)\n",This
, This
->ref
);
278 ref
= InterlockedDecrement(&This
->ref
);
281 TRACE("() - destroying IEnumFORMATETC(%p)\n",This
);
282 HeapFree(GetProcessHeap(), 0, This
->data
);
283 HeapFree(GetProcessHeap(), 0, This
);
288 /************************************************************************
289 * OLEClipbrd_IEnumFORMATETC_Next (IEnumFORMATETC)
291 * Standard enumerator members for IEnumFORMATETC
293 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Next
294 (LPENUMFORMATETC iface
, ULONG celt
, FORMATETC
*rgelt
, ULONG
*pceltFethed
)
296 enum_fmtetc
*This
= impl_from_IEnumFORMATETC(iface
);
298 HRESULT hres
= S_FALSE
;
300 TRACE("(%p)->(pos=%u)\n", This
, This
->pos
);
302 if (This
->pos
< This
->data
->count
)
304 cfetch
= This
->data
->count
- This
->pos
;
311 for(i
= 0; i
< cfetch
; i
++)
313 rgelt
[i
] = This
->data
->entries
[This
->pos
++].fmtetc
;
316 DVTARGETDEVICE
*target
= (DVTARGETDEVICE
*)((char *)This
->data
+ (DWORD
)rgelt
[i
].ptd
);
317 rgelt
[i
].ptd
= CoTaskMemAlloc(target
->tdSize
);
318 if(!rgelt
[i
].ptd
) return E_OUTOFMEMORY
;
319 memcpy(rgelt
[i
].ptd
, target
, target
->tdSize
);
330 *pceltFethed
= cfetch
;
336 /************************************************************************
337 * OLEClipbrd_IEnumFORMATETC_Skip (IEnumFORMATETC)
339 * Standard enumerator members for IEnumFORMATETC
341 static HRESULT WINAPI
OLEClipbrd_IEnumFORMATETC_Skip(LPENUMFORMATETC iface
, ULONG celt
)
343 enum_fmtetc
*This
= impl_from_IEnumFORMATETC(iface
);
344 TRACE("(%p)->(num=%u)\n", This
, celt
);
347 if (This
->pos
> This
->data
->count
)
349 This
->pos
= This
->data
->count
;
355 /************************************************************************
356 * OLEClipbrd_IEnumFORMATETC_Reset (IEnumFORMATETC)
358 * Standard enumerator members for IEnumFORMATETC
360 static HRESULT WINAPI
OLEClipbrd_IEnumFORMATETC_Reset(LPENUMFORMATETC iface
)
362 enum_fmtetc
*This
= impl_from_IEnumFORMATETC(iface
);
363 TRACE("(%p)->()\n", This
);
369 static HRESULT
enum_fmtetc_construct(ole_priv_data
*data
, UINT pos
, IEnumFORMATETC
**obj
);
371 /************************************************************************
372 * OLEClipbrd_IEnumFORMATETC_Clone (IEnumFORMATETC)
374 * Standard enumerator members for IEnumFORMATETC
376 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Clone
377 (LPENUMFORMATETC iface
, LPENUMFORMATETC
* obj
)
379 enum_fmtetc
*This
= impl_from_IEnumFORMATETC(iface
);
380 ole_priv_data
*new_data
;
382 TRACE("(%p)->(%p)\n", This
, obj
);
384 if ( !obj
) return E_INVALIDARG
;
387 new_data
= HeapAlloc(GetProcessHeap(), 0, This
->data
->size
);
388 if(!new_data
) return E_OUTOFMEMORY
;
390 return enum_fmtetc_construct(new_data
, This
->pos
, obj
);
393 static const IEnumFORMATETCVtbl efvt
=
395 OLEClipbrd_IEnumFORMATETC_QueryInterface
,
396 OLEClipbrd_IEnumFORMATETC_AddRef
,
397 OLEClipbrd_IEnumFORMATETC_Release
,
398 OLEClipbrd_IEnumFORMATETC_Next
,
399 OLEClipbrd_IEnumFORMATETC_Skip
,
400 OLEClipbrd_IEnumFORMATETC_Reset
,
401 OLEClipbrd_IEnumFORMATETC_Clone
404 /************************************************************************
405 * enum_fmtetc_construct
407 * Creates an IEnumFORMATETC enumerator from ole_priv_data which it then owns.
409 static HRESULT
enum_fmtetc_construct(ole_priv_data
*data
, UINT pos
, IEnumFORMATETC
**obj
)
414 ef
= HeapAlloc(GetProcessHeap(), 0, sizeof(*ef
));
415 if (!ef
) return E_OUTOFMEMORY
;
422 TRACE("(%p)->()\n", ef
);
423 *obj
= (IEnumFORMATETC
*)ef
;
427 /***********************************************************************
430 * Helper method to duplicate an HGLOBAL chunk of memory
432 static HRESULT
dup_global_mem( HGLOBAL src
, DWORD flags
, HGLOBAL
*dst
)
434 void *src_ptr
, *dst_ptr
;
438 if ( !src
) return S_FALSE
;
440 size
= GlobalSize(src
);
442 *dst
= GlobalAlloc( flags
, size
);
443 if ( !*dst
) return E_OUTOFMEMORY
;
445 src_ptr
= GlobalLock(src
);
446 dst_ptr
= GlobalLock(*dst
);
448 memcpy(dst_ptr
, src_ptr
, size
);
456 /************************************************************
457 * render_embed_source_hack
459 * This is clearly a hack and has no place in the clipboard code.
462 static HRESULT
render_embed_source_hack(IDataObject
*data
, LPFORMATETC fmt
)
465 HGLOBAL hStorage
= 0;
467 ILockBytes
*ptrILockBytes
;
469 memset(&std
, 0, sizeof(STGMEDIUM
));
470 std
.tymed
= fmt
->tymed
= TYMED_ISTORAGE
;
472 hStorage
= GlobalAlloc(GMEM_SHARE
|GMEM_MOVEABLE
, 0);
473 if (hStorage
== NULL
) return E_OUTOFMEMORY
;
474 hr
= CreateILockBytesOnHGlobal(hStorage
, FALSE
, &ptrILockBytes
);
475 hr
= StgCreateDocfileOnILockBytes(ptrILockBytes
, STGM_SHARE_EXCLUSIVE
|STGM_READWRITE
, 0, &std
.u
.pstg
);
476 ILockBytes_Release(ptrILockBytes
);
478 if (FAILED(hr
= IDataObject_GetDataHere(theOleClipboard
->src_data
, fmt
, &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
->src_data
, &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
);
548 ReleaseStgMedium(&std2
);
550 ReadClassStg(std
.u
.pstg
, &clsID
);
551 ProgIDFromCLSID(&clsID
, &strProgID
);
553 WideCharToMultiByte( CP_ACP
, 0, strProgID
, -1, strOleTypeName
, sizeof(strOleTypeName
), NULL
, NULL
);
554 OLECONVERT_CreateOleStream(std
.u
.pstg
);
555 OLECONVERT_CreateCompObjStream(std
.u
.pstg
, strOleTypeName
);
559 if ( !SetClipboardData( fmt
->cfFormat
, hStorage
) )
561 WARN("() : Failed to set rendered clipboard data into clipboard!\n");
562 GlobalFree(hStorage
);
563 hr
= CLIPBRD_E_CANT_SET
;
566 ReleaseStgMedium(&std
);
570 /************************************************************************
571 * find_format_in_list
573 * Returns the first entry that matches the provided clipboard format.
575 static inline ole_priv_data_entry
*find_format_in_list(ole_priv_data_entry
*entries
, DWORD num
, UINT cf
)
578 for(i
= 0; i
< num
; i
++)
579 if(entries
[i
].fmtetc
.cfFormat
== cf
)
585 /***************************************************************************
586 * get_data_from_storage
588 * Returns storage data in an HGLOBAL.
590 static HRESULT
get_data_from_storage(IDataObject
*data
, FORMATETC
*fmt
, HGLOBAL
*mem
)
601 h
= GlobalAlloc( GMEM_DDESHARE
|GMEM_MOVEABLE
, 0 );
602 if(!h
) return E_OUTOFMEMORY
;
604 hr
= CreateILockBytesOnHGlobal(h
, FALSE
, &lbs
);
607 hr
= StgCreateDocfileOnILockBytes(lbs
, STGM_CREATE
|STGM_SHARE_EXCLUSIVE
|STGM_READWRITE
, 0, &stg
);
608 ILockBytes_Release(lbs
);
617 med
.tymed
= stg_fmt
.tymed
= TYMED_ISTORAGE
;
619 med
.pUnkForRelease
= NULL
;
621 hr
= IDataObject_GetDataHere(data
, &stg_fmt
, &med
);
625 hr
= IDataObject_GetData(data
, &stg_fmt
, &med
);
626 if(FAILED(hr
)) goto end
;
628 hr
= IStorage_CopyTo(med
.u
.pstg
, 0, NULL
, NULL
, stg
);
629 ReleaseStgMedium(&med
);
630 if(FAILED(hr
)) goto end
;
635 IStorage_Release(stg
);
636 if(FAILED(hr
)) GlobalFree(h
);
640 /***************************************************************************
641 * get_data_from_stream
643 * Returns stream data in an HGLOBAL.
645 static HRESULT
get_data_from_stream(IDataObject
*data
, FORMATETC
*fmt
, HGLOBAL
*mem
)
655 h
= GlobalAlloc( GMEM_DDESHARE
|GMEM_MOVEABLE
, 0 );
656 if(!h
) return E_OUTOFMEMORY
;
658 hr
= CreateStreamOnHGlobal(h
, FALSE
, &stm
);
659 if(FAILED(hr
)) goto error
;
662 med
.tymed
= stm_fmt
.tymed
= TYMED_ISTREAM
;
664 med
.pUnkForRelease
= NULL
;
666 hr
= IDataObject_GetDataHere(data
, &stm_fmt
, &med
);
673 hr
= IDataObject_GetData(data
, &stm_fmt
, &med
);
674 if(FAILED(hr
)) goto error
;
677 IStream_Seek(med
.u
.pstm
, offs
, STREAM_SEEK_CUR
, &pos
);
678 IStream_Seek(med
.u
.pstm
, offs
, STREAM_SEEK_SET
, NULL
);
679 hr
= IStream_CopyTo(med
.u
.pstm
, stm
, pos
, NULL
, NULL
);
680 ReleaseStgMedium(&med
);
681 if(FAILED(hr
)) goto error
;
684 IStream_Release(stm
);
688 if(stm
) IStream_Release(stm
);
693 /***************************************************************************
694 * get_data_from_global
696 * Returns global data in an HGLOBAL.
698 static HRESULT
get_data_from_global(IDataObject
*data
, FORMATETC
*fmt
, HGLOBAL
*mem
)
708 mem_fmt
.tymed
= TYMED_HGLOBAL
;
710 hr
= IDataObject_GetData(data
, &mem_fmt
, &med
);
711 if(FAILED(hr
)) return hr
;
713 hr
= dup_global_mem(med
.u
.hGlobal
, GMEM_DDESHARE
|GMEM_MOVEABLE
, &h
);
715 if(SUCCEEDED(hr
)) *mem
= h
;
717 ReleaseStgMedium(&med
);
722 /***********************************************************************
725 * Render the clipboard data. Note that this call will delegate to the
726 * source data object.
728 static HRESULT
render_format(IDataObject
*data
, LPFORMATETC fmt
)
730 HGLOBAL clip_data
= NULL
;
733 /* Embed source hack */
734 if(fmt
->cfFormat
== embed_source_clipboard_format
)
736 return render_embed_source_hack(data
, fmt
);
739 if(fmt
->tymed
& TYMED_ISTORAGE
)
741 hr
= get_data_from_storage(data
, fmt
, &clip_data
);
743 else if(fmt
->tymed
& TYMED_ISTREAM
)
745 hr
= get_data_from_stream(data
, fmt
, &clip_data
);
747 else if(fmt
->tymed
& TYMED_HGLOBAL
)
749 hr
= get_data_from_global(data
, fmt
, &clip_data
);
753 FIXME("Unhandled tymed %x\n", fmt
->tymed
);
759 if ( !SetClipboardData(fmt
->cfFormat
, clip_data
) )
761 WARN("() : Failed to set rendered clipboard data into clipboard!\n");
762 GlobalFree(clip_data
);
763 hr
= CLIPBRD_E_CANT_SET
;
770 /*---------------------------------------------------------------------*
771 * Implementation of the internal IDataObject interface exposed by
773 *---------------------------------------------------------------------*/
776 /************************************************************************
777 * snapshot_QueryInterface
779 static HRESULT WINAPI
snapshot_QueryInterface(IDataObject
*iface
,
780 REFIID riid
, void **ppvObject
)
782 snapshot
*This
= impl_from_IDataObject(iface
);
783 TRACE("(%p)->(IID:%s, %p)\n", This
, debugstr_guid(riid
), ppvObject
);
785 if ( (This
==0) || (ppvObject
==0) )
790 if (IsEqualIID(&IID_IUnknown
, riid
) ||
791 IsEqualIID(&IID_IDataObject
, riid
))
797 WARN( "() : asking for unsupported interface %s\n", debugstr_guid(riid
));
798 return E_NOINTERFACE
;
801 IUnknown_AddRef((IUnknown
*)*ppvObject
);
806 /************************************************************************
809 static ULONG WINAPI
snapshot_AddRef(IDataObject
*iface
)
811 snapshot
*This
= impl_from_IDataObject(iface
);
813 TRACE("(%p)->(count=%u)\n", This
, This
->ref
);
815 return InterlockedIncrement(&This
->ref
);
818 /************************************************************************
821 static ULONG WINAPI
snapshot_Release(IDataObject
*iface
)
823 snapshot
*This
= impl_from_IDataObject(iface
);
826 TRACE("(%p)->(count=%u)\n", This
, This
->ref
);
828 ref
= InterlockedDecrement(&This
->ref
);
832 ole_clipbrd
*clipbrd
;
833 HRESULT hr
= get_ole_clipbrd(&clipbrd
);
835 if(This
->data
) IDataObject_Release(This
->data
);
837 if(SUCCEEDED(hr
) && clipbrd
->latest_snapshot
== This
)
838 clipbrd
->latest_snapshot
= NULL
;
839 HeapFree(GetProcessHeap(), 0, This
);
845 /************************************************************
846 * get_current_ole_clip_window
848 * Return the window that owns the ole clipboard.
850 * If the clipboard is flushed or not owned by ole this will
853 static HWND
get_current_ole_clip_window(void)
858 h
= GetClipboardData(dataobject_clipboard_format
);
861 if(!ptr
) return NULL
;
867 /************************************************************
868 * get_current_dataobject
870 * Return an unmarshalled IDataObject if there is a current
871 * (ie non-flushed) object on the ole clipboard.
873 static HRESULT
get_current_dataobject(IDataObject
**data
)
875 HRESULT hr
= S_FALSE
;
876 HWND wnd
= get_current_ole_clip_window();
883 if(!wnd
) return S_FALSE
;
885 h
= GetPropW(wnd
, wine_marshal_dataobject
);
886 if(!h
) return S_FALSE
;
888 if(!ptr
) return S_FALSE
;
890 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &stm
);
891 if(FAILED(hr
)) goto end
;
893 hr
= IStream_Write(stm
, ptr
, GlobalSize(h
), NULL
);
897 IStream_Seek(stm
, pos
, STREAM_SEEK_SET
, NULL
);
898 hr
= CoUnmarshalInterface(stm
, &IID_IDataObject
, (void**)data
);
900 IStream_Release(stm
);
907 /***********************************************************
910 * Returns a copy of the Ole Private Data
912 static HRESULT
get_priv_data(ole_priv_data
**data
)
919 handle
= GetClipboardData( ole_priv_data_clipboard_format
);
922 ole_priv_data
*src
= GlobalLock(handle
);
925 /* FIXME: sanity check on size */
926 *data
= HeapAlloc(GetProcessHeap(), 0, src
->size
);
929 GlobalUnlock(handle
);
930 return E_OUTOFMEMORY
;
932 memcpy(*data
, src
, src
->size
);
933 GlobalUnlock(handle
);
937 if(!*data
) hr
= create_empty_priv_data(data
);
942 /************************************************************************
943 * get_stgmed_for_global
945 * Returns a stg medium with a copy of the global handle
947 static HRESULT
get_stgmed_for_global(HGLOBAL h
, STGMEDIUM
*med
)
951 med
->pUnkForRelease
= NULL
;
952 med
->tymed
= TYMED_NULL
;
954 hr
= dup_global_mem(h
, GMEM_MOVEABLE
, &med
->u
.hGlobal
);
956 if(SUCCEEDED(hr
)) med
->tymed
= TYMED_HGLOBAL
;
961 /************************************************************************
962 * get_stgmed_for_stream
964 * Returns a stg medium with a stream based on the handle
966 static HRESULT
get_stgmed_for_stream(HGLOBAL h
, STGMEDIUM
*med
)
971 med
->pUnkForRelease
= NULL
;
972 med
->tymed
= TYMED_NULL
;
974 hr
= dup_global_mem(h
, GMEM_MOVEABLE
, &dst
);
975 if(FAILED(hr
)) return hr
;
977 hr
= CreateStreamOnHGlobal(dst
, TRUE
, &med
->u
.pstm
);
984 med
->tymed
= TYMED_ISTREAM
;
988 /************************************************************************
989 * get_stgmed_for_storage
991 * Returns a stg medium with a storage based on the handle
993 static HRESULT
get_stgmed_for_storage(HGLOBAL h
, STGMEDIUM
*med
)
999 med
->pUnkForRelease
= NULL
;
1000 med
->tymed
= TYMED_NULL
;
1002 hr
= dup_global_mem(h
, GMEM_MOVEABLE
, &dst
);
1003 if(FAILED(hr
)) return hr
;
1005 hr
= CreateILockBytesOnHGlobal(dst
, TRUE
, &lbs
);
1012 hr
= StgOpenStorageOnILockBytes(lbs
, NULL
, STGM_SHARE_EXCLUSIVE
| STGM_READWRITE
, NULL
, 0, &med
->u
.pstg
);
1013 ILockBytes_Release(lbs
);
1020 med
->tymed
= TYMED_ISTORAGE
;
1024 /************************************************************************
1027 static HRESULT WINAPI
snapshot_GetData(IDataObject
*iface
, FORMATETC
*fmt
,
1030 snapshot
*This
= impl_from_IDataObject(iface
);
1033 ole_priv_data
*enum_data
= NULL
;
1034 ole_priv_data_entry
*entry
;
1037 TRACE("(%p,%p,%p)\n", iface
, fmt
, med
);
1039 if ( !fmt
|| !med
) return E_INVALIDARG
;
1041 if ( !OpenClipboard(NULL
)) return CLIPBRD_E_CANT_OPEN
;
1044 hr
= get_current_dataobject(&This
->data
);
1048 hr
= IDataObject_GetData(This
->data
, fmt
, med
);
1053 h
= GetClipboardData(fmt
->cfFormat
);
1056 hr
= DV_E_FORMATETC
;
1060 hr
= get_priv_data(&enum_data
);
1061 if(FAILED(hr
)) goto end
;
1063 entry
= find_format_in_list(enum_data
->entries
, enum_data
->count
, fmt
->cfFormat
);
1065 mask
= fmt
->tymed
& entry
->fmtetc
.tymed
;
1066 else /* non-Ole format */
1067 mask
= fmt
->tymed
& TYMED_HGLOBAL
;
1069 if(mask
& TYMED_ISTORAGE
)
1070 hr
= get_stgmed_for_storage(h
, med
);
1071 else if(mask
& TYMED_HGLOBAL
)
1072 hr
= get_stgmed_for_global(h
, med
);
1073 else if(mask
& TYMED_ISTREAM
)
1074 hr
= get_stgmed_for_stream(h
, med
);
1077 FIXME("Unhandled tymed - emum tymed %x req tymed %x\n", entry
->fmtetc
.tymed
, fmt
->tymed
);
1083 if ( !CloseClipboard() ) hr
= CLIPBRD_E_CANT_CLOSE
;
1087 /************************************************************************
1088 * snapshot_GetDataHere
1090 static HRESULT WINAPI
snapshot_GetDataHere(IDataObject
*iface
, FORMATETC
*fmt
,
1093 FIXME("(%p, %p, %p): stub\n", iface
, fmt
, med
);
1097 /************************************************************************
1098 * snapshot_QueryGetData
1100 * The OLE Clipboard's implementation of this method delegates to
1101 * a data source if there is one or wraps around the windows clipboard
1102 * function IsClipboardFormatAvailable() otherwise.
1105 static HRESULT WINAPI
snapshot_QueryGetData(IDataObject
*iface
, FORMATETC
*fmt
)
1107 FIXME("(%p, %p)\n", iface
, fmt
);
1109 if (!fmt
) return E_INVALIDARG
;
1111 if ( fmt
->dwAspect
!= DVASPECT_CONTENT
) return DV_E_FORMATETC
;
1113 if ( fmt
->lindex
!= -1 ) return DV_E_FORMATETC
;
1115 return (IsClipboardFormatAvailable(fmt
->cfFormat
)) ? S_OK
: DV_E_CLIPFORMAT
;
1118 /************************************************************************
1119 * snapshot_GetCanonicalFormatEtc
1121 static HRESULT WINAPI
snapshot_GetCanonicalFormatEtc(IDataObject
*iface
, FORMATETC
*fmt_in
,
1124 TRACE("(%p, %p, %p)\n", iface
, fmt_in
, fmt_out
);
1126 if ( !fmt_in
|| !fmt_out
) return E_INVALIDARG
;
1129 return DATA_S_SAMEFORMATETC
;
1132 /************************************************************************
1135 * The OLE Clipboard does not implement this method
1137 static HRESULT WINAPI
snapshot_SetData(IDataObject
*iface
, FORMATETC
*fmt
,
1138 STGMEDIUM
*med
, BOOL release
)
1140 TRACE("(%p, %p, %p, %d): not implemented\n", iface
, fmt
, med
, release
);
1144 /************************************************************************
1145 * snapshot_EnumFormatEtc
1148 static HRESULT WINAPI
snapshot_EnumFormatEtc(IDataObject
*iface
, DWORD dir
,
1149 IEnumFORMATETC
**enum_fmt
)
1152 ole_priv_data
*data
= NULL
;
1154 TRACE("(%p, %x, %p)\n", iface
, dir
, enum_fmt
);
1158 if ( dir
!= DATADIR_GET
) return E_NOTIMPL
;
1159 if ( !OpenClipboard(NULL
) ) return CLIPBRD_E_CANT_OPEN
;
1161 hr
= get_priv_data(&data
);
1163 if(FAILED(hr
)) goto end
;
1165 hr
= enum_fmtetc_construct( data
, 0, enum_fmt
);
1168 if ( !CloseClipboard() ) hr
= CLIPBRD_E_CANT_CLOSE
;
1172 /************************************************************************
1175 * The OLE Clipboard does not implement this method
1177 static HRESULT WINAPI
snapshot_DAdvise(IDataObject
*iface
, FORMATETC
*fmt
,
1178 DWORD flags
, IAdviseSink
*sink
,
1181 TRACE("(%p, %p, %x, %p, %p): not implemented\n", iface
, fmt
, flags
, sink
, conn
);
1185 /************************************************************************
1186 * snapshot_DUnadvise
1188 * The OLE Clipboard does not implement this method
1190 static HRESULT WINAPI
snapshot_DUnadvise(IDataObject
* iface
, DWORD conn
)
1192 TRACE("(%p, %d): not implemented\n", iface
, conn
);
1196 /************************************************************************
1197 * snapshot_EnumDAdvise
1199 * The OLE Clipboard does not implement this method
1201 static HRESULT WINAPI
snapshot_EnumDAdvise(IDataObject
* iface
,
1202 IEnumSTATDATA
** enum_advise
)
1204 TRACE("(%p, %p): not implemented\n", iface
, enum_advise
);
1208 static const IDataObjectVtbl snapshot_vtable
=
1210 snapshot_QueryInterface
,
1214 snapshot_GetDataHere
,
1215 snapshot_QueryGetData
,
1216 snapshot_GetCanonicalFormatEtc
,
1218 snapshot_EnumFormatEtc
,
1221 snapshot_EnumDAdvise
1224 /*---------------------------------------------------------------------*
1225 * Internal implementation methods for the OLE clipboard
1226 *---------------------------------------------------------------------*/
1228 static snapshot
*snapshot_construct(DWORD seq_no
)
1232 This
= HeapAlloc( GetProcessHeap(), 0, sizeof(*This
) );
1233 if (!This
) return NULL
;
1235 This
->lpVtbl
= &snapshot_vtable
;
1237 This
->seq_no
= seq_no
;
1243 /*********************************************************
1244 * register_clipboard_formats
1246 static void register_clipboard_formats(void)
1248 static const WCHAR DataObjectW
[] = { 'D','a','t','a','O','b','j','e','c','t',0 };
1249 static const WCHAR OlePrivateDataW
[] = { 'O','l','e',' ','P','r','i','v','a','t','e',' ','D','a','t','a',0 };
1250 static const WCHAR EmbedSourceW
[] = { 'E','m','b','e','d',' ','S','o','u','r','c','e',0 };
1252 if(!dataobject_clipboard_format
)
1253 dataobject_clipboard_format
= RegisterClipboardFormatW(DataObjectW
);
1254 if(!ole_priv_data_clipboard_format
)
1255 ole_priv_data_clipboard_format
= RegisterClipboardFormatW(OlePrivateDataW
);
1256 if(!embed_source_clipboard_format
)
1257 embed_source_clipboard_format
= RegisterClipboardFormatW(EmbedSourceW
);
1260 /***********************************************************************
1261 * OLEClipbrd_Initialize()
1262 * Initializes the OLE clipboard.
1264 void OLEClipbrd_Initialize(void)
1266 register_clipboard_formats();
1268 if ( !theOleClipboard
)
1270 ole_clipbrd
* clipbrd
;
1275 clipbrd
= HeapAlloc( GetProcessHeap(), 0, sizeof(*clipbrd
) );
1276 if (!clipbrd
) return;
1278 clipbrd
->latest_snapshot
= NULL
;
1279 clipbrd
->window
= NULL
;
1280 clipbrd
->src_data
= NULL
;
1281 clipbrd
->cached_enum
= NULL
;
1283 h
= GlobalAlloc(GMEM_DDESHARE
| GMEM_MOVEABLE
, 0);
1286 HeapFree(GetProcessHeap(), 0, clipbrd
);
1290 if(FAILED(CreateStreamOnHGlobal(h
, TRUE
, &clipbrd
->marshal_data
)))
1293 HeapFree(GetProcessHeap(), 0, clipbrd
);
1297 theOleClipboard
= clipbrd
;
1301 /***********************************************************************
1302 * OLEClipbrd_UnInitialize()
1303 * Un-Initializes the OLE clipboard
1305 void OLEClipbrd_UnInitialize(void)
1307 ole_clipbrd
*clipbrd
= theOleClipboard
;
1313 static const WCHAR ole32W
[] = {'o','l','e','3','2',0};
1314 HINSTANCE hinst
= GetModuleHandleW(ole32W
);
1316 if ( clipbrd
->window
)
1318 DestroyWindow(clipbrd
->window
);
1319 UnregisterClassW( clipbrd_wndclass
, hinst
);
1322 IStream_Release(clipbrd
->marshal_data
);
1323 HeapFree(GetProcessHeap(), 0, clipbrd
);
1324 theOleClipboard
= NULL
;
1328 /*********************************************************************
1329 * set_clipboard_formats
1331 * Enumerate all formats supported by the source and make
1332 * those formats available using delayed rendering using SetClipboardData.
1333 * Cache the enumeration list and make that list visibile as the
1334 * 'Ole Private Data' format on the clipboard.
1337 static HRESULT
set_clipboard_formats(ole_clipbrd
*clipbrd
, IDataObject
*data
)
1341 IEnumFORMATETC
*enum_fmt
;
1342 HGLOBAL priv_data_handle
;
1343 DWORD target_offset
;
1344 ole_priv_data
*priv_data
;
1345 DWORD count
= 0, needed
= sizeof(*priv_data
), idx
;
1347 hr
= IDataObject_EnumFormatEtc(data
, DATADIR_GET
, &enum_fmt
);
1348 if(FAILED(hr
)) return hr
;
1350 while(IEnumFORMATETC_Next(enum_fmt
, 1, &fmt
, NULL
) == S_OK
)
1353 needed
+= sizeof(priv_data
->entries
[0]);
1356 needed
+= fmt
.ptd
->tdSize
;
1357 CoTaskMemFree(fmt
.ptd
);
1361 /* Windows pads the list with two empty ole_priv_data_entries, one
1362 * after the entries array and one after the target device data.
1363 * Allocating with zero init to zero these pads. */
1365 needed
+= sizeof(priv_data
->entries
[0]); /* initialisation of needed includes one of these. */
1366 priv_data_handle
= GlobalAlloc(GMEM_DDESHARE
| GMEM_MOVEABLE
| GMEM_ZEROINIT
, needed
);
1367 priv_data
= GlobalLock(priv_data_handle
);
1369 priv_data
->unk1
= 0;
1370 priv_data
->size
= needed
;
1371 priv_data
->unk2
= 1;
1372 priv_data
->count
= count
;
1373 priv_data
->unk3
[0] = 0;
1374 priv_data
->unk3
[1] = 0;
1376 IEnumFORMATETC_Reset(enum_fmt
);
1379 target_offset
= FIELD_OFFSET(ole_priv_data
, entries
[count
+ 1]); /* count entries + one pad. */
1381 while(IEnumFORMATETC_Next(enum_fmt
, 1, &fmt
, NULL
) == S_OK
)
1383 TRACE("%s\n", dump_fmtetc(&fmt
));
1385 priv_data
->entries
[idx
].fmtetc
= fmt
;
1388 memcpy((char*)priv_data
+ target_offset
, fmt
.ptd
, fmt
.ptd
->tdSize
);
1389 priv_data
->entries
[idx
].fmtetc
.ptd
= (DVTARGETDEVICE
*)target_offset
;
1390 target_offset
+= fmt
.ptd
->tdSize
;
1391 CoTaskMemFree(fmt
.ptd
);
1394 priv_data
->entries
[idx
].first_use
= !find_format_in_list(priv_data
->entries
, idx
, fmt
.cfFormat
);
1395 priv_data
->entries
[idx
].unk
[0] = 0;
1396 priv_data
->entries
[idx
].unk
[1] = 0;
1398 if (priv_data
->entries
[idx
].first_use
)
1399 SetClipboardData(fmt
.cfFormat
, NULL
);
1404 IEnumFORMATETC_Release(enum_fmt
);
1406 /* Cache the list and fixup any target device offsets to ptrs */
1407 clipbrd
->cached_enum
= HeapAlloc(GetProcessHeap(), 0, needed
);
1408 memcpy(clipbrd
->cached_enum
, priv_data
, needed
);
1409 for(idx
= 0; idx
< clipbrd
->cached_enum
->count
; idx
++)
1410 if(clipbrd
->cached_enum
->entries
[idx
].fmtetc
.ptd
)
1411 clipbrd
->cached_enum
->entries
[idx
].fmtetc
.ptd
=
1412 (DVTARGETDEVICE
*)((char*)clipbrd
->cached_enum
+ (DWORD
)clipbrd
->cached_enum
->entries
[idx
].fmtetc
.ptd
);
1414 GlobalUnlock(priv_data_handle
);
1415 SetClipboardData(ole_priv_data_clipboard_format
, priv_data_handle
);
1420 static HWND
create_clipbrd_window(void);
1422 /***********************************************************************
1423 * get_clipbrd_window
1425 static inline HRESULT
get_clipbrd_window(ole_clipbrd
*clipbrd
, HWND
*wnd
)
1427 if ( !clipbrd
->window
)
1428 clipbrd
->window
= create_clipbrd_window();
1430 *wnd
= clipbrd
->window
;
1431 return *wnd
? S_OK
: E_FAIL
;
1435 /**********************************************************************
1436 * release_marshal_data
1438 * Releases the data and sets the stream back to zero size.
1440 static inline void release_marshal_data(IStream
*stm
)
1443 ULARGE_INTEGER size
;
1444 pos
.QuadPart
= size
.QuadPart
= 0;
1446 IStream_Seek(stm
, pos
, STREAM_SEEK_SET
, NULL
);
1447 CoReleaseMarshalData(stm
);
1448 IStream_Seek(stm
, pos
, STREAM_SEEK_SET
, NULL
);
1449 IStream_SetSize(stm
, size
);
1452 /***********************************************************************
1453 * set_src_dataobject
1455 * Clears and sets the clipboard's src IDataObject.
1457 * To marshal the source dataobject we do something rather different from Windows.
1458 * We set a window prop which contains the marshalled data.
1459 * Windows set two props one of which is an IID, the other is an endpoint number.
1461 static HRESULT
set_src_dataobject(ole_clipbrd
*clipbrd
, IDataObject
*data
)
1466 if(FAILED(hr
= get_clipbrd_window(clipbrd
, &wnd
))) return hr
;
1468 if(clipbrd
->src_data
)
1470 RemovePropW(wnd
, wine_marshal_dataobject
);
1471 release_marshal_data(clipbrd
->marshal_data
);
1473 IDataObject_Release(clipbrd
->src_data
);
1474 clipbrd
->src_data
= NULL
;
1475 HeapFree(GetProcessHeap(), 0, clipbrd
->cached_enum
);
1476 clipbrd
->cached_enum
= NULL
;
1484 IDataObject_AddRef(data
);
1485 clipbrd
->src_data
= data
;
1487 IDataObject_QueryInterface(data
, &IID_IUnknown
, (void**)&unk
);
1488 hr
= CoMarshalInterface(clipbrd
->marshal_data
, &IID_IDataObject
, unk
,
1489 MSHCTX_LOCAL
, NULL
, MSHLFLAGS_TABLESTRONG
);
1490 IUnknown_Release(unk
); /* Don't hold a ref on IUnknown, we have one on IDataObject. */
1491 if(FAILED(hr
)) return hr
;
1492 GetHGlobalFromStream(clipbrd
->marshal_data
, &h
);
1493 SetPropW(wnd
, wine_marshal_dataobject
, h
);
1494 hr
= set_clipboard_formats(clipbrd
, data
);
1499 /***********************************************************************
1502 static LRESULT CALLBACK
clipbrd_wndproc(HWND hwnd
, UINT message
, WPARAM wparam
, LPARAM lparam
)
1504 ole_clipbrd
*clipbrd
;
1506 get_ole_clipbrd(&clipbrd
);
1510 case WM_RENDERFORMAT
:
1513 ole_priv_data_entry
*entry
;
1515 TRACE("(): WM_RENDERFORMAT(cfFormat=%x)\n", cf
);
1516 entry
= find_format_in_list(clipbrd
->cached_enum
->entries
, clipbrd
->cached_enum
->count
, cf
);
1519 render_format(clipbrd
->src_data
, &entry
->fmtetc
);
1524 case WM_RENDERALLFORMATS
:
1527 ole_priv_data_entry
*entries
= clipbrd
->cached_enum
->entries
;
1529 TRACE("(): WM_RENDERALLFORMATS\n");
1531 for(i
= 0; i
< clipbrd
->cached_enum
->count
; i
++)
1533 if(entries
[i
].first_use
)
1534 render_format(clipbrd
->src_data
, &entries
[i
].fmtetc
);
1539 case WM_DESTROYCLIPBOARD
:
1541 TRACE("(): WM_DESTROYCLIPBOARD\n");
1543 set_src_dataobject(clipbrd
, NULL
);
1548 return DefWindowProcW(hwnd
, message
, wparam
, lparam
);
1555 /***********************************************************************
1556 * create_clipbrd_window
1558 static HWND
create_clipbrd_window(void)
1561 static const WCHAR ole32W
[] = {'o','l','e','3','2',0};
1562 static const WCHAR title
[] = {'C','l','i','p','b','o','a','r','d','W','i','n','d','o','w',0};
1563 HINSTANCE hinst
= GetModuleHandleW(ole32W
);
1565 class.cbSize
= sizeof(class);
1567 class.lpfnWndProc
= clipbrd_wndproc
;
1568 class.cbClsExtra
= 0;
1569 class.cbWndExtra
= 0;
1570 class.hInstance
= hinst
;
1573 class.hbrBackground
= 0;
1574 class.lpszMenuName
= NULL
;
1575 class.lpszClassName
= clipbrd_wndclass
;
1576 class.hIconSm
= NULL
;
1578 RegisterClassExW(&class);
1580 return CreateWindowW(clipbrd_wndclass
, title
, WS_POPUP
| WS_CLIPSIBLINGS
| WS_OVERLAPPED
,
1581 CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
,
1582 NULL
, NULL
, hinst
, 0);
1585 /*********************************************************************
1586 * set_dataobject_format
1588 * Windows creates a 'DataObject' clipboard format that contains the
1589 * clipboard window's HWND or NULL if the Ole clipboard has been flushed.
1591 static HRESULT
set_dataobject_format(HWND hwnd
)
1593 HGLOBAL h
= GlobalAlloc(GMEM_DDESHARE
| GMEM_MOVEABLE
, sizeof(hwnd
));
1596 if(!h
) return E_OUTOFMEMORY
;
1598 data
= GlobalLock(h
);
1602 if(!SetClipboardData(dataobject_clipboard_format
, h
))
1605 return CLIPBRD_E_CANT_SET
;
1611 /*---------------------------------------------------------------------*
1612 * Win32 OLE clipboard API
1613 *---------------------------------------------------------------------*/
1615 /***********************************************************************
1616 * OleSetClipboard [OLE32.@]
1617 * Places a pointer to the specified data object onto the clipboard,
1618 * making the data object accessible to the OleGetClipboard function.
1622 * S_OK IDataObject pointer placed on the clipboard
1623 * CLIPBRD_E_CANT_OPEN OpenClipboard failed
1624 * CLIPBRD_E_CANT_EMPTY EmptyClipboard failed
1625 * CLIPBRD_E_CANT_CLOSE CloseClipboard failed
1626 * CLIPBRD_E_CANT_SET SetClipboard failed
1629 HRESULT WINAPI
OleSetClipboard(IDataObject
* data
)
1632 ole_clipbrd
*clipbrd
;
1635 TRACE("(%p)\n", data
);
1637 if(FAILED(hr
= get_ole_clipbrd(&clipbrd
))) return hr
;
1639 if(FAILED(hr
= get_clipbrd_window(clipbrd
, &wnd
))) return hr
;
1641 if ( !OpenClipboard(wnd
) ) return CLIPBRD_E_CANT_OPEN
;
1643 if ( !EmptyClipboard() )
1645 hr
= CLIPBRD_E_CANT_EMPTY
;
1649 hr
= set_src_dataobject(clipbrd
, data
);
1650 if(FAILED(hr
)) goto end
;
1652 hr
= set_dataobject_format(wnd
);
1656 if ( !CloseClipboard() ) hr
= CLIPBRD_E_CANT_CLOSE
;
1660 set_src_dataobject(clipbrd
, NULL
);
1667 /***********************************************************************
1668 * OleGetClipboard [OLE32.@]
1669 * Returns a pointer to our internal IDataObject which represents the conceptual
1670 * state of the Windows clipboard. If the current clipboard already contains
1671 * an IDataObject, our internal IDataObject will delegate to this object.
1673 HRESULT WINAPI
OleGetClipboard(IDataObject
**obj
)
1676 ole_clipbrd
*clipbrd
;
1679 TRACE("(%p)\n", obj
);
1681 if(!obj
) return E_INVALIDARG
;
1683 if(FAILED(hr
= get_ole_clipbrd(&clipbrd
))) return hr
;
1685 seq_no
= GetClipboardSequenceNumber();
1686 if(clipbrd
->latest_snapshot
&& clipbrd
->latest_snapshot
->seq_no
!= seq_no
)
1687 clipbrd
->latest_snapshot
= NULL
;
1689 if(!clipbrd
->latest_snapshot
)
1691 clipbrd
->latest_snapshot
= snapshot_construct(seq_no
);
1692 if(!clipbrd
->latest_snapshot
) return E_OUTOFMEMORY
;
1695 *obj
= (IDataObject
*)&clipbrd
->latest_snapshot
->lpVtbl
;
1696 IDataObject_AddRef(*obj
);
1701 /******************************************************************************
1702 * OleFlushClipboard [OLE32.@]
1703 * Renders the data from the source IDataObject into the windows clipboard
1705 * TODO: OleFlushClipboard needs to additionally handle TYMED_IStorage media
1706 * by copying the storage into global memory. Subsequently the default
1707 * data object exposed through OleGetClipboard must convert this TYMED_HGLOBAL
1708 * back to TYMED_IStorage.
1710 HRESULT WINAPI
OleFlushClipboard(void)
1713 ole_clipbrd
*clipbrd
;
1718 if(FAILED(hr
= get_ole_clipbrd(&clipbrd
))) return hr
;
1720 if(FAILED(hr
= get_clipbrd_window(clipbrd
, &wnd
))) return hr
;
1723 * Already flushed or no source DataObject? Nothing to do.
1725 if (!clipbrd
->src_data
) return S_OK
;
1727 if (!OpenClipboard(wnd
)) return CLIPBRD_E_CANT_OPEN
;
1729 SendMessageW(wnd
, WM_RENDERALLFORMATS
, 0, 0);
1731 hr
= set_dataobject_format(NULL
);
1733 set_src_dataobject(clipbrd
, NULL
);
1735 if ( !CloseClipboard() ) hr
= CLIPBRD_E_CANT_CLOSE
;
1741 /***********************************************************************
1742 * OleIsCurrentClipboard [OLE32.@]
1744 HRESULT WINAPI
OleIsCurrentClipboard(IDataObject
*data
)
1747 ole_clipbrd
*clipbrd
;
1750 if(FAILED(hr
= get_ole_clipbrd(&clipbrd
))) return hr
;
1752 if (data
== NULL
) return S_FALSE
;
1754 return (data
== clipbrd
->src_data
) ? S_OK
: S_FALSE
;