x3daudio1_5: Add stub dll.
[wine.git] / dlls / ole32 / clipboard.c
blobd40ee59f910da64fd1beebee2307eda36927fc13
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 /* Structure of 'Ole Private Data' clipboard format */
87 typedef struct
89 FORMATETC fmtetc;
90 DWORD first_use; /* Has this cf been added to the list already */
91 DWORD unk[2];
92 } ole_priv_data_entry;
94 typedef struct
96 DWORD unk1;
97 DWORD size; /* in bytes of the entire structure */
98 DWORD unk2;
99 DWORD count; /* no. of format entries */
100 DWORD unk3[2];
101 ole_priv_data_entry entries[1]; /* array of size count */
102 /* then follows any DVTARGETDEVICE structures referenced in the FORMATETCs */
103 } ole_priv_data;
105 /*****************************************************************************
106 * td_offs_to_ptr
108 * Returns a ptr to a target device at a given offset from the
109 * start of the ole_priv_data.
111 * Used when unpacking ole private data from the clipboard.
113 static inline DVTARGETDEVICE *td_offs_to_ptr(ole_priv_data *data, DWORD_PTR off)
115 if(off == 0) return NULL;
116 return (DVTARGETDEVICE*)((char*)data + off);
119 /*****************************************************************************
120 * td_get_offs
122 * Get the offset from the start of the ole_priv_data of the idx'th
123 * target device.
125 * Used when packing ole private data to the clipboard.
127 static inline DWORD_PTR td_get_offs(ole_priv_data *data, DWORD idx)
129 if(data->entries[idx].fmtetc.ptd == NULL) return 0;
130 return (char*)data->entries[idx].fmtetc.ptd - (char*)data;
133 /****************************************************************************
134 * Consumer snapshot. Represents the state of the ole clipboard
135 * returned by OleGetClipboard().
137 typedef struct snapshot
139 IDataObject IDataObject_iface;
140 LONG ref;
142 DWORD seq_no; /* Clipboard sequence number corresponding to this snapshot */
144 IDataObject *data; /* If we unmarshal a remote data object we hold a ref here */
145 } snapshot;
147 /****************************************************************************
148 * ole_clipbrd
150 typedef struct ole_clipbrd
152 snapshot *latest_snapshot; /* Latest consumer snapshot */
154 HWND window; /* Hidden clipboard window */
155 IDataObject *src_data; /* Source object passed to OleSetClipboard */
156 ole_priv_data *cached_enum; /* Cached result from the enumeration of src data object */
157 IStream *marshal_data; /* Stream onto which to marshal src_data */
158 } ole_clipbrd;
160 static inline snapshot *impl_from_IDataObject(IDataObject *iface)
162 return CONTAINING_RECORD(iface, snapshot, IDataObject_iface);
165 typedef struct PresentationDataHeader
167 BYTE unknown1[28];
168 DWORD dwObjectExtentX;
169 DWORD dwObjectExtentY;
170 DWORD dwSize;
171 } PresentationDataHeader;
174 * The one and only ole_clipbrd object which is created by OLEClipbrd_Initialize()
176 static ole_clipbrd* theOleClipboard;
178 static inline HRESULT get_ole_clipbrd(ole_clipbrd **clipbrd)
180 struct oletls *info = COM_CurrentInfo();
181 *clipbrd = NULL;
183 if(!info->ole_inits)
184 return CO_E_NOTINITIALIZED;
185 *clipbrd = theOleClipboard;
187 return S_OK;
191 * Name of our registered OLE clipboard window class
193 static const WCHAR clipbrd_wndclass[] = {'C','L','I','P','B','R','D','W','N','D','C','L','A','S','S',0};
195 UINT ownerlink_clipboard_format = 0;
196 UINT filename_clipboard_format = 0;
197 UINT filenameW_clipboard_format = 0;
198 UINT dataobject_clipboard_format = 0;
199 UINT embedded_object_clipboard_format = 0;
200 UINT embed_source_clipboard_format = 0;
201 UINT custom_link_source_clipboard_format = 0;
202 UINT link_source_clipboard_format = 0;
203 UINT object_descriptor_clipboard_format = 0;
204 UINT link_source_descriptor_clipboard_format = 0;
205 UINT ole_private_data_clipboard_format = 0;
207 static UINT wine_marshal_clipboard_format;
209 static inline const char *dump_fmtetc(FORMATETC *fmt)
211 if (!fmt) return "(null)";
212 return wine_dbg_sprintf("cf %04x ptd %p aspect %x lindex %d tymed %x",
213 fmt->cfFormat, fmt->ptd, fmt->dwAspect, fmt->lindex, fmt->tymed);
216 /*---------------------------------------------------------------------*
217 * Implementation of the internal IEnumFORMATETC interface returned by
218 * the OLE clipboard's IDataObject.
219 *---------------------------------------------------------------------*/
221 typedef struct enum_fmtetc
223 IEnumFORMATETC IEnumFORMATETC_iface;
224 LONG ref;
226 UINT pos; /* current enumerator position */
227 ole_priv_data *data;
228 } enum_fmtetc;
230 static inline enum_fmtetc *impl_from_IEnumFORMATETC(IEnumFORMATETC *iface)
232 return CONTAINING_RECORD(iface, enum_fmtetc, IEnumFORMATETC_iface);
235 /************************************************************************
236 * OLEClipbrd_IEnumFORMATETC_QueryInterface (IUnknown)
238 * See Windows documentation for more details on IUnknown methods.
240 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_QueryInterface
241 (LPENUMFORMATETC iface, REFIID riid, LPVOID* ppvObj)
243 enum_fmtetc *This = impl_from_IEnumFORMATETC(iface);
245 TRACE("(%p)->(IID: %s, %p)\n", This, debugstr_guid(riid), ppvObj);
247 *ppvObj = NULL;
249 if(IsEqualIID(riid, &IID_IUnknown) ||
250 IsEqualIID(riid, &IID_IEnumFORMATETC))
252 *ppvObj = iface;
255 if(*ppvObj)
257 IEnumFORMATETC_AddRef((IEnumFORMATETC*)*ppvObj);
258 TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
259 return S_OK;
262 TRACE("-- Interface: E_NOINTERFACE\n");
263 return E_NOINTERFACE;
266 /************************************************************************
267 * OLEClipbrd_IEnumFORMATETC_AddRef (IUnknown)
270 static ULONG WINAPI OLEClipbrd_IEnumFORMATETC_AddRef(LPENUMFORMATETC iface)
272 enum_fmtetc *This = impl_from_IEnumFORMATETC(iface);
273 TRACE("(%p)->(count=%u)\n",This, This->ref);
275 return InterlockedIncrement(&This->ref);
278 /************************************************************************
279 * OLEClipbrd_IEnumFORMATETC_Release (IUnknown)
281 * See Windows documentation for more details on IUnknown methods.
283 static ULONG WINAPI OLEClipbrd_IEnumFORMATETC_Release(LPENUMFORMATETC iface)
285 enum_fmtetc *This = impl_from_IEnumFORMATETC(iface);
286 ULONG ref;
288 TRACE("(%p)->(count=%u)\n",This, This->ref);
290 ref = InterlockedDecrement(&This->ref);
291 if (!ref)
293 TRACE("() - destroying IEnumFORMATETC(%p)\n",This);
294 HeapFree(GetProcessHeap(), 0, This->data);
295 HeapFree(GetProcessHeap(), 0, This);
297 return ref;
300 /************************************************************************
301 * OLEClipbrd_IEnumFORMATETC_Next (IEnumFORMATETC)
303 * Standard enumerator members for IEnumFORMATETC
305 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Next
306 (LPENUMFORMATETC iface, ULONG celt, FORMATETC *rgelt, ULONG *pceltFethed)
308 enum_fmtetc *This = impl_from_IEnumFORMATETC(iface);
309 UINT cfetch, i;
310 HRESULT hres = S_FALSE;
312 TRACE("(%p)->(pos=%u)\n", This, This->pos);
314 if (This->pos < This->data->count)
316 cfetch = This->data->count - This->pos;
317 if (cfetch >= celt)
319 cfetch = celt;
320 hres = S_OK;
323 for(i = 0; i < cfetch; i++)
325 rgelt[i] = This->data->entries[This->pos++].fmtetc;
326 if(rgelt[i].ptd)
328 DVTARGETDEVICE *target = rgelt[i].ptd;
329 rgelt[i].ptd = CoTaskMemAlloc(target->tdSize);
330 if(!rgelt[i].ptd) return E_OUTOFMEMORY;
331 memcpy(rgelt[i].ptd, target, target->tdSize);
335 else
337 cfetch = 0;
340 if (pceltFethed)
342 *pceltFethed = cfetch;
345 return hres;
348 /************************************************************************
349 * OLEClipbrd_IEnumFORMATETC_Skip (IEnumFORMATETC)
351 * Standard enumerator members for IEnumFORMATETC
353 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Skip(LPENUMFORMATETC iface, ULONG celt)
355 enum_fmtetc *This = impl_from_IEnumFORMATETC(iface);
356 TRACE("(%p)->(num=%u)\n", This, celt);
358 This->pos += celt;
359 if (This->pos > This->data->count)
361 This->pos = This->data->count;
362 return S_FALSE;
364 return S_OK;
367 /************************************************************************
368 * OLEClipbrd_IEnumFORMATETC_Reset (IEnumFORMATETC)
370 * Standard enumerator members for IEnumFORMATETC
372 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Reset(LPENUMFORMATETC iface)
374 enum_fmtetc *This = impl_from_IEnumFORMATETC(iface);
375 TRACE("(%p)->()\n", This);
377 This->pos = 0;
378 return S_OK;
381 static HRESULT enum_fmtetc_construct(ole_priv_data *data, UINT pos, IEnumFORMATETC **obj);
383 /************************************************************************
384 * OLEClipbrd_IEnumFORMATETC_Clone (IEnumFORMATETC)
386 * Standard enumerator members for IEnumFORMATETC
388 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Clone
389 (LPENUMFORMATETC iface, LPENUMFORMATETC* obj)
391 enum_fmtetc *This = impl_from_IEnumFORMATETC(iface);
392 ole_priv_data *new_data;
393 DWORD i;
395 TRACE("(%p)->(%p)\n", This, obj);
397 if ( !obj ) return E_INVALIDARG;
398 *obj = NULL;
400 new_data = HeapAlloc(GetProcessHeap(), 0, This->data->size);
401 if(!new_data) return E_OUTOFMEMORY;
402 memcpy(new_data, This->data, This->data->size);
404 /* Fixup any target device ptrs */
405 for(i = 0; i < This->data->count; i++)
406 new_data->entries[i].fmtetc.ptd =
407 td_offs_to_ptr(new_data, td_get_offs(This->data, i));
409 return enum_fmtetc_construct(new_data, This->pos, obj);
412 static const IEnumFORMATETCVtbl efvt =
414 OLEClipbrd_IEnumFORMATETC_QueryInterface,
415 OLEClipbrd_IEnumFORMATETC_AddRef,
416 OLEClipbrd_IEnumFORMATETC_Release,
417 OLEClipbrd_IEnumFORMATETC_Next,
418 OLEClipbrd_IEnumFORMATETC_Skip,
419 OLEClipbrd_IEnumFORMATETC_Reset,
420 OLEClipbrd_IEnumFORMATETC_Clone
423 /************************************************************************
424 * enum_fmtetc_construct
426 * Creates an IEnumFORMATETC enumerator from ole_priv_data which it then owns.
428 static HRESULT enum_fmtetc_construct(ole_priv_data *data, UINT pos, IEnumFORMATETC **obj)
430 enum_fmtetc* ef;
432 *obj = NULL;
433 ef = HeapAlloc(GetProcessHeap(), 0, sizeof(*ef));
434 if (!ef) return E_OUTOFMEMORY;
436 ef->ref = 1;
437 ef->IEnumFORMATETC_iface.lpVtbl = &efvt;
438 ef->data = data;
439 ef->pos = pos;
441 TRACE("(%p)->()\n", ef);
442 *obj = &ef->IEnumFORMATETC_iface;
443 return S_OK;
446 /***********************************************************************
447 * dup_global_mem
449 * Helper method to duplicate an HGLOBAL chunk of memory
451 static HRESULT dup_global_mem( HGLOBAL src, DWORD flags, HGLOBAL *dst )
453 void *src_ptr, *dst_ptr;
454 DWORD size;
456 *dst = NULL;
457 if ( !src ) return S_FALSE;
459 size = GlobalSize(src);
461 *dst = GlobalAlloc( flags, size );
462 if ( !*dst ) return E_OUTOFMEMORY;
464 src_ptr = GlobalLock(src);
465 dst_ptr = GlobalLock(*dst);
467 memcpy(dst_ptr, src_ptr, size);
469 GlobalUnlock(*dst);
470 GlobalUnlock(src);
472 return S_OK;
475 /***********************************************************************
476 * dup_metafilepict
478 * Helper function to duplicate a handle to a METAFILEPICT, and the
479 * contained HMETAFILE.
481 static HRESULT dup_metafilepict(HGLOBAL src, HGLOBAL *pdest)
483 HRESULT hr;
484 HGLOBAL dest;
485 METAFILEPICT *dest_ptr;
487 *pdest = NULL;
489 /* Copy the METAFILEPICT structure. */
490 hr = dup_global_mem(src, GMEM_DDESHARE|GMEM_MOVEABLE, &dest);
491 if (FAILED(hr)) return hr;
493 dest_ptr = GlobalLock(dest);
494 if (!dest_ptr) return E_FAIL;
496 /* Give the new METAFILEPICT a separate HMETAFILE. */
497 dest_ptr->hMF = CopyMetaFileW(dest_ptr->hMF, NULL);
498 if (dest_ptr->hMF)
500 GlobalUnlock(dest);
501 *pdest = dest;
502 return S_OK;
504 else
506 GlobalUnlock(dest);
507 GlobalFree(dest);
508 return E_FAIL;
512 /***********************************************************************
513 * free_metafilepict
515 * Helper function to GlobalFree a handle to a METAFILEPICT, and also
516 * free the contained HMETAFILE.
518 static void free_metafilepict(HGLOBAL src)
520 METAFILEPICT *src_ptr;
522 src_ptr = GlobalLock(src);
523 if (src_ptr)
525 DeleteMetaFile(src_ptr->hMF);
526 GlobalUnlock(src);
528 GlobalFree(src);
531 /***********************************************************************
532 * dup_bitmap
534 * Helper function to duplicate an HBITMAP.
536 static HRESULT dup_bitmap(HBITMAP src, HBITMAP *pdest)
538 HDC src_dc;
539 HGDIOBJ orig_src_bitmap;
540 BITMAP bm;
541 HBITMAP dest;
543 src_dc = CreateCompatibleDC(NULL);
544 orig_src_bitmap = SelectObject(src_dc, src);
545 GetObjectW(src, sizeof bm, &bm);
546 dest = CreateCompatibleBitmap(src_dc, bm.bmWidth, bm.bmHeight);
547 if (dest)
549 HDC dest_dc = CreateCompatibleDC(NULL);
550 HGDIOBJ orig_dest_bitmap = SelectObject(dest_dc, dest);
551 BitBlt(dest_dc, 0, 0, bm.bmWidth, bm.bmHeight, src_dc, 0, 0, SRCCOPY);
552 SelectObject(dest_dc, orig_dest_bitmap);
553 DeleteDC(dest_dc);
555 SelectObject(src_dc, orig_src_bitmap);
556 DeleteDC(src_dc);
557 *pdest = dest;
558 return dest ? S_OK : E_FAIL;
561 /************************************************************
562 * render_embed_source_hack
564 * This is clearly a hack and has no place in the clipboard code.
567 static HRESULT render_embed_source_hack(IDataObject *data, LPFORMATETC fmt)
569 STGMEDIUM std;
570 HGLOBAL hStorage = 0;
571 HRESULT hr = S_OK;
572 ILockBytes *ptrILockBytes;
574 memset(&std, 0, sizeof(STGMEDIUM));
575 std.tymed = fmt->tymed = TYMED_ISTORAGE;
577 hStorage = GlobalAlloc(GMEM_SHARE|GMEM_MOVEABLE, 0);
578 if (hStorage == NULL) return E_OUTOFMEMORY;
579 hr = CreateILockBytesOnHGlobal(hStorage, FALSE, &ptrILockBytes);
580 hr = StgCreateDocfileOnILockBytes(ptrILockBytes, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &std.u.pstg);
581 ILockBytes_Release(ptrILockBytes);
583 if (FAILED(hr = IDataObject_GetDataHere(theOleClipboard->src_data, fmt, &std)))
585 WARN("() : IDataObject_GetDataHere failed to render clipboard data! (%x)\n", hr);
586 GlobalFree(hStorage);
587 return hr;
590 if (1) /* check whether the presentation data is already -not- present */
592 FORMATETC fmt2;
593 STGMEDIUM std2;
594 METAFILEPICT *mfp = 0;
596 fmt2.cfFormat = CF_METAFILEPICT;
597 fmt2.ptd = 0;
598 fmt2.dwAspect = DVASPECT_CONTENT;
599 fmt2.lindex = -1;
600 fmt2.tymed = TYMED_MFPICT;
602 memset(&std2, 0, sizeof(STGMEDIUM));
603 std2.tymed = TYMED_MFPICT;
605 /* Get the metafile picture out of it */
607 if (SUCCEEDED(hr = IDataObject_GetData(theOleClipboard->src_data, &fmt2, &std2)))
609 mfp = GlobalLock(std2.u.hGlobal);
612 if (mfp)
614 OLECHAR name[]={ 2, 'O', 'l', 'e', 'P', 'r', 'e', 's', '0', '0', '0', 0};
615 IStream *pStream = 0;
616 void *mfBits;
617 PresentationDataHeader pdh;
618 INT nSize;
619 CLSID clsID;
620 LPOLESTR strProgID;
621 CHAR strOleTypeName[51];
622 BYTE OlePresStreamHeader [] =
624 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00,
625 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
626 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
627 0x00, 0x00, 0x00, 0x00
630 nSize = GetMetaFileBitsEx(mfp->hMF, 0, NULL);
632 memset(&pdh, 0, sizeof(PresentationDataHeader));
633 memcpy(&pdh, OlePresStreamHeader, sizeof(OlePresStreamHeader));
635 pdh.dwObjectExtentX = mfp->xExt;
636 pdh.dwObjectExtentY = mfp->yExt;
637 pdh.dwSize = nSize;
639 hr = IStorage_CreateStream(std.u.pstg, name, STGM_CREATE|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, 0, &pStream);
641 hr = IStream_Write(pStream, &pdh, sizeof(PresentationDataHeader), NULL);
643 mfBits = HeapAlloc(GetProcessHeap(), 0, nSize);
644 nSize = GetMetaFileBitsEx(mfp->hMF, nSize, mfBits);
646 hr = IStream_Write(pStream, mfBits, nSize, NULL);
648 IStream_Release(pStream);
650 HeapFree(GetProcessHeap(), 0, mfBits);
652 GlobalUnlock(std2.u.hGlobal);
653 ReleaseStgMedium(&std2);
655 ReadClassStg(std.u.pstg, &clsID);
656 ProgIDFromCLSID(&clsID, &strProgID);
658 WideCharToMultiByte( CP_ACP, 0, strProgID, -1, strOleTypeName, sizeof(strOleTypeName), NULL, NULL );
659 STORAGE_CreateOleStream(std.u.pstg, 0);
660 OLECONVERT_CreateCompObjStream(std.u.pstg, strOleTypeName);
661 CoTaskMemFree(strProgID);
665 if ( !SetClipboardData( fmt->cfFormat, hStorage ) )
667 WARN("() : Failed to set rendered clipboard data into clipboard!\n");
668 GlobalFree(hStorage);
669 hr = CLIPBRD_E_CANT_SET;
672 ReleaseStgMedium(&std);
673 return hr;
676 /************************************************************************
677 * find_format_in_list
679 * Returns the first entry that matches the provided clipboard format.
681 static inline ole_priv_data_entry *find_format_in_list(ole_priv_data_entry *entries, DWORD num, UINT cf)
683 DWORD i;
684 for(i = 0; i < num; i++)
685 if(entries[i].fmtetc.cfFormat == cf)
686 return &entries[i];
688 return NULL;
691 /***************************************************************************
692 * get_data_from_storage
694 * Returns storage data in an HGLOBAL.
696 static HRESULT get_data_from_storage(IDataObject *data, FORMATETC *fmt, HGLOBAL *mem)
698 HGLOBAL h;
699 IStorage *stg;
700 HRESULT hr;
701 FORMATETC stg_fmt;
702 STGMEDIUM med;
703 ILockBytes *lbs;
705 *mem = NULL;
707 h = GlobalAlloc( GMEM_DDESHARE|GMEM_MOVEABLE, 0 );
708 if(!h) return E_OUTOFMEMORY;
710 hr = CreateILockBytesOnHGlobal(h, FALSE, &lbs);
711 if(SUCCEEDED(hr))
713 hr = StgCreateDocfileOnILockBytes(lbs, STGM_CREATE|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &stg);
714 ILockBytes_Release(lbs);
716 if(FAILED(hr))
718 GlobalFree(h);
719 return hr;
722 stg_fmt = *fmt;
723 med.tymed = stg_fmt.tymed = TYMED_ISTORAGE;
724 med.u.pstg = stg;
725 med.pUnkForRelease = NULL;
727 hr = IDataObject_GetDataHere(data, &stg_fmt, &med);
728 if(FAILED(hr))
730 med.u.pstg = NULL;
731 hr = IDataObject_GetData(data, &stg_fmt, &med);
732 if(FAILED(hr)) goto end;
734 hr = IStorage_CopyTo(med.u.pstg, 0, NULL, NULL, stg);
735 ReleaseStgMedium(&med);
736 if(FAILED(hr)) goto end;
738 *mem = h;
740 end:
741 IStorage_Release(stg);
742 if(FAILED(hr)) GlobalFree(h);
743 return hr;
746 /***************************************************************************
747 * get_data_from_stream
749 * Returns stream data in an HGLOBAL.
751 static HRESULT get_data_from_stream(IDataObject *data, FORMATETC *fmt, HGLOBAL *mem)
753 HGLOBAL h;
754 IStream *stm = NULL;
755 HRESULT hr;
756 FORMATETC stm_fmt;
757 STGMEDIUM med;
759 *mem = NULL;
761 h = GlobalAlloc( GMEM_DDESHARE|GMEM_MOVEABLE, 0 );
762 if(!h) return E_OUTOFMEMORY;
764 hr = CreateStreamOnHGlobal(h, FALSE, &stm);
765 if(FAILED(hr)) goto error;
767 stm_fmt = *fmt;
768 med.tymed = stm_fmt.tymed = TYMED_ISTREAM;
769 med.u.pstm = stm;
770 med.pUnkForRelease = NULL;
772 hr = IDataObject_GetDataHere(data, &stm_fmt, &med);
773 if(FAILED(hr))
775 LARGE_INTEGER offs;
776 ULARGE_INTEGER pos;
778 med.u.pstm = NULL;
779 hr = IDataObject_GetData(data, &stm_fmt, &med);
780 if(FAILED(hr)) goto error;
782 offs.QuadPart = 0;
783 IStream_Seek(med.u.pstm, offs, STREAM_SEEK_CUR, &pos);
784 IStream_Seek(med.u.pstm, offs, STREAM_SEEK_SET, NULL);
785 hr = IStream_CopyTo(med.u.pstm, stm, pos, NULL, NULL);
786 ReleaseStgMedium(&med);
787 if(FAILED(hr)) goto error;
789 *mem = h;
790 IStream_Release(stm);
791 return S_OK;
793 error:
794 if(stm) IStream_Release(stm);
795 GlobalFree(h);
796 return hr;
799 /***************************************************************************
800 * get_data_from_global
802 * Returns global data in an HGLOBAL.
804 static HRESULT get_data_from_global(IDataObject *data, FORMATETC *fmt, HGLOBAL *mem)
806 HGLOBAL h;
807 HRESULT hr;
808 FORMATETC mem_fmt;
809 STGMEDIUM med;
811 *mem = NULL;
813 mem_fmt = *fmt;
814 mem_fmt.tymed = TYMED_HGLOBAL;
816 hr = IDataObject_GetData(data, &mem_fmt, &med);
817 if(FAILED(hr)) return hr;
819 hr = dup_global_mem(med.u.hGlobal, GMEM_DDESHARE|GMEM_MOVEABLE, &h);
821 if(SUCCEEDED(hr)) *mem = h;
823 ReleaseStgMedium(&med);
825 return hr;
828 /***************************************************************************
829 * get_data_from_enhmetafile
831 static HRESULT get_data_from_enhmetafile(IDataObject *data, FORMATETC *fmt, HGLOBAL *mem)
833 HENHMETAFILE copy;
834 HRESULT hr;
835 FORMATETC mem_fmt;
836 STGMEDIUM med;
838 *mem = NULL;
840 mem_fmt = *fmt;
841 mem_fmt.tymed = TYMED_ENHMF;
843 hr = IDataObject_GetData(data, &mem_fmt, &med);
844 if(FAILED(hr)) return hr;
846 copy = CopyEnhMetaFileW(med.u.hEnhMetaFile, NULL);
847 if(copy) *mem = (HGLOBAL)copy;
848 else hr = E_FAIL;
850 ReleaseStgMedium(&med);
852 return hr;
855 /***************************************************************************
856 * get_data_from_metafilepict
858 static HRESULT get_data_from_metafilepict(IDataObject *data, FORMATETC *fmt, HGLOBAL *mem)
860 HGLOBAL copy;
861 HRESULT hr;
862 FORMATETC mem_fmt;
863 STGMEDIUM med;
865 *mem = NULL;
867 mem_fmt = *fmt;
868 mem_fmt.tymed = TYMED_MFPICT;
870 hr = IDataObject_GetData(data, &mem_fmt, &med);
871 if(FAILED(hr)) return hr;
873 hr = dup_metafilepict(med.u.hMetaFilePict, &copy);
875 if(SUCCEEDED(hr)) *mem = copy;
877 ReleaseStgMedium(&med);
879 return hr;
882 /***************************************************************************
883 * get_data_from_bitmap
885 * Returns bitmap in an HBITMAP.
887 static HRESULT get_data_from_bitmap(IDataObject *data, FORMATETC *fmt, HBITMAP *hbm)
889 HBITMAP copy;
890 HRESULT hr;
891 FORMATETC mem_fmt;
892 STGMEDIUM med;
894 *hbm = NULL;
896 mem_fmt = *fmt;
897 mem_fmt.tymed = TYMED_GDI;
899 hr = IDataObject_GetData(data, &mem_fmt, &med);
900 if(FAILED(hr)) return hr;
902 hr = dup_bitmap(med.u.hBitmap, &copy);
904 if(SUCCEEDED(hr)) *hbm = copy;
906 ReleaseStgMedium(&med);
908 return hr;
911 /***********************************************************************
912 * render_format
914 * Render the clipboard data. Note that this call will delegate to the
915 * source data object.
917 static HRESULT render_format(IDataObject *data, LPFORMATETC fmt)
919 HANDLE clip_data = NULL; /* HGLOBAL unless otherwise specified */
920 HRESULT hr;
922 /* Embed source hack */
923 if(fmt->cfFormat == embed_source_clipboard_format)
925 return render_embed_source_hack(data, fmt);
928 if(fmt->tymed & TYMED_ISTORAGE)
930 hr = get_data_from_storage(data, fmt, &clip_data);
932 else if(fmt->tymed & TYMED_ISTREAM)
934 hr = get_data_from_stream(data, fmt, &clip_data);
936 else if(fmt->tymed & TYMED_HGLOBAL)
938 hr = get_data_from_global(data, fmt, &clip_data);
940 else if(fmt->tymed & TYMED_ENHMF)
942 hr = get_data_from_enhmetafile(data, fmt, &clip_data);
944 else if(fmt->tymed & TYMED_MFPICT)
946 /* Returns global handle to METAFILEPICT, containing a copied HMETAFILE */
947 hr = get_data_from_metafilepict(data, fmt, &clip_data);
949 else if(fmt->tymed & TYMED_GDI)
951 /* Returns HBITMAP not HGLOBAL */
952 hr = get_data_from_bitmap(data, fmt, (HBITMAP *)&clip_data);
954 else
956 FIXME("Unhandled tymed %x\n", fmt->tymed);
957 hr = DV_E_FORMATETC;
960 if(SUCCEEDED(hr))
962 if ( !SetClipboardData(fmt->cfFormat, clip_data) )
964 WARN("() : Failed to set rendered clipboard data into clipboard!\n");
965 if(fmt->tymed & TYMED_MFPICT)
966 free_metafilepict(clip_data);
967 else if(fmt->tymed & TYMED_GDI)
968 DeleteObject(clip_data);
969 else
970 GlobalFree(clip_data);
971 hr = CLIPBRD_E_CANT_SET;
975 return hr;
978 /*---------------------------------------------------------------------*
979 * Implementation of the internal IDataObject interface exposed by
980 * the OLE clipboard.
981 *---------------------------------------------------------------------*/
984 /************************************************************************
985 * snapshot_QueryInterface
987 static HRESULT WINAPI snapshot_QueryInterface(IDataObject *iface,
988 REFIID riid, void **ppvObject)
990 snapshot *This = impl_from_IDataObject(iface);
991 TRACE("(%p)->(IID:%s, %p)\n", This, debugstr_guid(riid), ppvObject);
993 if ( (This==0) || (ppvObject==0) )
994 return E_INVALIDARG;
996 *ppvObject = 0;
998 if (IsEqualIID(&IID_IUnknown, riid) ||
999 IsEqualIID(&IID_IDataObject, riid))
1001 *ppvObject = iface;
1003 else
1005 WARN( "() : asking for unsupported interface %s\n", debugstr_guid(riid));
1006 return E_NOINTERFACE;
1009 IUnknown_AddRef((IUnknown*)*ppvObject);
1011 return S_OK;
1014 /************************************************************************
1015 * snapshot_AddRef
1017 static ULONG WINAPI snapshot_AddRef(IDataObject *iface)
1019 snapshot *This = impl_from_IDataObject(iface);
1021 TRACE("(%p)->(count=%u)\n", This, This->ref);
1023 return InterlockedIncrement(&This->ref);
1026 /************************************************************************
1027 * snapshot_Release
1029 static ULONG WINAPI snapshot_Release(IDataObject *iface)
1031 snapshot *This = impl_from_IDataObject(iface);
1032 ULONG ref;
1034 TRACE("(%p)->(count=%u)\n", This, This->ref);
1036 ref = InterlockedDecrement(&This->ref);
1038 if (ref == 0)
1040 ole_clipbrd *clipbrd;
1041 HRESULT hr = get_ole_clipbrd(&clipbrd);
1043 if(This->data) IDataObject_Release(This->data);
1045 if(SUCCEEDED(hr) && clipbrd->latest_snapshot == This)
1046 clipbrd->latest_snapshot = NULL;
1047 HeapFree(GetProcessHeap(), 0, This);
1050 return ref;
1053 /************************************************************
1054 * get_current_ole_clip_window
1056 * Return the window that owns the ole clipboard.
1058 * If the clipboard is flushed or not owned by ole this will
1059 * return NULL.
1061 static HWND get_current_ole_clip_window(void)
1063 HGLOBAL h;
1064 HWND *ptr, wnd;
1066 h = GetClipboardData(dataobject_clipboard_format);
1067 if(!h) return NULL;
1068 ptr = GlobalLock(h);
1069 if(!ptr) return NULL;
1070 wnd = *ptr;
1071 GlobalUnlock(h);
1072 return wnd;
1075 /************************************************************
1076 * get_current_dataobject
1078 * Return an unmarshalled IDataObject if there is a current
1079 * (ie non-flushed) object on the ole clipboard.
1081 static HRESULT get_current_dataobject(IDataObject **data)
1083 HRESULT hr = S_FALSE;
1084 HWND wnd = get_current_ole_clip_window();
1085 HGLOBAL h;
1086 void *ptr;
1087 IStream *stm;
1088 LARGE_INTEGER pos;
1090 *data = NULL;
1091 if(!wnd) return S_FALSE;
1093 h = GetClipboardData(wine_marshal_clipboard_format);
1094 if(!h) return S_FALSE;
1095 if(GlobalSize(h) == 0) return S_FALSE;
1096 ptr = GlobalLock(h);
1097 if(!ptr) return S_FALSE;
1099 hr = CreateStreamOnHGlobal(NULL, TRUE, &stm);
1100 if(FAILED(hr)) goto end;
1102 hr = IStream_Write(stm, ptr, GlobalSize(h), NULL);
1103 if(SUCCEEDED(hr))
1105 pos.QuadPart = 0;
1106 IStream_Seek(stm, pos, STREAM_SEEK_SET, NULL);
1107 hr = CoUnmarshalInterface(stm, &IID_IDataObject, (void**)data);
1109 IStream_Release(stm);
1111 end:
1112 GlobalUnlock(h);
1113 return hr;
1116 static DWORD get_tymed_from_nonole_cf(UINT cf)
1118 if(cf >= 0xc000) return TYMED_ISTREAM | TYMED_HGLOBAL;
1120 switch(cf)
1122 case CF_TEXT:
1123 case CF_OEMTEXT:
1124 case CF_UNICODETEXT:
1125 return TYMED_ISTREAM | TYMED_HGLOBAL;
1126 case CF_ENHMETAFILE:
1127 return TYMED_ENHMF;
1128 case CF_METAFILEPICT:
1129 return TYMED_MFPICT;
1130 case CF_BITMAP:
1131 return TYMED_GDI;
1132 default:
1133 FIXME("returning TYMED_NULL for cf %04x\n", cf);
1134 return TYMED_NULL;
1138 /***********************************************************
1139 * get_priv_data
1141 * Returns a copy of the Ole Private Data
1143 static HRESULT get_priv_data(ole_priv_data **data)
1145 HGLOBAL handle;
1146 HRESULT hr = S_OK;
1147 ole_priv_data *ret = NULL;
1149 *data = NULL;
1151 handle = GetClipboardData( ole_private_data_clipboard_format );
1152 if(handle)
1154 ole_priv_data *src = GlobalLock(handle);
1155 if(src)
1157 DWORD i;
1159 /* FIXME: sanity check on size */
1160 ret = HeapAlloc(GetProcessHeap(), 0, src->size);
1161 if(!ret)
1163 GlobalUnlock(handle);
1164 return E_OUTOFMEMORY;
1166 memcpy(ret, src, src->size);
1167 GlobalUnlock(handle);
1169 /* Fixup any target device offsets to ptrs */
1170 for(i = 0; i < ret->count; i++)
1171 ret->entries[i].fmtetc.ptd =
1172 td_offs_to_ptr(ret, (DWORD_PTR) ret->entries[i].fmtetc.ptd);
1176 if(!ret) /* Non-ole data */
1178 UINT cf;
1179 DWORD count = 0, idx, size = FIELD_OFFSET(ole_priv_data, entries);
1181 for(cf = 0; (cf = EnumClipboardFormats(cf)) != 0; count++)
1183 char buf[100];
1184 GetClipboardFormatNameA(cf, buf, sizeof(buf));
1185 TRACE("cf %04x %s\n", cf, buf);
1187 TRACE("count %d\n", count);
1188 size += count * sizeof(ret->entries[0]);
1190 /* There are holes in fmtetc so zero init */
1191 ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
1192 if(!ret) return E_OUTOFMEMORY;
1193 ret->size = size;
1194 ret->count = count;
1196 for(cf = 0, idx = 0; (cf = EnumClipboardFormats(cf)) != 0; idx++)
1198 ret->entries[idx].fmtetc.cfFormat = cf;
1199 ret->entries[idx].fmtetc.ptd = NULL;
1200 ret->entries[idx].fmtetc.dwAspect = DVASPECT_CONTENT;
1201 ret->entries[idx].fmtetc.lindex = -1;
1202 ret->entries[idx].fmtetc.tymed = get_tymed_from_nonole_cf(cf);
1203 ret->entries[idx].first_use = 1;
1207 *data = ret;
1208 return hr;
1211 /************************************************************************
1212 * get_stgmed_for_global
1214 * Returns a stg medium with a copy of the global handle
1216 static HRESULT get_stgmed_for_global(HGLOBAL h, STGMEDIUM *med)
1218 HRESULT hr;
1220 med->pUnkForRelease = NULL;
1221 med->tymed = TYMED_NULL;
1223 hr = dup_global_mem(h, GMEM_MOVEABLE, &med->u.hGlobal);
1225 if(SUCCEEDED(hr)) med->tymed = TYMED_HGLOBAL;
1227 return hr;
1230 /************************************************************************
1231 * get_stgmed_for_stream
1233 * Returns a stg medium with a stream based on the handle
1235 static HRESULT get_stgmed_for_stream(HGLOBAL h, STGMEDIUM *med)
1237 HRESULT hr;
1238 HGLOBAL dst;
1240 med->pUnkForRelease = NULL;
1241 med->tymed = TYMED_NULL;
1243 hr = dup_global_mem(h, GMEM_MOVEABLE, &dst);
1244 if(FAILED(hr)) return hr;
1246 hr = CreateStreamOnHGlobal(dst, TRUE, &med->u.pstm);
1247 if(FAILED(hr))
1249 GlobalFree(dst);
1250 return hr;
1253 med->tymed = TYMED_ISTREAM;
1254 return hr;
1257 /************************************************************************
1258 * get_stgmed_for_storage
1260 * Returns a stg medium with a storage based on the handle
1262 static HRESULT get_stgmed_for_storage(HGLOBAL h, STGMEDIUM *med)
1264 HRESULT hr;
1265 HGLOBAL dst;
1266 ILockBytes *lbs;
1268 med->pUnkForRelease = NULL;
1269 med->tymed = TYMED_NULL;
1271 hr = dup_global_mem(h, GMEM_MOVEABLE, &dst);
1272 if(FAILED(hr)) return hr;
1274 hr = CreateILockBytesOnHGlobal(dst, TRUE, &lbs);
1275 if(FAILED(hr))
1277 GlobalFree(dst);
1278 return hr;
1281 hr = StgOpenStorageOnILockBytes(lbs, NULL, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, NULL, 0, &med->u.pstg);
1282 ILockBytes_Release(lbs);
1283 if(FAILED(hr))
1285 GlobalFree(dst);
1286 return hr;
1289 med->tymed = TYMED_ISTORAGE;
1290 return hr;
1293 /************************************************************************
1294 * get_stgmed_for_emf
1296 * Returns a stg medium with an enhanced metafile based on the handle
1298 static HRESULT get_stgmed_for_emf(HENHMETAFILE hemf, STGMEDIUM *med)
1300 med->pUnkForRelease = NULL;
1301 med->tymed = TYMED_NULL;
1303 med->u.hEnhMetaFile = CopyEnhMetaFileW(hemf, NULL);
1304 if(!med->u.hEnhMetaFile) return E_OUTOFMEMORY;
1305 med->tymed = TYMED_ENHMF;
1306 return S_OK;
1309 /************************************************************************
1310 * get_stgmed_for_bitmap
1312 * Returns a stg medium with a bitmap based on the handle
1314 static HRESULT get_stgmed_for_bitmap(HBITMAP hbmp, STGMEDIUM *med)
1316 HRESULT hr;
1318 med->pUnkForRelease = NULL;
1319 med->tymed = TYMED_NULL;
1321 hr = dup_bitmap(hbmp, &med->u.hBitmap);
1323 if (FAILED(hr))
1324 return hr;
1326 med->tymed = TYMED_GDI;
1327 return S_OK;
1330 static inline BOOL string_off_equal(const DVTARGETDEVICE *t1, WORD off1, const DVTARGETDEVICE *t2, WORD off2)
1332 const WCHAR *str1, *str2;
1334 if(off1 == 0 && off2 == 0) return TRUE;
1335 if(off1 == 0 || off2 == 0) return FALSE;
1337 str1 = (const WCHAR*)((const char*)t1 + off1);
1338 str2 = (const WCHAR*)((const char*)t2 + off2);
1340 return !lstrcmpW(str1, str2);
1343 static inline BOOL td_equal(const DVTARGETDEVICE *t1, const DVTARGETDEVICE *t2)
1345 if(t1 == NULL && t2 == NULL) return TRUE;
1346 if(t1 == NULL || t2 == NULL) return FALSE;
1348 if(!string_off_equal(t1, t1->tdDriverNameOffset, t2, t2->tdDriverNameOffset))
1349 return FALSE;
1350 if(!string_off_equal(t1, t1->tdDeviceNameOffset, t2, t2->tdDeviceNameOffset))
1351 return FALSE;
1352 if(!string_off_equal(t1, t1->tdPortNameOffset, t2, t2->tdPortNameOffset))
1353 return FALSE;
1355 /* FIXME check devmode? */
1357 return TRUE;
1360 /************************************************************************
1361 * snapshot_GetData
1363 static HRESULT WINAPI snapshot_GetData(IDataObject *iface, FORMATETC *fmt,
1364 STGMEDIUM *med)
1366 snapshot *This = impl_from_IDataObject(iface);
1367 HANDLE h;
1368 HRESULT hr;
1369 ole_priv_data *enum_data = NULL;
1370 ole_priv_data_entry *entry;
1371 DWORD mask;
1373 TRACE("(%p, %p {%s}, %p)\n", iface, fmt, dump_fmtetc(fmt), med);
1375 if ( !fmt || !med ) return E_INVALIDARG;
1377 if ( !OpenClipboard(NULL)) return CLIPBRD_E_CANT_OPEN;
1379 if(!This->data)
1380 hr = get_current_dataobject(&This->data);
1382 if(This->data)
1384 hr = IDataObject_GetData(This->data, fmt, med);
1385 CloseClipboard();
1386 return hr;
1389 h = GetClipboardData(fmt->cfFormat);
1390 if(!h)
1392 hr = DV_E_FORMATETC;
1393 goto end;
1396 hr = get_priv_data(&enum_data);
1397 if(FAILED(hr)) goto end;
1399 entry = find_format_in_list(enum_data->entries, enum_data->count, fmt->cfFormat);
1400 if(entry)
1402 if(!td_equal(fmt->ptd, entry->fmtetc.ptd))
1404 hr = DV_E_FORMATETC;
1405 goto end;
1407 mask = fmt->tymed & entry->fmtetc.tymed;
1408 if(!mask) mask = fmt->tymed & (TYMED_ISTREAM | TYMED_HGLOBAL);
1410 else /* non-Ole format */
1411 mask = fmt->tymed & TYMED_HGLOBAL;
1413 if(mask & TYMED_ISTORAGE)
1414 hr = get_stgmed_for_storage(h, med);
1415 else if(mask & TYMED_HGLOBAL)
1416 hr = get_stgmed_for_global(h, med);
1417 else if(mask & TYMED_ISTREAM)
1418 hr = get_stgmed_for_stream(h, med);
1419 else if(mask & TYMED_ENHMF)
1420 hr = get_stgmed_for_emf((HENHMETAFILE)h, med);
1421 else if(mask & TYMED_GDI)
1422 hr = get_stgmed_for_bitmap((HBITMAP)h, med);
1423 else
1425 FIXME("Unhandled tymed - mask %x req tymed %x\n", mask, fmt->tymed);
1426 hr = E_FAIL;
1427 goto end;
1430 end:
1431 HeapFree(GetProcessHeap(), 0, enum_data);
1432 if ( !CloseClipboard() ) hr = CLIPBRD_E_CANT_CLOSE;
1433 return hr;
1436 /************************************************************************
1437 * snapshot_GetDataHere
1439 static HRESULT WINAPI snapshot_GetDataHere(IDataObject *iface, FORMATETC *fmt,
1440 STGMEDIUM *med)
1442 snapshot *This = impl_from_IDataObject(iface);
1443 HANDLE h;
1444 HRESULT hr;
1445 ole_priv_data *enum_data = NULL;
1446 ole_priv_data_entry *entry;
1447 TYMED supported;
1449 if ( !fmt || !med ) return E_INVALIDARG;
1451 TRACE("(%p, %p {%s}, %p (tymed %x)\n", iface, fmt, dump_fmtetc(fmt), med, med->tymed);
1453 if ( !OpenClipboard(NULL)) return CLIPBRD_E_CANT_OPEN;
1455 if(!This->data)
1456 hr = get_current_dataobject(&This->data);
1458 if(This->data)
1460 hr = IDataObject_GetDataHere(This->data, fmt, med);
1461 if(SUCCEEDED(hr))
1463 CloseClipboard();
1464 return hr;
1468 h = GetClipboardData(fmt->cfFormat);
1469 if(!h)
1471 hr = DV_E_FORMATETC;
1472 goto end;
1475 hr = get_priv_data(&enum_data);
1476 if(FAILED(hr)) goto end;
1478 entry = find_format_in_list(enum_data->entries, enum_data->count, fmt->cfFormat);
1479 if(entry)
1481 if(!td_equal(fmt->ptd, entry->fmtetc.ptd))
1483 hr = DV_E_FORMATETC;
1484 goto end;
1486 supported = entry->fmtetc.tymed;
1488 else /* non-Ole format */
1489 supported = TYMED_HGLOBAL;
1491 switch(med->tymed)
1493 case TYMED_HGLOBAL:
1495 DWORD src_size = GlobalSize(h);
1496 DWORD dst_size = GlobalSize(med->u.hGlobal);
1497 hr = E_FAIL;
1498 if(dst_size >= src_size)
1500 void *src = GlobalLock(h);
1501 void *dst = GlobalLock(med->u.hGlobal);
1503 memcpy(dst, src, src_size);
1504 GlobalUnlock(med->u.hGlobal);
1505 GlobalUnlock(h);
1506 hr = S_OK;
1508 break;
1510 case TYMED_ISTREAM:
1512 DWORD src_size = GlobalSize(h);
1513 void *src = GlobalLock(h);
1514 hr = IStream_Write(med->u.pstm, src, src_size, NULL);
1515 GlobalUnlock(h);
1516 break;
1518 case TYMED_ISTORAGE:
1520 STGMEDIUM copy;
1521 if(!(supported & TYMED_ISTORAGE))
1523 hr = E_FAIL;
1524 goto end;
1526 hr = get_stgmed_for_storage(h, &copy);
1527 if(SUCCEEDED(hr))
1529 hr = IStorage_CopyTo(copy.u.pstg, 0, NULL, NULL, med->u.pstg);
1530 ReleaseStgMedium(&copy);
1532 break;
1534 default:
1535 FIXME("Unhandled tymed - supported %x req tymed %x\n", supported, med->tymed);
1536 hr = E_FAIL;
1537 goto end;
1540 end:
1541 HeapFree(GetProcessHeap(), 0, enum_data);
1542 if ( !CloseClipboard() ) hr = CLIPBRD_E_CANT_CLOSE;
1543 return hr;
1546 /************************************************************************
1547 * snapshot_QueryGetData
1549 * The OLE Clipboard's implementation of this method delegates to
1550 * a data source if there is one or wraps around the windows clipboard
1551 * function IsClipboardFormatAvailable() otherwise.
1554 static HRESULT WINAPI snapshot_QueryGetData(IDataObject *iface, FORMATETC *fmt)
1556 FIXME("(%p, %p {%s})\n", iface, fmt, dump_fmtetc(fmt));
1558 if (!fmt) return E_INVALIDARG;
1560 if ( fmt->dwAspect != DVASPECT_CONTENT ) return DV_E_FORMATETC;
1562 if ( fmt->lindex != -1 ) return DV_E_FORMATETC;
1564 return (IsClipboardFormatAvailable(fmt->cfFormat)) ? S_OK : DV_E_CLIPFORMAT;
1567 /************************************************************************
1568 * snapshot_GetCanonicalFormatEtc
1570 static HRESULT WINAPI snapshot_GetCanonicalFormatEtc(IDataObject *iface, FORMATETC *fmt_in,
1571 FORMATETC *fmt_out)
1573 TRACE("(%p, %p, %p)\n", iface, fmt_in, fmt_out);
1575 if ( !fmt_in || !fmt_out ) return E_INVALIDARG;
1577 *fmt_out = *fmt_in;
1578 return DATA_S_SAMEFORMATETC;
1581 /************************************************************************
1582 * snapshot_SetData
1584 * The OLE Clipboard does not implement this method
1586 static HRESULT WINAPI snapshot_SetData(IDataObject *iface, FORMATETC *fmt,
1587 STGMEDIUM *med, BOOL release)
1589 TRACE("(%p, %p, %p, %d): not implemented\n", iface, fmt, med, release);
1590 return E_NOTIMPL;
1593 /************************************************************************
1594 * snapshot_EnumFormatEtc
1597 static HRESULT WINAPI snapshot_EnumFormatEtc(IDataObject *iface, DWORD dir,
1598 IEnumFORMATETC **enum_fmt)
1600 HRESULT hr;
1601 ole_priv_data *data = NULL;
1603 TRACE("(%p, %x, %p)\n", iface, dir, enum_fmt);
1605 *enum_fmt = NULL;
1607 if ( dir != DATADIR_GET ) return E_NOTIMPL;
1608 if ( !OpenClipboard(NULL) ) return CLIPBRD_E_CANT_OPEN;
1610 hr = get_priv_data(&data);
1612 if(FAILED(hr)) goto end;
1614 hr = enum_fmtetc_construct( data, 0, enum_fmt );
1616 end:
1617 if ( !CloseClipboard() ) hr = CLIPBRD_E_CANT_CLOSE;
1618 return hr;
1621 /************************************************************************
1622 * snapshot_DAdvise
1624 * The OLE Clipboard does not implement this method
1626 static HRESULT WINAPI snapshot_DAdvise(IDataObject *iface, FORMATETC *fmt,
1627 DWORD flags, IAdviseSink *sink,
1628 DWORD *conn)
1630 TRACE("(%p, %p, %x, %p, %p): not implemented\n", iface, fmt, flags, sink, conn);
1631 return E_NOTIMPL;
1634 /************************************************************************
1635 * snapshot_DUnadvise
1637 * The OLE Clipboard does not implement this method
1639 static HRESULT WINAPI snapshot_DUnadvise(IDataObject* iface, DWORD conn)
1641 TRACE("(%p, %d): not implemented\n", iface, conn);
1642 return E_NOTIMPL;
1645 /************************************************************************
1646 * snapshot_EnumDAdvise
1648 * The OLE Clipboard does not implement this method
1650 static HRESULT WINAPI snapshot_EnumDAdvise(IDataObject* iface,
1651 IEnumSTATDATA** enum_advise)
1653 TRACE("(%p, %p): not implemented\n", iface, enum_advise);
1654 return E_NOTIMPL;
1657 static const IDataObjectVtbl snapshot_vtable =
1659 snapshot_QueryInterface,
1660 snapshot_AddRef,
1661 snapshot_Release,
1662 snapshot_GetData,
1663 snapshot_GetDataHere,
1664 snapshot_QueryGetData,
1665 snapshot_GetCanonicalFormatEtc,
1666 snapshot_SetData,
1667 snapshot_EnumFormatEtc,
1668 snapshot_DAdvise,
1669 snapshot_DUnadvise,
1670 snapshot_EnumDAdvise
1673 /*---------------------------------------------------------------------*
1674 * Internal implementation methods for the OLE clipboard
1675 *---------------------------------------------------------------------*/
1677 static snapshot *snapshot_construct(DWORD seq_no)
1679 snapshot *This;
1681 This = HeapAlloc( GetProcessHeap(), 0, sizeof(*This) );
1682 if (!This) return NULL;
1684 This->IDataObject_iface.lpVtbl = &snapshot_vtable;
1685 This->ref = 0;
1686 This->seq_no = seq_no;
1687 This->data = NULL;
1689 return This;
1692 /*********************************************************
1693 * register_clipboard_formats
1695 static void register_clipboard_formats(void)
1697 static const WCHAR OwnerLink[] = {'O','w','n','e','r','L','i','n','k',0};
1698 static const WCHAR FileName[] = {'F','i','l','e','N','a','m','e',0};
1699 static const WCHAR FileNameW[] = {'F','i','l','e','N','a','m','e','W',0};
1700 static const WCHAR DataObject[] = {'D','a','t','a','O','b','j','e','c','t',0};
1701 static const WCHAR EmbeddedObject[] = {'E','m','b','e','d','d','e','d',' ','O','b','j','e','c','t',0};
1702 static const WCHAR EmbedSource[] = {'E','m','b','e','d',' ','S','o','u','r','c','e',0};
1703 static const WCHAR CustomLinkSource[] = {'C','u','s','t','o','m',' ','L','i','n','k',' ','S','o','u','r','c','e',0};
1704 static const WCHAR LinkSource[] = {'L','i','n','k',' ','S','o','u','r','c','e',0};
1705 static const WCHAR ObjectDescriptor[] = {'O','b','j','e','c','t',' ','D','e','s','c','r','i','p','t','o','r',0};
1706 static const WCHAR LinkSourceDescriptor[] = {'L','i','n','k',' ','S','o','u','r','c','e',' ',
1707 'D','e','s','c','r','i','p','t','o','r',0};
1708 static const WCHAR OlePrivateData[] = {'O','l','e',' ','P','r','i','v','a','t','e',' ','D','a','t','a',0};
1710 static const WCHAR WineMarshalledDataObject[] = {'W','i','n','e',' ','M','a','r','s','h','a','l','l','e','d',' ',
1711 'D','a','t','a','O','b','j','e','c','t',0};
1713 ownerlink_clipboard_format = RegisterClipboardFormatW(OwnerLink);
1714 filename_clipboard_format = RegisterClipboardFormatW(FileName);
1715 filenameW_clipboard_format = RegisterClipboardFormatW(FileNameW);
1716 dataobject_clipboard_format = RegisterClipboardFormatW(DataObject);
1717 embedded_object_clipboard_format = RegisterClipboardFormatW(EmbeddedObject);
1718 embed_source_clipboard_format = RegisterClipboardFormatW(EmbedSource);
1719 custom_link_source_clipboard_format = RegisterClipboardFormatW(CustomLinkSource);
1720 link_source_clipboard_format = RegisterClipboardFormatW(LinkSource);
1721 object_descriptor_clipboard_format = RegisterClipboardFormatW(ObjectDescriptor);
1722 link_source_descriptor_clipboard_format = RegisterClipboardFormatW(LinkSourceDescriptor);
1723 ole_private_data_clipboard_format = RegisterClipboardFormatW(OlePrivateData);
1725 wine_marshal_clipboard_format = RegisterClipboardFormatW(WineMarshalledDataObject);
1728 /***********************************************************************
1729 * OLEClipbrd_Initialize()
1730 * Initializes the OLE clipboard.
1732 void OLEClipbrd_Initialize(void)
1734 register_clipboard_formats();
1736 if ( !theOleClipboard )
1738 ole_clipbrd* clipbrd;
1739 HGLOBAL h;
1741 TRACE("()\n");
1743 clipbrd = HeapAlloc( GetProcessHeap(), 0, sizeof(*clipbrd) );
1744 if (!clipbrd) return;
1746 clipbrd->latest_snapshot = NULL;
1747 clipbrd->window = NULL;
1748 clipbrd->src_data = NULL;
1749 clipbrd->cached_enum = NULL;
1751 h = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE, 0);
1752 if(!h)
1754 HeapFree(GetProcessHeap(), 0, clipbrd);
1755 return;
1758 if(FAILED(CreateStreamOnHGlobal(h, TRUE, &clipbrd->marshal_data)))
1760 GlobalFree(h);
1761 HeapFree(GetProcessHeap(), 0, clipbrd);
1762 return;
1765 theOleClipboard = clipbrd;
1769 /***********************************************************************
1770 * OLEClipbrd_UnInitialize()
1771 * Un-Initializes the OLE clipboard
1773 void OLEClipbrd_UnInitialize(void)
1775 ole_clipbrd *clipbrd = theOleClipboard;
1777 TRACE("()\n");
1779 if ( clipbrd )
1781 static const WCHAR ole32W[] = {'o','l','e','3','2',0};
1782 HINSTANCE hinst = GetModuleHandleW(ole32W);
1784 if ( clipbrd->window )
1786 DestroyWindow(clipbrd->window);
1787 UnregisterClassW( clipbrd_wndclass, hinst );
1790 IStream_Release(clipbrd->marshal_data);
1791 if (clipbrd->src_data) IDataObject_Release(clipbrd->src_data);
1792 HeapFree(GetProcessHeap(), 0, clipbrd->cached_enum);
1793 HeapFree(GetProcessHeap(), 0, clipbrd);
1794 theOleClipboard = NULL;
1798 /*********************************************************************
1799 * set_clipboard_formats
1801 * Enumerate all formats supported by the source and make
1802 * those formats available using delayed rendering using SetClipboardData.
1803 * Cache the enumeration list and make that list visibile as the
1804 * 'Ole Private Data' format on the clipboard.
1807 static HRESULT set_clipboard_formats(ole_clipbrd *clipbrd, IDataObject *data)
1809 HRESULT hr;
1810 FORMATETC fmt;
1811 IEnumFORMATETC *enum_fmt;
1812 HGLOBAL priv_data_handle;
1813 DWORD_PTR target_offset;
1814 ole_priv_data *priv_data;
1815 DWORD count = 0, needed = sizeof(*priv_data), idx;
1817 hr = IDataObject_EnumFormatEtc(data, DATADIR_GET, &enum_fmt);
1818 if(FAILED(hr)) return hr;
1820 while(IEnumFORMATETC_Next(enum_fmt, 1, &fmt, NULL) == S_OK)
1822 count++;
1823 needed += sizeof(priv_data->entries[0]);
1824 if(fmt.ptd)
1826 needed += fmt.ptd->tdSize;
1827 CoTaskMemFree(fmt.ptd);
1831 /* Windows pads the list with two empty ole_priv_data_entries, one
1832 * after the entries array and one after the target device data.
1833 * Allocating with zero init to zero these pads. */
1835 needed += sizeof(priv_data->entries[0]); /* initialisation of needed includes one of these. */
1836 priv_data_handle = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE | GMEM_ZEROINIT, needed);
1837 priv_data = GlobalLock(priv_data_handle);
1839 priv_data->unk1 = 0;
1840 priv_data->size = needed;
1841 priv_data->unk2 = 1;
1842 priv_data->count = count;
1843 priv_data->unk3[0] = 0;
1844 priv_data->unk3[1] = 0;
1846 IEnumFORMATETC_Reset(enum_fmt);
1848 idx = 0;
1849 target_offset = FIELD_OFFSET(ole_priv_data, entries[count + 1]); /* count entries + one pad. */
1851 while(IEnumFORMATETC_Next(enum_fmt, 1, &fmt, NULL) == S_OK)
1853 TRACE("%s\n", dump_fmtetc(&fmt));
1855 priv_data->entries[idx].fmtetc = fmt;
1856 if(fmt.ptd)
1858 memcpy((char*)priv_data + target_offset, fmt.ptd, fmt.ptd->tdSize);
1859 priv_data->entries[idx].fmtetc.ptd = (DVTARGETDEVICE*)target_offset;
1860 target_offset += fmt.ptd->tdSize;
1861 CoTaskMemFree(fmt.ptd);
1864 priv_data->entries[idx].first_use = !find_format_in_list(priv_data->entries, idx, fmt.cfFormat);
1865 priv_data->entries[idx].unk[0] = 0;
1866 priv_data->entries[idx].unk[1] = 0;
1868 if (priv_data->entries[idx].first_use)
1869 SetClipboardData(fmt.cfFormat, NULL);
1871 idx++;
1874 IEnumFORMATETC_Release(enum_fmt);
1876 /* Cache the list and fixup any target device offsets to ptrs */
1877 clipbrd->cached_enum = HeapAlloc(GetProcessHeap(), 0, needed);
1878 memcpy(clipbrd->cached_enum, priv_data, needed);
1879 for(idx = 0; idx < clipbrd->cached_enum->count; idx++)
1880 clipbrd->cached_enum->entries[idx].fmtetc.ptd =
1881 td_offs_to_ptr(clipbrd->cached_enum, (DWORD_PTR)clipbrd->cached_enum->entries[idx].fmtetc.ptd);
1883 GlobalUnlock(priv_data_handle);
1884 if(!SetClipboardData(ole_private_data_clipboard_format, priv_data_handle))
1886 GlobalFree(priv_data_handle);
1887 return CLIPBRD_E_CANT_SET;
1890 return S_OK;
1893 static HWND create_clipbrd_window(void);
1895 /***********************************************************************
1896 * get_clipbrd_window
1898 static inline HRESULT get_clipbrd_window(ole_clipbrd *clipbrd, HWND *wnd)
1900 if ( !clipbrd->window )
1901 clipbrd->window = create_clipbrd_window();
1903 *wnd = clipbrd->window;
1904 return *wnd ? S_OK : E_FAIL;
1908 /**********************************************************************
1909 * release_marshal_data
1911 * Releases the data and sets the stream back to zero size.
1913 static inline void release_marshal_data(IStream *stm)
1915 LARGE_INTEGER pos;
1916 ULARGE_INTEGER size;
1917 pos.QuadPart = size.QuadPart = 0;
1919 IStream_Seek(stm, pos, STREAM_SEEK_SET, NULL);
1920 CoReleaseMarshalData(stm);
1921 IStream_Seek(stm, pos, STREAM_SEEK_SET, NULL);
1922 IStream_SetSize(stm, size);
1925 /***********************************************************************
1926 * expose_marshalled_dataobject
1928 * Sets the marshalled dataobject to the clipboard. In the flushed case
1929 * we set a zero sized HGLOBAL to clear the old marshalled data.
1931 static HRESULT expose_marshalled_dataobject(ole_clipbrd *clipbrd, IDataObject *data)
1933 HGLOBAL h;
1935 if(data)
1937 HGLOBAL h_stm;
1938 GetHGlobalFromStream(clipbrd->marshal_data, &h_stm);
1939 dup_global_mem(h_stm, GMEM_DDESHARE|GMEM_MOVEABLE, &h);
1941 else /* flushed */
1942 h = GlobalAlloc(GMEM_DDESHARE|GMEM_MOVEABLE, 0);
1944 if(!h) return E_OUTOFMEMORY;
1946 if(!SetClipboardData(wine_marshal_clipboard_format, h))
1948 GlobalFree(h);
1949 return CLIPBRD_E_CANT_SET;
1951 return S_OK;
1954 /***********************************************************************
1955 * set_src_dataobject
1957 * Clears and sets the clipboard's src IDataObject.
1959 * To marshal the source dataobject we do something rather different from Windows.
1960 * We set a clipboard format which contains the marshalled data.
1961 * Windows sets two window props one of which is an IID, the other is an endpoint number.
1963 static HRESULT set_src_dataobject(ole_clipbrd *clipbrd, IDataObject *data)
1965 HRESULT hr;
1966 HWND wnd;
1968 if(FAILED(hr = get_clipbrd_window(clipbrd, &wnd))) return hr;
1970 if(clipbrd->src_data)
1972 release_marshal_data(clipbrd->marshal_data);
1974 IDataObject_Release(clipbrd->src_data);
1975 clipbrd->src_data = NULL;
1976 HeapFree(GetProcessHeap(), 0, clipbrd->cached_enum);
1977 clipbrd->cached_enum = NULL;
1980 if(data)
1982 IUnknown *unk;
1984 IDataObject_AddRef(data);
1985 clipbrd->src_data = data;
1987 IDataObject_QueryInterface(data, &IID_IUnknown, (void**)&unk);
1988 hr = CoMarshalInterface(clipbrd->marshal_data, &IID_IDataObject, unk,
1989 MSHCTX_LOCAL, NULL, MSHLFLAGS_TABLESTRONG);
1990 IUnknown_Release(unk); /* Don't hold a ref on IUnknown, we have one on IDataObject. */
1991 if(FAILED(hr)) return hr;
1992 hr = set_clipboard_formats(clipbrd, data);
1994 return hr;
1997 /***********************************************************************
1998 * clipbrd_wndproc
2000 static LRESULT CALLBACK clipbrd_wndproc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
2002 ole_clipbrd *clipbrd;
2004 get_ole_clipbrd(&clipbrd);
2006 switch (message)
2008 case WM_RENDERFORMAT:
2010 UINT cf = wparam;
2011 ole_priv_data_entry *entry;
2013 TRACE("(): WM_RENDERFORMAT(cfFormat=%x)\n", cf);
2014 entry = find_format_in_list(clipbrd->cached_enum->entries, clipbrd->cached_enum->count, cf);
2016 if(entry)
2017 render_format(clipbrd->src_data, &entry->fmtetc);
2019 break;
2022 case WM_RENDERALLFORMATS:
2024 DWORD i;
2025 ole_priv_data_entry *entries = clipbrd->cached_enum->entries;
2027 TRACE("(): WM_RENDERALLFORMATS\n");
2029 for(i = 0; i < clipbrd->cached_enum->count; i++)
2031 if(entries[i].first_use)
2032 render_format(clipbrd->src_data, &entries[i].fmtetc);
2034 break;
2037 case WM_DESTROYCLIPBOARD:
2039 TRACE("(): WM_DESTROYCLIPBOARD\n");
2041 set_src_dataobject(clipbrd, NULL);
2042 break;
2045 default:
2046 return DefWindowProcW(hwnd, message, wparam, lparam);
2049 return 0;
2053 /***********************************************************************
2054 * create_clipbrd_window
2056 static HWND create_clipbrd_window(void)
2058 WNDCLASSEXW class;
2059 static const WCHAR ole32W[] = {'o','l','e','3','2',0};
2060 static const WCHAR title[] = {'C','l','i','p','b','o','a','r','d','W','i','n','d','o','w',0};
2061 HINSTANCE hinst = GetModuleHandleW(ole32W);
2063 class.cbSize = sizeof(class);
2064 class.style = 0;
2065 class.lpfnWndProc = clipbrd_wndproc;
2066 class.cbClsExtra = 0;
2067 class.cbWndExtra = 0;
2068 class.hInstance = hinst;
2069 class.hIcon = 0;
2070 class.hCursor = 0;
2071 class.hbrBackground = 0;
2072 class.lpszMenuName = NULL;
2073 class.lpszClassName = clipbrd_wndclass;
2074 class.hIconSm = NULL;
2076 RegisterClassExW(&class);
2078 return CreateWindowW(clipbrd_wndclass, title, WS_POPUP | WS_CLIPSIBLINGS | WS_OVERLAPPED,
2079 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
2080 NULL, NULL, hinst, 0);
2083 /*********************************************************************
2084 * set_dataobject_format
2086 * Windows creates a 'DataObject' clipboard format that contains the
2087 * clipboard window's HWND or NULL if the Ole clipboard has been flushed.
2089 static HRESULT set_dataobject_format(HWND hwnd)
2091 HGLOBAL h = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE, sizeof(hwnd));
2092 HWND *data;
2094 if(!h) return E_OUTOFMEMORY;
2096 data = GlobalLock(h);
2097 *data = hwnd;
2098 GlobalUnlock(h);
2100 if(!SetClipboardData(dataobject_clipboard_format, h))
2102 GlobalFree(h);
2103 return CLIPBRD_E_CANT_SET;
2106 return S_OK;
2109 /*---------------------------------------------------------------------*
2110 * Win32 OLE clipboard API
2111 *---------------------------------------------------------------------*/
2113 /***********************************************************************
2114 * OleSetClipboard [OLE32.@]
2115 * Places a pointer to the specified data object onto the clipboard,
2116 * making the data object accessible to the OleGetClipboard function.
2118 * RETURNS
2120 * S_OK IDataObject pointer placed on the clipboard
2121 * CLIPBRD_E_CANT_OPEN OpenClipboard failed
2122 * CLIPBRD_E_CANT_EMPTY EmptyClipboard failed
2123 * CLIPBRD_E_CANT_CLOSE CloseClipboard failed
2124 * CLIPBRD_E_CANT_SET SetClipboard failed
2127 HRESULT WINAPI OleSetClipboard(IDataObject* data)
2129 HRESULT hr;
2130 ole_clipbrd *clipbrd;
2131 HWND wnd;
2133 TRACE("(%p)\n", data);
2135 if(FAILED(hr = get_ole_clipbrd(&clipbrd))) return hr;
2137 if(FAILED(hr = get_clipbrd_window(clipbrd, &wnd))) return hr;
2139 if ( !OpenClipboard(wnd) ) return CLIPBRD_E_CANT_OPEN;
2141 if ( !EmptyClipboard() )
2143 hr = CLIPBRD_E_CANT_EMPTY;
2144 goto end;
2147 hr = set_src_dataobject(clipbrd, data);
2148 if(FAILED(hr)) goto end;
2150 if(data)
2152 hr = expose_marshalled_dataobject(clipbrd, data);
2153 if(FAILED(hr)) goto end;
2154 hr = set_dataobject_format(wnd);
2157 end:
2159 if ( !CloseClipboard() ) hr = CLIPBRD_E_CANT_CLOSE;
2161 if ( FAILED(hr) )
2163 expose_marshalled_dataobject(clipbrd, NULL);
2164 set_src_dataobject(clipbrd, NULL);
2167 return hr;
2171 /***********************************************************************
2172 * OleGetClipboard [OLE32.@]
2173 * Returns a pointer to our internal IDataObject which represents the conceptual
2174 * state of the Windows clipboard. If the current clipboard already contains
2175 * an IDataObject, our internal IDataObject will delegate to this object.
2177 HRESULT WINAPI OleGetClipboard(IDataObject **obj)
2179 HRESULT hr;
2180 ole_clipbrd *clipbrd;
2181 DWORD seq_no;
2183 TRACE("(%p)\n", obj);
2185 if(!obj) return E_INVALIDARG;
2187 if(FAILED(hr = get_ole_clipbrd(&clipbrd))) return hr;
2189 seq_no = GetClipboardSequenceNumber();
2190 if(clipbrd->latest_snapshot && clipbrd->latest_snapshot->seq_no != seq_no)
2191 clipbrd->latest_snapshot = NULL;
2193 if(!clipbrd->latest_snapshot)
2195 clipbrd->latest_snapshot = snapshot_construct(seq_no);
2196 if(!clipbrd->latest_snapshot) return E_OUTOFMEMORY;
2199 *obj = &clipbrd->latest_snapshot->IDataObject_iface;
2200 IDataObject_AddRef(*obj);
2202 return S_OK;
2205 /******************************************************************************
2206 * OleFlushClipboard [OLE32.@]
2207 * Renders the data from the source IDataObject into the windows clipboard
2209 * TODO: OleFlushClipboard needs to additionally handle TYMED_IStorage media
2210 * by copying the storage into global memory. Subsequently the default
2211 * data object exposed through OleGetClipboard must convert this TYMED_HGLOBAL
2212 * back to TYMED_IStorage.
2214 HRESULT WINAPI OleFlushClipboard(void)
2216 HRESULT hr;
2217 ole_clipbrd *clipbrd;
2218 HWND wnd;
2220 TRACE("()\n");
2222 if(FAILED(hr = get_ole_clipbrd(&clipbrd))) return hr;
2224 if(FAILED(hr = get_clipbrd_window(clipbrd, &wnd))) return hr;
2227 * Already flushed or no source DataObject? Nothing to do.
2229 if (!clipbrd->src_data) return S_OK;
2231 if (!OpenClipboard(wnd)) return CLIPBRD_E_CANT_OPEN;
2233 SendMessageW(wnd, WM_RENDERALLFORMATS, 0, 0);
2235 hr = set_dataobject_format(NULL);
2237 expose_marshalled_dataobject(clipbrd, NULL);
2238 set_src_dataobject(clipbrd, NULL);
2240 if ( !CloseClipboard() ) hr = CLIPBRD_E_CANT_CLOSE;
2242 return hr;
2246 /***********************************************************************
2247 * OleIsCurrentClipboard [OLE32.@]
2249 HRESULT WINAPI OleIsCurrentClipboard(IDataObject *data)
2251 HRESULT hr;
2252 ole_clipbrd *clipbrd;
2253 TRACE("()\n");
2255 if(FAILED(hr = get_ole_clipbrd(&clipbrd))) return hr;
2257 if (data == NULL) return S_FALSE;
2259 return (data == clipbrd->src_data) ? S_OK : S_FALSE;