dpvoice: Turn GetCompressionTypes into a semi-stub.
[wine.git] / dlls / ole32 / clipboard.c
blob38df750038b6d350ada09fc8c5f03618422a17d3
1 /*
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
21 * NOTES:
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
46 * TODO:
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.
61 #include <assert.h>
62 #include <stdarg.h>
63 #include <string.h>
64 #include <stdio.h>
66 #define COBJMACROS
67 #define NONAMELESSUNION
68 #define NONAMELESSSTRUCT
70 #include "windef.h"
71 #include "winbase.h"
72 #include "wingdi.h"
73 #include "winuser.h"
74 #include "winerror.h"
75 #include "winnls.h"
76 #include "ole2.h"
77 #include "wine/debug.h"
78 #include "olestd.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 */
89 typedef struct
91 FORMATETC fmtetc;
92 DWORD first_use; /* Has this cf been added to the list already */
93 DWORD unk[2];
94 } ole_priv_data_entry;
96 typedef struct
98 DWORD unk1;
99 DWORD size; /* in bytes of the entire structure */
100 DWORD unk2;
101 DWORD count; /* no. of format entries */
102 DWORD unk3[2];
103 ole_priv_data_entry entries[1]; /* array of size count */
104 /* then follows any DVTARGETDEVICE structures referenced in the FORMATETCs */
105 } ole_priv_data;
107 /*****************************************************************************
108 * td_offs_to_ptr
110 * Returns a ptr to a target device at a given offset from the
111 * start of the ole_priv_data.
113 * Used when unpacking ole private data from the clipboard.
115 static inline DVTARGETDEVICE *td_offs_to_ptr(ole_priv_data *data, DWORD_PTR off)
117 if(off == 0) return NULL;
118 return (DVTARGETDEVICE*)((char*)data + off);
121 /*****************************************************************************
122 * td_get_offs
124 * Get the offset from the start of the ole_priv_data of the idx'th
125 * target device.
127 * Used when packing ole private data to the clipboard.
129 static inline DWORD_PTR td_get_offs(ole_priv_data *data, DWORD idx)
131 if(data->entries[idx].fmtetc.ptd == NULL) return 0;
132 return (char*)data->entries[idx].fmtetc.ptd - (char*)data;
135 /****************************************************************************
136 * Consumer snapshot. Represents the state of the ole clipboard
137 * returned by OleGetClipboard().
139 typedef struct snapshot
141 IDataObject IDataObject_iface;
142 LONG ref;
144 DWORD seq_no; /* Clipboard sequence number corresponding to this snapshot */
146 IDataObject *data; /* If we unmarshal a remote data object we hold a ref here */
147 } snapshot;
149 /****************************************************************************
150 * ole_clipbrd
152 typedef struct ole_clipbrd
154 snapshot *latest_snapshot; /* Latest consumer snapshot */
156 HWND window; /* Hidden clipboard window */
157 IDataObject *src_data; /* Source object passed to OleSetClipboard */
158 ole_priv_data *cached_enum; /* Cached result from the enumeration of src data object */
159 IStream *marshal_data; /* Stream onto which to marshal src_data */
160 } ole_clipbrd;
162 static inline snapshot *impl_from_IDataObject(IDataObject *iface)
164 return CONTAINING_RECORD(iface, snapshot, IDataObject_iface);
167 typedef struct PresentationDataHeader
169 BYTE unknown1[28];
170 DWORD dwObjectExtentX;
171 DWORD dwObjectExtentY;
172 DWORD dwSize;
173 } PresentationDataHeader;
176 * The one and only ole_clipbrd object which is created by OLEClipbrd_Initialize()
178 static ole_clipbrd* theOleClipboard;
180 static inline HRESULT get_ole_clipbrd(ole_clipbrd **clipbrd)
182 struct oletls *info = COM_CurrentInfo();
183 *clipbrd = NULL;
185 if(!info->ole_inits)
186 return CO_E_NOTINITIALIZED;
187 *clipbrd = theOleClipboard;
189 return S_OK;
193 * Name of our registered OLE clipboard window class
195 static const WCHAR clipbrd_wndclass[] = {'C','L','I','P','B','R','D','W','N','D','C','L','A','S','S',0};
197 UINT ownerlink_clipboard_format = 0;
198 UINT filename_clipboard_format = 0;
199 UINT filenameW_clipboard_format = 0;
200 UINT dataobject_clipboard_format = 0;
201 UINT embedded_object_clipboard_format = 0;
202 UINT embed_source_clipboard_format = 0;
203 UINT custom_link_source_clipboard_format = 0;
204 UINT link_source_clipboard_format = 0;
205 UINT object_descriptor_clipboard_format = 0;
206 UINT link_source_descriptor_clipboard_format = 0;
207 UINT ole_private_data_clipboard_format = 0;
209 static UINT wine_marshal_clipboard_format;
211 static inline const char *dump_fmtetc(FORMATETC *fmt)
213 if (!fmt) return "(null)";
214 return wine_dbg_sprintf("cf %04x ptd %p aspect %x lindex %d tymed %x",
215 fmt->cfFormat, fmt->ptd, fmt->dwAspect, fmt->lindex, fmt->tymed);
218 /*---------------------------------------------------------------------*
219 * Implementation of the internal IEnumFORMATETC interface returned by
220 * the OLE clipboard's IDataObject.
221 *---------------------------------------------------------------------*/
223 typedef struct enum_fmtetc
225 IEnumFORMATETC IEnumFORMATETC_iface;
226 LONG ref;
228 UINT pos; /* current enumerator position */
229 ole_priv_data *data;
230 } enum_fmtetc;
232 static inline enum_fmtetc *impl_from_IEnumFORMATETC(IEnumFORMATETC *iface)
234 return CONTAINING_RECORD(iface, enum_fmtetc, IEnumFORMATETC_iface);
237 /************************************************************************
238 * OLEClipbrd_IEnumFORMATETC_QueryInterface (IUnknown)
240 * See Windows documentation for more details on IUnknown methods.
242 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_QueryInterface
243 (LPENUMFORMATETC iface, REFIID riid, LPVOID* ppvObj)
245 enum_fmtetc *This = impl_from_IEnumFORMATETC(iface);
247 TRACE("(%p)->(IID: %s, %p)\n", This, debugstr_guid(riid), ppvObj);
249 *ppvObj = NULL;
251 if(IsEqualIID(riid, &IID_IUnknown) ||
252 IsEqualIID(riid, &IID_IEnumFORMATETC))
254 *ppvObj = iface;
257 if(*ppvObj)
259 IEnumFORMATETC_AddRef((IEnumFORMATETC*)*ppvObj);
260 TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
261 return S_OK;
264 TRACE("-- Interface: E_NOINTERFACE\n");
265 return E_NOINTERFACE;
268 /************************************************************************
269 * OLEClipbrd_IEnumFORMATETC_AddRef (IUnknown)
272 static ULONG WINAPI OLEClipbrd_IEnumFORMATETC_AddRef(LPENUMFORMATETC iface)
274 enum_fmtetc *This = impl_from_IEnumFORMATETC(iface);
275 TRACE("(%p)->(count=%u)\n",This, This->ref);
277 return InterlockedIncrement(&This->ref);
280 /************************************************************************
281 * OLEClipbrd_IEnumFORMATETC_Release (IUnknown)
283 * See Windows documentation for more details on IUnknown methods.
285 static ULONG WINAPI OLEClipbrd_IEnumFORMATETC_Release(LPENUMFORMATETC iface)
287 enum_fmtetc *This = impl_from_IEnumFORMATETC(iface);
288 ULONG ref;
290 TRACE("(%p)->(count=%u)\n",This, This->ref);
292 ref = InterlockedDecrement(&This->ref);
293 if (!ref)
295 TRACE("() - destroying IEnumFORMATETC(%p)\n",This);
296 HeapFree(GetProcessHeap(), 0, This->data);
297 HeapFree(GetProcessHeap(), 0, This);
299 return ref;
302 /************************************************************************
303 * OLEClipbrd_IEnumFORMATETC_Next (IEnumFORMATETC)
305 * Standard enumerator members for IEnumFORMATETC
307 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Next
308 (LPENUMFORMATETC iface, ULONG celt, FORMATETC *rgelt, ULONG *pceltFethed)
310 enum_fmtetc *This = impl_from_IEnumFORMATETC(iface);
311 UINT cfetch, i;
312 HRESULT hres = S_FALSE;
314 TRACE("(%p)->(pos=%u)\n", This, This->pos);
316 if (This->pos < This->data->count)
318 cfetch = This->data->count - This->pos;
319 if (cfetch >= celt)
321 cfetch = celt;
322 hres = S_OK;
325 for(i = 0; i < cfetch; i++)
327 rgelt[i] = This->data->entries[This->pos++].fmtetc;
328 if(rgelt[i].ptd)
330 DVTARGETDEVICE *target = rgelt[i].ptd;
331 rgelt[i].ptd = CoTaskMemAlloc(target->tdSize);
332 if(!rgelt[i].ptd) return E_OUTOFMEMORY;
333 memcpy(rgelt[i].ptd, target, target->tdSize);
337 else
339 cfetch = 0;
342 if (pceltFethed)
344 *pceltFethed = cfetch;
347 return hres;
350 /************************************************************************
351 * OLEClipbrd_IEnumFORMATETC_Skip (IEnumFORMATETC)
353 * Standard enumerator members for IEnumFORMATETC
355 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Skip(LPENUMFORMATETC iface, ULONG celt)
357 enum_fmtetc *This = impl_from_IEnumFORMATETC(iface);
358 TRACE("(%p)->(num=%u)\n", This, celt);
360 This->pos += celt;
361 if (This->pos > This->data->count)
363 This->pos = This->data->count;
364 return S_FALSE;
366 return S_OK;
369 /************************************************************************
370 * OLEClipbrd_IEnumFORMATETC_Reset (IEnumFORMATETC)
372 * Standard enumerator members for IEnumFORMATETC
374 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Reset(LPENUMFORMATETC iface)
376 enum_fmtetc *This = impl_from_IEnumFORMATETC(iface);
377 TRACE("(%p)->()\n", This);
379 This->pos = 0;
380 return S_OK;
383 static HRESULT enum_fmtetc_construct(ole_priv_data *data, UINT pos, IEnumFORMATETC **obj);
385 /************************************************************************
386 * OLEClipbrd_IEnumFORMATETC_Clone (IEnumFORMATETC)
388 * Standard enumerator members for IEnumFORMATETC
390 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Clone
391 (LPENUMFORMATETC iface, LPENUMFORMATETC* obj)
393 enum_fmtetc *This = impl_from_IEnumFORMATETC(iface);
394 ole_priv_data *new_data;
395 DWORD i;
397 TRACE("(%p)->(%p)\n", This, obj);
399 if ( !obj ) return E_INVALIDARG;
400 *obj = NULL;
402 new_data = HeapAlloc(GetProcessHeap(), 0, This->data->size);
403 if(!new_data) return E_OUTOFMEMORY;
404 memcpy(new_data, This->data, This->data->size);
406 /* Fixup any target device ptrs */
407 for(i = 0; i < This->data->count; i++)
408 new_data->entries[i].fmtetc.ptd =
409 td_offs_to_ptr(new_data, td_get_offs(This->data, i));
411 return enum_fmtetc_construct(new_data, This->pos, obj);
414 static const IEnumFORMATETCVtbl efvt =
416 OLEClipbrd_IEnumFORMATETC_QueryInterface,
417 OLEClipbrd_IEnumFORMATETC_AddRef,
418 OLEClipbrd_IEnumFORMATETC_Release,
419 OLEClipbrd_IEnumFORMATETC_Next,
420 OLEClipbrd_IEnumFORMATETC_Skip,
421 OLEClipbrd_IEnumFORMATETC_Reset,
422 OLEClipbrd_IEnumFORMATETC_Clone
425 /************************************************************************
426 * enum_fmtetc_construct
428 * Creates an IEnumFORMATETC enumerator from ole_priv_data which it then owns.
430 static HRESULT enum_fmtetc_construct(ole_priv_data *data, UINT pos, IEnumFORMATETC **obj)
432 enum_fmtetc* ef;
434 *obj = NULL;
435 ef = HeapAlloc(GetProcessHeap(), 0, sizeof(*ef));
436 if (!ef) return E_OUTOFMEMORY;
438 ef->ref = 1;
439 ef->IEnumFORMATETC_iface.lpVtbl = &efvt;
440 ef->data = data;
441 ef->pos = pos;
443 TRACE("(%p)->()\n", ef);
444 *obj = &ef->IEnumFORMATETC_iface;
445 return S_OK;
448 /***********************************************************************
449 * dup_global_mem
451 * Helper method to duplicate an HGLOBAL chunk of memory
453 static HRESULT dup_global_mem( HGLOBAL src, DWORD flags, HGLOBAL *dst )
455 void *src_ptr, *dst_ptr;
456 DWORD size;
458 *dst = NULL;
459 if ( !src ) return S_FALSE;
461 size = GlobalSize(src);
463 *dst = GlobalAlloc( flags, size );
464 if ( !*dst ) return E_OUTOFMEMORY;
466 src_ptr = GlobalLock(src);
467 dst_ptr = GlobalLock(*dst);
469 memcpy(dst_ptr, src_ptr, size);
471 GlobalUnlock(*dst);
472 GlobalUnlock(src);
474 return S_OK;
477 /***********************************************************************
478 * dup_metafilepict
480 * Helper function to duplicate a handle to a METAFILEPICT, and the
481 * contained HMETAFILE.
483 static HRESULT dup_metafilepict(HGLOBAL src, HGLOBAL *pdest)
485 HRESULT hr;
486 HGLOBAL dest;
487 METAFILEPICT *dest_ptr;
489 *pdest = NULL;
491 /* Copy the METAFILEPICT structure. */
492 hr = dup_global_mem(src, GMEM_DDESHARE|GMEM_MOVEABLE, &dest);
493 if (FAILED(hr)) return hr;
495 dest_ptr = GlobalLock(dest);
496 if (!dest_ptr) return E_FAIL;
498 /* Give the new METAFILEPICT a separate HMETAFILE. */
499 dest_ptr->hMF = CopyMetaFileW(dest_ptr->hMF, NULL);
500 if (dest_ptr->hMF)
502 GlobalUnlock(dest);
503 *pdest = dest;
504 return S_OK;
506 else
508 GlobalUnlock(dest);
509 GlobalFree(dest);
510 return E_FAIL;
514 /***********************************************************************
515 * free_metafilepict
517 * Helper function to GlobalFree a handle to a METAFILEPICT, and also
518 * free the contained HMETAFILE.
520 static void free_metafilepict(HGLOBAL src)
522 METAFILEPICT *src_ptr;
524 src_ptr = GlobalLock(src);
525 if (src_ptr)
527 DeleteMetaFile(src_ptr->hMF);
528 GlobalUnlock(src);
530 GlobalFree(src);
533 /***********************************************************************
534 * dup_bitmap
536 * Helper function to duplicate an HBITMAP.
538 static HRESULT dup_bitmap(HBITMAP src, HBITMAP *pdest)
540 HDC src_dc;
541 HGDIOBJ orig_src_bitmap;
542 BITMAP bm;
543 HBITMAP dest;
545 src_dc = CreateCompatibleDC(NULL);
546 orig_src_bitmap = SelectObject(src_dc, src);
547 GetObjectW(src, sizeof bm, &bm);
548 dest = CreateCompatibleBitmap(src_dc, bm.bmWidth, bm.bmHeight);
549 if (dest)
551 HDC dest_dc = CreateCompatibleDC(NULL);
552 HGDIOBJ orig_dest_bitmap = SelectObject(dest_dc, dest);
553 BitBlt(dest_dc, 0, 0, bm.bmWidth, bm.bmHeight, src_dc, 0, 0, SRCCOPY);
554 SelectObject(dest_dc, orig_dest_bitmap);
555 DeleteDC(dest_dc);
557 SelectObject(src_dc, orig_src_bitmap);
558 DeleteDC(src_dc);
559 *pdest = dest;
560 return dest ? S_OK : E_FAIL;
563 /************************************************************
564 * render_embed_source_hack
566 * This is clearly a hack and has no place in the clipboard code.
569 static HRESULT render_embed_source_hack(IDataObject *data, LPFORMATETC fmt)
571 STGMEDIUM std;
572 HGLOBAL hStorage = 0;
573 HRESULT hr = S_OK;
574 ILockBytes *ptrILockBytes;
576 memset(&std, 0, sizeof(STGMEDIUM));
577 std.tymed = fmt->tymed = TYMED_ISTORAGE;
579 hStorage = GlobalAlloc(GMEM_SHARE|GMEM_MOVEABLE, 0);
580 if (hStorage == NULL) return E_OUTOFMEMORY;
581 hr = CreateILockBytesOnHGlobal(hStorage, FALSE, &ptrILockBytes);
582 hr = StgCreateDocfileOnILockBytes(ptrILockBytes, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &std.u.pstg);
583 ILockBytes_Release(ptrILockBytes);
585 if (FAILED(hr = IDataObject_GetDataHere(theOleClipboard->src_data, fmt, &std)))
587 WARN("() : IDataObject_GetDataHere failed to render clipboard data! (%x)\n", hr);
588 GlobalFree(hStorage);
589 return hr;
592 if (1) /* check whether the presentation data is already -not- present */
594 FORMATETC fmt2;
595 STGMEDIUM std2;
596 METAFILEPICT *mfp = 0;
598 fmt2.cfFormat = CF_METAFILEPICT;
599 fmt2.ptd = 0;
600 fmt2.dwAspect = DVASPECT_CONTENT;
601 fmt2.lindex = -1;
602 fmt2.tymed = TYMED_MFPICT;
604 memset(&std2, 0, sizeof(STGMEDIUM));
605 std2.tymed = TYMED_MFPICT;
607 /* Get the metafile picture out of it */
609 if (SUCCEEDED(hr = IDataObject_GetData(theOleClipboard->src_data, &fmt2, &std2)))
611 mfp = GlobalLock(std2.u.hGlobal);
614 if (mfp)
616 OLECHAR name[]={ 2, 'O', 'l', 'e', 'P', 'r', 'e', 's', '0', '0', '0', 0};
617 IStream *pStream = 0;
618 void *mfBits;
619 PresentationDataHeader pdh;
620 INT nSize;
621 CLSID clsID;
622 LPOLESTR strProgID;
623 CHAR strOleTypeName[51];
624 BYTE OlePresStreamHeader [] =
626 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00,
627 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
628 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
629 0x00, 0x00, 0x00, 0x00
632 nSize = GetMetaFileBitsEx(mfp->hMF, 0, NULL);
634 memset(&pdh, 0, sizeof(PresentationDataHeader));
635 memcpy(&pdh, OlePresStreamHeader, sizeof(OlePresStreamHeader));
637 pdh.dwObjectExtentX = mfp->xExt;
638 pdh.dwObjectExtentY = mfp->yExt;
639 pdh.dwSize = nSize;
641 hr = IStorage_CreateStream(std.u.pstg, name, STGM_CREATE|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, 0, &pStream);
643 hr = IStream_Write(pStream, &pdh, sizeof(PresentationDataHeader), NULL);
645 mfBits = HeapAlloc(GetProcessHeap(), 0, nSize);
646 nSize = GetMetaFileBitsEx(mfp->hMF, nSize, mfBits);
648 hr = IStream_Write(pStream, mfBits, nSize, NULL);
650 IStream_Release(pStream);
652 HeapFree(GetProcessHeap(), 0, mfBits);
654 GlobalUnlock(std2.u.hGlobal);
655 ReleaseStgMedium(&std2);
657 ReadClassStg(std.u.pstg, &clsID);
658 ProgIDFromCLSID(&clsID, &strProgID);
660 WideCharToMultiByte( CP_ACP, 0, strProgID, -1, strOleTypeName, sizeof(strOleTypeName), NULL, NULL );
661 STORAGE_CreateOleStream(std.u.pstg, 0);
662 OLECONVERT_CreateCompObjStream(std.u.pstg, strOleTypeName);
663 CoTaskMemFree(strProgID);
667 if ( !SetClipboardData( fmt->cfFormat, hStorage ) )
669 WARN("() : Failed to set rendered clipboard data into clipboard!\n");
670 GlobalFree(hStorage);
671 hr = CLIPBRD_E_CANT_SET;
674 ReleaseStgMedium(&std);
675 return hr;
678 /************************************************************************
679 * find_format_in_list
681 * Returns the first entry that matches the provided clipboard format.
683 static inline ole_priv_data_entry *find_format_in_list(ole_priv_data_entry *entries, DWORD num, UINT cf)
685 DWORD i;
686 for(i = 0; i < num; i++)
687 if(entries[i].fmtetc.cfFormat == cf)
688 return &entries[i];
690 return NULL;
693 /***************************************************************************
694 * get_data_from_storage
696 * Returns storage data in an HGLOBAL.
698 static HRESULT get_data_from_storage(IDataObject *data, FORMATETC *fmt, HGLOBAL *mem)
700 HGLOBAL h;
701 IStorage *stg;
702 HRESULT hr;
703 FORMATETC stg_fmt;
704 STGMEDIUM med;
705 ILockBytes *lbs;
707 *mem = NULL;
709 h = GlobalAlloc( GMEM_DDESHARE|GMEM_MOVEABLE, 0 );
710 if(!h) return E_OUTOFMEMORY;
712 hr = CreateILockBytesOnHGlobal(h, FALSE, &lbs);
713 if(SUCCEEDED(hr))
715 hr = StgCreateDocfileOnILockBytes(lbs, STGM_CREATE|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &stg);
716 ILockBytes_Release(lbs);
718 if(FAILED(hr))
720 GlobalFree(h);
721 return hr;
724 stg_fmt = *fmt;
725 med.tymed = stg_fmt.tymed = TYMED_ISTORAGE;
726 med.u.pstg = stg;
727 med.pUnkForRelease = NULL;
729 hr = IDataObject_GetDataHere(data, &stg_fmt, &med);
730 if(FAILED(hr))
732 med.u.pstg = NULL;
733 hr = IDataObject_GetData(data, &stg_fmt, &med);
734 if(FAILED(hr)) goto end;
736 hr = IStorage_CopyTo(med.u.pstg, 0, NULL, NULL, stg);
737 ReleaseStgMedium(&med);
738 if(FAILED(hr)) goto end;
740 *mem = h;
742 end:
743 IStorage_Release(stg);
744 if(FAILED(hr)) GlobalFree(h);
745 return hr;
748 /***************************************************************************
749 * get_data_from_stream
751 * Returns stream data in an HGLOBAL.
753 static HRESULT get_data_from_stream(IDataObject *data, FORMATETC *fmt, HGLOBAL *mem)
755 HGLOBAL h;
756 IStream *stm = NULL;
757 HRESULT hr;
758 FORMATETC stm_fmt;
759 STGMEDIUM med;
761 *mem = NULL;
763 h = GlobalAlloc( GMEM_DDESHARE|GMEM_MOVEABLE, 0 );
764 if(!h) return E_OUTOFMEMORY;
766 hr = CreateStreamOnHGlobal(h, FALSE, &stm);
767 if(FAILED(hr)) goto error;
769 stm_fmt = *fmt;
770 med.tymed = stm_fmt.tymed = TYMED_ISTREAM;
771 med.u.pstm = stm;
772 med.pUnkForRelease = NULL;
774 hr = IDataObject_GetDataHere(data, &stm_fmt, &med);
775 if(FAILED(hr))
777 LARGE_INTEGER offs;
778 ULARGE_INTEGER pos;
780 med.u.pstm = NULL;
781 hr = IDataObject_GetData(data, &stm_fmt, &med);
782 if(FAILED(hr)) goto error;
784 offs.QuadPart = 0;
785 IStream_Seek(med.u.pstm, offs, STREAM_SEEK_CUR, &pos);
786 IStream_Seek(med.u.pstm, offs, STREAM_SEEK_SET, NULL);
787 hr = IStream_CopyTo(med.u.pstm, stm, pos, NULL, NULL);
788 ReleaseStgMedium(&med);
789 if(FAILED(hr)) goto error;
791 *mem = h;
792 IStream_Release(stm);
793 return S_OK;
795 error:
796 if(stm) IStream_Release(stm);
797 GlobalFree(h);
798 return hr;
801 /***************************************************************************
802 * get_data_from_global
804 * Returns global data in an HGLOBAL.
806 static HRESULT get_data_from_global(IDataObject *data, FORMATETC *fmt, HGLOBAL *mem)
808 HGLOBAL h;
809 HRESULT hr;
810 FORMATETC mem_fmt;
811 STGMEDIUM med;
813 *mem = NULL;
815 mem_fmt = *fmt;
816 mem_fmt.tymed = TYMED_HGLOBAL;
818 hr = IDataObject_GetData(data, &mem_fmt, &med);
819 if(FAILED(hr)) return hr;
821 hr = dup_global_mem(med.u.hGlobal, GMEM_DDESHARE|GMEM_MOVEABLE, &h);
823 if(SUCCEEDED(hr)) *mem = h;
825 ReleaseStgMedium(&med);
827 return hr;
830 /***************************************************************************
831 * get_data_from_enhmetafile
833 static HRESULT get_data_from_enhmetafile(IDataObject *data, FORMATETC *fmt, HGLOBAL *mem)
835 HENHMETAFILE copy;
836 HRESULT hr;
837 FORMATETC mem_fmt;
838 STGMEDIUM med;
840 *mem = NULL;
842 mem_fmt = *fmt;
843 mem_fmt.tymed = TYMED_ENHMF;
845 hr = IDataObject_GetData(data, &mem_fmt, &med);
846 if(FAILED(hr)) return hr;
848 copy = CopyEnhMetaFileW(med.u.hEnhMetaFile, NULL);
849 if(copy) *mem = (HGLOBAL)copy;
850 else hr = E_FAIL;
852 ReleaseStgMedium(&med);
854 return hr;
857 /***************************************************************************
858 * get_data_from_metafilepict
860 static HRESULT get_data_from_metafilepict(IDataObject *data, FORMATETC *fmt, HGLOBAL *mem)
862 HGLOBAL copy;
863 HRESULT hr;
864 FORMATETC mem_fmt;
865 STGMEDIUM med;
867 *mem = NULL;
869 mem_fmt = *fmt;
870 mem_fmt.tymed = TYMED_MFPICT;
872 hr = IDataObject_GetData(data, &mem_fmt, &med);
873 if(FAILED(hr)) return hr;
875 hr = dup_metafilepict(med.u.hMetaFilePict, &copy);
877 if(SUCCEEDED(hr)) *mem = copy;
879 ReleaseStgMedium(&med);
881 return hr;
884 /***************************************************************************
885 * get_data_from_bitmap
887 * Returns bitmap in an HBITMAP.
889 static HRESULT get_data_from_bitmap(IDataObject *data, FORMATETC *fmt, HBITMAP *hbm)
891 HBITMAP copy;
892 HRESULT hr;
893 FORMATETC mem_fmt;
894 STGMEDIUM med;
896 *hbm = NULL;
898 mem_fmt = *fmt;
899 mem_fmt.tymed = TYMED_GDI;
901 hr = IDataObject_GetData(data, &mem_fmt, &med);
902 if(FAILED(hr)) return hr;
904 hr = dup_bitmap(med.u.hBitmap, &copy);
906 if(SUCCEEDED(hr)) *hbm = copy;
908 ReleaseStgMedium(&med);
910 return hr;
913 /***********************************************************************
914 * render_format
916 * Render the clipboard data. Note that this call will delegate to the
917 * source data object.
919 static HRESULT render_format(IDataObject *data, LPFORMATETC fmt)
921 HANDLE clip_data = NULL; /* HGLOBAL unless otherwise specified */
922 HRESULT hr;
924 /* Embed source hack */
925 if(fmt->cfFormat == embed_source_clipboard_format)
927 return render_embed_source_hack(data, fmt);
930 if(fmt->tymed & TYMED_ISTORAGE)
932 hr = get_data_from_storage(data, fmt, &clip_data);
934 else if(fmt->tymed & TYMED_ISTREAM)
936 hr = get_data_from_stream(data, fmt, &clip_data);
938 else if(fmt->tymed & TYMED_HGLOBAL)
940 hr = get_data_from_global(data, fmt, &clip_data);
942 else if(fmt->tymed & TYMED_ENHMF)
944 hr = get_data_from_enhmetafile(data, fmt, &clip_data);
946 else if(fmt->tymed & TYMED_MFPICT)
948 /* Returns global handle to METAFILEPICT, containing a copied HMETAFILE */
949 hr = get_data_from_metafilepict(data, fmt, &clip_data);
951 else if(fmt->tymed & TYMED_GDI)
953 /* Returns HBITMAP not HGLOBAL */
954 hr = get_data_from_bitmap(data, fmt, (HBITMAP *)&clip_data);
956 else
958 FIXME("Unhandled tymed %x\n", fmt->tymed);
959 hr = DV_E_FORMATETC;
962 if(SUCCEEDED(hr))
964 if ( !SetClipboardData(fmt->cfFormat, clip_data) )
966 WARN("() : Failed to set rendered clipboard data into clipboard!\n");
967 if(fmt->tymed & TYMED_MFPICT)
968 free_metafilepict(clip_data);
969 else if(fmt->tymed & TYMED_GDI)
970 DeleteObject(clip_data);
971 else
972 GlobalFree(clip_data);
973 hr = CLIPBRD_E_CANT_SET;
977 return hr;
980 /*---------------------------------------------------------------------*
981 * Implementation of the internal IDataObject interface exposed by
982 * the OLE clipboard.
983 *---------------------------------------------------------------------*/
986 /************************************************************************
987 * snapshot_QueryInterface
989 static HRESULT WINAPI snapshot_QueryInterface(IDataObject *iface,
990 REFIID riid, void **ppvObject)
992 snapshot *This = impl_from_IDataObject(iface);
993 TRACE("(%p)->(IID:%s, %p)\n", This, debugstr_guid(riid), ppvObject);
995 if ( (This==0) || (ppvObject==0) )
996 return E_INVALIDARG;
998 *ppvObject = 0;
1000 if (IsEqualIID(&IID_IUnknown, riid) ||
1001 IsEqualIID(&IID_IDataObject, riid))
1003 *ppvObject = iface;
1005 else
1007 WARN( "() : asking for unsupported interface %s\n", debugstr_guid(riid));
1008 return E_NOINTERFACE;
1011 IUnknown_AddRef((IUnknown*)*ppvObject);
1013 return S_OK;
1016 /************************************************************************
1017 * snapshot_AddRef
1019 static ULONG WINAPI snapshot_AddRef(IDataObject *iface)
1021 snapshot *This = impl_from_IDataObject(iface);
1023 TRACE("(%p)->(count=%u)\n", This, This->ref);
1025 return InterlockedIncrement(&This->ref);
1028 /************************************************************************
1029 * snapshot_Release
1031 static ULONG WINAPI snapshot_Release(IDataObject *iface)
1033 snapshot *This = impl_from_IDataObject(iface);
1034 ULONG ref;
1036 TRACE("(%p)->(count=%u)\n", This, This->ref);
1038 ref = InterlockedDecrement(&This->ref);
1040 if (ref == 0)
1042 ole_clipbrd *clipbrd;
1043 HRESULT hr = get_ole_clipbrd(&clipbrd);
1045 if(This->data) IDataObject_Release(This->data);
1047 if(SUCCEEDED(hr) && clipbrd->latest_snapshot == This)
1048 clipbrd->latest_snapshot = NULL;
1049 HeapFree(GetProcessHeap(), 0, This);
1052 return ref;
1055 /************************************************************
1056 * get_current_ole_clip_window
1058 * Return the window that owns the ole clipboard.
1060 * If the clipboard is flushed or not owned by ole this will
1061 * return NULL.
1063 static HWND get_current_ole_clip_window(void)
1065 HGLOBAL h;
1066 HWND *ptr, wnd;
1068 h = GetClipboardData(dataobject_clipboard_format);
1069 if(!h) return NULL;
1070 ptr = GlobalLock(h);
1071 if(!ptr) return NULL;
1072 wnd = *ptr;
1073 GlobalUnlock(h);
1074 return wnd;
1077 /************************************************************
1078 * get_current_dataobject
1080 * Return an unmarshalled IDataObject if there is a current
1081 * (ie non-flushed) object on the ole clipboard.
1083 static HRESULT get_current_dataobject(IDataObject **data)
1085 HRESULT hr = S_FALSE;
1086 HWND wnd = get_current_ole_clip_window();
1087 HGLOBAL h;
1088 void *ptr;
1089 IStream *stm;
1090 LARGE_INTEGER pos;
1092 *data = NULL;
1093 if(!wnd) return S_FALSE;
1095 h = GetClipboardData(wine_marshal_clipboard_format);
1096 if(!h) return S_FALSE;
1097 if(GlobalSize(h) == 0) return S_FALSE;
1098 ptr = GlobalLock(h);
1099 if(!ptr) return S_FALSE;
1101 hr = CreateStreamOnHGlobal(NULL, TRUE, &stm);
1102 if(FAILED(hr)) goto end;
1104 hr = IStream_Write(stm, ptr, GlobalSize(h), NULL);
1105 if(SUCCEEDED(hr))
1107 pos.QuadPart = 0;
1108 IStream_Seek(stm, pos, STREAM_SEEK_SET, NULL);
1109 hr = CoUnmarshalInterface(stm, &IID_IDataObject, (void**)data);
1111 IStream_Release(stm);
1113 end:
1114 GlobalUnlock(h);
1115 return hr;
1118 static DWORD get_tymed_from_nonole_cf(UINT cf)
1120 if(cf >= 0xc000) return TYMED_ISTREAM | TYMED_HGLOBAL;
1122 switch(cf)
1124 case CF_TEXT:
1125 case CF_OEMTEXT:
1126 case CF_UNICODETEXT:
1127 return TYMED_ISTREAM | TYMED_HGLOBAL;
1128 case CF_ENHMETAFILE:
1129 return TYMED_ENHMF;
1130 case CF_METAFILEPICT:
1131 return TYMED_MFPICT;
1132 case CF_BITMAP:
1133 return TYMED_GDI;
1134 default:
1135 FIXME("returning TYMED_NULL for cf %04x\n", cf);
1136 return TYMED_NULL;
1140 /***********************************************************
1141 * get_priv_data
1143 * Returns a copy of the Ole Private Data
1145 static HRESULT get_priv_data(ole_priv_data **data)
1147 HGLOBAL handle;
1148 HRESULT hr = S_OK;
1149 ole_priv_data *ret = NULL;
1151 *data = NULL;
1153 handle = GetClipboardData( ole_private_data_clipboard_format );
1154 if(handle)
1156 ole_priv_data *src = GlobalLock(handle);
1157 if(src)
1159 DWORD i;
1161 /* FIXME: sanity check on size */
1162 ret = HeapAlloc(GetProcessHeap(), 0, src->size);
1163 if(!ret)
1165 GlobalUnlock(handle);
1166 return E_OUTOFMEMORY;
1168 memcpy(ret, src, src->size);
1169 GlobalUnlock(handle);
1171 /* Fixup any target device offsets to ptrs */
1172 for(i = 0; i < ret->count; i++)
1173 ret->entries[i].fmtetc.ptd =
1174 td_offs_to_ptr(ret, (DWORD_PTR) ret->entries[i].fmtetc.ptd);
1178 if(!ret) /* Non-ole data */
1180 UINT cf;
1181 DWORD count = 0, idx, size = FIELD_OFFSET(ole_priv_data, entries);
1183 for(cf = 0; (cf = EnumClipboardFormats(cf)) != 0; count++)
1185 char buf[100];
1186 GetClipboardFormatNameA(cf, buf, sizeof(buf));
1187 TRACE("cf %04x %s\n", cf, buf);
1189 TRACE("count %d\n", count);
1190 size += count * sizeof(ret->entries[0]);
1192 /* There are holes in fmtetc so zero init */
1193 ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
1194 if(!ret) return E_OUTOFMEMORY;
1195 ret->size = size;
1196 ret->count = count;
1198 for(cf = 0, idx = 0; (cf = EnumClipboardFormats(cf)) != 0; idx++)
1200 ret->entries[idx].fmtetc.cfFormat = cf;
1201 ret->entries[idx].fmtetc.ptd = NULL;
1202 ret->entries[idx].fmtetc.dwAspect = DVASPECT_CONTENT;
1203 ret->entries[idx].fmtetc.lindex = -1;
1204 ret->entries[idx].fmtetc.tymed = get_tymed_from_nonole_cf(cf);
1205 ret->entries[idx].first_use = 1;
1209 *data = ret;
1210 return hr;
1213 /************************************************************************
1214 * get_stgmed_for_global
1216 * Returns a stg medium with a copy of the global handle
1218 static HRESULT get_stgmed_for_global(HGLOBAL h, STGMEDIUM *med)
1220 HRESULT hr;
1222 med->pUnkForRelease = NULL;
1223 med->tymed = TYMED_NULL;
1225 hr = dup_global_mem(h, GMEM_MOVEABLE, &med->u.hGlobal);
1227 if(SUCCEEDED(hr)) med->tymed = TYMED_HGLOBAL;
1229 return hr;
1232 /************************************************************************
1233 * get_stgmed_for_stream
1235 * Returns a stg medium with a stream based on the handle
1237 static HRESULT get_stgmed_for_stream(HGLOBAL h, STGMEDIUM *med)
1239 HRESULT hr;
1240 HGLOBAL dst;
1242 med->pUnkForRelease = NULL;
1243 med->tymed = TYMED_NULL;
1245 hr = dup_global_mem(h, GMEM_MOVEABLE, &dst);
1246 if(FAILED(hr)) return hr;
1248 hr = CreateStreamOnHGlobal(dst, TRUE, &med->u.pstm);
1249 if(FAILED(hr))
1251 GlobalFree(dst);
1252 return hr;
1255 med->tymed = TYMED_ISTREAM;
1256 return hr;
1259 /************************************************************************
1260 * get_stgmed_for_storage
1262 * Returns a stg medium with a storage based on the handle
1264 static HRESULT get_stgmed_for_storage(HGLOBAL h, STGMEDIUM *med)
1266 HRESULT hr;
1267 HGLOBAL dst;
1268 ILockBytes *lbs;
1270 med->pUnkForRelease = NULL;
1271 med->tymed = TYMED_NULL;
1273 hr = dup_global_mem(h, GMEM_MOVEABLE, &dst);
1274 if(FAILED(hr)) return hr;
1276 hr = CreateILockBytesOnHGlobal(dst, TRUE, &lbs);
1277 if(FAILED(hr))
1279 GlobalFree(dst);
1280 return hr;
1283 hr = StgOpenStorageOnILockBytes(lbs, NULL, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, NULL, 0, &med->u.pstg);
1284 ILockBytes_Release(lbs);
1285 if(FAILED(hr))
1287 GlobalFree(dst);
1288 return hr;
1291 med->tymed = TYMED_ISTORAGE;
1292 return hr;
1295 /************************************************************************
1296 * get_stgmed_for_emf
1298 * Returns a stg medium with an enhanced metafile based on the handle
1300 static HRESULT get_stgmed_for_emf(HENHMETAFILE hemf, STGMEDIUM *med)
1302 med->pUnkForRelease = NULL;
1303 med->tymed = TYMED_NULL;
1305 med->u.hEnhMetaFile = CopyEnhMetaFileW(hemf, NULL);
1306 if(!med->u.hEnhMetaFile) return E_OUTOFMEMORY;
1307 med->tymed = TYMED_ENHMF;
1308 return S_OK;
1311 /************************************************************************
1312 * get_stgmed_for_bitmap
1314 * Returns a stg medium with a bitmap based on the handle
1316 static HRESULT get_stgmed_for_bitmap(HBITMAP hbmp, STGMEDIUM *med)
1318 HRESULT hr;
1320 med->pUnkForRelease = NULL;
1321 med->tymed = TYMED_NULL;
1323 hr = dup_bitmap(hbmp, &med->u.hBitmap);
1325 if (FAILED(hr))
1326 return hr;
1328 med->tymed = TYMED_GDI;
1329 return S_OK;
1332 static inline BOOL string_off_equal(const DVTARGETDEVICE *t1, WORD off1, const DVTARGETDEVICE *t2, WORD off2)
1334 const WCHAR *str1, *str2;
1336 if(off1 == 0 && off2 == 0) return TRUE;
1337 if(off1 == 0 || off2 == 0) return FALSE;
1339 str1 = (const WCHAR*)((const char*)t1 + off1);
1340 str2 = (const WCHAR*)((const char*)t2 + off2);
1342 return !lstrcmpW(str1, str2);
1345 static inline BOOL td_equal(const DVTARGETDEVICE *t1, const DVTARGETDEVICE *t2)
1347 if(t1 == NULL && t2 == NULL) return TRUE;
1348 if(t1 == NULL || t2 == NULL) return FALSE;
1350 if(!string_off_equal(t1, t1->tdDriverNameOffset, t2, t2->tdDriverNameOffset))
1351 return FALSE;
1352 if(!string_off_equal(t1, t1->tdDeviceNameOffset, t2, t2->tdDeviceNameOffset))
1353 return FALSE;
1354 if(!string_off_equal(t1, t1->tdPortNameOffset, t2, t2->tdPortNameOffset))
1355 return FALSE;
1357 /* FIXME check devmode? */
1359 return TRUE;
1362 /************************************************************************
1363 * snapshot_GetData
1365 static HRESULT WINAPI snapshot_GetData(IDataObject *iface, FORMATETC *fmt,
1366 STGMEDIUM *med)
1368 snapshot *This = impl_from_IDataObject(iface);
1369 HANDLE h;
1370 HRESULT hr;
1371 ole_priv_data *enum_data = NULL;
1372 ole_priv_data_entry *entry;
1373 DWORD mask;
1375 TRACE("(%p, %p {%s}, %p)\n", iface, fmt, dump_fmtetc(fmt), med);
1377 if ( !fmt || !med ) return E_INVALIDARG;
1379 if ( !OpenClipboard(NULL)) return CLIPBRD_E_CANT_OPEN;
1381 if(!This->data)
1382 hr = get_current_dataobject(&This->data);
1384 if(This->data)
1386 hr = IDataObject_GetData(This->data, fmt, med);
1387 CloseClipboard();
1388 return hr;
1391 h = GetClipboardData(fmt->cfFormat);
1392 if(!h)
1394 hr = DV_E_FORMATETC;
1395 goto end;
1398 hr = get_priv_data(&enum_data);
1399 if(FAILED(hr)) goto end;
1401 entry = find_format_in_list(enum_data->entries, enum_data->count, fmt->cfFormat);
1402 if(entry)
1404 if(!td_equal(fmt->ptd, entry->fmtetc.ptd))
1406 hr = DV_E_FORMATETC;
1407 goto end;
1409 mask = fmt->tymed & entry->fmtetc.tymed;
1410 if(!mask) mask = fmt->tymed & (TYMED_ISTREAM | TYMED_HGLOBAL);
1412 else /* non-Ole format */
1413 mask = fmt->tymed & TYMED_HGLOBAL;
1415 if(mask & TYMED_ISTORAGE)
1416 hr = get_stgmed_for_storage(h, med);
1417 else if(mask & TYMED_HGLOBAL)
1418 hr = get_stgmed_for_global(h, med);
1419 else if(mask & TYMED_ISTREAM)
1420 hr = get_stgmed_for_stream(h, med);
1421 else if(mask & TYMED_ENHMF)
1422 hr = get_stgmed_for_emf((HENHMETAFILE)h, med);
1423 else if(mask & TYMED_GDI)
1424 hr = get_stgmed_for_bitmap((HBITMAP)h, med);
1425 else
1427 FIXME("Unhandled tymed - mask %x req tymed %x\n", mask, fmt->tymed);
1428 hr = E_FAIL;
1429 goto end;
1432 end:
1433 HeapFree(GetProcessHeap(), 0, enum_data);
1434 if ( !CloseClipboard() ) hr = CLIPBRD_E_CANT_CLOSE;
1435 return hr;
1438 /************************************************************************
1439 * snapshot_GetDataHere
1441 static HRESULT WINAPI snapshot_GetDataHere(IDataObject *iface, FORMATETC *fmt,
1442 STGMEDIUM *med)
1444 snapshot *This = impl_from_IDataObject(iface);
1445 HANDLE h;
1446 HRESULT hr;
1447 ole_priv_data *enum_data = NULL;
1448 ole_priv_data_entry *entry;
1449 TYMED supported;
1451 if ( !fmt || !med ) return E_INVALIDARG;
1453 TRACE("(%p, %p {%s}, %p (tymed %x)\n", iface, fmt, dump_fmtetc(fmt), med, med->tymed);
1455 if ( !OpenClipboard(NULL)) return CLIPBRD_E_CANT_OPEN;
1457 if(!This->data)
1458 hr = get_current_dataobject(&This->data);
1460 if(This->data)
1462 hr = IDataObject_GetDataHere(This->data, fmt, med);
1463 if(SUCCEEDED(hr))
1465 CloseClipboard();
1466 return hr;
1470 h = GetClipboardData(fmt->cfFormat);
1471 if(!h)
1473 hr = DV_E_FORMATETC;
1474 goto end;
1477 hr = get_priv_data(&enum_data);
1478 if(FAILED(hr)) goto end;
1480 entry = find_format_in_list(enum_data->entries, enum_data->count, fmt->cfFormat);
1481 if(entry)
1483 if(!td_equal(fmt->ptd, entry->fmtetc.ptd))
1485 hr = DV_E_FORMATETC;
1486 goto end;
1488 supported = entry->fmtetc.tymed;
1490 else /* non-Ole format */
1491 supported = TYMED_HGLOBAL;
1493 switch(med->tymed)
1495 case TYMED_HGLOBAL:
1497 DWORD src_size = GlobalSize(h);
1498 DWORD dst_size = GlobalSize(med->u.hGlobal);
1499 hr = E_FAIL;
1500 if(dst_size >= src_size)
1502 void *src = GlobalLock(h);
1503 void *dst = GlobalLock(med->u.hGlobal);
1505 memcpy(dst, src, src_size);
1506 GlobalUnlock(med->u.hGlobal);
1507 GlobalUnlock(h);
1508 hr = S_OK;
1510 break;
1512 case TYMED_ISTREAM:
1514 DWORD src_size = GlobalSize(h);
1515 void *src = GlobalLock(h);
1516 hr = IStream_Write(med->u.pstm, src, src_size, NULL);
1517 GlobalUnlock(h);
1518 break;
1520 case TYMED_ISTORAGE:
1522 STGMEDIUM copy;
1523 if(!(supported & TYMED_ISTORAGE))
1525 hr = E_FAIL;
1526 goto end;
1528 hr = get_stgmed_for_storage(h, &copy);
1529 if(SUCCEEDED(hr))
1531 hr = IStorage_CopyTo(copy.u.pstg, 0, NULL, NULL, med->u.pstg);
1532 ReleaseStgMedium(&copy);
1534 break;
1536 default:
1537 FIXME("Unhandled tymed - supported %x req tymed %x\n", supported, med->tymed);
1538 hr = E_FAIL;
1539 goto end;
1542 end:
1543 HeapFree(GetProcessHeap(), 0, enum_data);
1544 if ( !CloseClipboard() ) hr = CLIPBRD_E_CANT_CLOSE;
1545 return hr;
1548 /************************************************************************
1549 * snapshot_QueryGetData
1551 * The OLE Clipboard's implementation of this method delegates to
1552 * a data source if there is one or wraps around the windows clipboard
1553 * function IsClipboardFormatAvailable() otherwise.
1556 static HRESULT WINAPI snapshot_QueryGetData(IDataObject *iface, FORMATETC *fmt)
1558 FIXME("(%p, %p {%s})\n", iface, fmt, dump_fmtetc(fmt));
1560 if (!fmt) return E_INVALIDARG;
1562 if ( fmt->dwAspect != DVASPECT_CONTENT ) return DV_E_FORMATETC;
1564 if ( fmt->lindex != -1 ) return DV_E_FORMATETC;
1566 return (IsClipboardFormatAvailable(fmt->cfFormat)) ? S_OK : DV_E_CLIPFORMAT;
1569 /************************************************************************
1570 * snapshot_GetCanonicalFormatEtc
1572 static HRESULT WINAPI snapshot_GetCanonicalFormatEtc(IDataObject *iface, FORMATETC *fmt_in,
1573 FORMATETC *fmt_out)
1575 TRACE("(%p, %p, %p)\n", iface, fmt_in, fmt_out);
1577 if ( !fmt_in || !fmt_out ) return E_INVALIDARG;
1579 *fmt_out = *fmt_in;
1580 return DATA_S_SAMEFORMATETC;
1583 /************************************************************************
1584 * snapshot_SetData
1586 * The OLE Clipboard does not implement this method
1588 static HRESULT WINAPI snapshot_SetData(IDataObject *iface, FORMATETC *fmt,
1589 STGMEDIUM *med, BOOL release)
1591 TRACE("(%p, %p, %p, %d): not implemented\n", iface, fmt, med, release);
1592 return E_NOTIMPL;
1595 /************************************************************************
1596 * snapshot_EnumFormatEtc
1599 static HRESULT WINAPI snapshot_EnumFormatEtc(IDataObject *iface, DWORD dir,
1600 IEnumFORMATETC **enum_fmt)
1602 HRESULT hr;
1603 ole_priv_data *data = NULL;
1605 TRACE("(%p, %x, %p)\n", iface, dir, enum_fmt);
1607 *enum_fmt = NULL;
1609 if ( dir != DATADIR_GET ) return E_NOTIMPL;
1610 if ( !OpenClipboard(NULL) ) return CLIPBRD_E_CANT_OPEN;
1612 hr = get_priv_data(&data);
1614 if(FAILED(hr)) goto end;
1616 hr = enum_fmtetc_construct( data, 0, enum_fmt );
1618 end:
1619 if ( !CloseClipboard() ) hr = CLIPBRD_E_CANT_CLOSE;
1620 return hr;
1623 /************************************************************************
1624 * snapshot_DAdvise
1626 * The OLE Clipboard does not implement this method
1628 static HRESULT WINAPI snapshot_DAdvise(IDataObject *iface, FORMATETC *fmt,
1629 DWORD flags, IAdviseSink *sink,
1630 DWORD *conn)
1632 TRACE("(%p, %p, %x, %p, %p): not implemented\n", iface, fmt, flags, sink, conn);
1633 return E_NOTIMPL;
1636 /************************************************************************
1637 * snapshot_DUnadvise
1639 * The OLE Clipboard does not implement this method
1641 static HRESULT WINAPI snapshot_DUnadvise(IDataObject* iface, DWORD conn)
1643 TRACE("(%p, %d): not implemented\n", iface, conn);
1644 return E_NOTIMPL;
1647 /************************************************************************
1648 * snapshot_EnumDAdvise
1650 * The OLE Clipboard does not implement this method
1652 static HRESULT WINAPI snapshot_EnumDAdvise(IDataObject* iface,
1653 IEnumSTATDATA** enum_advise)
1655 TRACE("(%p, %p): not implemented\n", iface, enum_advise);
1656 return E_NOTIMPL;
1659 static const IDataObjectVtbl snapshot_vtable =
1661 snapshot_QueryInterface,
1662 snapshot_AddRef,
1663 snapshot_Release,
1664 snapshot_GetData,
1665 snapshot_GetDataHere,
1666 snapshot_QueryGetData,
1667 snapshot_GetCanonicalFormatEtc,
1668 snapshot_SetData,
1669 snapshot_EnumFormatEtc,
1670 snapshot_DAdvise,
1671 snapshot_DUnadvise,
1672 snapshot_EnumDAdvise
1675 /*---------------------------------------------------------------------*
1676 * Internal implementation methods for the OLE clipboard
1677 *---------------------------------------------------------------------*/
1679 static snapshot *snapshot_construct(DWORD seq_no)
1681 snapshot *This;
1683 This = HeapAlloc( GetProcessHeap(), 0, sizeof(*This) );
1684 if (!This) return NULL;
1686 This->IDataObject_iface.lpVtbl = &snapshot_vtable;
1687 This->ref = 0;
1688 This->seq_no = seq_no;
1689 This->data = NULL;
1691 return This;
1694 /*********************************************************
1695 * register_clipboard_formats
1697 static void register_clipboard_formats(void)
1699 static const WCHAR OwnerLink[] = {'O','w','n','e','r','L','i','n','k',0};
1700 static const WCHAR FileName[] = {'F','i','l','e','N','a','m','e',0};
1701 static const WCHAR FileNameW[] = {'F','i','l','e','N','a','m','e','W',0};
1702 static const WCHAR DataObject[] = {'D','a','t','a','O','b','j','e','c','t',0};
1703 static const WCHAR EmbeddedObject[] = {'E','m','b','e','d','d','e','d',' ','O','b','j','e','c','t',0};
1704 static const WCHAR EmbedSource[] = {'E','m','b','e','d',' ','S','o','u','r','c','e',0};
1705 static const WCHAR CustomLinkSource[] = {'C','u','s','t','o','m',' ','L','i','n','k',' ','S','o','u','r','c','e',0};
1706 static const WCHAR LinkSource[] = {'L','i','n','k',' ','S','o','u','r','c','e',0};
1707 static const WCHAR ObjectDescriptor[] = {'O','b','j','e','c','t',' ','D','e','s','c','r','i','p','t','o','r',0};
1708 static const WCHAR LinkSourceDescriptor[] = {'L','i','n','k',' ','S','o','u','r','c','e',' ',
1709 'D','e','s','c','r','i','p','t','o','r',0};
1710 static const WCHAR OlePrivateData[] = {'O','l','e',' ','P','r','i','v','a','t','e',' ','D','a','t','a',0};
1712 static const WCHAR WineMarshalledDataObject[] = {'W','i','n','e',' ','M','a','r','s','h','a','l','l','e','d',' ',
1713 'D','a','t','a','O','b','j','e','c','t',0};
1715 ownerlink_clipboard_format = RegisterClipboardFormatW(OwnerLink);
1716 filename_clipboard_format = RegisterClipboardFormatW(FileName);
1717 filenameW_clipboard_format = RegisterClipboardFormatW(FileNameW);
1718 dataobject_clipboard_format = RegisterClipboardFormatW(DataObject);
1719 embedded_object_clipboard_format = RegisterClipboardFormatW(EmbeddedObject);
1720 embed_source_clipboard_format = RegisterClipboardFormatW(EmbedSource);
1721 custom_link_source_clipboard_format = RegisterClipboardFormatW(CustomLinkSource);
1722 link_source_clipboard_format = RegisterClipboardFormatW(LinkSource);
1723 object_descriptor_clipboard_format = RegisterClipboardFormatW(ObjectDescriptor);
1724 link_source_descriptor_clipboard_format = RegisterClipboardFormatW(LinkSourceDescriptor);
1725 ole_private_data_clipboard_format = RegisterClipboardFormatW(OlePrivateData);
1727 wine_marshal_clipboard_format = RegisterClipboardFormatW(WineMarshalledDataObject);
1730 /***********************************************************************
1731 * OLEClipbrd_Initialize()
1732 * Initializes the OLE clipboard.
1734 void OLEClipbrd_Initialize(void)
1736 register_clipboard_formats();
1738 if ( !theOleClipboard )
1740 ole_clipbrd* clipbrd;
1741 HGLOBAL h;
1743 TRACE("()\n");
1745 clipbrd = HeapAlloc( GetProcessHeap(), 0, sizeof(*clipbrd) );
1746 if (!clipbrd) return;
1748 clipbrd->latest_snapshot = NULL;
1749 clipbrd->window = NULL;
1750 clipbrd->src_data = NULL;
1751 clipbrd->cached_enum = NULL;
1753 h = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE, 0);
1754 if(!h)
1756 HeapFree(GetProcessHeap(), 0, clipbrd);
1757 return;
1760 if(FAILED(CreateStreamOnHGlobal(h, TRUE, &clipbrd->marshal_data)))
1762 GlobalFree(h);
1763 HeapFree(GetProcessHeap(), 0, clipbrd);
1764 return;
1767 theOleClipboard = clipbrd;
1771 /***********************************************************************
1772 * OLEClipbrd_UnInitialize()
1773 * Un-Initializes the OLE clipboard
1775 void OLEClipbrd_UnInitialize(void)
1777 ole_clipbrd *clipbrd = theOleClipboard;
1779 TRACE("()\n");
1781 if ( clipbrd )
1783 static const WCHAR ole32W[] = {'o','l','e','3','2',0};
1784 HINSTANCE hinst = GetModuleHandleW(ole32W);
1786 if ( clipbrd->window )
1788 DestroyWindow(clipbrd->window);
1789 UnregisterClassW( clipbrd_wndclass, hinst );
1792 IStream_Release(clipbrd->marshal_data);
1793 if (clipbrd->src_data) IDataObject_Release(clipbrd->src_data);
1794 HeapFree(GetProcessHeap(), 0, clipbrd->cached_enum);
1795 HeapFree(GetProcessHeap(), 0, clipbrd);
1796 theOleClipboard = NULL;
1800 /*********************************************************************
1801 * set_clipboard_formats
1803 * Enumerate all formats supported by the source and make
1804 * those formats available using delayed rendering using SetClipboardData.
1805 * Cache the enumeration list and make that list visibile as the
1806 * 'Ole Private Data' format on the clipboard.
1809 static HRESULT set_clipboard_formats(ole_clipbrd *clipbrd, IDataObject *data)
1811 HRESULT hr;
1812 FORMATETC fmt;
1813 IEnumFORMATETC *enum_fmt;
1814 HGLOBAL priv_data_handle;
1815 DWORD_PTR target_offset;
1816 ole_priv_data *priv_data;
1817 DWORD count = 0, needed = sizeof(*priv_data), idx;
1819 hr = IDataObject_EnumFormatEtc(data, DATADIR_GET, &enum_fmt);
1820 if(FAILED(hr)) return hr;
1822 while(IEnumFORMATETC_Next(enum_fmt, 1, &fmt, NULL) == S_OK)
1824 count++;
1825 needed += sizeof(priv_data->entries[0]);
1826 if(fmt.ptd)
1828 needed += fmt.ptd->tdSize;
1829 CoTaskMemFree(fmt.ptd);
1833 /* Windows pads the list with two empty ole_priv_data_entries, one
1834 * after the entries array and one after the target device data.
1835 * Allocating with zero init to zero these pads. */
1837 needed += sizeof(priv_data->entries[0]); /* initialisation of needed includes one of these. */
1838 priv_data_handle = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE | GMEM_ZEROINIT, needed);
1839 priv_data = GlobalLock(priv_data_handle);
1841 priv_data->unk1 = 0;
1842 priv_data->size = needed;
1843 priv_data->unk2 = 1;
1844 priv_data->count = count;
1845 priv_data->unk3[0] = 0;
1846 priv_data->unk3[1] = 0;
1848 IEnumFORMATETC_Reset(enum_fmt);
1850 idx = 0;
1851 target_offset = FIELD_OFFSET(ole_priv_data, entries[count + 1]); /* count entries + one pad. */
1853 while(IEnumFORMATETC_Next(enum_fmt, 1, &fmt, NULL) == S_OK)
1855 TRACE("%s\n", dump_fmtetc(&fmt));
1857 priv_data->entries[idx].fmtetc = fmt;
1858 if(fmt.ptd)
1860 memcpy((char*)priv_data + target_offset, fmt.ptd, fmt.ptd->tdSize);
1861 priv_data->entries[idx].fmtetc.ptd = (DVTARGETDEVICE*)target_offset;
1862 target_offset += fmt.ptd->tdSize;
1863 CoTaskMemFree(fmt.ptd);
1866 priv_data->entries[idx].first_use = !find_format_in_list(priv_data->entries, idx, fmt.cfFormat);
1867 priv_data->entries[idx].unk[0] = 0;
1868 priv_data->entries[idx].unk[1] = 0;
1870 if (priv_data->entries[idx].first_use)
1871 SetClipboardData(fmt.cfFormat, NULL);
1873 idx++;
1876 IEnumFORMATETC_Release(enum_fmt);
1878 /* Cache the list and fixup any target device offsets to ptrs */
1879 clipbrd->cached_enum = HeapAlloc(GetProcessHeap(), 0, needed);
1880 memcpy(clipbrd->cached_enum, priv_data, needed);
1881 for(idx = 0; idx < clipbrd->cached_enum->count; idx++)
1882 clipbrd->cached_enum->entries[idx].fmtetc.ptd =
1883 td_offs_to_ptr(clipbrd->cached_enum, (DWORD_PTR)clipbrd->cached_enum->entries[idx].fmtetc.ptd);
1885 GlobalUnlock(priv_data_handle);
1886 if(!SetClipboardData(ole_private_data_clipboard_format, priv_data_handle))
1888 GlobalFree(priv_data_handle);
1889 return CLIPBRD_E_CANT_SET;
1892 return S_OK;
1895 static HWND create_clipbrd_window(void);
1897 /***********************************************************************
1898 * get_clipbrd_window
1900 static inline HRESULT get_clipbrd_window(ole_clipbrd *clipbrd, HWND *wnd)
1902 if ( !clipbrd->window )
1903 clipbrd->window = create_clipbrd_window();
1905 *wnd = clipbrd->window;
1906 return *wnd ? S_OK : E_FAIL;
1910 /**********************************************************************
1911 * release_marshal_data
1913 * Releases the data and sets the stream back to zero size.
1915 static inline void release_marshal_data(IStream *stm)
1917 LARGE_INTEGER pos;
1918 ULARGE_INTEGER size;
1919 pos.QuadPart = size.QuadPart = 0;
1921 IStream_Seek(stm, pos, STREAM_SEEK_SET, NULL);
1922 CoReleaseMarshalData(stm);
1923 IStream_Seek(stm, pos, STREAM_SEEK_SET, NULL);
1924 IStream_SetSize(stm, size);
1927 /***********************************************************************
1928 * expose_marshalled_dataobject
1930 * Sets the marshalled dataobject to the clipboard. In the flushed case
1931 * we set a zero sized HGLOBAL to clear the old marshalled data.
1933 static HRESULT expose_marshalled_dataobject(ole_clipbrd *clipbrd, IDataObject *data)
1935 HGLOBAL h;
1937 if(data)
1939 HGLOBAL h_stm;
1940 GetHGlobalFromStream(clipbrd->marshal_data, &h_stm);
1941 dup_global_mem(h_stm, GMEM_DDESHARE|GMEM_MOVEABLE, &h);
1943 else /* flushed */
1944 h = GlobalAlloc(GMEM_DDESHARE|GMEM_MOVEABLE, 0);
1946 if(!h) return E_OUTOFMEMORY;
1948 if(!SetClipboardData(wine_marshal_clipboard_format, h))
1950 GlobalFree(h);
1951 return CLIPBRD_E_CANT_SET;
1953 return S_OK;
1956 /***********************************************************************
1957 * set_src_dataobject
1959 * Clears and sets the clipboard's src IDataObject.
1961 * To marshal the source dataobject we do something rather different from Windows.
1962 * We set a clipboard format which contains the marshalled data.
1963 * Windows sets two window props one of which is an IID, the other is an endpoint number.
1965 static HRESULT set_src_dataobject(ole_clipbrd *clipbrd, IDataObject *data)
1967 HRESULT hr;
1968 HWND wnd;
1970 if(FAILED(hr = get_clipbrd_window(clipbrd, &wnd))) return hr;
1972 if(clipbrd->src_data)
1974 release_marshal_data(clipbrd->marshal_data);
1976 IDataObject_Release(clipbrd->src_data);
1977 clipbrd->src_data = NULL;
1978 HeapFree(GetProcessHeap(), 0, clipbrd->cached_enum);
1979 clipbrd->cached_enum = NULL;
1982 if(data)
1984 IUnknown *unk;
1986 IDataObject_AddRef(data);
1987 clipbrd->src_data = data;
1989 IDataObject_QueryInterface(data, &IID_IUnknown, (void**)&unk);
1990 hr = CoMarshalInterface(clipbrd->marshal_data, &IID_IDataObject, unk,
1991 MSHCTX_LOCAL, NULL, MSHLFLAGS_TABLESTRONG);
1992 IUnknown_Release(unk); /* Don't hold a ref on IUnknown, we have one on IDataObject. */
1993 if(FAILED(hr)) return hr;
1994 hr = set_clipboard_formats(clipbrd, data);
1996 return hr;
1999 /***********************************************************************
2000 * clipbrd_wndproc
2002 static LRESULT CALLBACK clipbrd_wndproc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
2004 ole_clipbrd *clipbrd;
2006 get_ole_clipbrd(&clipbrd);
2008 switch (message)
2010 case WM_RENDERFORMAT:
2012 UINT cf = wparam;
2013 ole_priv_data_entry *entry;
2015 TRACE("(): WM_RENDERFORMAT(cfFormat=%x)\n", cf);
2016 entry = find_format_in_list(clipbrd->cached_enum->entries, clipbrd->cached_enum->count, cf);
2018 if(entry)
2019 render_format(clipbrd->src_data, &entry->fmtetc);
2021 break;
2024 case WM_RENDERALLFORMATS:
2026 DWORD i;
2027 ole_priv_data_entry *entries = clipbrd->cached_enum->entries;
2029 TRACE("(): WM_RENDERALLFORMATS\n");
2031 for(i = 0; i < clipbrd->cached_enum->count; i++)
2033 if(entries[i].first_use)
2034 render_format(clipbrd->src_data, &entries[i].fmtetc);
2036 break;
2039 case WM_DESTROYCLIPBOARD:
2041 TRACE("(): WM_DESTROYCLIPBOARD\n");
2043 set_src_dataobject(clipbrd, NULL);
2044 break;
2047 default:
2048 return DefWindowProcW(hwnd, message, wparam, lparam);
2051 return 0;
2055 /***********************************************************************
2056 * create_clipbrd_window
2058 static HWND create_clipbrd_window(void)
2060 WNDCLASSEXW class;
2061 static const WCHAR ole32W[] = {'o','l','e','3','2',0};
2062 static const WCHAR title[] = {'C','l','i','p','b','o','a','r','d','W','i','n','d','o','w',0};
2063 HINSTANCE hinst = GetModuleHandleW(ole32W);
2065 class.cbSize = sizeof(class);
2066 class.style = 0;
2067 class.lpfnWndProc = clipbrd_wndproc;
2068 class.cbClsExtra = 0;
2069 class.cbWndExtra = 0;
2070 class.hInstance = hinst;
2071 class.hIcon = 0;
2072 class.hCursor = 0;
2073 class.hbrBackground = 0;
2074 class.lpszMenuName = NULL;
2075 class.lpszClassName = clipbrd_wndclass;
2076 class.hIconSm = NULL;
2078 RegisterClassExW(&class);
2080 return CreateWindowW(clipbrd_wndclass, title, WS_POPUP | WS_CLIPSIBLINGS | WS_OVERLAPPED,
2081 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
2082 NULL, NULL, hinst, 0);
2085 /*********************************************************************
2086 * set_dataobject_format
2088 * Windows creates a 'DataObject' clipboard format that contains the
2089 * clipboard window's HWND or NULL if the Ole clipboard has been flushed.
2091 static HRESULT set_dataobject_format(HWND hwnd)
2093 HGLOBAL h = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE, sizeof(hwnd));
2094 HWND *data;
2096 if(!h) return E_OUTOFMEMORY;
2098 data = GlobalLock(h);
2099 *data = hwnd;
2100 GlobalUnlock(h);
2102 if(!SetClipboardData(dataobject_clipboard_format, h))
2104 GlobalFree(h);
2105 return CLIPBRD_E_CANT_SET;
2108 return S_OK;
2111 /*---------------------------------------------------------------------*
2112 * Win32 OLE clipboard API
2113 *---------------------------------------------------------------------*/
2115 /***********************************************************************
2116 * OleSetClipboard [OLE32.@]
2117 * Places a pointer to the specified data object onto the clipboard,
2118 * making the data object accessible to the OleGetClipboard function.
2120 * RETURNS
2122 * S_OK IDataObject pointer placed on the clipboard
2123 * CLIPBRD_E_CANT_OPEN OpenClipboard failed
2124 * CLIPBRD_E_CANT_EMPTY EmptyClipboard failed
2125 * CLIPBRD_E_CANT_CLOSE CloseClipboard failed
2126 * CLIPBRD_E_CANT_SET SetClipboard failed
2129 HRESULT WINAPI OleSetClipboard(IDataObject* data)
2131 HRESULT hr;
2132 ole_clipbrd *clipbrd;
2133 HWND wnd;
2135 TRACE("(%p)\n", data);
2137 if(FAILED(hr = get_ole_clipbrd(&clipbrd))) return hr;
2139 if(FAILED(hr = get_clipbrd_window(clipbrd, &wnd))) return hr;
2141 if ( !OpenClipboard(wnd) ) return CLIPBRD_E_CANT_OPEN;
2143 if ( !EmptyClipboard() )
2145 hr = CLIPBRD_E_CANT_EMPTY;
2146 goto end;
2149 hr = set_src_dataobject(clipbrd, data);
2150 if(FAILED(hr)) goto end;
2152 if(data)
2154 hr = expose_marshalled_dataobject(clipbrd, data);
2155 if(FAILED(hr)) goto end;
2156 hr = set_dataobject_format(wnd);
2159 end:
2161 if ( !CloseClipboard() ) hr = CLIPBRD_E_CANT_CLOSE;
2163 if ( FAILED(hr) )
2165 expose_marshalled_dataobject(clipbrd, NULL);
2166 set_src_dataobject(clipbrd, NULL);
2169 return hr;
2173 /***********************************************************************
2174 * OleGetClipboard [OLE32.@]
2175 * Returns a pointer to our internal IDataObject which represents the conceptual
2176 * state of the Windows clipboard. If the current clipboard already contains
2177 * an IDataObject, our internal IDataObject will delegate to this object.
2179 HRESULT WINAPI OleGetClipboard(IDataObject **obj)
2181 HRESULT hr;
2182 ole_clipbrd *clipbrd;
2183 DWORD seq_no;
2185 TRACE("(%p)\n", obj);
2187 if(!obj) return E_INVALIDARG;
2189 if(FAILED(hr = get_ole_clipbrd(&clipbrd))) return hr;
2191 seq_no = GetClipboardSequenceNumber();
2192 if(clipbrd->latest_snapshot && clipbrd->latest_snapshot->seq_no != seq_no)
2193 clipbrd->latest_snapshot = NULL;
2195 if(!clipbrd->latest_snapshot)
2197 clipbrd->latest_snapshot = snapshot_construct(seq_no);
2198 if(!clipbrd->latest_snapshot) return E_OUTOFMEMORY;
2201 *obj = &clipbrd->latest_snapshot->IDataObject_iface;
2202 IDataObject_AddRef(*obj);
2204 return S_OK;
2207 /******************************************************************************
2208 * OleFlushClipboard [OLE32.@]
2209 * Renders the data from the source IDataObject into the windows clipboard
2211 * TODO: OleFlushClipboard needs to additionally handle TYMED_IStorage media
2212 * by copying the storage into global memory. Subsequently the default
2213 * data object exposed through OleGetClipboard must convert this TYMED_HGLOBAL
2214 * back to TYMED_IStorage.
2216 HRESULT WINAPI OleFlushClipboard(void)
2218 HRESULT hr;
2219 ole_clipbrd *clipbrd;
2220 HWND wnd;
2222 TRACE("()\n");
2224 if(FAILED(hr = get_ole_clipbrd(&clipbrd))) return hr;
2226 if(FAILED(hr = get_clipbrd_window(clipbrd, &wnd))) return hr;
2229 * Already flushed or no source DataObject? Nothing to do.
2231 if (!clipbrd->src_data) return S_OK;
2233 if (!OpenClipboard(wnd)) return CLIPBRD_E_CANT_OPEN;
2235 SendMessageW(wnd, WM_RENDERALLFORMATS, 0, 0);
2237 hr = set_dataobject_format(NULL);
2239 expose_marshalled_dataobject(clipbrd, NULL);
2240 set_src_dataobject(clipbrd, NULL);
2242 if ( !CloseClipboard() ) hr = CLIPBRD_E_CANT_CLOSE;
2244 return hr;
2248 /***********************************************************************
2249 * OleIsCurrentClipboard [OLE32.@]
2251 HRESULT WINAPI OleIsCurrentClipboard(IDataObject *data)
2253 HRESULT hr;
2254 ole_clipbrd *clipbrd;
2255 TRACE("()\n");
2257 if(FAILED(hr = get_ole_clipbrd(&clipbrd))) return hr;
2259 if (data == NULL) return S_FALSE;
2261 return (data == clipbrd->src_data) ? S_OK : S_FALSE;