oleaut32: Remove unneeded NONAMELESSXXX directives.
[wine.git] / dlls / ole32 / clipboard.c
blobc7d58d6336d1f6d0ef044d6de27ab88c82ec91b8
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
69 #include "windef.h"
70 #include "winbase.h"
71 #include "wingdi.h"
72 #include "winuser.h"
73 #include "winerror.h"
74 #include "winnls.h"
75 #include "ole2.h"
76 #include "wine/debug.h"
77 #include "olestd.h"
79 #include "storage32.h"
81 #include "compobj_private.h"
83 WINE_DEFAULT_DEBUG_CHANNEL(ole);
85 /* Structure of 'Ole Private Data' clipboard format */
86 typedef struct
88 FORMATETC fmtetc;
89 DWORD first_use; /* Has this cf been added to the list already */
90 DWORD unk[2];
91 } ole_priv_data_entry;
93 typedef struct
95 DWORD unk1;
96 DWORD size; /* in bytes of the entire structure */
97 DWORD unk2;
98 DWORD count; /* no. of format entries */
99 DWORD unk3[2];
100 ole_priv_data_entry entries[1]; /* array of size count */
101 /* then follows any DVTARGETDEVICE structures referenced in the FORMATETCs */
102 } ole_priv_data;
104 /*****************************************************************************
105 * td_offs_to_ptr
107 * Returns a ptr to a target device at a given offset from the
108 * start of the ole_priv_data.
110 * Used when unpacking ole private data from the clipboard.
112 static inline DVTARGETDEVICE *td_offs_to_ptr(ole_priv_data *data, DWORD_PTR off)
114 if(off == 0) return NULL;
115 return (DVTARGETDEVICE*)((char*)data + off);
118 /*****************************************************************************
119 * td_get_offs
121 * Get the offset from the start of the ole_priv_data of the idx'th
122 * target device.
124 * Used when packing ole private data to the clipboard.
126 static inline DWORD_PTR td_get_offs(ole_priv_data *data, DWORD idx)
128 if(data->entries[idx].fmtetc.ptd == NULL) return 0;
129 return (char*)data->entries[idx].fmtetc.ptd - (char*)data;
132 /****************************************************************************
133 * Consumer snapshot. Represents the state of the ole clipboard
134 * returned by OleGetClipboard().
136 typedef struct snapshot
138 IDataObject IDataObject_iface;
139 LONG ref;
141 DWORD seq_no; /* Clipboard sequence number corresponding to this snapshot */
143 IDataObject *data; /* If we unmarshal a remote data object we hold a ref here */
144 } snapshot;
146 /****************************************************************************
147 * ole_clipbrd
149 typedef struct ole_clipbrd
151 snapshot *latest_snapshot; /* Latest consumer snapshot */
153 HWND window; /* Hidden clipboard window */
154 IDataObject *src_data; /* Source object passed to OleSetClipboard */
155 ole_priv_data *cached_enum; /* Cached result from the enumeration of src data object */
156 IStream *marshal_data; /* Stream onto which to marshal src_data */
157 } ole_clipbrd;
159 static inline snapshot *impl_from_IDataObject(IDataObject *iface)
161 return CONTAINING_RECORD(iface, snapshot, IDataObject_iface);
164 typedef struct PresentationDataHeader
166 BYTE unknown1[28];
167 DWORD dwObjectExtentX;
168 DWORD dwObjectExtentY;
169 DWORD dwSize;
170 } PresentationDataHeader;
173 * The one and only ole_clipbrd object which is created by OLEClipbrd_Initialize()
175 static ole_clipbrd* theOleClipboard;
177 static inline HRESULT get_ole_clipbrd(ole_clipbrd **clipbrd)
179 struct oletls *info = COM_CurrentInfo();
180 *clipbrd = NULL;
182 if(!info->ole_inits)
183 return CO_E_NOTINITIALIZED;
184 *clipbrd = theOleClipboard;
186 return S_OK;
190 * Name of our registered OLE clipboard window class
192 static const WCHAR clipbrd_wndclass[] = {'C','L','I','P','B','R','D','W','N','D','C','L','A','S','S',0};
194 UINT ownerlink_clipboard_format = 0;
195 UINT filename_clipboard_format = 0;
196 UINT filenameW_clipboard_format = 0;
197 UINT dataobject_clipboard_format = 0;
198 UINT embedded_object_clipboard_format = 0;
199 UINT embed_source_clipboard_format = 0;
200 UINT custom_link_source_clipboard_format = 0;
201 UINT link_source_clipboard_format = 0;
202 UINT object_descriptor_clipboard_format = 0;
203 UINT link_source_descriptor_clipboard_format = 0;
204 UINT ole_private_data_clipboard_format = 0;
206 static UINT wine_marshal_clipboard_format;
208 static inline const char *dump_fmtetc(FORMATETC *fmt)
210 if (!fmt) return "(null)";
211 return wine_dbg_sprintf("cf %04x ptd %p aspect %x lindex %d tymed %x",
212 fmt->cfFormat, fmt->ptd, fmt->dwAspect, fmt->lindex, fmt->tymed);
215 /*---------------------------------------------------------------------*
216 * Implementation of the internal IEnumFORMATETC interface returned by
217 * the OLE clipboard's IDataObject.
218 *---------------------------------------------------------------------*/
220 typedef struct enum_fmtetc
222 IEnumFORMATETC IEnumFORMATETC_iface;
223 LONG ref;
225 UINT pos; /* current enumerator position */
226 ole_priv_data *data;
227 } enum_fmtetc;
229 static inline enum_fmtetc *impl_from_IEnumFORMATETC(IEnumFORMATETC *iface)
231 return CONTAINING_RECORD(iface, enum_fmtetc, IEnumFORMATETC_iface);
234 /************************************************************************
235 * OLEClipbrd_IEnumFORMATETC_QueryInterface (IUnknown)
237 * See Windows documentation for more details on IUnknown methods.
239 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_QueryInterface
240 (LPENUMFORMATETC iface, REFIID riid, LPVOID* ppvObj)
242 enum_fmtetc *This = impl_from_IEnumFORMATETC(iface);
244 TRACE("(%p)->(IID: %s, %p)\n", This, debugstr_guid(riid), ppvObj);
246 *ppvObj = NULL;
248 if(IsEqualIID(riid, &IID_IUnknown) ||
249 IsEqualIID(riid, &IID_IEnumFORMATETC))
251 *ppvObj = iface;
254 if(*ppvObj)
256 IEnumFORMATETC_AddRef((IEnumFORMATETC*)*ppvObj);
257 TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
258 return S_OK;
261 TRACE("-- Interface: E_NOINTERFACE\n");
262 return E_NOINTERFACE;
265 /************************************************************************
266 * OLEClipbrd_IEnumFORMATETC_AddRef (IUnknown)
269 static ULONG WINAPI OLEClipbrd_IEnumFORMATETC_AddRef(LPENUMFORMATETC iface)
271 enum_fmtetc *This = impl_from_IEnumFORMATETC(iface);
272 TRACE("(%p)->(count=%u)\n",This, This->ref);
274 return InterlockedIncrement(&This->ref);
277 /************************************************************************
278 * OLEClipbrd_IEnumFORMATETC_Release (IUnknown)
280 * See Windows documentation for more details on IUnknown methods.
282 static ULONG WINAPI OLEClipbrd_IEnumFORMATETC_Release(LPENUMFORMATETC iface)
284 enum_fmtetc *This = impl_from_IEnumFORMATETC(iface);
285 ULONG ref;
287 TRACE("(%p)->(count=%u)\n",This, This->ref);
289 ref = InterlockedDecrement(&This->ref);
290 if (!ref)
292 TRACE("() - destroying IEnumFORMATETC(%p)\n",This);
293 HeapFree(GetProcessHeap(), 0, This->data);
294 HeapFree(GetProcessHeap(), 0, This);
296 return ref;
299 /************************************************************************
300 * OLEClipbrd_IEnumFORMATETC_Next (IEnumFORMATETC)
302 * Standard enumerator members for IEnumFORMATETC
304 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Next
305 (LPENUMFORMATETC iface, ULONG celt, FORMATETC *rgelt, ULONG *pceltFethed)
307 enum_fmtetc *This = impl_from_IEnumFORMATETC(iface);
308 UINT cfetch, i;
309 HRESULT hres = S_FALSE;
311 TRACE("(%p)->(pos=%u)\n", This, This->pos);
313 if (This->pos < This->data->count)
315 cfetch = This->data->count - This->pos;
316 if (cfetch >= celt)
318 cfetch = celt;
319 hres = S_OK;
322 for(i = 0; i < cfetch; i++)
324 rgelt[i] = This->data->entries[This->pos++].fmtetc;
325 if(rgelt[i].ptd)
327 DVTARGETDEVICE *target = rgelt[i].ptd;
328 rgelt[i].ptd = CoTaskMemAlloc(target->tdSize);
329 if(!rgelt[i].ptd) return E_OUTOFMEMORY;
330 memcpy(rgelt[i].ptd, target, target->tdSize);
334 else
336 cfetch = 0;
339 if (pceltFethed)
341 *pceltFethed = cfetch;
344 return hres;
347 /************************************************************************
348 * OLEClipbrd_IEnumFORMATETC_Skip (IEnumFORMATETC)
350 * Standard enumerator members for IEnumFORMATETC
352 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Skip(LPENUMFORMATETC iface, ULONG celt)
354 enum_fmtetc *This = impl_from_IEnumFORMATETC(iface);
355 TRACE("(%p)->(num=%u)\n", This, celt);
357 This->pos += celt;
358 if (This->pos > This->data->count)
360 This->pos = This->data->count;
361 return S_FALSE;
363 return S_OK;
366 /************************************************************************
367 * OLEClipbrd_IEnumFORMATETC_Reset (IEnumFORMATETC)
369 * Standard enumerator members for IEnumFORMATETC
371 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Reset(LPENUMFORMATETC iface)
373 enum_fmtetc *This = impl_from_IEnumFORMATETC(iface);
374 TRACE("(%p)->()\n", This);
376 This->pos = 0;
377 return S_OK;
380 static HRESULT enum_fmtetc_construct(ole_priv_data *data, UINT pos, IEnumFORMATETC **obj);
382 /************************************************************************
383 * OLEClipbrd_IEnumFORMATETC_Clone (IEnumFORMATETC)
385 * Standard enumerator members for IEnumFORMATETC
387 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Clone
388 (LPENUMFORMATETC iface, LPENUMFORMATETC* obj)
390 enum_fmtetc *This = impl_from_IEnumFORMATETC(iface);
391 ole_priv_data *new_data;
392 DWORD i;
394 TRACE("(%p)->(%p)\n", This, obj);
396 if ( !obj ) return E_INVALIDARG;
397 *obj = NULL;
399 new_data = HeapAlloc(GetProcessHeap(), 0, This->data->size);
400 if(!new_data) return E_OUTOFMEMORY;
401 memcpy(new_data, This->data, This->data->size);
403 /* Fixup any target device ptrs */
404 for(i = 0; i < This->data->count; i++)
405 new_data->entries[i].fmtetc.ptd =
406 td_offs_to_ptr(new_data, td_get_offs(This->data, i));
408 return enum_fmtetc_construct(new_data, This->pos, obj);
411 static const IEnumFORMATETCVtbl efvt =
413 OLEClipbrd_IEnumFORMATETC_QueryInterface,
414 OLEClipbrd_IEnumFORMATETC_AddRef,
415 OLEClipbrd_IEnumFORMATETC_Release,
416 OLEClipbrd_IEnumFORMATETC_Next,
417 OLEClipbrd_IEnumFORMATETC_Skip,
418 OLEClipbrd_IEnumFORMATETC_Reset,
419 OLEClipbrd_IEnumFORMATETC_Clone
422 /************************************************************************
423 * enum_fmtetc_construct
425 * Creates an IEnumFORMATETC enumerator from ole_priv_data which it then owns.
427 static HRESULT enum_fmtetc_construct(ole_priv_data *data, UINT pos, IEnumFORMATETC **obj)
429 enum_fmtetc* ef;
431 *obj = NULL;
432 ef = HeapAlloc(GetProcessHeap(), 0, sizeof(*ef));
433 if (!ef) return E_OUTOFMEMORY;
435 ef->ref = 1;
436 ef->IEnumFORMATETC_iface.lpVtbl = &efvt;
437 ef->data = data;
438 ef->pos = pos;
440 TRACE("(%p)->()\n", ef);
441 *obj = &ef->IEnumFORMATETC_iface;
442 return S_OK;
445 /***********************************************************************
446 * dup_global_mem
448 * Helper method to duplicate an HGLOBAL chunk of memory
450 static HRESULT dup_global_mem( HGLOBAL src, DWORD flags, HGLOBAL *dst )
452 void *src_ptr, *dst_ptr;
453 DWORD size;
455 *dst = NULL;
456 if ( !src ) return S_FALSE;
458 size = GlobalSize(src);
460 *dst = GlobalAlloc( flags, size );
461 if ( !*dst ) return E_OUTOFMEMORY;
463 src_ptr = GlobalLock(src);
464 dst_ptr = GlobalLock(*dst);
466 memcpy(dst_ptr, src_ptr, size);
468 GlobalUnlock(*dst);
469 GlobalUnlock(src);
471 return S_OK;
474 /***********************************************************************
475 * dup_metafilepict
477 * Helper function to duplicate a handle to a METAFILEPICT, and the
478 * contained HMETAFILE.
480 static HRESULT dup_metafilepict(HGLOBAL src, HGLOBAL *pdest)
482 HRESULT hr;
483 HGLOBAL dest;
484 METAFILEPICT *dest_ptr;
486 *pdest = NULL;
488 /* Copy the METAFILEPICT structure. */
489 hr = dup_global_mem(src, GMEM_DDESHARE|GMEM_MOVEABLE, &dest);
490 if (FAILED(hr)) return hr;
492 dest_ptr = GlobalLock(dest);
493 if (!dest_ptr) return E_FAIL;
495 /* Give the new METAFILEPICT a separate HMETAFILE. */
496 dest_ptr->hMF = CopyMetaFileW(dest_ptr->hMF, NULL);
497 if (dest_ptr->hMF)
499 GlobalUnlock(dest);
500 *pdest = dest;
501 return S_OK;
503 else
505 GlobalUnlock(dest);
506 GlobalFree(dest);
507 return E_FAIL;
511 /***********************************************************************
512 * free_metafilepict
514 * Helper function to GlobalFree a handle to a METAFILEPICT, and also
515 * free the contained HMETAFILE.
517 static void free_metafilepict(HGLOBAL src)
519 METAFILEPICT *src_ptr;
521 src_ptr = GlobalLock(src);
522 if (src_ptr)
524 DeleteMetaFile(src_ptr->hMF);
525 GlobalUnlock(src);
527 GlobalFree(src);
530 /***********************************************************************
531 * dup_bitmap
533 * Helper function to duplicate an HBITMAP.
535 static HRESULT dup_bitmap(HBITMAP src, HBITMAP *pdest)
537 HDC src_dc;
538 HGDIOBJ orig_src_bitmap;
539 BITMAP bm;
540 HBITMAP dest;
542 src_dc = CreateCompatibleDC(NULL);
543 orig_src_bitmap = SelectObject(src_dc, src);
544 GetObjectW(src, sizeof bm, &bm);
545 dest = CreateCompatibleBitmap(src_dc, bm.bmWidth, bm.bmHeight);
546 if (dest)
548 HDC dest_dc = CreateCompatibleDC(NULL);
549 HGDIOBJ orig_dest_bitmap = SelectObject(dest_dc, dest);
550 BitBlt(dest_dc, 0, 0, bm.bmWidth, bm.bmHeight, src_dc, 0, 0, SRCCOPY);
551 SelectObject(dest_dc, orig_dest_bitmap);
552 DeleteDC(dest_dc);
554 SelectObject(src_dc, orig_src_bitmap);
555 DeleteDC(src_dc);
556 *pdest = dest;
557 return dest ? S_OK : E_FAIL;
560 /************************************************************
561 * render_embed_source_hack
563 * This is clearly a hack and has no place in the clipboard code.
566 static HRESULT render_embed_source_hack(IDataObject *data, LPFORMATETC fmt)
568 STGMEDIUM std;
569 HGLOBAL hStorage = 0;
570 HRESULT hr = S_OK;
571 ILockBytes *ptrILockBytes;
573 memset(&std, 0, sizeof(STGMEDIUM));
574 std.tymed = fmt->tymed = TYMED_ISTORAGE;
576 hStorage = GlobalAlloc(GMEM_SHARE|GMEM_MOVEABLE, 0);
577 if (hStorage == NULL) return E_OUTOFMEMORY;
578 hr = CreateILockBytesOnHGlobal(hStorage, FALSE, &ptrILockBytes);
579 hr = StgCreateDocfileOnILockBytes(ptrILockBytes, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &std.u.pstg);
580 ILockBytes_Release(ptrILockBytes);
582 if (FAILED(hr = IDataObject_GetDataHere(theOleClipboard->src_data, fmt, &std)))
584 WARN("() : IDataObject_GetDataHere failed to render clipboard data! (%x)\n", hr);
585 GlobalFree(hStorage);
586 return hr;
589 if (1) /* check whether the presentation data is already -not- present */
591 FORMATETC fmt2;
592 STGMEDIUM std2;
593 METAFILEPICT *mfp = 0;
595 fmt2.cfFormat = CF_METAFILEPICT;
596 fmt2.ptd = 0;
597 fmt2.dwAspect = DVASPECT_CONTENT;
598 fmt2.lindex = -1;
599 fmt2.tymed = TYMED_MFPICT;
601 memset(&std2, 0, sizeof(STGMEDIUM));
602 std2.tymed = TYMED_MFPICT;
604 /* Get the metafile picture out of it */
606 if (SUCCEEDED(hr = IDataObject_GetData(theOleClipboard->src_data, &fmt2, &std2)))
608 mfp = GlobalLock(std2.u.hGlobal);
611 if (mfp)
613 OLECHAR name[]={ 2, 'O', 'l', 'e', 'P', 'r', 'e', 's', '0', '0', '0', 0};
614 IStream *pStream = 0;
615 void *mfBits;
616 PresentationDataHeader pdh;
617 INT nSize;
618 CLSID clsID;
619 LPOLESTR strProgID;
620 CHAR strOleTypeName[51];
621 BYTE OlePresStreamHeader [] =
623 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00,
624 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
625 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
626 0x00, 0x00, 0x00, 0x00
629 nSize = GetMetaFileBitsEx(mfp->hMF, 0, NULL);
631 memset(&pdh, 0, sizeof(PresentationDataHeader));
632 memcpy(&pdh, OlePresStreamHeader, sizeof(OlePresStreamHeader));
634 pdh.dwObjectExtentX = mfp->xExt;
635 pdh.dwObjectExtentY = mfp->yExt;
636 pdh.dwSize = nSize;
638 hr = IStorage_CreateStream(std.u.pstg, name, STGM_CREATE|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, 0, &pStream);
640 hr = IStream_Write(pStream, &pdh, sizeof(PresentationDataHeader), NULL);
642 mfBits = HeapAlloc(GetProcessHeap(), 0, nSize);
643 nSize = GetMetaFileBitsEx(mfp->hMF, nSize, mfBits);
645 hr = IStream_Write(pStream, mfBits, nSize, NULL);
647 IStream_Release(pStream);
649 HeapFree(GetProcessHeap(), 0, mfBits);
651 GlobalUnlock(std2.u.hGlobal);
652 ReleaseStgMedium(&std2);
654 ReadClassStg(std.u.pstg, &clsID);
655 ProgIDFromCLSID(&clsID, &strProgID);
657 WideCharToMultiByte( CP_ACP, 0, strProgID, -1, strOleTypeName, sizeof(strOleTypeName), NULL, NULL );
658 STORAGE_CreateOleStream(std.u.pstg, 0);
659 OLECONVERT_CreateCompObjStream(std.u.pstg, strOleTypeName);
660 CoTaskMemFree(strProgID);
664 if ( !SetClipboardData( fmt->cfFormat, hStorage ) )
666 WARN("() : Failed to set rendered clipboard data into clipboard!\n");
667 GlobalFree(hStorage);
668 hr = CLIPBRD_E_CANT_SET;
671 ReleaseStgMedium(&std);
672 return hr;
675 /************************************************************************
676 * find_format_in_list
678 * Returns the first entry that matches the provided clipboard format.
680 static inline ole_priv_data_entry *find_format_in_list(ole_priv_data_entry *entries, DWORD num, UINT cf)
682 DWORD i;
683 for(i = 0; i < num; i++)
684 if(entries[i].fmtetc.cfFormat == cf)
685 return &entries[i];
687 return NULL;
690 /***************************************************************************
691 * get_data_from_storage
693 * Returns storage data in an HGLOBAL.
695 static HRESULT get_data_from_storage(IDataObject *data, FORMATETC *fmt, HGLOBAL *mem)
697 HGLOBAL h;
698 IStorage *stg;
699 HRESULT hr;
700 FORMATETC stg_fmt;
701 STGMEDIUM med;
702 ILockBytes *lbs;
704 *mem = NULL;
706 h = GlobalAlloc( GMEM_DDESHARE|GMEM_MOVEABLE, 0 );
707 if(!h) return E_OUTOFMEMORY;
709 hr = CreateILockBytesOnHGlobal(h, FALSE, &lbs);
710 if(SUCCEEDED(hr))
712 hr = StgCreateDocfileOnILockBytes(lbs, STGM_CREATE|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &stg);
713 ILockBytes_Release(lbs);
715 if(FAILED(hr))
717 GlobalFree(h);
718 return hr;
721 stg_fmt = *fmt;
722 med.tymed = stg_fmt.tymed = TYMED_ISTORAGE;
723 med.u.pstg = stg;
724 med.pUnkForRelease = NULL;
726 hr = IDataObject_GetDataHere(data, &stg_fmt, &med);
727 if(FAILED(hr))
729 med.u.pstg = NULL;
730 hr = IDataObject_GetData(data, &stg_fmt, &med);
731 if(FAILED(hr)) goto end;
733 hr = IStorage_CopyTo(med.u.pstg, 0, NULL, NULL, stg);
734 ReleaseStgMedium(&med);
735 if(FAILED(hr)) goto end;
737 *mem = h;
739 end:
740 IStorage_Release(stg);
741 if(FAILED(hr)) GlobalFree(h);
742 return hr;
745 /***************************************************************************
746 * get_data_from_stream
748 * Returns stream data in an HGLOBAL.
750 static HRESULT get_data_from_stream(IDataObject *data, FORMATETC *fmt, HGLOBAL *mem)
752 HGLOBAL h;
753 IStream *stm = NULL;
754 HRESULT hr;
755 FORMATETC stm_fmt;
756 STGMEDIUM med;
758 *mem = NULL;
760 h = GlobalAlloc( GMEM_DDESHARE|GMEM_MOVEABLE, 0 );
761 if(!h) return E_OUTOFMEMORY;
763 hr = CreateStreamOnHGlobal(h, FALSE, &stm);
764 if(FAILED(hr)) goto error;
766 stm_fmt = *fmt;
767 med.tymed = stm_fmt.tymed = TYMED_ISTREAM;
768 med.u.pstm = stm;
769 med.pUnkForRelease = NULL;
771 hr = IDataObject_GetDataHere(data, &stm_fmt, &med);
772 if(FAILED(hr))
774 LARGE_INTEGER offs;
775 ULARGE_INTEGER pos;
777 med.u.pstm = NULL;
778 hr = IDataObject_GetData(data, &stm_fmt, &med);
779 if(FAILED(hr)) goto error;
781 offs.QuadPart = 0;
782 IStream_Seek(med.u.pstm, offs, STREAM_SEEK_CUR, &pos);
783 IStream_Seek(med.u.pstm, offs, STREAM_SEEK_SET, NULL);
784 hr = IStream_CopyTo(med.u.pstm, stm, pos, NULL, NULL);
785 ReleaseStgMedium(&med);
786 if(FAILED(hr)) goto error;
788 *mem = h;
789 IStream_Release(stm);
790 return S_OK;
792 error:
793 if(stm) IStream_Release(stm);
794 GlobalFree(h);
795 return hr;
798 /***************************************************************************
799 * get_data_from_global
801 * Returns global data in an HGLOBAL.
803 static HRESULT get_data_from_global(IDataObject *data, FORMATETC *fmt, HGLOBAL *mem)
805 HGLOBAL h;
806 HRESULT hr;
807 FORMATETC mem_fmt;
808 STGMEDIUM med;
810 *mem = NULL;
812 mem_fmt = *fmt;
813 mem_fmt.tymed = TYMED_HGLOBAL;
815 hr = IDataObject_GetData(data, &mem_fmt, &med);
816 if(FAILED(hr)) return hr;
818 hr = dup_global_mem(med.u.hGlobal, GMEM_DDESHARE|GMEM_MOVEABLE, &h);
820 if(SUCCEEDED(hr)) *mem = h;
822 ReleaseStgMedium(&med);
824 return hr;
827 /***************************************************************************
828 * get_data_from_enhmetafile
830 static HRESULT get_data_from_enhmetafile(IDataObject *data, FORMATETC *fmt, HGLOBAL *mem)
832 HENHMETAFILE copy;
833 HRESULT hr;
834 FORMATETC mem_fmt;
835 STGMEDIUM med;
837 *mem = NULL;
839 mem_fmt = *fmt;
840 mem_fmt.tymed = TYMED_ENHMF;
842 hr = IDataObject_GetData(data, &mem_fmt, &med);
843 if(FAILED(hr)) return hr;
845 copy = CopyEnhMetaFileW(med.u.hEnhMetaFile, NULL);
846 if(copy) *mem = (HGLOBAL)copy;
847 else hr = E_FAIL;
849 ReleaseStgMedium(&med);
851 return hr;
854 /***************************************************************************
855 * get_data_from_metafilepict
857 static HRESULT get_data_from_metafilepict(IDataObject *data, FORMATETC *fmt, HGLOBAL *mem)
859 HGLOBAL copy;
860 HRESULT hr;
861 FORMATETC mem_fmt;
862 STGMEDIUM med;
864 *mem = NULL;
866 mem_fmt = *fmt;
867 mem_fmt.tymed = TYMED_MFPICT;
869 hr = IDataObject_GetData(data, &mem_fmt, &med);
870 if(FAILED(hr)) return hr;
872 hr = dup_metafilepict(med.u.hMetaFilePict, &copy);
874 if(SUCCEEDED(hr)) *mem = copy;
876 ReleaseStgMedium(&med);
878 return hr;
881 /***************************************************************************
882 * get_data_from_bitmap
884 * Returns bitmap in an HBITMAP.
886 static HRESULT get_data_from_bitmap(IDataObject *data, FORMATETC *fmt, HBITMAP *hbm)
888 HBITMAP copy;
889 HRESULT hr;
890 FORMATETC mem_fmt;
891 STGMEDIUM med;
893 *hbm = NULL;
895 mem_fmt = *fmt;
896 mem_fmt.tymed = TYMED_GDI;
898 hr = IDataObject_GetData(data, &mem_fmt, &med);
899 if(FAILED(hr)) return hr;
901 hr = dup_bitmap(med.u.hBitmap, &copy);
903 if(SUCCEEDED(hr)) *hbm = copy;
905 ReleaseStgMedium(&med);
907 return hr;
910 /***********************************************************************
911 * render_format
913 * Render the clipboard data. Note that this call will delegate to the
914 * source data object.
916 static HRESULT render_format(IDataObject *data, LPFORMATETC fmt)
918 HANDLE clip_data = NULL; /* HGLOBAL unless otherwise specified */
919 HRESULT hr;
921 /* Embed source hack */
922 if(fmt->cfFormat == embed_source_clipboard_format)
924 return render_embed_source_hack(data, fmt);
927 if(fmt->tymed & TYMED_ISTORAGE)
929 hr = get_data_from_storage(data, fmt, &clip_data);
931 else if(fmt->tymed & TYMED_ISTREAM)
933 hr = get_data_from_stream(data, fmt, &clip_data);
935 else if(fmt->tymed & TYMED_HGLOBAL)
937 hr = get_data_from_global(data, fmt, &clip_data);
939 else if(fmt->tymed & TYMED_ENHMF)
941 hr = get_data_from_enhmetafile(data, fmt, &clip_data);
943 else if(fmt->tymed & TYMED_MFPICT)
945 /* Returns global handle to METAFILEPICT, containing a copied HMETAFILE */
946 hr = get_data_from_metafilepict(data, fmt, &clip_data);
948 else if(fmt->tymed & TYMED_GDI)
950 /* Returns HBITMAP not HGLOBAL */
951 hr = get_data_from_bitmap(data, fmt, (HBITMAP *)&clip_data);
953 else
955 FIXME("Unhandled tymed %x\n", fmt->tymed);
956 hr = DV_E_FORMATETC;
959 if(SUCCEEDED(hr))
961 if ( !SetClipboardData(fmt->cfFormat, clip_data) )
963 WARN("() : Failed to set rendered clipboard data into clipboard!\n");
964 if(fmt->tymed & TYMED_MFPICT)
965 free_metafilepict(clip_data);
966 else if(fmt->tymed & TYMED_GDI)
967 DeleteObject(clip_data);
968 else
969 GlobalFree(clip_data);
970 hr = CLIPBRD_E_CANT_SET;
974 return hr;
977 /*---------------------------------------------------------------------*
978 * Implementation of the internal IDataObject interface exposed by
979 * the OLE clipboard.
980 *---------------------------------------------------------------------*/
983 /************************************************************************
984 * snapshot_QueryInterface
986 static HRESULT WINAPI snapshot_QueryInterface(IDataObject *iface,
987 REFIID riid, void **ppvObject)
989 snapshot *This = impl_from_IDataObject(iface);
990 TRACE("(%p)->(IID:%s, %p)\n", This, debugstr_guid(riid), ppvObject);
992 if ( (This==0) || (ppvObject==0) )
993 return E_INVALIDARG;
995 *ppvObject = 0;
997 if (IsEqualIID(&IID_IUnknown, riid) ||
998 IsEqualIID(&IID_IDataObject, riid))
1000 *ppvObject = iface;
1002 else
1004 WARN( "() : asking for unsupported interface %s\n", debugstr_guid(riid));
1005 return E_NOINTERFACE;
1008 IUnknown_AddRef((IUnknown*)*ppvObject);
1010 return S_OK;
1013 /************************************************************************
1014 * snapshot_AddRef
1016 static ULONG WINAPI snapshot_AddRef(IDataObject *iface)
1018 snapshot *This = impl_from_IDataObject(iface);
1020 TRACE("(%p)->(count=%u)\n", This, This->ref);
1022 return InterlockedIncrement(&This->ref);
1025 /************************************************************************
1026 * snapshot_Release
1028 static ULONG WINAPI snapshot_Release(IDataObject *iface)
1030 snapshot *This = impl_from_IDataObject(iface);
1031 ULONG ref;
1033 TRACE("(%p)->(count=%u)\n", This, This->ref);
1035 ref = InterlockedDecrement(&This->ref);
1037 if (ref == 0)
1039 ole_clipbrd *clipbrd;
1040 HRESULT hr = get_ole_clipbrd(&clipbrd);
1042 if(This->data) IDataObject_Release(This->data);
1044 if(SUCCEEDED(hr) && clipbrd->latest_snapshot == This)
1045 clipbrd->latest_snapshot = NULL;
1046 HeapFree(GetProcessHeap(), 0, This);
1049 return ref;
1052 /************************************************************
1053 * get_current_ole_clip_window
1055 * Return the window that owns the ole clipboard.
1057 * If the clipboard is flushed or not owned by ole this will
1058 * return NULL.
1060 static HWND get_current_ole_clip_window(void)
1062 HGLOBAL h;
1063 HWND *ptr, wnd;
1065 h = GetClipboardData(dataobject_clipboard_format);
1066 if(!h) return NULL;
1067 ptr = GlobalLock(h);
1068 if(!ptr) return NULL;
1069 wnd = *ptr;
1070 GlobalUnlock(h);
1071 return wnd;
1074 /************************************************************
1075 * get_current_dataobject
1077 * Return an unmarshalled IDataObject if there is a current
1078 * (ie non-flushed) object on the ole clipboard.
1080 static HRESULT get_current_dataobject(IDataObject **data)
1082 HRESULT hr = S_FALSE;
1083 HWND wnd = get_current_ole_clip_window();
1084 HGLOBAL h;
1085 void *ptr;
1086 IStream *stm;
1087 LARGE_INTEGER pos;
1089 *data = NULL;
1090 if(!wnd) return S_FALSE;
1092 h = GetClipboardData(wine_marshal_clipboard_format);
1093 if(!h) return S_FALSE;
1094 if(GlobalSize(h) == 0) return S_FALSE;
1095 ptr = GlobalLock(h);
1096 if(!ptr) return S_FALSE;
1098 hr = CreateStreamOnHGlobal(NULL, TRUE, &stm);
1099 if(FAILED(hr)) goto end;
1101 hr = IStream_Write(stm, ptr, GlobalSize(h), NULL);
1102 if(SUCCEEDED(hr))
1104 pos.QuadPart = 0;
1105 IStream_Seek(stm, pos, STREAM_SEEK_SET, NULL);
1106 hr = CoUnmarshalInterface(stm, &IID_IDataObject, (void**)data);
1108 IStream_Release(stm);
1110 end:
1111 GlobalUnlock(h);
1112 return hr;
1115 static DWORD get_tymed_from_nonole_cf(UINT cf)
1117 if(cf >= 0xc000) return TYMED_ISTREAM | TYMED_HGLOBAL;
1119 switch(cf)
1121 case CF_TEXT:
1122 case CF_OEMTEXT:
1123 case CF_UNICODETEXT:
1124 return TYMED_ISTREAM | TYMED_HGLOBAL;
1125 case CF_ENHMETAFILE:
1126 return TYMED_ENHMF;
1127 case CF_METAFILEPICT:
1128 return TYMED_MFPICT;
1129 case CF_BITMAP:
1130 return TYMED_GDI;
1131 default:
1132 FIXME("returning TYMED_NULL for cf %04x\n", cf);
1133 return TYMED_NULL;
1137 /***********************************************************
1138 * get_priv_data
1140 * Returns a copy of the Ole Private Data
1142 static HRESULT get_priv_data(ole_priv_data **data)
1144 HGLOBAL handle;
1145 HRESULT hr = S_OK;
1146 ole_priv_data *ret = NULL;
1148 *data = NULL;
1150 handle = GetClipboardData( ole_private_data_clipboard_format );
1151 if(handle)
1153 ole_priv_data *src = GlobalLock(handle);
1154 if(src)
1156 DWORD i;
1158 /* FIXME: sanity check on size */
1159 ret = HeapAlloc(GetProcessHeap(), 0, src->size);
1160 if(!ret)
1162 GlobalUnlock(handle);
1163 return E_OUTOFMEMORY;
1165 memcpy(ret, src, src->size);
1166 GlobalUnlock(handle);
1168 /* Fixup any target device offsets to ptrs */
1169 for(i = 0; i < ret->count; i++)
1170 ret->entries[i].fmtetc.ptd =
1171 td_offs_to_ptr(ret, (DWORD_PTR) ret->entries[i].fmtetc.ptd);
1175 if(!ret) /* Non-ole data */
1177 UINT cf;
1178 DWORD count = 0, idx, size = FIELD_OFFSET(ole_priv_data, entries);
1180 for(cf = 0; (cf = EnumClipboardFormats(cf)) != 0; count++)
1182 char buf[100];
1183 GetClipboardFormatNameA(cf, buf, sizeof(buf));
1184 TRACE("cf %04x %s\n", cf, buf);
1186 TRACE("count %d\n", count);
1187 size += count * sizeof(ret->entries[0]);
1189 /* There are holes in fmtetc so zero init */
1190 ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
1191 if(!ret) return E_OUTOFMEMORY;
1192 ret->size = size;
1193 ret->count = count;
1195 for(cf = 0, idx = 0; (cf = EnumClipboardFormats(cf)) != 0; idx++)
1197 ret->entries[idx].fmtetc.cfFormat = cf;
1198 ret->entries[idx].fmtetc.ptd = NULL;
1199 ret->entries[idx].fmtetc.dwAspect = DVASPECT_CONTENT;
1200 ret->entries[idx].fmtetc.lindex = -1;
1201 ret->entries[idx].fmtetc.tymed = get_tymed_from_nonole_cf(cf);
1202 ret->entries[idx].first_use = 1;
1206 *data = ret;
1207 return hr;
1210 /************************************************************************
1211 * get_stgmed_for_global
1213 * Returns a stg medium with a copy of the global handle
1215 static HRESULT get_stgmed_for_global(HGLOBAL h, STGMEDIUM *med)
1217 HRESULT hr;
1219 med->pUnkForRelease = NULL;
1220 med->tymed = TYMED_NULL;
1222 hr = dup_global_mem(h, GMEM_MOVEABLE, &med->u.hGlobal);
1224 if(SUCCEEDED(hr)) med->tymed = TYMED_HGLOBAL;
1226 return hr;
1229 /************************************************************************
1230 * get_stgmed_for_stream
1232 * Returns a stg medium with a stream based on the handle
1234 static HRESULT get_stgmed_for_stream(HGLOBAL h, STGMEDIUM *med)
1236 HRESULT hr;
1237 HGLOBAL dst;
1239 med->pUnkForRelease = NULL;
1240 med->tymed = TYMED_NULL;
1242 hr = dup_global_mem(h, GMEM_MOVEABLE, &dst);
1243 if(FAILED(hr)) return hr;
1245 hr = CreateStreamOnHGlobal(dst, TRUE, &med->u.pstm);
1246 if(FAILED(hr))
1248 GlobalFree(dst);
1249 return hr;
1252 med->tymed = TYMED_ISTREAM;
1253 return hr;
1256 /************************************************************************
1257 * get_stgmed_for_storage
1259 * Returns a stg medium with a storage based on the handle
1261 static HRESULT get_stgmed_for_storage(HGLOBAL h, STGMEDIUM *med)
1263 HRESULT hr;
1264 HGLOBAL dst;
1265 ILockBytes *lbs;
1267 med->pUnkForRelease = NULL;
1268 med->tymed = TYMED_NULL;
1270 hr = dup_global_mem(h, GMEM_MOVEABLE, &dst);
1271 if(FAILED(hr)) return hr;
1273 hr = CreateILockBytesOnHGlobal(dst, TRUE, &lbs);
1274 if(FAILED(hr))
1276 GlobalFree(dst);
1277 return hr;
1280 hr = StgOpenStorageOnILockBytes(lbs, NULL, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, NULL, 0, &med->u.pstg);
1281 ILockBytes_Release(lbs);
1282 if(FAILED(hr))
1284 GlobalFree(dst);
1285 return hr;
1288 med->tymed = TYMED_ISTORAGE;
1289 return hr;
1292 /************************************************************************
1293 * get_stgmed_for_emf
1295 * Returns a stg medium with an enhanced metafile based on the handle
1297 static HRESULT get_stgmed_for_emf(HENHMETAFILE hemf, STGMEDIUM *med)
1299 med->pUnkForRelease = NULL;
1300 med->tymed = TYMED_NULL;
1302 med->u.hEnhMetaFile = CopyEnhMetaFileW(hemf, NULL);
1303 if(!med->u.hEnhMetaFile) return E_OUTOFMEMORY;
1304 med->tymed = TYMED_ENHMF;
1305 return S_OK;
1308 /************************************************************************
1309 * get_stgmed_for_bitmap
1311 * Returns a stg medium with a bitmap based on the handle
1313 static HRESULT get_stgmed_for_bitmap(HBITMAP hbmp, STGMEDIUM *med)
1315 HRESULT hr;
1317 med->pUnkForRelease = NULL;
1318 med->tymed = TYMED_NULL;
1320 hr = dup_bitmap(hbmp, &med->u.hBitmap);
1322 if (FAILED(hr))
1323 return hr;
1325 med->tymed = TYMED_GDI;
1326 return S_OK;
1329 static inline BOOL string_off_equal(const DVTARGETDEVICE *t1, WORD off1, const DVTARGETDEVICE *t2, WORD off2)
1331 const WCHAR *str1, *str2;
1333 if(off1 == 0 && off2 == 0) return TRUE;
1334 if(off1 == 0 || off2 == 0) return FALSE;
1336 str1 = (const WCHAR*)((const char*)t1 + off1);
1337 str2 = (const WCHAR*)((const char*)t2 + off2);
1339 return !lstrcmpW(str1, str2);
1342 static inline BOOL td_equal(const DVTARGETDEVICE *t1, const DVTARGETDEVICE *t2)
1344 if(t1 == NULL && t2 == NULL) return TRUE;
1345 if(t1 == NULL || t2 == NULL) return FALSE;
1347 if(!string_off_equal(t1, t1->tdDriverNameOffset, t2, t2->tdDriverNameOffset))
1348 return FALSE;
1349 if(!string_off_equal(t1, t1->tdDeviceNameOffset, t2, t2->tdDeviceNameOffset))
1350 return FALSE;
1351 if(!string_off_equal(t1, t1->tdPortNameOffset, t2, t2->tdPortNameOffset))
1352 return FALSE;
1354 /* FIXME check devmode? */
1356 return TRUE;
1359 /************************************************************************
1360 * snapshot_GetData
1362 static HRESULT WINAPI snapshot_GetData(IDataObject *iface, FORMATETC *fmt,
1363 STGMEDIUM *med)
1365 snapshot *This = impl_from_IDataObject(iface);
1366 HANDLE h;
1367 HRESULT hr;
1368 ole_priv_data *enum_data = NULL;
1369 ole_priv_data_entry *entry;
1370 DWORD mask;
1372 TRACE("(%p, %p {%s}, %p)\n", iface, fmt, dump_fmtetc(fmt), med);
1374 if ( !fmt || !med ) return E_INVALIDARG;
1376 if ( !OpenClipboard(NULL)) return CLIPBRD_E_CANT_OPEN;
1378 if(!This->data)
1379 hr = get_current_dataobject(&This->data);
1381 if(This->data)
1383 hr = IDataObject_GetData(This->data, fmt, med);
1384 CloseClipboard();
1385 return hr;
1388 h = GetClipboardData(fmt->cfFormat);
1389 if(!h)
1391 hr = DV_E_FORMATETC;
1392 goto end;
1395 hr = get_priv_data(&enum_data);
1396 if(FAILED(hr)) goto end;
1398 entry = find_format_in_list(enum_data->entries, enum_data->count, fmt->cfFormat);
1399 if(entry)
1401 if(!td_equal(fmt->ptd, entry->fmtetc.ptd))
1403 hr = DV_E_FORMATETC;
1404 goto end;
1406 mask = fmt->tymed & entry->fmtetc.tymed;
1407 if(!mask) mask = fmt->tymed & (TYMED_ISTREAM | TYMED_HGLOBAL);
1409 else /* non-Ole format */
1410 mask = fmt->tymed & TYMED_HGLOBAL;
1412 if(mask & TYMED_ISTORAGE)
1413 hr = get_stgmed_for_storage(h, med);
1414 else if(mask & TYMED_HGLOBAL)
1415 hr = get_stgmed_for_global(h, med);
1416 else if(mask & TYMED_ISTREAM)
1417 hr = get_stgmed_for_stream(h, med);
1418 else if(mask & TYMED_ENHMF)
1419 hr = get_stgmed_for_emf((HENHMETAFILE)h, med);
1420 else if(mask & TYMED_GDI)
1421 hr = get_stgmed_for_bitmap((HBITMAP)h, med);
1422 else
1424 FIXME("Unhandled tymed - mask %x req tymed %x\n", mask, fmt->tymed);
1425 hr = E_FAIL;
1426 goto end;
1429 end:
1430 HeapFree(GetProcessHeap(), 0, enum_data);
1431 if ( !CloseClipboard() ) hr = CLIPBRD_E_CANT_CLOSE;
1432 return hr;
1435 /************************************************************************
1436 * snapshot_GetDataHere
1438 static HRESULT WINAPI snapshot_GetDataHere(IDataObject *iface, FORMATETC *fmt,
1439 STGMEDIUM *med)
1441 snapshot *This = impl_from_IDataObject(iface);
1442 HANDLE h;
1443 HRESULT hr;
1444 ole_priv_data *enum_data = NULL;
1445 ole_priv_data_entry *entry;
1446 TYMED supported;
1448 if ( !fmt || !med ) return E_INVALIDARG;
1450 TRACE("(%p, %p {%s}, %p (tymed %x)\n", iface, fmt, dump_fmtetc(fmt), med, med->tymed);
1452 if ( !OpenClipboard(NULL)) return CLIPBRD_E_CANT_OPEN;
1454 if(!This->data)
1455 hr = get_current_dataobject(&This->data);
1457 if(This->data)
1459 hr = IDataObject_GetDataHere(This->data, fmt, med);
1460 if(SUCCEEDED(hr))
1462 CloseClipboard();
1463 return hr;
1467 h = GetClipboardData(fmt->cfFormat);
1468 if(!h)
1470 hr = DV_E_FORMATETC;
1471 goto end;
1474 hr = get_priv_data(&enum_data);
1475 if(FAILED(hr)) goto end;
1477 entry = find_format_in_list(enum_data->entries, enum_data->count, fmt->cfFormat);
1478 if(entry)
1480 if(!td_equal(fmt->ptd, entry->fmtetc.ptd))
1482 hr = DV_E_FORMATETC;
1483 goto end;
1485 supported = entry->fmtetc.tymed;
1487 else /* non-Ole format */
1488 supported = TYMED_HGLOBAL;
1490 switch(med->tymed)
1492 case TYMED_HGLOBAL:
1494 DWORD src_size = GlobalSize(h);
1495 DWORD dst_size = GlobalSize(med->u.hGlobal);
1496 hr = E_FAIL;
1497 if(dst_size >= src_size)
1499 void *src = GlobalLock(h);
1500 void *dst = GlobalLock(med->u.hGlobal);
1502 memcpy(dst, src, src_size);
1503 GlobalUnlock(med->u.hGlobal);
1504 GlobalUnlock(h);
1505 hr = S_OK;
1507 break;
1509 case TYMED_ISTREAM:
1511 DWORD src_size = GlobalSize(h);
1512 void *src = GlobalLock(h);
1513 hr = IStream_Write(med->u.pstm, src, src_size, NULL);
1514 GlobalUnlock(h);
1515 break;
1517 case TYMED_ISTORAGE:
1519 STGMEDIUM copy;
1520 if(!(supported & TYMED_ISTORAGE))
1522 hr = E_FAIL;
1523 goto end;
1525 hr = get_stgmed_for_storage(h, &copy);
1526 if(SUCCEEDED(hr))
1528 hr = IStorage_CopyTo(copy.u.pstg, 0, NULL, NULL, med->u.pstg);
1529 ReleaseStgMedium(&copy);
1531 break;
1533 default:
1534 FIXME("Unhandled tymed - supported %x req tymed %x\n", supported, med->tymed);
1535 hr = E_FAIL;
1536 goto end;
1539 end:
1540 HeapFree(GetProcessHeap(), 0, enum_data);
1541 if ( !CloseClipboard() ) hr = CLIPBRD_E_CANT_CLOSE;
1542 return hr;
1545 /************************************************************************
1546 * snapshot_QueryGetData
1548 * The OLE Clipboard's implementation of this method delegates to
1549 * a data source if there is one or wraps around the windows clipboard
1550 * function IsClipboardFormatAvailable() otherwise.
1553 static HRESULT WINAPI snapshot_QueryGetData(IDataObject *iface, FORMATETC *fmt)
1555 FIXME("(%p, %p {%s})\n", iface, fmt, dump_fmtetc(fmt));
1557 if (!fmt) return E_INVALIDARG;
1559 if ( fmt->dwAspect != DVASPECT_CONTENT ) return DV_E_FORMATETC;
1561 if ( fmt->lindex != -1 ) return DV_E_FORMATETC;
1563 return (IsClipboardFormatAvailable(fmt->cfFormat)) ? S_OK : DV_E_CLIPFORMAT;
1566 /************************************************************************
1567 * snapshot_GetCanonicalFormatEtc
1569 static HRESULT WINAPI snapshot_GetCanonicalFormatEtc(IDataObject *iface, FORMATETC *fmt_in,
1570 FORMATETC *fmt_out)
1572 TRACE("(%p, %p, %p)\n", iface, fmt_in, fmt_out);
1574 if ( !fmt_in || !fmt_out ) return E_INVALIDARG;
1576 *fmt_out = *fmt_in;
1577 return DATA_S_SAMEFORMATETC;
1580 /************************************************************************
1581 * snapshot_SetData
1583 * The OLE Clipboard does not implement this method
1585 static HRESULT WINAPI snapshot_SetData(IDataObject *iface, FORMATETC *fmt,
1586 STGMEDIUM *med, BOOL release)
1588 TRACE("(%p, %p, %p, %d): not implemented\n", iface, fmt, med, release);
1589 return E_NOTIMPL;
1592 /************************************************************************
1593 * snapshot_EnumFormatEtc
1596 static HRESULT WINAPI snapshot_EnumFormatEtc(IDataObject *iface, DWORD dir,
1597 IEnumFORMATETC **enum_fmt)
1599 HRESULT hr;
1600 ole_priv_data *data = NULL;
1602 TRACE("(%p, %x, %p)\n", iface, dir, enum_fmt);
1604 *enum_fmt = NULL;
1606 if ( dir != DATADIR_GET ) return E_NOTIMPL;
1607 if ( !OpenClipboard(NULL) ) return CLIPBRD_E_CANT_OPEN;
1609 hr = get_priv_data(&data);
1611 if(FAILED(hr)) goto end;
1613 hr = enum_fmtetc_construct( data, 0, enum_fmt );
1615 end:
1616 if ( !CloseClipboard() ) hr = CLIPBRD_E_CANT_CLOSE;
1617 return hr;
1620 /************************************************************************
1621 * snapshot_DAdvise
1623 * The OLE Clipboard does not implement this method
1625 static HRESULT WINAPI snapshot_DAdvise(IDataObject *iface, FORMATETC *fmt,
1626 DWORD flags, IAdviseSink *sink,
1627 DWORD *conn)
1629 TRACE("(%p, %p, %x, %p, %p): not implemented\n", iface, fmt, flags, sink, conn);
1630 return E_NOTIMPL;
1633 /************************************************************************
1634 * snapshot_DUnadvise
1636 * The OLE Clipboard does not implement this method
1638 static HRESULT WINAPI snapshot_DUnadvise(IDataObject* iface, DWORD conn)
1640 TRACE("(%p, %d): not implemented\n", iface, conn);
1641 return E_NOTIMPL;
1644 /************************************************************************
1645 * snapshot_EnumDAdvise
1647 * The OLE Clipboard does not implement this method
1649 static HRESULT WINAPI snapshot_EnumDAdvise(IDataObject* iface,
1650 IEnumSTATDATA** enum_advise)
1652 TRACE("(%p, %p): not implemented\n", iface, enum_advise);
1653 return E_NOTIMPL;
1656 static const IDataObjectVtbl snapshot_vtable =
1658 snapshot_QueryInterface,
1659 snapshot_AddRef,
1660 snapshot_Release,
1661 snapshot_GetData,
1662 snapshot_GetDataHere,
1663 snapshot_QueryGetData,
1664 snapshot_GetCanonicalFormatEtc,
1665 snapshot_SetData,
1666 snapshot_EnumFormatEtc,
1667 snapshot_DAdvise,
1668 snapshot_DUnadvise,
1669 snapshot_EnumDAdvise
1672 /*---------------------------------------------------------------------*
1673 * Internal implementation methods for the OLE clipboard
1674 *---------------------------------------------------------------------*/
1676 static snapshot *snapshot_construct(DWORD seq_no)
1678 snapshot *This;
1680 This = HeapAlloc( GetProcessHeap(), 0, sizeof(*This) );
1681 if (!This) return NULL;
1683 This->IDataObject_iface.lpVtbl = &snapshot_vtable;
1684 This->ref = 0;
1685 This->seq_no = seq_no;
1686 This->data = NULL;
1688 return This;
1691 /*********************************************************
1692 * register_clipboard_formats
1694 static void register_clipboard_formats(void)
1696 static const WCHAR OwnerLink[] = {'O','w','n','e','r','L','i','n','k',0};
1697 static const WCHAR FileName[] = {'F','i','l','e','N','a','m','e',0};
1698 static const WCHAR FileNameW[] = {'F','i','l','e','N','a','m','e','W',0};
1699 static const WCHAR DataObject[] = {'D','a','t','a','O','b','j','e','c','t',0};
1700 static const WCHAR EmbeddedObject[] = {'E','m','b','e','d','d','e','d',' ','O','b','j','e','c','t',0};
1701 static const WCHAR EmbedSource[] = {'E','m','b','e','d',' ','S','o','u','r','c','e',0};
1702 static const WCHAR CustomLinkSource[] = {'C','u','s','t','o','m',' ','L','i','n','k',' ','S','o','u','r','c','e',0};
1703 static const WCHAR LinkSource[] = {'L','i','n','k',' ','S','o','u','r','c','e',0};
1704 static const WCHAR ObjectDescriptor[] = {'O','b','j','e','c','t',' ','D','e','s','c','r','i','p','t','o','r',0};
1705 static const WCHAR LinkSourceDescriptor[] = {'L','i','n','k',' ','S','o','u','r','c','e',' ',
1706 'D','e','s','c','r','i','p','t','o','r',0};
1707 static const WCHAR OlePrivateData[] = {'O','l','e',' ','P','r','i','v','a','t','e',' ','D','a','t','a',0};
1709 static const WCHAR WineMarshalledDataObject[] = {'W','i','n','e',' ','M','a','r','s','h','a','l','l','e','d',' ',
1710 'D','a','t','a','O','b','j','e','c','t',0};
1712 ownerlink_clipboard_format = RegisterClipboardFormatW(OwnerLink);
1713 filename_clipboard_format = RegisterClipboardFormatW(FileName);
1714 filenameW_clipboard_format = RegisterClipboardFormatW(FileNameW);
1715 dataobject_clipboard_format = RegisterClipboardFormatW(DataObject);
1716 embedded_object_clipboard_format = RegisterClipboardFormatW(EmbeddedObject);
1717 embed_source_clipboard_format = RegisterClipboardFormatW(EmbedSource);
1718 custom_link_source_clipboard_format = RegisterClipboardFormatW(CustomLinkSource);
1719 link_source_clipboard_format = RegisterClipboardFormatW(LinkSource);
1720 object_descriptor_clipboard_format = RegisterClipboardFormatW(ObjectDescriptor);
1721 link_source_descriptor_clipboard_format = RegisterClipboardFormatW(LinkSourceDescriptor);
1722 ole_private_data_clipboard_format = RegisterClipboardFormatW(OlePrivateData);
1724 wine_marshal_clipboard_format = RegisterClipboardFormatW(WineMarshalledDataObject);
1727 /***********************************************************************
1728 * OLEClipbrd_Initialize()
1729 * Initializes the OLE clipboard.
1731 void OLEClipbrd_Initialize(void)
1733 register_clipboard_formats();
1735 if ( !theOleClipboard )
1737 ole_clipbrd* clipbrd;
1738 HGLOBAL h;
1740 TRACE("()\n");
1742 clipbrd = HeapAlloc( GetProcessHeap(), 0, sizeof(*clipbrd) );
1743 if (!clipbrd) return;
1745 clipbrd->latest_snapshot = NULL;
1746 clipbrd->window = NULL;
1747 clipbrd->src_data = NULL;
1748 clipbrd->cached_enum = NULL;
1750 h = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE, 0);
1751 if(!h)
1753 HeapFree(GetProcessHeap(), 0, clipbrd);
1754 return;
1757 if(FAILED(CreateStreamOnHGlobal(h, TRUE, &clipbrd->marshal_data)))
1759 GlobalFree(h);
1760 HeapFree(GetProcessHeap(), 0, clipbrd);
1761 return;
1764 theOleClipboard = clipbrd;
1768 /***********************************************************************
1769 * OLEClipbrd_UnInitialize()
1770 * Un-Initializes the OLE clipboard
1772 void OLEClipbrd_UnInitialize(void)
1774 ole_clipbrd *clipbrd = theOleClipboard;
1776 TRACE("()\n");
1778 if ( clipbrd )
1780 static const WCHAR ole32W[] = {'o','l','e','3','2',0};
1781 HINSTANCE hinst = GetModuleHandleW(ole32W);
1783 if ( clipbrd->window )
1785 DestroyWindow(clipbrd->window);
1786 UnregisterClassW( clipbrd_wndclass, hinst );
1789 IStream_Release(clipbrd->marshal_data);
1790 if (clipbrd->src_data) IDataObject_Release(clipbrd->src_data);
1791 HeapFree(GetProcessHeap(), 0, clipbrd->cached_enum);
1792 HeapFree(GetProcessHeap(), 0, clipbrd);
1793 theOleClipboard = NULL;
1797 /*********************************************************************
1798 * set_clipboard_formats
1800 * Enumerate all formats supported by the source and make
1801 * those formats available using delayed rendering using SetClipboardData.
1802 * Cache the enumeration list and make that list visibile as the
1803 * 'Ole Private Data' format on the clipboard.
1806 static HRESULT set_clipboard_formats(ole_clipbrd *clipbrd, IDataObject *data)
1808 HRESULT hr;
1809 FORMATETC fmt;
1810 IEnumFORMATETC *enum_fmt;
1811 HGLOBAL priv_data_handle;
1812 DWORD_PTR target_offset;
1813 ole_priv_data *priv_data;
1814 DWORD count = 0, needed = sizeof(*priv_data), idx;
1816 hr = IDataObject_EnumFormatEtc(data, DATADIR_GET, &enum_fmt);
1817 if(FAILED(hr)) return hr;
1819 while(IEnumFORMATETC_Next(enum_fmt, 1, &fmt, NULL) == S_OK)
1821 count++;
1822 needed += sizeof(priv_data->entries[0]);
1823 if(fmt.ptd)
1825 needed += fmt.ptd->tdSize;
1826 CoTaskMemFree(fmt.ptd);
1830 /* Windows pads the list with two empty ole_priv_data_entries, one
1831 * after the entries array and one after the target device data.
1832 * Allocating with zero init to zero these pads. */
1834 needed += sizeof(priv_data->entries[0]); /* initialisation of needed includes one of these. */
1835 priv_data_handle = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE | GMEM_ZEROINIT, needed);
1836 priv_data = GlobalLock(priv_data_handle);
1838 priv_data->unk1 = 0;
1839 priv_data->size = needed;
1840 priv_data->unk2 = 1;
1841 priv_data->count = count;
1842 priv_data->unk3[0] = 0;
1843 priv_data->unk3[1] = 0;
1845 IEnumFORMATETC_Reset(enum_fmt);
1847 idx = 0;
1848 target_offset = FIELD_OFFSET(ole_priv_data, entries[count + 1]); /* count entries + one pad. */
1850 while(IEnumFORMATETC_Next(enum_fmt, 1, &fmt, NULL) == S_OK)
1852 TRACE("%s\n", dump_fmtetc(&fmt));
1854 priv_data->entries[idx].fmtetc = fmt;
1855 if(fmt.ptd)
1857 memcpy((char*)priv_data + target_offset, fmt.ptd, fmt.ptd->tdSize);
1858 priv_data->entries[idx].fmtetc.ptd = (DVTARGETDEVICE*)target_offset;
1859 target_offset += fmt.ptd->tdSize;
1860 CoTaskMemFree(fmt.ptd);
1863 priv_data->entries[idx].first_use = !find_format_in_list(priv_data->entries, idx, fmt.cfFormat);
1864 priv_data->entries[idx].unk[0] = 0;
1865 priv_data->entries[idx].unk[1] = 0;
1867 if (priv_data->entries[idx].first_use)
1868 SetClipboardData(fmt.cfFormat, NULL);
1870 idx++;
1873 IEnumFORMATETC_Release(enum_fmt);
1875 /* Cache the list and fixup any target device offsets to ptrs */
1876 clipbrd->cached_enum = HeapAlloc(GetProcessHeap(), 0, needed);
1877 memcpy(clipbrd->cached_enum, priv_data, needed);
1878 for(idx = 0; idx < clipbrd->cached_enum->count; idx++)
1879 clipbrd->cached_enum->entries[idx].fmtetc.ptd =
1880 td_offs_to_ptr(clipbrd->cached_enum, (DWORD_PTR)clipbrd->cached_enum->entries[idx].fmtetc.ptd);
1882 GlobalUnlock(priv_data_handle);
1883 if(!SetClipboardData(ole_private_data_clipboard_format, priv_data_handle))
1885 GlobalFree(priv_data_handle);
1886 return CLIPBRD_E_CANT_SET;
1889 return S_OK;
1892 static HWND create_clipbrd_window(void);
1894 /***********************************************************************
1895 * get_clipbrd_window
1897 static inline HRESULT get_clipbrd_window(ole_clipbrd *clipbrd, HWND *wnd)
1899 if ( !clipbrd->window )
1900 clipbrd->window = create_clipbrd_window();
1902 *wnd = clipbrd->window;
1903 return *wnd ? S_OK : E_FAIL;
1907 /**********************************************************************
1908 * release_marshal_data
1910 * Releases the data and sets the stream back to zero size.
1912 static inline void release_marshal_data(IStream *stm)
1914 LARGE_INTEGER pos;
1915 ULARGE_INTEGER size;
1916 pos.QuadPart = size.QuadPart = 0;
1918 IStream_Seek(stm, pos, STREAM_SEEK_SET, NULL);
1919 CoReleaseMarshalData(stm);
1920 IStream_Seek(stm, pos, STREAM_SEEK_SET, NULL);
1921 IStream_SetSize(stm, size);
1924 /***********************************************************************
1925 * expose_marshalled_dataobject
1927 * Sets the marshalled dataobject to the clipboard. In the flushed case
1928 * we set a zero sized HGLOBAL to clear the old marshalled data.
1930 static HRESULT expose_marshalled_dataobject(ole_clipbrd *clipbrd, IDataObject *data)
1932 HGLOBAL h;
1934 if(data)
1936 HGLOBAL h_stm;
1937 GetHGlobalFromStream(clipbrd->marshal_data, &h_stm);
1938 dup_global_mem(h_stm, GMEM_DDESHARE|GMEM_MOVEABLE, &h);
1940 else /* flushed */
1941 h = GlobalAlloc(GMEM_DDESHARE|GMEM_MOVEABLE, 0);
1943 if(!h) return E_OUTOFMEMORY;
1945 if(!SetClipboardData(wine_marshal_clipboard_format, h))
1947 GlobalFree(h);
1948 return CLIPBRD_E_CANT_SET;
1950 return S_OK;
1953 /***********************************************************************
1954 * set_src_dataobject
1956 * Clears and sets the clipboard's src IDataObject.
1958 * To marshal the source dataobject we do something rather different from Windows.
1959 * We set a clipboard format which contains the marshalled data.
1960 * Windows sets two window props one of which is an IID, the other is an endpoint number.
1962 static HRESULT set_src_dataobject(ole_clipbrd *clipbrd, IDataObject *data)
1964 HRESULT hr;
1965 HWND wnd;
1967 if(FAILED(hr = get_clipbrd_window(clipbrd, &wnd))) return hr;
1969 if(clipbrd->src_data)
1971 release_marshal_data(clipbrd->marshal_data);
1973 IDataObject_Release(clipbrd->src_data);
1974 clipbrd->src_data = NULL;
1975 HeapFree(GetProcessHeap(), 0, clipbrd->cached_enum);
1976 clipbrd->cached_enum = NULL;
1979 if(data)
1981 IUnknown *unk;
1983 IDataObject_AddRef(data);
1984 clipbrd->src_data = data;
1986 IDataObject_QueryInterface(data, &IID_IUnknown, (void**)&unk);
1987 hr = CoMarshalInterface(clipbrd->marshal_data, &IID_IDataObject, unk,
1988 MSHCTX_LOCAL, NULL, MSHLFLAGS_TABLESTRONG);
1989 IUnknown_Release(unk); /* Don't hold a ref on IUnknown, we have one on IDataObject. */
1990 if(FAILED(hr)) return hr;
1991 hr = set_clipboard_formats(clipbrd, data);
1993 return hr;
1996 /***********************************************************************
1997 * clipbrd_wndproc
1999 static LRESULT CALLBACK clipbrd_wndproc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
2001 ole_clipbrd *clipbrd;
2003 get_ole_clipbrd(&clipbrd);
2005 switch (message)
2007 case WM_RENDERFORMAT:
2009 UINT cf = wparam;
2010 ole_priv_data_entry *entry;
2012 TRACE("(): WM_RENDERFORMAT(cfFormat=%x)\n", cf);
2013 entry = find_format_in_list(clipbrd->cached_enum->entries, clipbrd->cached_enum->count, cf);
2015 if(entry)
2016 render_format(clipbrd->src_data, &entry->fmtetc);
2018 break;
2021 case WM_RENDERALLFORMATS:
2023 DWORD i;
2024 ole_priv_data_entry *entries = clipbrd->cached_enum->entries;
2026 TRACE("(): WM_RENDERALLFORMATS\n");
2028 for(i = 0; i < clipbrd->cached_enum->count; i++)
2030 if(entries[i].first_use)
2031 render_format(clipbrd->src_data, &entries[i].fmtetc);
2033 break;
2036 case WM_DESTROYCLIPBOARD:
2038 TRACE("(): WM_DESTROYCLIPBOARD\n");
2040 set_src_dataobject(clipbrd, NULL);
2041 break;
2044 default:
2045 return DefWindowProcW(hwnd, message, wparam, lparam);
2048 return 0;
2052 /***********************************************************************
2053 * create_clipbrd_window
2055 static HWND create_clipbrd_window(void)
2057 WNDCLASSEXW class;
2058 static const WCHAR ole32W[] = {'o','l','e','3','2',0};
2059 static const WCHAR title[] = {'C','l','i','p','b','o','a','r','d','W','i','n','d','o','w',0};
2060 HINSTANCE hinst = GetModuleHandleW(ole32W);
2062 class.cbSize = sizeof(class);
2063 class.style = 0;
2064 class.lpfnWndProc = clipbrd_wndproc;
2065 class.cbClsExtra = 0;
2066 class.cbWndExtra = 0;
2067 class.hInstance = hinst;
2068 class.hIcon = 0;
2069 class.hCursor = 0;
2070 class.hbrBackground = 0;
2071 class.lpszMenuName = NULL;
2072 class.lpszClassName = clipbrd_wndclass;
2073 class.hIconSm = NULL;
2075 RegisterClassExW(&class);
2077 return CreateWindowW(clipbrd_wndclass, title, WS_POPUP | WS_CLIPSIBLINGS | WS_OVERLAPPED,
2078 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
2079 NULL, NULL, hinst, 0);
2082 /*********************************************************************
2083 * set_dataobject_format
2085 * Windows creates a 'DataObject' clipboard format that contains the
2086 * clipboard window's HWND or NULL if the Ole clipboard has been flushed.
2088 static HRESULT set_dataobject_format(HWND hwnd)
2090 HGLOBAL h = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE, sizeof(hwnd));
2091 HWND *data;
2093 if(!h) return E_OUTOFMEMORY;
2095 data = GlobalLock(h);
2096 *data = hwnd;
2097 GlobalUnlock(h);
2099 if(!SetClipboardData(dataobject_clipboard_format, h))
2101 GlobalFree(h);
2102 return CLIPBRD_E_CANT_SET;
2105 return S_OK;
2108 /*---------------------------------------------------------------------*
2109 * Win32 OLE clipboard API
2110 *---------------------------------------------------------------------*/
2112 /***********************************************************************
2113 * OleSetClipboard [OLE32.@]
2114 * Places a pointer to the specified data object onto the clipboard,
2115 * making the data object accessible to the OleGetClipboard function.
2117 * RETURNS
2119 * S_OK IDataObject pointer placed on the clipboard
2120 * CLIPBRD_E_CANT_OPEN OpenClipboard failed
2121 * CLIPBRD_E_CANT_EMPTY EmptyClipboard failed
2122 * CLIPBRD_E_CANT_CLOSE CloseClipboard failed
2123 * CLIPBRD_E_CANT_SET SetClipboard failed
2126 HRESULT WINAPI OleSetClipboard(IDataObject* data)
2128 HRESULT hr;
2129 ole_clipbrd *clipbrd;
2130 HWND wnd;
2132 TRACE("(%p)\n", data);
2134 if(FAILED(hr = get_ole_clipbrd(&clipbrd))) return hr;
2136 if(FAILED(hr = get_clipbrd_window(clipbrd, &wnd))) return hr;
2138 if ( !OpenClipboard(wnd) ) return CLIPBRD_E_CANT_OPEN;
2140 if ( !EmptyClipboard() )
2142 hr = CLIPBRD_E_CANT_EMPTY;
2143 goto end;
2146 hr = set_src_dataobject(clipbrd, data);
2147 if(FAILED(hr)) goto end;
2149 if(data)
2151 hr = expose_marshalled_dataobject(clipbrd, data);
2152 if(FAILED(hr)) goto end;
2153 hr = set_dataobject_format(wnd);
2156 end:
2158 if ( !CloseClipboard() ) hr = CLIPBRD_E_CANT_CLOSE;
2160 if ( FAILED(hr) )
2162 expose_marshalled_dataobject(clipbrd, NULL);
2163 set_src_dataobject(clipbrd, NULL);
2166 return hr;
2170 /***********************************************************************
2171 * OleGetClipboard [OLE32.@]
2172 * Returns a pointer to our internal IDataObject which represents the conceptual
2173 * state of the Windows clipboard. If the current clipboard already contains
2174 * an IDataObject, our internal IDataObject will delegate to this object.
2176 HRESULT WINAPI OleGetClipboard(IDataObject **obj)
2178 HRESULT hr;
2179 ole_clipbrd *clipbrd;
2180 DWORD seq_no;
2182 TRACE("(%p)\n", obj);
2184 if(!obj) return E_INVALIDARG;
2186 if(FAILED(hr = get_ole_clipbrd(&clipbrd))) return hr;
2188 seq_no = GetClipboardSequenceNumber();
2189 if(clipbrd->latest_snapshot && clipbrd->latest_snapshot->seq_no != seq_no)
2190 clipbrd->latest_snapshot = NULL;
2192 if(!clipbrd->latest_snapshot)
2194 clipbrd->latest_snapshot = snapshot_construct(seq_no);
2195 if(!clipbrd->latest_snapshot) return E_OUTOFMEMORY;
2198 *obj = &clipbrd->latest_snapshot->IDataObject_iface;
2199 IDataObject_AddRef(*obj);
2201 return S_OK;
2204 /******************************************************************************
2205 * OleFlushClipboard [OLE32.@]
2206 * Renders the data from the source IDataObject into the windows clipboard
2208 * TODO: OleFlushClipboard needs to additionally handle TYMED_IStorage media
2209 * by copying the storage into global memory. Subsequently the default
2210 * data object exposed through OleGetClipboard must convert this TYMED_HGLOBAL
2211 * back to TYMED_IStorage.
2213 HRESULT WINAPI OleFlushClipboard(void)
2215 HRESULT hr;
2216 ole_clipbrd *clipbrd;
2217 HWND wnd;
2219 TRACE("()\n");
2221 if(FAILED(hr = get_ole_clipbrd(&clipbrd))) return hr;
2223 if(FAILED(hr = get_clipbrd_window(clipbrd, &wnd))) return hr;
2226 * Already flushed or no source DataObject? Nothing to do.
2228 if (!clipbrd->src_data) return S_OK;
2230 if (!OpenClipboard(wnd)) return CLIPBRD_E_CANT_OPEN;
2232 SendMessageW(wnd, WM_RENDERALLFORMATS, 0, 0);
2234 hr = set_dataobject_format(NULL);
2236 expose_marshalled_dataobject(clipbrd, NULL);
2237 set_src_dataobject(clipbrd, NULL);
2239 if ( !CloseClipboard() ) hr = CLIPBRD_E_CANT_CLOSE;
2241 return hr;
2245 /***********************************************************************
2246 * OleIsCurrentClipboard [OLE32.@]
2248 HRESULT WINAPI OleIsCurrentClipboard(IDataObject *data)
2250 HRESULT hr;
2251 ole_clipbrd *clipbrd;
2252 TRACE("()\n");
2254 if(FAILED(hr = get_ole_clipbrd(&clipbrd))) return hr;
2256 if (data == NULL) return S_FALSE;
2258 return (data == clipbrd->src_data) ? S_OK : S_FALSE;