msvcirt: Add implementation of streambuf::sputbackc.
[wine.git] / dlls / ole32 / clipboard.c
blobdb1e4a8ffc3d1f25fcd562ac395566124c6d8ad6
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 if (FAILED(hr))
581 GlobalFree(hStorage);
582 return hr;
585 hr = StgCreateDocfileOnILockBytes(ptrILockBytes, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &std.u.pstg);
586 ILockBytes_Release(ptrILockBytes);
588 if (FAILED(hr = IDataObject_GetDataHere(theOleClipboard->src_data, fmt, &std)))
590 WARN("() : IDataObject_GetDataHere failed to render clipboard data! (%x)\n", hr);
591 GlobalFree(hStorage);
592 return hr;
595 if (1) /* check whether the presentation data is already -not- present */
597 FORMATETC fmt2;
598 STGMEDIUM std2;
599 METAFILEPICT *mfp = 0;
601 fmt2.cfFormat = CF_METAFILEPICT;
602 fmt2.ptd = 0;
603 fmt2.dwAspect = DVASPECT_CONTENT;
604 fmt2.lindex = -1;
605 fmt2.tymed = TYMED_MFPICT;
607 memset(&std2, 0, sizeof(STGMEDIUM));
608 std2.tymed = TYMED_MFPICT;
610 /* Get the metafile picture out of it */
612 if (SUCCEEDED(hr = IDataObject_GetData(theOleClipboard->src_data, &fmt2, &std2)))
614 mfp = GlobalLock(std2.u.hGlobal);
617 if (mfp)
619 OLECHAR name[]={ 2, 'O', 'l', 'e', 'P', 'r', 'e', 's', '0', '0', '0', 0};
620 IStream *pStream = 0;
621 void *mfBits;
622 PresentationDataHeader pdh;
623 INT nSize;
624 CLSID clsID;
625 LPOLESTR strProgID;
626 CHAR strOleTypeName[51];
627 BYTE OlePresStreamHeader [] =
629 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00,
630 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
631 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
632 0x00, 0x00, 0x00, 0x00
635 nSize = GetMetaFileBitsEx(mfp->hMF, 0, NULL);
637 memset(&pdh, 0, sizeof(PresentationDataHeader));
638 memcpy(&pdh, OlePresStreamHeader, sizeof(OlePresStreamHeader));
640 pdh.dwObjectExtentX = mfp->xExt;
641 pdh.dwObjectExtentY = mfp->yExt;
642 pdh.dwSize = nSize;
644 hr = IStorage_CreateStream(std.u.pstg, name, STGM_CREATE|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, 0, &pStream);
646 hr = IStream_Write(pStream, &pdh, sizeof(PresentationDataHeader), NULL);
648 mfBits = HeapAlloc(GetProcessHeap(), 0, nSize);
649 nSize = GetMetaFileBitsEx(mfp->hMF, nSize, mfBits);
651 hr = IStream_Write(pStream, mfBits, nSize, NULL);
653 IStream_Release(pStream);
655 HeapFree(GetProcessHeap(), 0, mfBits);
657 GlobalUnlock(std2.u.hGlobal);
658 ReleaseStgMedium(&std2);
660 ReadClassStg(std.u.pstg, &clsID);
661 ProgIDFromCLSID(&clsID, &strProgID);
663 WideCharToMultiByte( CP_ACP, 0, strProgID, -1, strOleTypeName, sizeof(strOleTypeName), NULL, NULL );
664 STORAGE_CreateOleStream(std.u.pstg, 0);
665 OLECONVERT_CreateCompObjStream(std.u.pstg, strOleTypeName);
666 CoTaskMemFree(strProgID);
670 if ( !SetClipboardData( fmt->cfFormat, hStorage ) )
672 WARN("() : Failed to set rendered clipboard data into clipboard!\n");
673 GlobalFree(hStorage);
674 hr = CLIPBRD_E_CANT_SET;
677 ReleaseStgMedium(&std);
678 return hr;
681 /************************************************************************
682 * find_format_in_list
684 * Returns the first entry that matches the provided clipboard format.
686 static inline ole_priv_data_entry *find_format_in_list(ole_priv_data_entry *entries, DWORD num, UINT cf)
688 DWORD i;
689 for(i = 0; i < num; i++)
690 if(entries[i].fmtetc.cfFormat == cf)
691 return &entries[i];
693 return NULL;
696 /***************************************************************************
697 * get_data_from_storage
699 * Returns storage data in an HGLOBAL.
701 static HRESULT get_data_from_storage(IDataObject *data, FORMATETC *fmt, HGLOBAL *mem)
703 HGLOBAL h;
704 IStorage *stg;
705 HRESULT hr;
706 FORMATETC stg_fmt;
707 STGMEDIUM med;
708 ILockBytes *lbs;
710 *mem = NULL;
712 h = GlobalAlloc( GMEM_DDESHARE|GMEM_MOVEABLE, 0 );
713 if(!h) return E_OUTOFMEMORY;
715 hr = CreateILockBytesOnHGlobal(h, FALSE, &lbs);
716 if(SUCCEEDED(hr))
718 hr = StgCreateDocfileOnILockBytes(lbs, STGM_CREATE|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &stg);
719 ILockBytes_Release(lbs);
721 if(FAILED(hr))
723 GlobalFree(h);
724 return hr;
727 stg_fmt = *fmt;
728 med.tymed = stg_fmt.tymed = TYMED_ISTORAGE;
729 med.u.pstg = stg;
730 med.pUnkForRelease = NULL;
732 hr = IDataObject_GetDataHere(data, &stg_fmt, &med);
733 if(FAILED(hr))
735 med.u.pstg = NULL;
736 hr = IDataObject_GetData(data, &stg_fmt, &med);
737 if(FAILED(hr)) goto end;
739 hr = IStorage_CopyTo(med.u.pstg, 0, NULL, NULL, stg);
740 ReleaseStgMedium(&med);
741 if(FAILED(hr)) goto end;
743 *mem = h;
745 end:
746 IStorage_Release(stg);
747 if(FAILED(hr)) GlobalFree(h);
748 return hr;
751 /***************************************************************************
752 * get_data_from_stream
754 * Returns stream data in an HGLOBAL.
756 static HRESULT get_data_from_stream(IDataObject *data, FORMATETC *fmt, HGLOBAL *mem)
758 HGLOBAL h;
759 IStream *stm = NULL;
760 HRESULT hr;
761 FORMATETC stm_fmt;
762 STGMEDIUM med;
764 *mem = NULL;
766 h = GlobalAlloc( GMEM_DDESHARE|GMEM_MOVEABLE, 0 );
767 if(!h) return E_OUTOFMEMORY;
769 hr = CreateStreamOnHGlobal(h, FALSE, &stm);
770 if(FAILED(hr)) goto error;
772 stm_fmt = *fmt;
773 med.tymed = stm_fmt.tymed = TYMED_ISTREAM;
774 med.u.pstm = stm;
775 med.pUnkForRelease = NULL;
777 hr = IDataObject_GetDataHere(data, &stm_fmt, &med);
778 if(FAILED(hr))
780 LARGE_INTEGER offs;
781 ULARGE_INTEGER pos;
783 med.u.pstm = NULL;
784 hr = IDataObject_GetData(data, &stm_fmt, &med);
785 if(FAILED(hr)) goto error;
787 offs.QuadPart = 0;
788 IStream_Seek(med.u.pstm, offs, STREAM_SEEK_CUR, &pos);
789 IStream_Seek(med.u.pstm, offs, STREAM_SEEK_SET, NULL);
790 hr = IStream_CopyTo(med.u.pstm, stm, pos, NULL, NULL);
791 ReleaseStgMedium(&med);
792 if(FAILED(hr)) goto error;
794 *mem = h;
795 IStream_Release(stm);
796 return S_OK;
798 error:
799 if(stm) IStream_Release(stm);
800 GlobalFree(h);
801 return hr;
804 /***************************************************************************
805 * get_data_from_global
807 * Returns global data in an HGLOBAL.
809 static HRESULT get_data_from_global(IDataObject *data, FORMATETC *fmt, HGLOBAL *mem)
811 HGLOBAL h;
812 HRESULT hr;
813 FORMATETC mem_fmt;
814 STGMEDIUM med;
816 *mem = NULL;
818 mem_fmt = *fmt;
819 mem_fmt.tymed = TYMED_HGLOBAL;
821 hr = IDataObject_GetData(data, &mem_fmt, &med);
822 if(FAILED(hr)) return hr;
824 hr = dup_global_mem(med.u.hGlobal, GMEM_DDESHARE|GMEM_MOVEABLE, &h);
826 if(SUCCEEDED(hr)) *mem = h;
828 ReleaseStgMedium(&med);
830 return hr;
833 /***************************************************************************
834 * get_data_from_enhmetafile
836 static HRESULT get_data_from_enhmetafile(IDataObject *data, FORMATETC *fmt, HGLOBAL *mem)
838 HENHMETAFILE copy;
839 HRESULT hr;
840 FORMATETC mem_fmt;
841 STGMEDIUM med;
843 *mem = NULL;
845 mem_fmt = *fmt;
846 mem_fmt.tymed = TYMED_ENHMF;
848 hr = IDataObject_GetData(data, &mem_fmt, &med);
849 if(FAILED(hr)) return hr;
851 copy = CopyEnhMetaFileW(med.u.hEnhMetaFile, NULL);
852 if(copy) *mem = (HGLOBAL)copy;
853 else hr = E_FAIL;
855 ReleaseStgMedium(&med);
857 return hr;
860 /***************************************************************************
861 * get_data_from_metafilepict
863 static HRESULT get_data_from_metafilepict(IDataObject *data, FORMATETC *fmt, HGLOBAL *mem)
865 HGLOBAL copy;
866 HRESULT hr;
867 FORMATETC mem_fmt;
868 STGMEDIUM med;
870 *mem = NULL;
872 mem_fmt = *fmt;
873 mem_fmt.tymed = TYMED_MFPICT;
875 hr = IDataObject_GetData(data, &mem_fmt, &med);
876 if(FAILED(hr)) return hr;
878 hr = dup_metafilepict(med.u.hMetaFilePict, &copy);
880 if(SUCCEEDED(hr)) *mem = copy;
882 ReleaseStgMedium(&med);
884 return hr;
887 /***************************************************************************
888 * get_data_from_bitmap
890 * Returns bitmap in an HBITMAP.
892 static HRESULT get_data_from_bitmap(IDataObject *data, FORMATETC *fmt, HBITMAP *hbm)
894 HBITMAP copy;
895 HRESULT hr;
896 FORMATETC mem_fmt;
897 STGMEDIUM med;
899 *hbm = NULL;
901 mem_fmt = *fmt;
902 mem_fmt.tymed = TYMED_GDI;
904 hr = IDataObject_GetData(data, &mem_fmt, &med);
905 if(FAILED(hr)) return hr;
907 hr = dup_bitmap(med.u.hBitmap, &copy);
909 if(SUCCEEDED(hr)) *hbm = copy;
911 ReleaseStgMedium(&med);
913 return hr;
916 /***********************************************************************
917 * render_format
919 * Render the clipboard data. Note that this call will delegate to the
920 * source data object.
922 static HRESULT render_format(IDataObject *data, LPFORMATETC fmt)
924 HANDLE clip_data = NULL; /* HGLOBAL unless otherwise specified */
925 HRESULT hr;
927 /* Embed source hack */
928 if(fmt->cfFormat == embed_source_clipboard_format)
930 return render_embed_source_hack(data, fmt);
933 if(fmt->tymed & TYMED_ISTORAGE)
935 hr = get_data_from_storage(data, fmt, &clip_data);
937 else if(fmt->tymed & TYMED_ISTREAM)
939 hr = get_data_from_stream(data, fmt, &clip_data);
941 else if(fmt->tymed & TYMED_HGLOBAL)
943 hr = get_data_from_global(data, fmt, &clip_data);
945 else if(fmt->tymed & TYMED_ENHMF)
947 hr = get_data_from_enhmetafile(data, fmt, &clip_data);
949 else if(fmt->tymed & TYMED_MFPICT)
951 /* Returns global handle to METAFILEPICT, containing a copied HMETAFILE */
952 hr = get_data_from_metafilepict(data, fmt, &clip_data);
954 else if(fmt->tymed & TYMED_GDI)
956 /* Returns HBITMAP not HGLOBAL */
957 hr = get_data_from_bitmap(data, fmt, (HBITMAP *)&clip_data);
959 else
961 FIXME("Unhandled tymed %x\n", fmt->tymed);
962 hr = DV_E_FORMATETC;
965 if(SUCCEEDED(hr))
967 if ( !SetClipboardData(fmt->cfFormat, clip_data) )
969 WARN("() : Failed to set rendered clipboard data into clipboard!\n");
970 if(fmt->tymed & TYMED_MFPICT)
971 free_metafilepict(clip_data);
972 else if(fmt->tymed & TYMED_GDI)
973 DeleteObject(clip_data);
974 else
975 GlobalFree(clip_data);
976 hr = CLIPBRD_E_CANT_SET;
980 return hr;
983 /*---------------------------------------------------------------------*
984 * Implementation of the internal IDataObject interface exposed by
985 * the OLE clipboard.
986 *---------------------------------------------------------------------*/
989 /************************************************************************
990 * snapshot_QueryInterface
992 static HRESULT WINAPI snapshot_QueryInterface(IDataObject *iface,
993 REFIID riid, void **ppvObject)
995 snapshot *This = impl_from_IDataObject(iface);
996 TRACE("(%p)->(IID:%s, %p)\n", This, debugstr_guid(riid), ppvObject);
998 if ( (This==0) || (ppvObject==0) )
999 return E_INVALIDARG;
1001 *ppvObject = 0;
1003 if (IsEqualIID(&IID_IUnknown, riid) ||
1004 IsEqualIID(&IID_IDataObject, riid))
1006 *ppvObject = iface;
1008 else
1010 WARN( "() : asking for unsupported interface %s\n", debugstr_guid(riid));
1011 return E_NOINTERFACE;
1014 IUnknown_AddRef((IUnknown*)*ppvObject);
1016 return S_OK;
1019 /************************************************************************
1020 * snapshot_AddRef
1022 static ULONG WINAPI snapshot_AddRef(IDataObject *iface)
1024 snapshot *This = impl_from_IDataObject(iface);
1026 TRACE("(%p)->(count=%u)\n", This, This->ref);
1028 return InterlockedIncrement(&This->ref);
1031 /************************************************************************
1032 * snapshot_Release
1034 static ULONG WINAPI snapshot_Release(IDataObject *iface)
1036 snapshot *This = impl_from_IDataObject(iface);
1037 ULONG ref;
1039 TRACE("(%p)->(count=%u)\n", This, This->ref);
1041 ref = InterlockedDecrement(&This->ref);
1043 if (ref == 0)
1045 ole_clipbrd *clipbrd;
1046 HRESULT hr = get_ole_clipbrd(&clipbrd);
1048 if(This->data) IDataObject_Release(This->data);
1050 if(SUCCEEDED(hr) && clipbrd->latest_snapshot == This)
1051 clipbrd->latest_snapshot = NULL;
1052 HeapFree(GetProcessHeap(), 0, This);
1055 return ref;
1058 /************************************************************
1059 * get_current_ole_clip_window
1061 * Return the window that owns the ole clipboard.
1063 * If the clipboard is flushed or not owned by ole this will
1064 * return NULL.
1066 static HWND get_current_ole_clip_window(void)
1068 HGLOBAL h;
1069 HWND *ptr, wnd;
1071 h = GetClipboardData(dataobject_clipboard_format);
1072 if(!h) return NULL;
1073 ptr = GlobalLock(h);
1074 if(!ptr) return NULL;
1075 wnd = *ptr;
1076 GlobalUnlock(h);
1077 return wnd;
1080 /************************************************************
1081 * get_current_dataobject
1083 * Return an unmarshalled IDataObject if there is a current
1084 * (ie non-flushed) object on the ole clipboard.
1086 static HRESULT get_current_dataobject(IDataObject **data)
1088 HRESULT hr = S_FALSE;
1089 HWND wnd = get_current_ole_clip_window();
1090 HGLOBAL h;
1091 void *ptr;
1092 IStream *stm;
1093 LARGE_INTEGER pos;
1095 *data = NULL;
1096 if(!wnd) return S_FALSE;
1098 h = GetClipboardData(wine_marshal_clipboard_format);
1099 if(!h) return S_FALSE;
1100 if(GlobalSize(h) == 0) return S_FALSE;
1101 ptr = GlobalLock(h);
1102 if(!ptr) return S_FALSE;
1104 hr = CreateStreamOnHGlobal(NULL, TRUE, &stm);
1105 if(FAILED(hr)) goto end;
1107 hr = IStream_Write(stm, ptr, GlobalSize(h), NULL);
1108 if(SUCCEEDED(hr))
1110 pos.QuadPart = 0;
1111 IStream_Seek(stm, pos, STREAM_SEEK_SET, NULL);
1112 hr = CoUnmarshalInterface(stm, &IID_IDataObject, (void**)data);
1114 IStream_Release(stm);
1116 end:
1117 GlobalUnlock(h);
1118 return hr;
1121 static DWORD get_tymed_from_nonole_cf(UINT cf)
1123 if(cf >= 0xc000) return TYMED_ISTREAM | TYMED_HGLOBAL;
1125 switch(cf)
1127 case CF_TEXT:
1128 case CF_OEMTEXT:
1129 case CF_UNICODETEXT:
1130 return TYMED_ISTREAM | TYMED_HGLOBAL;
1131 case CF_ENHMETAFILE:
1132 return TYMED_ENHMF;
1133 case CF_METAFILEPICT:
1134 return TYMED_MFPICT;
1135 case CF_BITMAP:
1136 return TYMED_GDI;
1137 default:
1138 FIXME("returning TYMED_NULL for cf %04x\n", cf);
1139 return TYMED_NULL;
1143 /***********************************************************
1144 * get_priv_data
1146 * Returns a copy of the Ole Private Data
1148 static HRESULT get_priv_data(ole_priv_data **data)
1150 HGLOBAL handle;
1151 HRESULT hr = S_OK;
1152 ole_priv_data *ret = NULL;
1154 *data = NULL;
1156 handle = GetClipboardData( ole_private_data_clipboard_format );
1157 if(handle)
1159 ole_priv_data *src = GlobalLock(handle);
1160 if(src)
1162 DWORD i;
1164 /* FIXME: sanity check on size */
1165 ret = HeapAlloc(GetProcessHeap(), 0, src->size);
1166 if(!ret)
1168 GlobalUnlock(handle);
1169 return E_OUTOFMEMORY;
1171 memcpy(ret, src, src->size);
1172 GlobalUnlock(handle);
1174 /* Fixup any target device offsets to ptrs */
1175 for(i = 0; i < ret->count; i++)
1176 ret->entries[i].fmtetc.ptd =
1177 td_offs_to_ptr(ret, (DWORD_PTR) ret->entries[i].fmtetc.ptd);
1181 if(!ret) /* Non-ole data */
1183 UINT cf;
1184 DWORD count = 0, idx, size = FIELD_OFFSET(ole_priv_data, entries);
1186 for(cf = 0; (cf = EnumClipboardFormats(cf)) != 0; count++)
1188 char buf[100];
1189 GetClipboardFormatNameA(cf, buf, sizeof(buf));
1190 TRACE("cf %04x %s\n", cf, buf);
1192 TRACE("count %d\n", count);
1193 size += count * sizeof(ret->entries[0]);
1195 /* There are holes in fmtetc so zero init */
1196 ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
1197 if(!ret) return E_OUTOFMEMORY;
1198 ret->size = size;
1199 ret->count = count;
1201 for(cf = 0, idx = 0; (cf = EnumClipboardFormats(cf)) != 0; idx++)
1203 ret->entries[idx].fmtetc.cfFormat = cf;
1204 ret->entries[idx].fmtetc.ptd = NULL;
1205 ret->entries[idx].fmtetc.dwAspect = DVASPECT_CONTENT;
1206 ret->entries[idx].fmtetc.lindex = -1;
1207 ret->entries[idx].fmtetc.tymed = get_tymed_from_nonole_cf(cf);
1208 ret->entries[idx].first_use = 1;
1212 *data = ret;
1213 return hr;
1216 /************************************************************************
1217 * get_stgmed_for_global
1219 * Returns a stg medium with a copy of the global handle
1221 static HRESULT get_stgmed_for_global(HGLOBAL h, STGMEDIUM *med)
1223 HRESULT hr;
1225 med->pUnkForRelease = NULL;
1226 med->tymed = TYMED_NULL;
1228 hr = dup_global_mem(h, GMEM_MOVEABLE, &med->u.hGlobal);
1230 if(SUCCEEDED(hr)) med->tymed = TYMED_HGLOBAL;
1232 return hr;
1235 /************************************************************************
1236 * get_stgmed_for_stream
1238 * Returns a stg medium with a stream based on the handle
1240 static HRESULT get_stgmed_for_stream(HGLOBAL h, STGMEDIUM *med)
1242 HRESULT hr;
1243 HGLOBAL dst;
1245 med->pUnkForRelease = NULL;
1246 med->tymed = TYMED_NULL;
1248 hr = dup_global_mem(h, GMEM_MOVEABLE, &dst);
1249 if(FAILED(hr)) return hr;
1251 hr = CreateStreamOnHGlobal(dst, TRUE, &med->u.pstm);
1252 if(FAILED(hr))
1254 GlobalFree(dst);
1255 return hr;
1258 med->tymed = TYMED_ISTREAM;
1259 return hr;
1262 /************************************************************************
1263 * get_stgmed_for_storage
1265 * Returns a stg medium with a storage based on the handle
1267 static HRESULT get_stgmed_for_storage(HGLOBAL h, STGMEDIUM *med)
1269 HRESULT hr;
1270 HGLOBAL dst;
1271 ILockBytes *lbs;
1273 med->pUnkForRelease = NULL;
1274 med->tymed = TYMED_NULL;
1276 hr = dup_global_mem(h, GMEM_MOVEABLE, &dst);
1277 if(FAILED(hr)) return hr;
1279 hr = CreateILockBytesOnHGlobal(dst, TRUE, &lbs);
1280 if(FAILED(hr))
1282 GlobalFree(dst);
1283 return hr;
1286 hr = StgOpenStorageOnILockBytes(lbs, NULL, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, NULL, 0, &med->u.pstg);
1287 ILockBytes_Release(lbs);
1288 if(FAILED(hr))
1290 GlobalFree(dst);
1291 return hr;
1294 med->tymed = TYMED_ISTORAGE;
1295 return hr;
1298 /************************************************************************
1299 * get_stgmed_for_emf
1301 * Returns a stg medium with an enhanced metafile based on the handle
1303 static HRESULT get_stgmed_for_emf(HENHMETAFILE hemf, STGMEDIUM *med)
1305 med->pUnkForRelease = NULL;
1306 med->tymed = TYMED_NULL;
1308 med->u.hEnhMetaFile = CopyEnhMetaFileW(hemf, NULL);
1309 if(!med->u.hEnhMetaFile) return E_OUTOFMEMORY;
1310 med->tymed = TYMED_ENHMF;
1311 return S_OK;
1314 /************************************************************************
1315 * get_stgmed_for_bitmap
1317 * Returns a stg medium with a bitmap based on the handle
1319 static HRESULT get_stgmed_for_bitmap(HBITMAP hbmp, STGMEDIUM *med)
1321 HRESULT hr;
1323 med->pUnkForRelease = NULL;
1324 med->tymed = TYMED_NULL;
1326 hr = dup_bitmap(hbmp, &med->u.hBitmap);
1328 if (FAILED(hr))
1329 return hr;
1331 med->tymed = TYMED_GDI;
1332 return S_OK;
1335 static inline BOOL string_off_equal(const DVTARGETDEVICE *t1, WORD off1, const DVTARGETDEVICE *t2, WORD off2)
1337 const WCHAR *str1, *str2;
1339 if(off1 == 0 && off2 == 0) return TRUE;
1340 if(off1 == 0 || off2 == 0) return FALSE;
1342 str1 = (const WCHAR*)((const char*)t1 + off1);
1343 str2 = (const WCHAR*)((const char*)t2 + off2);
1345 return !lstrcmpW(str1, str2);
1348 static inline BOOL td_equal(const DVTARGETDEVICE *t1, const DVTARGETDEVICE *t2)
1350 if(t1 == NULL && t2 == NULL) return TRUE;
1351 if(t1 == NULL || t2 == NULL) return FALSE;
1353 if(!string_off_equal(t1, t1->tdDriverNameOffset, t2, t2->tdDriverNameOffset))
1354 return FALSE;
1355 if(!string_off_equal(t1, t1->tdDeviceNameOffset, t2, t2->tdDeviceNameOffset))
1356 return FALSE;
1357 if(!string_off_equal(t1, t1->tdPortNameOffset, t2, t2->tdPortNameOffset))
1358 return FALSE;
1360 /* FIXME check devmode? */
1362 return TRUE;
1365 /************************************************************************
1366 * snapshot_GetData
1368 static HRESULT WINAPI snapshot_GetData(IDataObject *iface, FORMATETC *fmt,
1369 STGMEDIUM *med)
1371 snapshot *This = impl_from_IDataObject(iface);
1372 HANDLE h;
1373 HRESULT hr;
1374 ole_priv_data *enum_data = NULL;
1375 ole_priv_data_entry *entry;
1376 DWORD mask;
1378 TRACE("(%p, %p {%s}, %p)\n", iface, fmt, dump_fmtetc(fmt), med);
1380 if ( !fmt || !med ) return E_INVALIDARG;
1382 if ( !OpenClipboard(NULL)) return CLIPBRD_E_CANT_OPEN;
1384 if(!This->data)
1385 hr = get_current_dataobject(&This->data);
1387 if(This->data)
1389 hr = IDataObject_GetData(This->data, fmt, med);
1390 CloseClipboard();
1391 return hr;
1394 h = GetClipboardData(fmt->cfFormat);
1395 if(!h)
1397 hr = DV_E_FORMATETC;
1398 goto end;
1401 hr = get_priv_data(&enum_data);
1402 if(FAILED(hr)) goto end;
1404 entry = find_format_in_list(enum_data->entries, enum_data->count, fmt->cfFormat);
1405 if(entry)
1407 if(!td_equal(fmt->ptd, entry->fmtetc.ptd))
1409 hr = DV_E_FORMATETC;
1410 goto end;
1412 mask = fmt->tymed & entry->fmtetc.tymed;
1413 if(!mask) mask = fmt->tymed & (TYMED_ISTREAM | TYMED_HGLOBAL);
1415 else /* non-Ole format */
1416 mask = fmt->tymed & TYMED_HGLOBAL;
1418 if(mask & TYMED_ISTORAGE)
1419 hr = get_stgmed_for_storage(h, med);
1420 else if(mask & TYMED_HGLOBAL)
1421 hr = get_stgmed_for_global(h, med);
1422 else if(mask & TYMED_ISTREAM)
1423 hr = get_stgmed_for_stream(h, med);
1424 else if(mask & TYMED_ENHMF)
1425 hr = get_stgmed_for_emf((HENHMETAFILE)h, med);
1426 else if(mask & TYMED_GDI)
1427 hr = get_stgmed_for_bitmap((HBITMAP)h, med);
1428 else
1430 FIXME("Unhandled tymed - mask %x req tymed %x\n", mask, fmt->tymed);
1431 hr = E_FAIL;
1432 goto end;
1435 end:
1436 HeapFree(GetProcessHeap(), 0, enum_data);
1437 if ( !CloseClipboard() ) hr = CLIPBRD_E_CANT_CLOSE;
1438 return hr;
1441 /************************************************************************
1442 * snapshot_GetDataHere
1444 static HRESULT WINAPI snapshot_GetDataHere(IDataObject *iface, FORMATETC *fmt,
1445 STGMEDIUM *med)
1447 snapshot *This = impl_from_IDataObject(iface);
1448 HANDLE h;
1449 HRESULT hr;
1450 ole_priv_data *enum_data = NULL;
1451 ole_priv_data_entry *entry;
1452 TYMED supported;
1454 if ( !fmt || !med ) return E_INVALIDARG;
1456 TRACE("(%p, %p {%s}, %p (tymed %x)\n", iface, fmt, dump_fmtetc(fmt), med, med->tymed);
1458 if ( !OpenClipboard(NULL)) return CLIPBRD_E_CANT_OPEN;
1460 if(!This->data)
1461 hr = get_current_dataobject(&This->data);
1463 if(This->data)
1465 hr = IDataObject_GetDataHere(This->data, fmt, med);
1466 if(SUCCEEDED(hr))
1468 CloseClipboard();
1469 return hr;
1473 h = GetClipboardData(fmt->cfFormat);
1474 if(!h)
1476 hr = DV_E_FORMATETC;
1477 goto end;
1480 hr = get_priv_data(&enum_data);
1481 if(FAILED(hr)) goto end;
1483 entry = find_format_in_list(enum_data->entries, enum_data->count, fmt->cfFormat);
1484 if(entry)
1486 if(!td_equal(fmt->ptd, entry->fmtetc.ptd))
1488 hr = DV_E_FORMATETC;
1489 goto end;
1491 supported = entry->fmtetc.tymed;
1493 else /* non-Ole format */
1494 supported = TYMED_HGLOBAL;
1496 switch(med->tymed)
1498 case TYMED_HGLOBAL:
1500 DWORD src_size = GlobalSize(h);
1501 DWORD dst_size = GlobalSize(med->u.hGlobal);
1502 hr = E_FAIL;
1503 if(dst_size >= src_size)
1505 void *src = GlobalLock(h);
1506 void *dst = GlobalLock(med->u.hGlobal);
1508 memcpy(dst, src, src_size);
1509 GlobalUnlock(med->u.hGlobal);
1510 GlobalUnlock(h);
1511 hr = S_OK;
1513 break;
1515 case TYMED_ISTREAM:
1517 DWORD src_size = GlobalSize(h);
1518 void *src = GlobalLock(h);
1519 hr = IStream_Write(med->u.pstm, src, src_size, NULL);
1520 GlobalUnlock(h);
1521 break;
1523 case TYMED_ISTORAGE:
1525 STGMEDIUM copy;
1526 if(!(supported & TYMED_ISTORAGE))
1528 hr = E_FAIL;
1529 goto end;
1531 hr = get_stgmed_for_storage(h, &copy);
1532 if(SUCCEEDED(hr))
1534 hr = IStorage_CopyTo(copy.u.pstg, 0, NULL, NULL, med->u.pstg);
1535 ReleaseStgMedium(&copy);
1537 break;
1539 default:
1540 FIXME("Unhandled tymed - supported %x req tymed %x\n", supported, med->tymed);
1541 hr = E_FAIL;
1542 goto end;
1545 end:
1546 HeapFree(GetProcessHeap(), 0, enum_data);
1547 if ( !CloseClipboard() ) hr = CLIPBRD_E_CANT_CLOSE;
1548 return hr;
1551 /************************************************************************
1552 * snapshot_QueryGetData
1554 * The OLE Clipboard's implementation of this method delegates to
1555 * a data source if there is one or wraps around the windows clipboard
1556 * function IsClipboardFormatAvailable() otherwise.
1559 static HRESULT WINAPI snapshot_QueryGetData(IDataObject *iface, FORMATETC *fmt)
1561 FIXME("(%p, %p {%s})\n", iface, fmt, dump_fmtetc(fmt));
1563 if (!fmt) return E_INVALIDARG;
1565 if ( fmt->dwAspect != DVASPECT_CONTENT ) return DV_E_FORMATETC;
1567 if ( fmt->lindex != -1 ) return DV_E_FORMATETC;
1569 return (IsClipboardFormatAvailable(fmt->cfFormat)) ? S_OK : DV_E_CLIPFORMAT;
1572 /************************************************************************
1573 * snapshot_GetCanonicalFormatEtc
1575 static HRESULT WINAPI snapshot_GetCanonicalFormatEtc(IDataObject *iface, FORMATETC *fmt_in,
1576 FORMATETC *fmt_out)
1578 TRACE("(%p, %p, %p)\n", iface, fmt_in, fmt_out);
1580 if ( !fmt_in || !fmt_out ) return E_INVALIDARG;
1582 *fmt_out = *fmt_in;
1583 return DATA_S_SAMEFORMATETC;
1586 /************************************************************************
1587 * snapshot_SetData
1589 * The OLE Clipboard does not implement this method
1591 static HRESULT WINAPI snapshot_SetData(IDataObject *iface, FORMATETC *fmt,
1592 STGMEDIUM *med, BOOL release)
1594 TRACE("(%p, %p, %p, %d): not implemented\n", iface, fmt, med, release);
1595 return E_NOTIMPL;
1598 /************************************************************************
1599 * snapshot_EnumFormatEtc
1602 static HRESULT WINAPI snapshot_EnumFormatEtc(IDataObject *iface, DWORD dir,
1603 IEnumFORMATETC **enum_fmt)
1605 HRESULT hr;
1606 ole_priv_data *data = NULL;
1608 TRACE("(%p, %x, %p)\n", iface, dir, enum_fmt);
1610 *enum_fmt = NULL;
1612 if ( dir != DATADIR_GET ) return E_NOTIMPL;
1613 if ( !OpenClipboard(NULL) ) return CLIPBRD_E_CANT_OPEN;
1615 hr = get_priv_data(&data);
1617 if(FAILED(hr)) goto end;
1619 hr = enum_fmtetc_construct( data, 0, enum_fmt );
1621 end:
1622 if ( !CloseClipboard() ) hr = CLIPBRD_E_CANT_CLOSE;
1623 return hr;
1626 /************************************************************************
1627 * snapshot_DAdvise
1629 * The OLE Clipboard does not implement this method
1631 static HRESULT WINAPI snapshot_DAdvise(IDataObject *iface, FORMATETC *fmt,
1632 DWORD flags, IAdviseSink *sink,
1633 DWORD *conn)
1635 TRACE("(%p, %p, %x, %p, %p): not implemented\n", iface, fmt, flags, sink, conn);
1636 return E_NOTIMPL;
1639 /************************************************************************
1640 * snapshot_DUnadvise
1642 * The OLE Clipboard does not implement this method
1644 static HRESULT WINAPI snapshot_DUnadvise(IDataObject* iface, DWORD conn)
1646 TRACE("(%p, %d): not implemented\n", iface, conn);
1647 return E_NOTIMPL;
1650 /************************************************************************
1651 * snapshot_EnumDAdvise
1653 * The OLE Clipboard does not implement this method
1655 static HRESULT WINAPI snapshot_EnumDAdvise(IDataObject* iface,
1656 IEnumSTATDATA** enum_advise)
1658 TRACE("(%p, %p): not implemented\n", iface, enum_advise);
1659 return E_NOTIMPL;
1662 static const IDataObjectVtbl snapshot_vtable =
1664 snapshot_QueryInterface,
1665 snapshot_AddRef,
1666 snapshot_Release,
1667 snapshot_GetData,
1668 snapshot_GetDataHere,
1669 snapshot_QueryGetData,
1670 snapshot_GetCanonicalFormatEtc,
1671 snapshot_SetData,
1672 snapshot_EnumFormatEtc,
1673 snapshot_DAdvise,
1674 snapshot_DUnadvise,
1675 snapshot_EnumDAdvise
1678 /*---------------------------------------------------------------------*
1679 * Internal implementation methods for the OLE clipboard
1680 *---------------------------------------------------------------------*/
1682 static snapshot *snapshot_construct(DWORD seq_no)
1684 snapshot *This;
1686 This = HeapAlloc( GetProcessHeap(), 0, sizeof(*This) );
1687 if (!This) return NULL;
1689 This->IDataObject_iface.lpVtbl = &snapshot_vtable;
1690 This->ref = 0;
1691 This->seq_no = seq_no;
1692 This->data = NULL;
1694 return This;
1697 /*********************************************************
1698 * register_clipboard_formats
1700 static void register_clipboard_formats(void)
1702 static const WCHAR OwnerLink[] = {'O','w','n','e','r','L','i','n','k',0};
1703 static const WCHAR FileName[] = {'F','i','l','e','N','a','m','e',0};
1704 static const WCHAR FileNameW[] = {'F','i','l','e','N','a','m','e','W',0};
1705 static const WCHAR DataObject[] = {'D','a','t','a','O','b','j','e','c','t',0};
1706 static const WCHAR EmbeddedObject[] = {'E','m','b','e','d','d','e','d',' ','O','b','j','e','c','t',0};
1707 static const WCHAR EmbedSource[] = {'E','m','b','e','d',' ','S','o','u','r','c','e',0};
1708 static const WCHAR CustomLinkSource[] = {'C','u','s','t','o','m',' ','L','i','n','k',' ','S','o','u','r','c','e',0};
1709 static const WCHAR LinkSource[] = {'L','i','n','k',' ','S','o','u','r','c','e',0};
1710 static const WCHAR ObjectDescriptor[] = {'O','b','j','e','c','t',' ','D','e','s','c','r','i','p','t','o','r',0};
1711 static const WCHAR LinkSourceDescriptor[] = {'L','i','n','k',' ','S','o','u','r','c','e',' ',
1712 'D','e','s','c','r','i','p','t','o','r',0};
1713 static const WCHAR OlePrivateData[] = {'O','l','e',' ','P','r','i','v','a','t','e',' ','D','a','t','a',0};
1715 static const WCHAR WineMarshalledDataObject[] = {'W','i','n','e',' ','M','a','r','s','h','a','l','l','e','d',' ',
1716 'D','a','t','a','O','b','j','e','c','t',0};
1718 ownerlink_clipboard_format = RegisterClipboardFormatW(OwnerLink);
1719 filename_clipboard_format = RegisterClipboardFormatW(FileName);
1720 filenameW_clipboard_format = RegisterClipboardFormatW(FileNameW);
1721 dataobject_clipboard_format = RegisterClipboardFormatW(DataObject);
1722 embedded_object_clipboard_format = RegisterClipboardFormatW(EmbeddedObject);
1723 embed_source_clipboard_format = RegisterClipboardFormatW(EmbedSource);
1724 custom_link_source_clipboard_format = RegisterClipboardFormatW(CustomLinkSource);
1725 link_source_clipboard_format = RegisterClipboardFormatW(LinkSource);
1726 object_descriptor_clipboard_format = RegisterClipboardFormatW(ObjectDescriptor);
1727 link_source_descriptor_clipboard_format = RegisterClipboardFormatW(LinkSourceDescriptor);
1728 ole_private_data_clipboard_format = RegisterClipboardFormatW(OlePrivateData);
1730 wine_marshal_clipboard_format = RegisterClipboardFormatW(WineMarshalledDataObject);
1733 /***********************************************************************
1734 * OLEClipbrd_Initialize()
1735 * Initializes the OLE clipboard.
1737 void OLEClipbrd_Initialize(void)
1739 register_clipboard_formats();
1741 if ( !theOleClipboard )
1743 ole_clipbrd* clipbrd;
1744 HGLOBAL h;
1746 TRACE("()\n");
1748 clipbrd = HeapAlloc( GetProcessHeap(), 0, sizeof(*clipbrd) );
1749 if (!clipbrd) return;
1751 clipbrd->latest_snapshot = NULL;
1752 clipbrd->window = NULL;
1753 clipbrd->src_data = NULL;
1754 clipbrd->cached_enum = NULL;
1756 h = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE, 0);
1757 if(!h)
1759 HeapFree(GetProcessHeap(), 0, clipbrd);
1760 return;
1763 if(FAILED(CreateStreamOnHGlobal(h, TRUE, &clipbrd->marshal_data)))
1765 GlobalFree(h);
1766 HeapFree(GetProcessHeap(), 0, clipbrd);
1767 return;
1770 theOleClipboard = clipbrd;
1774 /***********************************************************************
1775 * OLEClipbrd_UnInitialize()
1776 * Un-Initializes the OLE clipboard
1778 void OLEClipbrd_UnInitialize(void)
1780 ole_clipbrd *clipbrd = theOleClipboard;
1782 TRACE("()\n");
1784 if ( clipbrd )
1786 static const WCHAR ole32W[] = {'o','l','e','3','2',0};
1787 HINSTANCE hinst = GetModuleHandleW(ole32W);
1789 if ( clipbrd->window )
1791 DestroyWindow(clipbrd->window);
1792 UnregisterClassW( clipbrd_wndclass, hinst );
1795 IStream_Release(clipbrd->marshal_data);
1796 if (clipbrd->src_data) IDataObject_Release(clipbrd->src_data);
1797 HeapFree(GetProcessHeap(), 0, clipbrd->cached_enum);
1798 HeapFree(GetProcessHeap(), 0, clipbrd);
1799 theOleClipboard = NULL;
1803 /*********************************************************************
1804 * set_clipboard_formats
1806 * Enumerate all formats supported by the source and make
1807 * those formats available using delayed rendering using SetClipboardData.
1808 * Cache the enumeration list and make that list visibile as the
1809 * 'Ole Private Data' format on the clipboard.
1812 static HRESULT set_clipboard_formats(ole_clipbrd *clipbrd, IDataObject *data)
1814 HRESULT hr;
1815 FORMATETC fmt;
1816 IEnumFORMATETC *enum_fmt;
1817 HGLOBAL priv_data_handle;
1818 DWORD_PTR target_offset;
1819 ole_priv_data *priv_data;
1820 DWORD count = 0, needed = sizeof(*priv_data), idx;
1822 hr = IDataObject_EnumFormatEtc(data, DATADIR_GET, &enum_fmt);
1823 if(FAILED(hr)) return hr;
1825 while(IEnumFORMATETC_Next(enum_fmt, 1, &fmt, NULL) == S_OK)
1827 count++;
1828 needed += sizeof(priv_data->entries[0]);
1829 if(fmt.ptd)
1831 needed += fmt.ptd->tdSize;
1832 CoTaskMemFree(fmt.ptd);
1836 /* Windows pads the list with two empty ole_priv_data_entries, one
1837 * after the entries array and one after the target device data.
1838 * Allocating with zero init to zero these pads. */
1840 needed += sizeof(priv_data->entries[0]); /* initialisation of needed includes one of these. */
1841 priv_data_handle = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE | GMEM_ZEROINIT, needed);
1842 priv_data = GlobalLock(priv_data_handle);
1844 priv_data->unk1 = 0;
1845 priv_data->size = needed;
1846 priv_data->unk2 = 1;
1847 priv_data->count = count;
1848 priv_data->unk3[0] = 0;
1849 priv_data->unk3[1] = 0;
1851 IEnumFORMATETC_Reset(enum_fmt);
1853 idx = 0;
1854 target_offset = FIELD_OFFSET(ole_priv_data, entries[count + 1]); /* count entries + one pad. */
1856 while(IEnumFORMATETC_Next(enum_fmt, 1, &fmt, NULL) == S_OK)
1858 TRACE("%s\n", dump_fmtetc(&fmt));
1860 priv_data->entries[idx].fmtetc = fmt;
1861 if(fmt.ptd)
1863 memcpy((char*)priv_data + target_offset, fmt.ptd, fmt.ptd->tdSize);
1864 priv_data->entries[idx].fmtetc.ptd = (DVTARGETDEVICE*)target_offset;
1865 target_offset += fmt.ptd->tdSize;
1866 CoTaskMemFree(fmt.ptd);
1869 priv_data->entries[idx].first_use = !find_format_in_list(priv_data->entries, idx, fmt.cfFormat);
1870 priv_data->entries[idx].unk[0] = 0;
1871 priv_data->entries[idx].unk[1] = 0;
1873 if (priv_data->entries[idx].first_use)
1874 SetClipboardData(fmt.cfFormat, NULL);
1876 idx++;
1879 IEnumFORMATETC_Release(enum_fmt);
1881 /* Cache the list and fixup any target device offsets to ptrs */
1882 clipbrd->cached_enum = HeapAlloc(GetProcessHeap(), 0, needed);
1883 memcpy(clipbrd->cached_enum, priv_data, needed);
1884 for(idx = 0; idx < clipbrd->cached_enum->count; idx++)
1885 clipbrd->cached_enum->entries[idx].fmtetc.ptd =
1886 td_offs_to_ptr(clipbrd->cached_enum, (DWORD_PTR)clipbrd->cached_enum->entries[idx].fmtetc.ptd);
1888 GlobalUnlock(priv_data_handle);
1889 if(!SetClipboardData(ole_private_data_clipboard_format, priv_data_handle))
1891 GlobalFree(priv_data_handle);
1892 return CLIPBRD_E_CANT_SET;
1895 return S_OK;
1898 static HWND create_clipbrd_window(void);
1900 /***********************************************************************
1901 * get_clipbrd_window
1903 static inline HRESULT get_clipbrd_window(ole_clipbrd *clipbrd, HWND *wnd)
1905 if ( !clipbrd->window )
1906 clipbrd->window = create_clipbrd_window();
1908 *wnd = clipbrd->window;
1909 return *wnd ? S_OK : E_FAIL;
1913 /**********************************************************************
1914 * release_marshal_data
1916 * Releases the data and sets the stream back to zero size.
1918 static inline void release_marshal_data(IStream *stm)
1920 LARGE_INTEGER pos;
1921 ULARGE_INTEGER size;
1922 pos.QuadPart = size.QuadPart = 0;
1924 IStream_Seek(stm, pos, STREAM_SEEK_SET, NULL);
1925 CoReleaseMarshalData(stm);
1926 IStream_Seek(stm, pos, STREAM_SEEK_SET, NULL);
1927 IStream_SetSize(stm, size);
1930 /***********************************************************************
1931 * expose_marshalled_dataobject
1933 * Sets the marshalled dataobject to the clipboard. In the flushed case
1934 * we set a zero sized HGLOBAL to clear the old marshalled data.
1936 static HRESULT expose_marshalled_dataobject(ole_clipbrd *clipbrd, IDataObject *data)
1938 HGLOBAL h;
1940 if(data)
1942 HGLOBAL h_stm;
1943 GetHGlobalFromStream(clipbrd->marshal_data, &h_stm);
1944 dup_global_mem(h_stm, GMEM_DDESHARE|GMEM_MOVEABLE, &h);
1946 else /* flushed */
1947 h = GlobalAlloc(GMEM_DDESHARE|GMEM_MOVEABLE, 0);
1949 if(!h) return E_OUTOFMEMORY;
1951 if(!SetClipboardData(wine_marshal_clipboard_format, h))
1953 GlobalFree(h);
1954 return CLIPBRD_E_CANT_SET;
1956 return S_OK;
1959 /***********************************************************************
1960 * set_src_dataobject
1962 * Clears and sets the clipboard's src IDataObject.
1964 * To marshal the source dataobject we do something rather different from Windows.
1965 * We set a clipboard format which contains the marshalled data.
1966 * Windows sets two window props one of which is an IID, the other is an endpoint number.
1968 static HRESULT set_src_dataobject(ole_clipbrd *clipbrd, IDataObject *data)
1970 HRESULT hr;
1971 HWND wnd;
1973 if(FAILED(hr = get_clipbrd_window(clipbrd, &wnd))) return hr;
1975 if(clipbrd->src_data)
1977 release_marshal_data(clipbrd->marshal_data);
1979 IDataObject_Release(clipbrd->src_data);
1980 clipbrd->src_data = NULL;
1981 HeapFree(GetProcessHeap(), 0, clipbrd->cached_enum);
1982 clipbrd->cached_enum = NULL;
1985 if(data)
1987 IUnknown *unk;
1989 IDataObject_AddRef(data);
1990 clipbrd->src_data = data;
1992 IDataObject_QueryInterface(data, &IID_IUnknown, (void**)&unk);
1993 hr = CoMarshalInterface(clipbrd->marshal_data, &IID_IDataObject, unk,
1994 MSHCTX_LOCAL, NULL, MSHLFLAGS_TABLESTRONG);
1995 IUnknown_Release(unk); /* Don't hold a ref on IUnknown, we have one on IDataObject. */
1996 if(FAILED(hr)) return hr;
1997 hr = set_clipboard_formats(clipbrd, data);
1999 return hr;
2002 /***********************************************************************
2003 * clipbrd_wndproc
2005 static LRESULT CALLBACK clipbrd_wndproc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
2007 ole_clipbrd *clipbrd;
2009 get_ole_clipbrd(&clipbrd);
2011 switch (message)
2013 case WM_RENDERFORMAT:
2015 UINT cf = wparam;
2016 ole_priv_data_entry *entry;
2018 TRACE("(): WM_RENDERFORMAT(cfFormat=%x)\n", cf);
2019 entry = find_format_in_list(clipbrd->cached_enum->entries, clipbrd->cached_enum->count, cf);
2021 if(entry)
2022 render_format(clipbrd->src_data, &entry->fmtetc);
2024 break;
2027 case WM_RENDERALLFORMATS:
2029 DWORD i;
2030 ole_priv_data_entry *entries = clipbrd->cached_enum->entries;
2032 TRACE("(): WM_RENDERALLFORMATS\n");
2034 for(i = 0; i < clipbrd->cached_enum->count; i++)
2036 if(entries[i].first_use)
2037 render_format(clipbrd->src_data, &entries[i].fmtetc);
2039 break;
2042 case WM_DESTROYCLIPBOARD:
2044 TRACE("(): WM_DESTROYCLIPBOARD\n");
2046 set_src_dataobject(clipbrd, NULL);
2047 break;
2050 default:
2051 return DefWindowProcW(hwnd, message, wparam, lparam);
2054 return 0;
2058 /***********************************************************************
2059 * create_clipbrd_window
2061 static HWND create_clipbrd_window(void)
2063 WNDCLASSEXW class;
2064 static const WCHAR ole32W[] = {'o','l','e','3','2',0};
2065 static const WCHAR title[] = {'C','l','i','p','b','o','a','r','d','W','i','n','d','o','w',0};
2066 HINSTANCE hinst = GetModuleHandleW(ole32W);
2068 class.cbSize = sizeof(class);
2069 class.style = 0;
2070 class.lpfnWndProc = clipbrd_wndproc;
2071 class.cbClsExtra = 0;
2072 class.cbWndExtra = 0;
2073 class.hInstance = hinst;
2074 class.hIcon = 0;
2075 class.hCursor = 0;
2076 class.hbrBackground = 0;
2077 class.lpszMenuName = NULL;
2078 class.lpszClassName = clipbrd_wndclass;
2079 class.hIconSm = NULL;
2081 RegisterClassExW(&class);
2083 return CreateWindowW(clipbrd_wndclass, title, WS_POPUP | WS_CLIPSIBLINGS | WS_OVERLAPPED,
2084 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
2085 NULL, NULL, hinst, 0);
2088 /*********************************************************************
2089 * set_dataobject_format
2091 * Windows creates a 'DataObject' clipboard format that contains the
2092 * clipboard window's HWND or NULL if the Ole clipboard has been flushed.
2094 static HRESULT set_dataobject_format(HWND hwnd)
2096 HGLOBAL h = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE, sizeof(hwnd));
2097 HWND *data;
2099 if(!h) return E_OUTOFMEMORY;
2101 data = GlobalLock(h);
2102 *data = hwnd;
2103 GlobalUnlock(h);
2105 if(!SetClipboardData(dataobject_clipboard_format, h))
2107 GlobalFree(h);
2108 return CLIPBRD_E_CANT_SET;
2111 return S_OK;
2114 /*---------------------------------------------------------------------*
2115 * Win32 OLE clipboard API
2116 *---------------------------------------------------------------------*/
2118 /***********************************************************************
2119 * OleSetClipboard [OLE32.@]
2120 * Places a pointer to the specified data object onto the clipboard,
2121 * making the data object accessible to the OleGetClipboard function.
2123 * RETURNS
2125 * S_OK IDataObject pointer placed on the clipboard
2126 * CLIPBRD_E_CANT_OPEN OpenClipboard failed
2127 * CLIPBRD_E_CANT_EMPTY EmptyClipboard failed
2128 * CLIPBRD_E_CANT_CLOSE CloseClipboard failed
2129 * CLIPBRD_E_CANT_SET SetClipboard failed
2132 HRESULT WINAPI OleSetClipboard(IDataObject* data)
2134 HRESULT hr;
2135 ole_clipbrd *clipbrd;
2136 HWND wnd;
2138 TRACE("(%p)\n", data);
2140 if(FAILED(hr = get_ole_clipbrd(&clipbrd))) return hr;
2142 if(FAILED(hr = get_clipbrd_window(clipbrd, &wnd))) return hr;
2144 if ( !OpenClipboard(wnd) ) return CLIPBRD_E_CANT_OPEN;
2146 if ( !EmptyClipboard() )
2148 hr = CLIPBRD_E_CANT_EMPTY;
2149 goto end;
2152 hr = set_src_dataobject(clipbrd, data);
2153 if(FAILED(hr)) goto end;
2155 if(data)
2157 hr = expose_marshalled_dataobject(clipbrd, data);
2158 if(FAILED(hr)) goto end;
2159 hr = set_dataobject_format(wnd);
2162 end:
2164 if ( !CloseClipboard() ) hr = CLIPBRD_E_CANT_CLOSE;
2166 if ( FAILED(hr) )
2168 expose_marshalled_dataobject(clipbrd, NULL);
2169 set_src_dataobject(clipbrd, NULL);
2172 return hr;
2176 /***********************************************************************
2177 * OleGetClipboard [OLE32.@]
2178 * Returns a pointer to our internal IDataObject which represents the conceptual
2179 * state of the Windows clipboard. If the current clipboard already contains
2180 * an IDataObject, our internal IDataObject will delegate to this object.
2182 HRESULT WINAPI OleGetClipboard(IDataObject **obj)
2184 HRESULT hr;
2185 ole_clipbrd *clipbrd;
2186 DWORD seq_no;
2188 TRACE("(%p)\n", obj);
2190 if(!obj) return E_INVALIDARG;
2192 if(FAILED(hr = get_ole_clipbrd(&clipbrd))) return hr;
2194 seq_no = GetClipboardSequenceNumber();
2195 if(clipbrd->latest_snapshot && clipbrd->latest_snapshot->seq_no != seq_no)
2196 clipbrd->latest_snapshot = NULL;
2198 if(!clipbrd->latest_snapshot)
2200 clipbrd->latest_snapshot = snapshot_construct(seq_no);
2201 if(!clipbrd->latest_snapshot) return E_OUTOFMEMORY;
2204 *obj = &clipbrd->latest_snapshot->IDataObject_iface;
2205 IDataObject_AddRef(*obj);
2207 return S_OK;
2210 /******************************************************************************
2211 * OleFlushClipboard [OLE32.@]
2212 * Renders the data from the source IDataObject into the windows clipboard
2214 * TODO: OleFlushClipboard needs to additionally handle TYMED_IStorage media
2215 * by copying the storage into global memory. Subsequently the default
2216 * data object exposed through OleGetClipboard must convert this TYMED_HGLOBAL
2217 * back to TYMED_IStorage.
2219 HRESULT WINAPI OleFlushClipboard(void)
2221 HRESULT hr;
2222 ole_clipbrd *clipbrd;
2223 HWND wnd;
2225 TRACE("()\n");
2227 if(FAILED(hr = get_ole_clipbrd(&clipbrd))) return hr;
2229 if(FAILED(hr = get_clipbrd_window(clipbrd, &wnd))) return hr;
2232 * Already flushed or no source DataObject? Nothing to do.
2234 if (!clipbrd->src_data) return S_OK;
2236 if (!OpenClipboard(wnd)) return CLIPBRD_E_CANT_OPEN;
2238 SendMessageW(wnd, WM_RENDERALLFORMATS, 0, 0);
2240 hr = set_dataobject_format(NULL);
2242 expose_marshalled_dataobject(clipbrd, NULL);
2243 set_src_dataobject(clipbrd, NULL);
2245 if ( !CloseClipboard() ) hr = CLIPBRD_E_CANT_CLOSE;
2247 return hr;
2251 /***********************************************************************
2252 * OleIsCurrentClipboard [OLE32.@]
2254 HRESULT WINAPI OleIsCurrentClipboard(IDataObject *data)
2256 HRESULT hr;
2257 ole_clipbrd *clipbrd;
2258 TRACE("()\n");
2260 if(FAILED(hr = get_ole_clipbrd(&clipbrd))) return hr;
2262 if (data == NULL) return S_FALSE;
2264 return (data == clipbrd->src_data) ? S_OK : S_FALSE;