dmsynth: Remove DECLSPEC_HIDDEN usage.
[wine.git] / dlls / ole32 / clipboard.c
blob5d1be63a3f7298914b6a3a86562a59606a2d727e
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 APIs. 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 clipbrd_create()
175 static ole_clipbrd* theOleClipboard;
177 static CRITICAL_SECTION latest_snapshot_cs;
178 static CRITICAL_SECTION_DEBUG latest_snapshot_cs_debug =
180 0, 0, &latest_snapshot_cs,
181 { &latest_snapshot_cs_debug.ProcessLocksList, &latest_snapshot_cs_debug.ProcessLocksList },
182 0, 0, { (DWORD_PTR)(__FILE__ ": clipboard last snapshot") }
184 static CRITICAL_SECTION latest_snapshot_cs = { &latest_snapshot_cs_debug, -1, 0, 0, 0, 0 };
187 * Name of our registered OLE clipboard window class
189 static const WCHAR clipbrd_wndclass[] = L"CLIPBRDWNDCLASS";
191 UINT ownerlink_clipboard_format = 0;
192 UINT filename_clipboard_format = 0;
193 UINT filenameW_clipboard_format = 0;
194 UINT dataobject_clipboard_format = 0;
195 UINT embedded_object_clipboard_format = 0;
196 UINT embed_source_clipboard_format = 0;
197 UINT custom_link_source_clipboard_format = 0;
198 UINT link_source_clipboard_format = 0;
199 UINT object_descriptor_clipboard_format = 0;
200 UINT link_source_descriptor_clipboard_format = 0;
201 UINT ole_private_data_clipboard_format = 0;
203 static UINT wine_marshal_clipboard_format;
205 static void register_clipboard_formats(void)
207 ownerlink_clipboard_format = RegisterClipboardFormatW(L"OwnerLink");
208 filename_clipboard_format = RegisterClipboardFormatW(L"FileName");
209 filenameW_clipboard_format = RegisterClipboardFormatW(L"FileNameW");
210 dataobject_clipboard_format = RegisterClipboardFormatW(L"DataObject");
211 embedded_object_clipboard_format = RegisterClipboardFormatW(L"Embedded Object");
212 embed_source_clipboard_format = RegisterClipboardFormatW(L"Embed Source");
213 custom_link_source_clipboard_format = RegisterClipboardFormatW(L"Custom Link Source");
214 link_source_clipboard_format = RegisterClipboardFormatW(L"Link Source");
215 object_descriptor_clipboard_format = RegisterClipboardFormatW(L"Object Descriptor");
216 link_source_descriptor_clipboard_format = RegisterClipboardFormatW(L"Link Source Descriptor");
217 ole_private_data_clipboard_format = RegisterClipboardFormatW(L"Ole Private Data");
219 wine_marshal_clipboard_format = RegisterClipboardFormatW(L"Wine Marshalled DataObject");
222 static BOOL WINAPI clipbrd_create(INIT_ONCE *init_once, void *parameter, void **context)
224 ole_clipbrd* clipbrd;
225 HGLOBAL h;
227 TRACE("()\n");
229 register_clipboard_formats();
231 clipbrd = HeapAlloc( GetProcessHeap(), 0, sizeof(*clipbrd) );
232 if (!clipbrd)
234 ERR("No memory.\n");
235 return FALSE;
238 clipbrd->latest_snapshot = NULL;
239 clipbrd->window = NULL;
240 clipbrd->src_data = NULL;
241 clipbrd->cached_enum = NULL;
243 h = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE, 0);
244 if(!h)
246 ERR("No memory.\n");
247 HeapFree(GetProcessHeap(), 0, clipbrd);
248 return FALSE;
251 if(FAILED(CreateStreamOnHGlobal(h, TRUE, &clipbrd->marshal_data)))
253 ERR("CreateStreamOnHGlobal failed.\n");
254 GlobalFree(h);
255 HeapFree(GetProcessHeap(), 0, clipbrd);
256 return FALSE;
259 theOleClipboard = clipbrd;
260 return TRUE;
263 static inline HRESULT get_ole_clipbrd(ole_clipbrd **clipbrd)
265 static INIT_ONCE init_once = INIT_ONCE_STATIC_INIT;
267 if (!InitOnceExecuteOnce(&init_once, clipbrd_create, NULL, NULL))
269 *clipbrd = NULL;
270 return CO_E_NOTINITIALIZED;
273 *clipbrd = theOleClipboard;
274 return S_OK;
277 static inline const char *dump_fmtetc(FORMATETC *fmt)
279 if (!fmt) return "(null)";
280 return wine_dbg_sprintf("cf %04x ptd %p aspect %lx lindex %ld tymed %lx",
281 fmt->cfFormat, fmt->ptd, fmt->dwAspect, fmt->lindex, fmt->tymed);
284 /*---------------------------------------------------------------------*
285 * Implementation of the internal IEnumFORMATETC interface returned by
286 * the OLE clipboard's IDataObject.
287 *---------------------------------------------------------------------*/
289 typedef struct enum_fmtetc
291 IEnumFORMATETC IEnumFORMATETC_iface;
292 LONG ref;
294 UINT pos; /* current enumerator position */
295 ole_priv_data *data;
296 } enum_fmtetc;
298 static inline enum_fmtetc *impl_from_IEnumFORMATETC(IEnumFORMATETC *iface)
300 return CONTAINING_RECORD(iface, enum_fmtetc, IEnumFORMATETC_iface);
303 /************************************************************************
304 * OLEClipbrd_IEnumFORMATETC_QueryInterface (IUnknown)
306 * See Windows documentation for more details on IUnknown methods.
308 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_QueryInterface
309 (LPENUMFORMATETC iface, REFIID riid, LPVOID* ppvObj)
311 enum_fmtetc *This = impl_from_IEnumFORMATETC(iface);
313 TRACE("(%p)->(IID: %s, %p)\n", This, debugstr_guid(riid), ppvObj);
315 *ppvObj = NULL;
317 if(IsEqualIID(riid, &IID_IUnknown) ||
318 IsEqualIID(riid, &IID_IEnumFORMATETC))
320 *ppvObj = iface;
323 if(*ppvObj)
325 IEnumFORMATETC_AddRef((IEnumFORMATETC*)*ppvObj);
326 TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
327 return S_OK;
330 TRACE("-- Interface: E_NOINTERFACE\n");
331 return E_NOINTERFACE;
334 /************************************************************************
335 * OLEClipbrd_IEnumFORMATETC_AddRef (IUnknown)
338 static ULONG WINAPI OLEClipbrd_IEnumFORMATETC_AddRef(LPENUMFORMATETC iface)
340 enum_fmtetc *This = impl_from_IEnumFORMATETC(iface);
341 ULONG ref = InterlockedIncrement(&This->ref);
343 TRACE("%p, refcount %lu.\n", iface, ref);
345 return ref;
348 /************************************************************************
349 * OLEClipbrd_IEnumFORMATETC_Release (IUnknown)
351 * See Windows documentation for more details on IUnknown methods.
353 static ULONG WINAPI OLEClipbrd_IEnumFORMATETC_Release(LPENUMFORMATETC iface)
355 enum_fmtetc *This = impl_from_IEnumFORMATETC(iface);
356 ULONG ref = InterlockedDecrement(&This->ref);
358 TRACE("%p, refcount %lu.\n", iface, ref);
360 if (!ref)
362 TRACE("() - destroying IEnumFORMATETC(%p)\n",This);
363 HeapFree(GetProcessHeap(), 0, This->data);
364 HeapFree(GetProcessHeap(), 0, This);
366 return ref;
369 /************************************************************************
370 * OLEClipbrd_IEnumFORMATETC_Next (IEnumFORMATETC)
372 * Standard enumerator members for IEnumFORMATETC
374 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Next
375 (LPENUMFORMATETC iface, ULONG celt, FORMATETC *rgelt, ULONG *pceltFethed)
377 enum_fmtetc *This = impl_from_IEnumFORMATETC(iface);
378 UINT cfetch, i;
379 HRESULT hres = S_FALSE;
381 TRACE("(%p)->(pos=%u)\n", This, This->pos);
383 if (This->pos < This->data->count)
385 cfetch = This->data->count - This->pos;
386 if (cfetch >= celt)
388 cfetch = celt;
389 hres = S_OK;
392 for(i = 0; i < cfetch; i++)
394 hres = copy_formatetc(rgelt + i, &This->data->entries[This->pos++].fmtetc);
395 if(FAILED(hres)) return hres;
398 else
400 cfetch = 0;
403 if (pceltFethed)
405 *pceltFethed = cfetch;
408 return hres;
411 /************************************************************************
412 * OLEClipbrd_IEnumFORMATETC_Skip (IEnumFORMATETC)
414 * Standard enumerator members for IEnumFORMATETC
416 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Skip(LPENUMFORMATETC iface, ULONG celt)
418 enum_fmtetc *This = impl_from_IEnumFORMATETC(iface);
419 TRACE("%p, %lu.\n", iface, celt);
421 This->pos += celt;
422 if (This->pos > This->data->count)
424 This->pos = This->data->count;
425 return S_FALSE;
427 return S_OK;
430 /************************************************************************
431 * OLEClipbrd_IEnumFORMATETC_Reset (IEnumFORMATETC)
433 * Standard enumerator members for IEnumFORMATETC
435 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Reset(LPENUMFORMATETC iface)
437 enum_fmtetc *This = impl_from_IEnumFORMATETC(iface);
438 TRACE("(%p)->()\n", This);
440 This->pos = 0;
441 return S_OK;
444 static HRESULT enum_fmtetc_construct(ole_priv_data *data, UINT pos, IEnumFORMATETC **obj);
446 /************************************************************************
447 * OLEClipbrd_IEnumFORMATETC_Clone (IEnumFORMATETC)
449 * Standard enumerator members for IEnumFORMATETC
451 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Clone
452 (LPENUMFORMATETC iface, LPENUMFORMATETC* obj)
454 enum_fmtetc *This = impl_from_IEnumFORMATETC(iface);
455 ole_priv_data *new_data;
456 DWORD i;
458 TRACE("(%p)->(%p)\n", This, obj);
460 if ( !obj ) return E_INVALIDARG;
461 *obj = NULL;
463 new_data = HeapAlloc(GetProcessHeap(), 0, This->data->size);
464 if(!new_data) return E_OUTOFMEMORY;
465 memcpy(new_data, This->data, This->data->size);
467 /* Fixup any target device ptrs */
468 for(i = 0; i < This->data->count; i++)
469 new_data->entries[i].fmtetc.ptd =
470 td_offs_to_ptr(new_data, td_get_offs(This->data, i));
472 return enum_fmtetc_construct(new_data, This->pos, obj);
475 static const IEnumFORMATETCVtbl efvt =
477 OLEClipbrd_IEnumFORMATETC_QueryInterface,
478 OLEClipbrd_IEnumFORMATETC_AddRef,
479 OLEClipbrd_IEnumFORMATETC_Release,
480 OLEClipbrd_IEnumFORMATETC_Next,
481 OLEClipbrd_IEnumFORMATETC_Skip,
482 OLEClipbrd_IEnumFORMATETC_Reset,
483 OLEClipbrd_IEnumFORMATETC_Clone
486 /************************************************************************
487 * enum_fmtetc_construct
489 * Creates an IEnumFORMATETC enumerator from ole_priv_data which it then owns.
491 static HRESULT enum_fmtetc_construct(ole_priv_data *data, UINT pos, IEnumFORMATETC **obj)
493 enum_fmtetc* ef;
495 *obj = NULL;
496 ef = HeapAlloc(GetProcessHeap(), 0, sizeof(*ef));
497 if (!ef) return E_OUTOFMEMORY;
499 ef->ref = 1;
500 ef->IEnumFORMATETC_iface.lpVtbl = &efvt;
501 ef->data = data;
502 ef->pos = pos;
504 TRACE("(%p)->()\n", ef);
505 *obj = &ef->IEnumFORMATETC_iface;
506 return S_OK;
509 /***********************************************************************
510 * dup_global_mem
512 * Helper method to duplicate an HGLOBAL chunk of memory
514 static HRESULT dup_global_mem( HGLOBAL src, DWORD flags, HGLOBAL *dst )
516 void *src_ptr, *dst_ptr;
517 DWORD size;
519 *dst = NULL;
520 if ( !src ) return S_FALSE;
522 size = GlobalSize(src);
524 *dst = GlobalAlloc( flags, size );
525 if ( !*dst ) return E_OUTOFMEMORY;
527 src_ptr = GlobalLock(src);
528 dst_ptr = GlobalLock(*dst);
530 memcpy(dst_ptr, src_ptr, size);
532 GlobalUnlock(*dst);
533 GlobalUnlock(src);
535 return S_OK;
538 /***********************************************************************
539 * dup_metafilepict
541 * Helper function to duplicate a handle to a METAFILEPICT, and the
542 * contained HMETAFILE.
544 static HRESULT dup_metafilepict(HGLOBAL src, HGLOBAL *pdest)
546 HRESULT hr;
547 HGLOBAL dest;
548 METAFILEPICT *dest_ptr;
550 *pdest = NULL;
552 /* Copy the METAFILEPICT structure. */
553 hr = dup_global_mem(src, GMEM_DDESHARE|GMEM_MOVEABLE, &dest);
554 if (FAILED(hr)) return hr;
556 dest_ptr = GlobalLock(dest);
557 if (!dest_ptr) return E_FAIL;
559 /* Give the new METAFILEPICT a separate HMETAFILE. */
560 dest_ptr->hMF = CopyMetaFileW(dest_ptr->hMF, NULL);
561 if (dest_ptr->hMF)
563 GlobalUnlock(dest);
564 *pdest = dest;
565 return S_OK;
567 else
569 GlobalUnlock(dest);
570 GlobalFree(dest);
571 return E_FAIL;
575 /***********************************************************************
576 * free_metafilepict
578 * Helper function to GlobalFree a handle to a METAFILEPICT, and also
579 * free the contained HMETAFILE.
581 static void free_metafilepict(HGLOBAL src)
583 METAFILEPICT *src_ptr;
585 src_ptr = GlobalLock(src);
586 if (src_ptr)
588 DeleteMetaFile(src_ptr->hMF);
589 GlobalUnlock(src);
591 GlobalFree(src);
594 /***********************************************************************
595 * dup_bitmap
597 * Helper function to duplicate an HBITMAP.
599 static HRESULT dup_bitmap(HBITMAP src, HBITMAP *pdest)
601 HDC src_dc;
602 HGDIOBJ orig_src_bitmap;
603 BITMAP bm;
604 HBITMAP dest;
606 src_dc = CreateCompatibleDC(NULL);
607 orig_src_bitmap = SelectObject(src_dc, src);
608 GetObjectW(src, sizeof bm, &bm);
609 dest = CreateCompatibleBitmap(src_dc, bm.bmWidth, bm.bmHeight);
610 if (dest)
612 HDC dest_dc = CreateCompatibleDC(NULL);
613 HGDIOBJ orig_dest_bitmap = SelectObject(dest_dc, dest);
614 BitBlt(dest_dc, 0, 0, bm.bmWidth, bm.bmHeight, src_dc, 0, 0, SRCCOPY);
615 SelectObject(dest_dc, orig_dest_bitmap);
616 DeleteDC(dest_dc);
618 SelectObject(src_dc, orig_src_bitmap);
619 DeleteDC(src_dc);
620 *pdest = dest;
621 return dest ? S_OK : E_FAIL;
624 /************************************************************
625 * render_embed_source_hack
627 * This is clearly a hack and has no place in the clipboard code.
630 static HRESULT render_embed_source_hack(IDataObject *data, LPFORMATETC fmt)
632 STGMEDIUM std;
633 HGLOBAL hStorage = 0;
634 HRESULT hr = S_OK;
635 ILockBytes *ptrILockBytes;
637 memset(&std, 0, sizeof(STGMEDIUM));
638 std.tymed = fmt->tymed = TYMED_ISTORAGE;
640 hStorage = GlobalAlloc(GMEM_SHARE|GMEM_MOVEABLE, 0);
641 if (hStorage == NULL) return E_OUTOFMEMORY;
642 hr = CreateILockBytesOnHGlobal(hStorage, FALSE, &ptrILockBytes);
643 if (FAILED(hr))
645 GlobalFree(hStorage);
646 return hr;
649 hr = StgCreateDocfileOnILockBytes(ptrILockBytes, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &std.u.pstg);
650 ILockBytes_Release(ptrILockBytes);
652 if (FAILED(hr = IDataObject_GetDataHere(theOleClipboard->src_data, fmt, &std)))
654 WARN("() : IDataObject_GetDataHere failed to render clipboard data! (%lx)\n", hr);
655 GlobalFree(hStorage);
656 return hr;
659 if (1) /* check whether the presentation data is already -not- present */
661 FORMATETC fmt2;
662 STGMEDIUM std2;
663 METAFILEPICT *mfp = 0;
665 fmt2.cfFormat = CF_METAFILEPICT;
666 fmt2.ptd = 0;
667 fmt2.dwAspect = DVASPECT_CONTENT;
668 fmt2.lindex = -1;
669 fmt2.tymed = TYMED_MFPICT;
671 memset(&std2, 0, sizeof(STGMEDIUM));
672 std2.tymed = TYMED_MFPICT;
674 /* Get the metafile picture out of it */
676 if (SUCCEEDED(hr = IDataObject_GetData(theOleClipboard->src_data, &fmt2, &std2)))
678 mfp = GlobalLock(std2.u.hGlobal);
681 if (mfp)
683 IStream *pStream = 0;
684 void *mfBits;
685 PresentationDataHeader pdh;
686 INT nSize;
687 CLSID clsID;
688 LPOLESTR strProgID;
689 CHAR strOleTypeName[51];
690 BYTE OlePresStreamHeader [] =
692 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00,
693 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
694 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
695 0x00, 0x00, 0x00, 0x00
698 nSize = GetMetaFileBitsEx(mfp->hMF, 0, NULL);
700 memset(&pdh, 0, sizeof(PresentationDataHeader));
701 memcpy(&pdh, OlePresStreamHeader, sizeof(OlePresStreamHeader));
703 pdh.dwObjectExtentX = mfp->xExt;
704 pdh.dwObjectExtentY = mfp->yExt;
705 pdh.dwSize = nSize;
707 hr = IStorage_CreateStream(std.u.pstg, L"\2OlePres000",
708 STGM_CREATE|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, 0, &pStream);
710 hr = IStream_Write(pStream, &pdh, sizeof(PresentationDataHeader), NULL);
712 mfBits = HeapAlloc(GetProcessHeap(), 0, nSize);
713 nSize = GetMetaFileBitsEx(mfp->hMF, nSize, mfBits);
715 hr = IStream_Write(pStream, mfBits, nSize, NULL);
717 IStream_Release(pStream);
719 HeapFree(GetProcessHeap(), 0, mfBits);
721 GlobalUnlock(std2.u.hGlobal);
722 ReleaseStgMedium(&std2);
724 ReadClassStg(std.u.pstg, &clsID);
725 ProgIDFromCLSID(&clsID, &strProgID);
727 WideCharToMultiByte( CP_ACP, 0, strProgID, -1, strOleTypeName, sizeof(strOleTypeName), NULL, NULL );
728 STORAGE_CreateOleStream(std.u.pstg, 0);
729 OLECONVERT_CreateCompObjStream(std.u.pstg, strOleTypeName);
730 CoTaskMemFree(strProgID);
734 if ( !SetClipboardData( fmt->cfFormat, hStorage ) )
736 WARN("() : Failed to set rendered clipboard data into clipboard!\n");
737 GlobalFree(hStorage);
738 hr = CLIPBRD_E_CANT_SET;
741 ReleaseStgMedium(&std);
742 return hr;
745 /************************************************************************
746 * find_format_in_list
748 * Returns the first entry that matches the provided clipboard format.
750 static inline ole_priv_data_entry *find_format_in_list(ole_priv_data_entry *entries, DWORD num, UINT cf)
752 DWORD i;
753 for(i = 0; i < num; i++)
754 if(entries[i].fmtetc.cfFormat == cf)
755 return &entries[i];
757 return NULL;
760 /***************************************************************************
761 * get_data_from_storage
763 * Returns storage data in an HGLOBAL.
765 static HRESULT get_data_from_storage(IDataObject *data, FORMATETC *fmt, HGLOBAL *mem)
767 HGLOBAL h;
768 IStorage *stg;
769 HRESULT hr;
770 FORMATETC stg_fmt;
771 STGMEDIUM med;
772 ILockBytes *lbs;
774 *mem = NULL;
776 h = GlobalAlloc( GMEM_DDESHARE|GMEM_MOVEABLE, 0 );
777 if(!h) return E_OUTOFMEMORY;
779 hr = CreateILockBytesOnHGlobal(h, FALSE, &lbs);
780 if(SUCCEEDED(hr))
782 hr = StgCreateDocfileOnILockBytes(lbs, STGM_CREATE|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &stg);
783 ILockBytes_Release(lbs);
785 if(FAILED(hr))
787 GlobalFree(h);
788 return hr;
791 stg_fmt = *fmt;
792 med.tymed = stg_fmt.tymed = TYMED_ISTORAGE;
793 med.u.pstg = stg;
794 med.pUnkForRelease = NULL;
796 hr = IDataObject_GetDataHere(data, &stg_fmt, &med);
797 if(FAILED(hr))
799 memset(&med, 0, sizeof(med));
800 hr = IDataObject_GetData(data, &stg_fmt, &med);
801 if(FAILED(hr)) goto end;
803 hr = IStorage_CopyTo(med.u.pstg, 0, NULL, NULL, stg);
804 ReleaseStgMedium(&med);
805 if(FAILED(hr)) goto end;
807 *mem = h;
809 end:
810 IStorage_Release(stg);
811 if(FAILED(hr)) GlobalFree(h);
812 return hr;
815 /***************************************************************************
816 * get_data_from_stream
818 * Returns stream data in an HGLOBAL.
820 static HRESULT get_data_from_stream(IDataObject *data, FORMATETC *fmt, HGLOBAL *mem)
822 HGLOBAL h;
823 IStream *stm = NULL;
824 HRESULT hr;
825 FORMATETC stm_fmt;
826 STGMEDIUM med;
828 *mem = NULL;
830 h = GlobalAlloc( GMEM_DDESHARE|GMEM_MOVEABLE, 0 );
831 if(!h) return E_OUTOFMEMORY;
833 hr = CreateStreamOnHGlobal(h, FALSE, &stm);
834 if(FAILED(hr)) goto error;
836 stm_fmt = *fmt;
837 med.tymed = stm_fmt.tymed = TYMED_ISTREAM;
838 med.u.pstm = stm;
839 med.pUnkForRelease = NULL;
841 hr = IDataObject_GetDataHere(data, &stm_fmt, &med);
842 if(FAILED(hr))
844 LARGE_INTEGER offs;
845 ULARGE_INTEGER pos;
847 memset(&med, 0, sizeof(med));
848 hr = IDataObject_GetData(data, &stm_fmt, &med);
849 if(FAILED(hr)) goto error;
851 offs.QuadPart = 0;
852 IStream_Seek(med.u.pstm, offs, STREAM_SEEK_END, &pos);
853 IStream_Seek(med.u.pstm, offs, STREAM_SEEK_SET, NULL);
854 hr = IStream_CopyTo(med.u.pstm, stm, pos, NULL, NULL);
855 ReleaseStgMedium(&med);
856 if(FAILED(hr)) goto error;
858 *mem = h;
859 IStream_Release(stm);
860 return S_OK;
862 error:
863 if(stm) IStream_Release(stm);
864 GlobalFree(h);
865 return hr;
868 /***************************************************************************
869 * get_data_from_global
871 * Returns global data in an HGLOBAL.
873 static HRESULT get_data_from_global(IDataObject *data, FORMATETC *fmt, HGLOBAL *mem)
875 HGLOBAL h;
876 HRESULT hr;
877 FORMATETC mem_fmt;
878 STGMEDIUM med;
880 *mem = NULL;
882 mem_fmt = *fmt;
883 mem_fmt.tymed = TYMED_HGLOBAL;
884 memset(&med, 0, sizeof(med));
886 hr = IDataObject_GetData(data, &mem_fmt, &med);
887 if(FAILED(hr)) return hr;
889 hr = dup_global_mem(med.u.hGlobal, GMEM_DDESHARE|GMEM_MOVEABLE, &h);
891 if(SUCCEEDED(hr)) *mem = h;
893 ReleaseStgMedium(&med);
895 return hr;
898 /***************************************************************************
899 * get_data_from_enhmetafile
901 static HRESULT get_data_from_enhmetafile(IDataObject *data, FORMATETC *fmt, HGLOBAL *mem)
903 HENHMETAFILE copy;
904 HRESULT hr;
905 FORMATETC mem_fmt;
906 STGMEDIUM med;
908 *mem = NULL;
910 mem_fmt = *fmt;
911 mem_fmt.tymed = TYMED_ENHMF;
912 memset(&med, 0, sizeof(med));
914 hr = IDataObject_GetData(data, &mem_fmt, &med);
915 if(FAILED(hr)) return hr;
917 copy = CopyEnhMetaFileW(med.u.hEnhMetaFile, NULL);
918 if(copy) *mem = (HGLOBAL)copy;
919 else hr = E_FAIL;
921 ReleaseStgMedium(&med);
923 return hr;
926 /***************************************************************************
927 * get_data_from_metafilepict
929 static HRESULT get_data_from_metafilepict(IDataObject *data, FORMATETC *fmt, HGLOBAL *mem)
931 HGLOBAL copy;
932 HRESULT hr;
933 FORMATETC mem_fmt;
934 STGMEDIUM med;
936 *mem = NULL;
938 mem_fmt = *fmt;
939 mem_fmt.tymed = TYMED_MFPICT;
940 memset(&med, 0, sizeof(med));
942 hr = IDataObject_GetData(data, &mem_fmt, &med);
943 if(FAILED(hr)) return hr;
945 hr = dup_metafilepict(med.u.hMetaFilePict, &copy);
947 if(SUCCEEDED(hr)) *mem = copy;
949 ReleaseStgMedium(&med);
951 return hr;
954 /***************************************************************************
955 * get_data_from_bitmap
957 * Returns bitmap in an HBITMAP.
959 static HRESULT get_data_from_bitmap(IDataObject *data, FORMATETC *fmt, HBITMAP *hbm)
961 HBITMAP copy;
962 HRESULT hr;
963 FORMATETC mem_fmt;
964 STGMEDIUM med;
966 *hbm = NULL;
968 mem_fmt = *fmt;
969 mem_fmt.tymed = TYMED_GDI;
970 memset(&med, 0, sizeof(med));
972 hr = IDataObject_GetData(data, &mem_fmt, &med);
973 if(FAILED(hr)) return hr;
975 hr = dup_bitmap(med.u.hBitmap, &copy);
977 if(SUCCEEDED(hr)) *hbm = copy;
979 ReleaseStgMedium(&med);
981 return hr;
984 /***********************************************************************
985 * render_format
987 * Render the clipboard data. Note that this call will delegate to the
988 * source data object.
990 static HRESULT render_format(IDataObject *data, LPFORMATETC fmt)
992 HANDLE clip_data = NULL; /* HGLOBAL unless otherwise specified */
993 HRESULT hr;
995 /* Embed source hack */
996 if(fmt->cfFormat == embed_source_clipboard_format)
998 return render_embed_source_hack(data, fmt);
1001 if(fmt->tymed & TYMED_ISTORAGE)
1003 hr = get_data_from_storage(data, fmt, &clip_data);
1005 else if(fmt->tymed & TYMED_ISTREAM)
1007 hr = get_data_from_stream(data, fmt, &clip_data);
1009 else if(fmt->tymed & TYMED_HGLOBAL)
1011 hr = get_data_from_global(data, fmt, &clip_data);
1013 else if(fmt->tymed & TYMED_ENHMF)
1015 hr = get_data_from_enhmetafile(data, fmt, &clip_data);
1017 else if(fmt->tymed & TYMED_MFPICT)
1019 /* Returns global handle to METAFILEPICT, containing a copied HMETAFILE */
1020 hr = get_data_from_metafilepict(data, fmt, &clip_data);
1022 else if(fmt->tymed & TYMED_GDI)
1024 /* Returns HBITMAP not HGLOBAL */
1025 hr = get_data_from_bitmap(data, fmt, (HBITMAP *)&clip_data);
1027 else
1029 FIXME("Unhandled tymed %lx\n", fmt->tymed);
1030 hr = DV_E_FORMATETC;
1033 if(SUCCEEDED(hr))
1035 if ( !SetClipboardData(fmt->cfFormat, clip_data) )
1037 WARN("() : Failed to set rendered clipboard data into clipboard!\n");
1038 if(fmt->tymed & TYMED_MFPICT)
1039 free_metafilepict(clip_data);
1040 else if(fmt->tymed & TYMED_GDI)
1041 DeleteObject(clip_data);
1042 else
1043 GlobalFree(clip_data);
1044 hr = CLIPBRD_E_CANT_SET;
1048 return hr;
1051 /*---------------------------------------------------------------------*
1052 * Implementation of the internal IDataObject interface exposed by
1053 * the OLE clipboard.
1054 *---------------------------------------------------------------------*/
1057 /************************************************************************
1058 * snapshot_QueryInterface
1060 static HRESULT WINAPI snapshot_QueryInterface(IDataObject *iface,
1061 REFIID riid, void **ppvObject)
1063 snapshot *This = impl_from_IDataObject(iface);
1064 TRACE("(%p)->(IID:%s, %p)\n", This, debugstr_guid(riid), ppvObject);
1066 if ( (This==0) || (ppvObject==0) )
1067 return E_INVALIDARG;
1069 *ppvObject = 0;
1071 if (IsEqualIID(&IID_IUnknown, riid) ||
1072 IsEqualIID(&IID_IDataObject, riid))
1074 *ppvObject = iface;
1076 else
1078 WARN( "() : asking for unsupported interface %s\n", debugstr_guid(riid));
1079 return E_NOINTERFACE;
1082 IUnknown_AddRef((IUnknown*)*ppvObject);
1084 return S_OK;
1087 /************************************************************************
1088 * snapshot_AddRef
1090 static ULONG WINAPI snapshot_AddRef(IDataObject *iface)
1092 snapshot *This = impl_from_IDataObject(iface);
1093 ULONG ref = InterlockedIncrement(&This->ref);
1095 TRACE("%p, refcount %lu.\n", iface, ref);
1097 return ref;
1100 /************************************************************************
1101 * snapshot_Release
1103 static ULONG WINAPI snapshot_Release(IDataObject *iface)
1105 snapshot *This = impl_from_IDataObject(iface);
1106 ULONG ref = InterlockedDecrement(&This->ref);
1108 TRACE("%p, refcount %lu.\n", iface, ref);
1110 if (ref == 0)
1112 EnterCriticalSection(&latest_snapshot_cs);
1113 if (This->ref)
1115 LeaveCriticalSection(&latest_snapshot_cs);
1116 return ref;
1118 if (theOleClipboard->latest_snapshot == This)
1119 theOleClipboard->latest_snapshot = NULL;
1120 LeaveCriticalSection(&latest_snapshot_cs);
1122 if(This->data) IDataObject_Release(This->data);
1123 HeapFree(GetProcessHeap(), 0, This);
1126 return ref;
1129 /************************************************************
1130 * get_current_ole_clip_window
1132 * Return the window that owns the ole clipboard.
1134 * If the clipboard is flushed or not owned by ole this will
1135 * return NULL.
1137 static HWND get_current_ole_clip_window(void)
1139 HGLOBAL h;
1140 HWND *ptr, wnd;
1142 h = GetClipboardData(dataobject_clipboard_format);
1143 if(!h) return NULL;
1144 ptr = GlobalLock(h);
1145 if(!ptr) return NULL;
1146 wnd = *ptr;
1147 GlobalUnlock(h);
1148 return wnd;
1151 /************************************************************
1152 * get_current_dataobject
1154 * Return an unmarshalled IDataObject if there is a current
1155 * (ie non-flushed) object on the ole clipboard.
1157 static HRESULT get_current_dataobject(IDataObject **data)
1159 HRESULT hr = S_FALSE;
1160 HWND wnd = get_current_ole_clip_window();
1161 HGLOBAL h;
1162 void *ptr;
1163 IStream *stm;
1164 LARGE_INTEGER pos;
1166 *data = NULL;
1167 if(!wnd) return S_FALSE;
1169 h = GetClipboardData(wine_marshal_clipboard_format);
1170 if(!h) return S_FALSE;
1171 if(GlobalSize(h) <= 1) return S_FALSE;
1172 ptr = GlobalLock(h);
1173 if(!ptr) return S_FALSE;
1175 hr = CreateStreamOnHGlobal(NULL, TRUE, &stm);
1176 if(FAILED(hr)) goto end;
1178 hr = IStream_Write(stm, ptr, GlobalSize(h), NULL);
1179 if(SUCCEEDED(hr))
1181 pos.QuadPart = 0;
1182 IStream_Seek(stm, pos, STREAM_SEEK_SET, NULL);
1183 hr = CoUnmarshalInterface(stm, &IID_IDataObject, (void**)data);
1185 IStream_Release(stm);
1187 end:
1188 GlobalUnlock(h);
1189 return hr;
1192 static DWORD get_tymed_from_nonole_cf(UINT cf)
1194 if(cf >= 0xc000) return TYMED_ISTREAM | TYMED_HGLOBAL;
1196 switch(cf)
1198 case CF_TEXT:
1199 case CF_OEMTEXT:
1200 case CF_UNICODETEXT:
1201 case CF_HDROP:
1202 return TYMED_ISTREAM | TYMED_HGLOBAL;
1203 case CF_ENHMETAFILE:
1204 return TYMED_ENHMF;
1205 case CF_METAFILEPICT:
1206 return TYMED_MFPICT;
1207 case CF_BITMAP:
1208 return TYMED_GDI;
1209 default:
1210 FIXME("returning TYMED_NULL for cf %04x\n", cf);
1211 return TYMED_NULL;
1215 /***********************************************************
1216 * get_priv_data
1218 * Returns a copy of the Ole Private Data
1220 static HRESULT get_priv_data(ole_priv_data **data)
1222 HGLOBAL handle;
1223 HRESULT hr = S_OK;
1224 ole_priv_data *ret = NULL;
1226 *data = NULL;
1228 handle = GetClipboardData( ole_private_data_clipboard_format );
1229 if(handle)
1231 ole_priv_data *src = GlobalLock(handle);
1232 if(src)
1234 DWORD i;
1236 /* FIXME: sanity check on size */
1237 ret = HeapAlloc(GetProcessHeap(), 0, src->size);
1238 if(!ret)
1240 GlobalUnlock(handle);
1241 return E_OUTOFMEMORY;
1243 memcpy(ret, src, src->size);
1244 GlobalUnlock(handle);
1246 /* Fixup any target device offsets to ptrs */
1247 for(i = 0; i < ret->count; i++)
1248 ret->entries[i].fmtetc.ptd =
1249 td_offs_to_ptr(ret, (DWORD_PTR) ret->entries[i].fmtetc.ptd);
1253 if(!ret) /* Non-ole data */
1255 UINT cf;
1256 DWORD count = 0, idx, size = FIELD_OFFSET(ole_priv_data, entries);
1258 for(cf = 0; (cf = EnumClipboardFormats(cf)) != 0; count++)
1260 WCHAR buf[256];
1261 if (GetClipboardFormatNameW(cf, buf, ARRAY_SIZE(buf)))
1262 TRACE("cf %04x %s\n", cf, debugstr_w(buf));
1263 else
1264 TRACE("cf %04x\n", cf);
1266 TRACE("count %ld\n", count);
1267 size += count * sizeof(ret->entries[0]);
1269 /* There are holes in fmtetc so zero init */
1270 ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
1271 if(!ret) return E_OUTOFMEMORY;
1272 ret->size = size;
1273 ret->count = count;
1275 for(cf = 0, idx = 0; (cf = EnumClipboardFormats(cf)) != 0; idx++)
1277 ret->entries[idx].fmtetc.cfFormat = cf;
1278 ret->entries[idx].fmtetc.ptd = NULL;
1279 ret->entries[idx].fmtetc.dwAspect = DVASPECT_CONTENT;
1280 ret->entries[idx].fmtetc.lindex = -1;
1281 ret->entries[idx].fmtetc.tymed = get_tymed_from_nonole_cf(cf);
1282 ret->entries[idx].first_use = 1;
1286 *data = ret;
1287 return hr;
1290 /************************************************************************
1291 * get_stgmed_for_global
1293 * Returns a stg medium with a copy of the global handle
1295 static HRESULT get_stgmed_for_global(HGLOBAL h, STGMEDIUM *med)
1297 HRESULT hr;
1299 med->pUnkForRelease = NULL;
1300 med->tymed = TYMED_NULL;
1302 hr = dup_global_mem(h, GMEM_MOVEABLE, &med->u.hGlobal);
1304 if(SUCCEEDED(hr)) med->tymed = TYMED_HGLOBAL;
1306 return hr;
1309 /************************************************************************
1310 * get_stgmed_for_stream
1312 * Returns a stg medium with a stream based on the handle
1314 static HRESULT get_stgmed_for_stream(HGLOBAL h, STGMEDIUM *med)
1316 HRESULT hr;
1317 HGLOBAL dst;
1319 med->pUnkForRelease = NULL;
1320 med->tymed = TYMED_NULL;
1322 hr = dup_global_mem(h, GMEM_MOVEABLE, &dst);
1323 if(FAILED(hr)) return hr;
1325 hr = CreateStreamOnHGlobal(dst, TRUE, &med->u.pstm);
1326 if(FAILED(hr))
1328 GlobalFree(dst);
1329 return hr;
1332 med->tymed = TYMED_ISTREAM;
1333 return hr;
1336 /************************************************************************
1337 * get_stgmed_for_storage
1339 * Returns a stg medium with a storage based on the handle
1341 static HRESULT get_stgmed_for_storage(HGLOBAL h, STGMEDIUM *med)
1343 HRESULT hr;
1344 HGLOBAL dst;
1345 ILockBytes *lbs;
1347 med->pUnkForRelease = NULL;
1348 med->tymed = TYMED_NULL;
1350 hr = dup_global_mem(h, GMEM_MOVEABLE, &dst);
1351 if(FAILED(hr)) return hr;
1353 hr = CreateILockBytesOnHGlobal(dst, TRUE, &lbs);
1354 if(FAILED(hr))
1356 GlobalFree(dst);
1357 return hr;
1360 hr = StgIsStorageILockBytes(lbs);
1361 if(hr!=S_OK)
1363 ILockBytes_Release(lbs);
1364 GlobalFree(dst);
1365 return SUCCEEDED(hr) ? E_FAIL : hr;
1368 hr = StgOpenStorageOnILockBytes(lbs, NULL, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, NULL, 0, &med->u.pstg);
1369 ILockBytes_Release(lbs);
1370 if(FAILED(hr))
1372 GlobalFree(dst);
1373 return hr;
1376 med->tymed = TYMED_ISTORAGE;
1377 return hr;
1380 /************************************************************************
1381 * get_stgmed_for_emf
1383 * Returns a stg medium with an enhanced metafile based on the handle
1385 static HRESULT get_stgmed_for_emf(HENHMETAFILE hemf, STGMEDIUM *med)
1387 med->pUnkForRelease = NULL;
1388 med->tymed = TYMED_NULL;
1390 med->u.hEnhMetaFile = CopyEnhMetaFileW(hemf, NULL);
1391 if(!med->u.hEnhMetaFile) return E_OUTOFMEMORY;
1392 med->tymed = TYMED_ENHMF;
1393 return S_OK;
1396 /************************************************************************
1397 * get_stgmed_for_bitmap
1399 * Returns a stg medium with a bitmap based on the handle
1401 static HRESULT get_stgmed_for_bitmap(HBITMAP hbmp, STGMEDIUM *med)
1403 HRESULT hr;
1405 med->pUnkForRelease = NULL;
1406 med->tymed = TYMED_NULL;
1408 hr = dup_bitmap(hbmp, &med->u.hBitmap);
1410 if (FAILED(hr))
1411 return hr;
1413 med->tymed = TYMED_GDI;
1414 return S_OK;
1417 static inline BOOL string_off_equal(const DVTARGETDEVICE *t1, WORD off1, const DVTARGETDEVICE *t2, WORD off2)
1419 const WCHAR *str1, *str2;
1421 if(off1 == 0 && off2 == 0) return TRUE;
1422 if(off1 == 0 || off2 == 0) return FALSE;
1424 str1 = (const WCHAR*)((const char*)t1 + off1);
1425 str2 = (const WCHAR*)((const char*)t2 + off2);
1427 return !wcscmp(str1, str2);
1430 static inline BOOL td_equal(const DVTARGETDEVICE *t1, const DVTARGETDEVICE *t2)
1432 if(t1 == NULL && t2 == NULL) return TRUE;
1433 if(t1 == NULL || t2 == NULL) return FALSE;
1435 if(!string_off_equal(t1, t1->tdDriverNameOffset, t2, t2->tdDriverNameOffset))
1436 return FALSE;
1437 if(!string_off_equal(t1, t1->tdDeviceNameOffset, t2, t2->tdDeviceNameOffset))
1438 return FALSE;
1439 if(!string_off_equal(t1, t1->tdPortNameOffset, t2, t2->tdPortNameOffset))
1440 return FALSE;
1442 /* FIXME check devmode? */
1444 return TRUE;
1447 /************************************************************************
1448 * snapshot_GetData
1450 static HRESULT WINAPI snapshot_GetData(IDataObject *iface, FORMATETC *fmt,
1451 STGMEDIUM *med)
1453 snapshot *This = impl_from_IDataObject(iface);
1454 HANDLE h;
1455 HRESULT hr;
1456 ole_priv_data *enum_data = NULL;
1457 ole_priv_data_entry *entry;
1458 DWORD mask;
1460 TRACE("(%p, %p {%s}, %p)\n", iface, fmt, dump_fmtetc(fmt), med);
1462 if ( !fmt || !med ) return E_INVALIDARG;
1464 memset(med, 0, sizeof(*med));
1466 if ( !OpenClipboard(NULL)) return CLIPBRD_E_CANT_OPEN;
1468 if(!This->data)
1469 hr = get_current_dataobject(&This->data);
1471 if(This->data)
1473 hr = IDataObject_GetData(This->data, fmt, med);
1474 if(SUCCEEDED(hr))
1476 CloseClipboard();
1477 return hr;
1480 if(fmt->lindex != -1)
1482 hr = DV_E_FORMATETC;
1483 goto end;
1486 if(!IsClipboardFormatAvailable(fmt->cfFormat))
1488 hr = DV_E_FORMATETC;
1489 goto end;
1492 hr = get_priv_data(&enum_data);
1493 if(FAILED(hr)) goto end;
1495 entry = find_format_in_list(enum_data->entries, enum_data->count, fmt->cfFormat);
1496 if(entry)
1498 if(!td_equal(fmt->ptd, entry->fmtetc.ptd))
1500 hr = DV_E_FORMATETC;
1501 goto end;
1503 mask = fmt->tymed & entry->fmtetc.tymed;
1504 if(!mask && (entry->fmtetc.tymed & (TYMED_ISTREAM | TYMED_HGLOBAL | TYMED_ISTORAGE)))
1505 mask = fmt->tymed & (TYMED_ISTREAM | TYMED_HGLOBAL | TYMED_ISTORAGE);
1507 else /* non-Ole format */
1508 mask = fmt->tymed & get_tymed_from_nonole_cf(fmt->cfFormat);
1510 if(!mask)
1512 hr = DV_E_TYMED;
1513 goto end;
1516 h = GetClipboardData(fmt->cfFormat);
1517 if(!h)
1519 hr = DV_E_FORMATETC;
1520 goto end;
1523 if(mask & TYMED_HGLOBAL)
1524 hr = get_stgmed_for_global(h, med);
1525 else if(mask & TYMED_ISTREAM)
1526 hr = get_stgmed_for_stream(h, med);
1527 else if(mask & TYMED_ISTORAGE)
1528 hr = get_stgmed_for_storage(h, med);
1529 else if(mask & TYMED_ENHMF)
1530 hr = get_stgmed_for_emf((HENHMETAFILE)h, med);
1531 else if(mask & TYMED_GDI)
1532 hr = get_stgmed_for_bitmap((HBITMAP)h, med);
1533 else
1535 FIXME("Unhandled tymed - mask %lx req tymed %lx\n", mask, fmt->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_GetDataHere
1549 static HRESULT WINAPI snapshot_GetDataHere(IDataObject *iface, FORMATETC *fmt,
1550 STGMEDIUM *med)
1552 snapshot *This = impl_from_IDataObject(iface);
1553 HANDLE h;
1554 HRESULT hr;
1555 ole_priv_data *enum_data = NULL;
1556 ole_priv_data_entry *entry;
1557 TYMED supported;
1559 if ( !fmt || !med ) return E_INVALIDARG;
1561 TRACE("%p, %p {%s}, %p (tymed %lx)\n", iface, fmt, dump_fmtetc(fmt), med, med->tymed);
1563 if ( !OpenClipboard(NULL)) return CLIPBRD_E_CANT_OPEN;
1565 if(!This->data)
1566 hr = get_current_dataobject(&This->data);
1568 if(This->data)
1570 hr = IDataObject_GetDataHere(This->data, fmt, med);
1571 if(SUCCEEDED(hr))
1573 CloseClipboard();
1574 return hr;
1578 h = GetClipboardData(fmt->cfFormat);
1579 if(!h)
1581 hr = DV_E_FORMATETC;
1582 goto end;
1585 hr = get_priv_data(&enum_data);
1586 if(FAILED(hr)) goto end;
1588 entry = find_format_in_list(enum_data->entries, enum_data->count, fmt->cfFormat);
1589 if(entry)
1591 if(!td_equal(fmt->ptd, entry->fmtetc.ptd))
1593 hr = DV_E_FORMATETC;
1594 goto end;
1596 supported = entry->fmtetc.tymed;
1598 else /* non-Ole format */
1599 supported = TYMED_HGLOBAL;
1601 switch(med->tymed)
1603 case TYMED_HGLOBAL:
1605 DWORD src_size = GlobalSize(h);
1606 DWORD dst_size = GlobalSize(med->u.hGlobal);
1607 hr = E_FAIL;
1608 if(dst_size >= src_size)
1610 void *src = GlobalLock(h);
1611 void *dst = GlobalLock(med->u.hGlobal);
1613 memcpy(dst, src, src_size);
1614 GlobalUnlock(med->u.hGlobal);
1615 GlobalUnlock(h);
1616 hr = S_OK;
1618 break;
1620 case TYMED_ISTREAM:
1622 DWORD src_size = GlobalSize(h);
1623 void *src = GlobalLock(h);
1624 hr = IStream_Write(med->u.pstm, src, src_size, NULL);
1625 GlobalUnlock(h);
1626 break;
1628 case TYMED_ISTORAGE:
1630 STGMEDIUM copy;
1631 if(!(supported & TYMED_ISTORAGE))
1633 hr = E_FAIL;
1634 goto end;
1636 hr = get_stgmed_for_storage(h, &copy);
1637 if(SUCCEEDED(hr))
1639 hr = IStorage_CopyTo(copy.u.pstg, 0, NULL, NULL, med->u.pstg);
1640 ReleaseStgMedium(&copy);
1642 break;
1644 default:
1645 FIXME("Unhandled tymed - supported %x req tymed %lx\n", supported, med->tymed);
1646 hr = E_FAIL;
1647 goto end;
1650 end:
1651 HeapFree(GetProcessHeap(), 0, enum_data);
1652 if ( !CloseClipboard() ) hr = CLIPBRD_E_CANT_CLOSE;
1653 return hr;
1656 /************************************************************************
1657 * snapshot_QueryGetData
1659 * The OLE Clipboard's implementation of this method delegates to
1660 * a data source if there is one or wraps around the windows clipboard
1661 * function IsClipboardFormatAvailable() otherwise.
1664 static HRESULT WINAPI snapshot_QueryGetData(IDataObject *iface, FORMATETC *fmt)
1666 TRACE("(%p, %p {%s})\n", iface, fmt, dump_fmtetc(fmt));
1668 if (!fmt) return E_INVALIDARG;
1670 if ( fmt->dwAspect != DVASPECT_CONTENT ) return DV_E_FORMATETC;
1672 if ( fmt->lindex != -1 ) return DV_E_FORMATETC;
1674 return (IsClipboardFormatAvailable(fmt->cfFormat)) ? S_OK : DV_E_CLIPFORMAT;
1677 /************************************************************************
1678 * snapshot_GetCanonicalFormatEtc
1680 static HRESULT WINAPI snapshot_GetCanonicalFormatEtc(IDataObject *iface, FORMATETC *fmt_in,
1681 FORMATETC *fmt_out)
1683 TRACE("(%p, %p, %p)\n", iface, fmt_in, fmt_out);
1685 if ( !fmt_in || !fmt_out ) return E_INVALIDARG;
1687 *fmt_out = *fmt_in;
1688 return DATA_S_SAMEFORMATETC;
1691 /************************************************************************
1692 * snapshot_SetData
1694 * The OLE Clipboard does not implement this method
1696 static HRESULT WINAPI snapshot_SetData(IDataObject *iface, FORMATETC *fmt,
1697 STGMEDIUM *med, BOOL release)
1699 TRACE("(%p, %p, %p, %d): not implemented\n", iface, fmt, med, release);
1700 return E_NOTIMPL;
1703 /************************************************************************
1704 * snapshot_EnumFormatEtc
1707 static HRESULT WINAPI snapshot_EnumFormatEtc(IDataObject *iface, DWORD dir,
1708 IEnumFORMATETC **enum_fmt)
1710 HRESULT hr;
1711 ole_priv_data *data = NULL;
1713 TRACE("%p, %lx, %p.\n", iface, dir, enum_fmt);
1715 *enum_fmt = NULL;
1717 if ( dir != DATADIR_GET ) return E_NOTIMPL;
1718 if ( !OpenClipboard(NULL) ) return CLIPBRD_E_CANT_OPEN;
1720 hr = get_priv_data(&data);
1722 if(FAILED(hr)) goto end;
1724 hr = enum_fmtetc_construct( data, 0, enum_fmt );
1726 end:
1727 if ( !CloseClipboard() ) hr = CLIPBRD_E_CANT_CLOSE;
1728 return hr;
1731 /************************************************************************
1732 * snapshot_DAdvise
1734 * The OLE Clipboard does not implement this method
1736 static HRESULT WINAPI snapshot_DAdvise(IDataObject *iface, FORMATETC *fmt,
1737 DWORD flags, IAdviseSink *sink,
1738 DWORD *conn)
1740 TRACE("%p, %p, %lx, %p, %p.\n", iface, fmt, flags, sink, conn);
1741 return E_NOTIMPL;
1744 /************************************************************************
1745 * snapshot_DUnadvise
1747 * The OLE Clipboard does not implement this method
1749 static HRESULT WINAPI snapshot_DUnadvise(IDataObject* iface, DWORD conn)
1751 TRACE("%p, %ld.\n", iface, conn);
1752 return E_NOTIMPL;
1755 /************************************************************************
1756 * snapshot_EnumDAdvise
1758 * The OLE Clipboard does not implement this method
1760 static HRESULT WINAPI snapshot_EnumDAdvise(IDataObject* iface,
1761 IEnumSTATDATA** enum_advise)
1763 TRACE("(%p, %p): not implemented\n", iface, enum_advise);
1764 return E_NOTIMPL;
1767 static const IDataObjectVtbl snapshot_vtable =
1769 snapshot_QueryInterface,
1770 snapshot_AddRef,
1771 snapshot_Release,
1772 snapshot_GetData,
1773 snapshot_GetDataHere,
1774 snapshot_QueryGetData,
1775 snapshot_GetCanonicalFormatEtc,
1776 snapshot_SetData,
1777 snapshot_EnumFormatEtc,
1778 snapshot_DAdvise,
1779 snapshot_DUnadvise,
1780 snapshot_EnumDAdvise
1783 /*---------------------------------------------------------------------*
1784 * Internal implementation methods for the OLE clipboard
1785 *---------------------------------------------------------------------*/
1787 static snapshot *snapshot_construct(DWORD seq_no)
1789 snapshot *This;
1791 This = HeapAlloc( GetProcessHeap(), 0, sizeof(*This) );
1792 if (!This) return NULL;
1794 This->IDataObject_iface.lpVtbl = &snapshot_vtable;
1795 This->ref = 0;
1796 This->seq_no = seq_no;
1797 This->data = NULL;
1799 return This;
1802 /*********************************************************************
1803 * set_clipboard_formats
1805 * Enumerate all formats supported by the source and make
1806 * those formats available using delayed rendering using SetClipboardData.
1807 * Cache the enumeration list and make that list visible as the
1808 * 'Ole Private Data' format on the clipboard.
1811 static HRESULT set_clipboard_formats(ole_clipbrd *clipbrd, IDataObject *data)
1813 HRESULT hr;
1814 FORMATETC fmt;
1815 IEnumFORMATETC *enum_fmt;
1816 HGLOBAL priv_data_handle;
1817 DWORD_PTR target_offset;
1818 ole_priv_data *priv_data;
1819 DWORD count = 0, needed = sizeof(*priv_data), idx;
1821 hr = IDataObject_EnumFormatEtc(data, DATADIR_GET, &enum_fmt);
1822 if(FAILED(hr)) return hr;
1824 while(IEnumFORMATETC_Next(enum_fmt, 1, &fmt, NULL) == S_OK)
1826 count++;
1827 needed += sizeof(priv_data->entries[0]);
1828 if(fmt.ptd)
1830 needed += fmt.ptd->tdSize;
1831 CoTaskMemFree(fmt.ptd);
1835 /* Windows pads the list with two empty ole_priv_data_entries, one
1836 * after the entries array and one after the target device data.
1837 * Allocating with zero init to zero these pads. */
1839 needed += sizeof(priv_data->entries[0]); /* initialisation of needed includes one of these. */
1840 priv_data_handle = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE | GMEM_ZEROINIT, needed);
1841 priv_data = GlobalLock(priv_data_handle);
1843 priv_data->unk1 = 0;
1844 priv_data->size = needed;
1845 priv_data->unk2 = 1;
1846 priv_data->count = count;
1847 priv_data->unk3[0] = 0;
1848 priv_data->unk3[1] = 0;
1850 IEnumFORMATETC_Reset(enum_fmt);
1852 idx = 0;
1853 target_offset = FIELD_OFFSET(ole_priv_data, entries[count + 1]); /* count entries + one pad. */
1855 while(IEnumFORMATETC_Next(enum_fmt, 1, &fmt, NULL) == S_OK)
1857 TRACE("%s\n", dump_fmtetc(&fmt));
1859 priv_data->entries[idx].fmtetc = fmt;
1860 if(fmt.ptd)
1862 memcpy((char*)priv_data + target_offset, fmt.ptd, fmt.ptd->tdSize);
1863 priv_data->entries[idx].fmtetc.ptd = (DVTARGETDEVICE*)target_offset;
1864 target_offset += fmt.ptd->tdSize;
1865 CoTaskMemFree(fmt.ptd);
1868 priv_data->entries[idx].first_use = !find_format_in_list(priv_data->entries, idx, fmt.cfFormat);
1869 priv_data->entries[idx].unk[0] = 0;
1870 priv_data->entries[idx].unk[1] = 0;
1872 if (priv_data->entries[idx].first_use)
1873 SetClipboardData(fmt.cfFormat, NULL);
1875 idx++;
1878 IEnumFORMATETC_Release(enum_fmt);
1880 /* Cache the list and fixup any target device offsets to ptrs */
1881 clipbrd->cached_enum = HeapAlloc(GetProcessHeap(), 0, needed);
1882 memcpy(clipbrd->cached_enum, priv_data, needed);
1883 for(idx = 0; idx < clipbrd->cached_enum->count; idx++)
1884 clipbrd->cached_enum->entries[idx].fmtetc.ptd =
1885 td_offs_to_ptr(clipbrd->cached_enum, (DWORD_PTR)clipbrd->cached_enum->entries[idx].fmtetc.ptd);
1887 GlobalUnlock(priv_data_handle);
1888 if(!SetClipboardData(ole_private_data_clipboard_format, priv_data_handle))
1890 GlobalFree(priv_data_handle);
1891 return CLIPBRD_E_CANT_SET;
1894 return S_OK;
1897 static HWND create_clipbrd_window(void);
1899 /***********************************************************************
1900 * get_clipbrd_window
1902 static inline HRESULT get_clipbrd_window(ole_clipbrd *clipbrd, HWND *wnd)
1904 if ( !clipbrd->window )
1905 clipbrd->window = create_clipbrd_window();
1907 *wnd = clipbrd->window;
1908 return *wnd ? S_OK : E_FAIL;
1912 /**********************************************************************
1913 * release_marshal_data
1915 * Releases the data and sets the stream back to zero size.
1917 static inline void release_marshal_data(IStream *stm)
1919 LARGE_INTEGER pos;
1920 ULARGE_INTEGER size;
1921 pos.QuadPart = size.QuadPart = 0;
1923 IStream_Seek(stm, pos, STREAM_SEEK_SET, NULL);
1924 CoReleaseMarshalData(stm);
1925 IStream_Seek(stm, pos, STREAM_SEEK_SET, NULL);
1926 IStream_SetSize(stm, size);
1929 /***********************************************************************
1930 * expose_marshalled_dataobject
1932 * Sets the marshalled dataobject to the clipboard. In the flushed case
1933 * we set a zero sized HGLOBAL to clear the old marshalled data.
1935 static HRESULT expose_marshalled_dataobject(ole_clipbrd *clipbrd, IDataObject *data)
1937 HGLOBAL h;
1939 if(data)
1941 HGLOBAL h_stm;
1942 GetHGlobalFromStream(clipbrd->marshal_data, &h_stm);
1943 dup_global_mem(h_stm, GMEM_DDESHARE|GMEM_MOVEABLE, &h);
1945 else /* flushed */
1946 h = GlobalAlloc(GMEM_DDESHARE|GMEM_MOVEABLE, 1);
1948 if(!h) return E_OUTOFMEMORY;
1950 if(!SetClipboardData(wine_marshal_clipboard_format, h))
1952 GlobalFree(h);
1953 return CLIPBRD_E_CANT_SET;
1955 return S_OK;
1958 /***********************************************************************
1959 * set_src_dataobject
1961 * Clears and sets the clipboard's src IDataObject.
1963 * To marshal the source dataobject we do something rather different from Windows.
1964 * We set a clipboard format which contains the marshalled data.
1965 * Windows sets two window props one of which is an IID, the other is an endpoint number.
1967 static HRESULT set_src_dataobject(ole_clipbrd *clipbrd, IDataObject *data)
1969 HRESULT hr;
1970 HWND wnd;
1972 if(FAILED(hr = get_clipbrd_window(clipbrd, &wnd))) return hr;
1974 if(clipbrd->src_data)
1976 release_marshal_data(clipbrd->marshal_data);
1978 IDataObject_Release(clipbrd->src_data);
1979 clipbrd->src_data = NULL;
1980 HeapFree(GetProcessHeap(), 0, clipbrd->cached_enum);
1981 clipbrd->cached_enum = NULL;
1984 if(data)
1986 IUnknown *unk;
1988 IDataObject_AddRef(data);
1989 clipbrd->src_data = data;
1991 IDataObject_QueryInterface(data, &IID_IUnknown, (void**)&unk);
1992 hr = CoMarshalInterface(clipbrd->marshal_data, &IID_IDataObject, unk,
1993 MSHCTX_LOCAL, NULL, MSHLFLAGS_TABLESTRONG);
1994 IUnknown_Release(unk); /* Don't hold a ref on IUnknown, we have one on IDataObject. */
1995 if(FAILED(hr)) return hr;
1996 hr = set_clipboard_formats(clipbrd, data);
1998 return hr;
2001 /***********************************************************************
2002 * clipbrd_uninitialize()
2003 * Un-Initializes the OLE clipboard
2005 void clipbrd_uninitialize(void)
2007 ole_clipbrd *clipbrd = theOleClipboard;
2009 TRACE("()\n");
2011 if ( clipbrd )
2013 /* OleUninitialize() does not release the reference to the dataobject, so
2014 take an additional reference here. This reference is then leaked. */
2015 if (clipbrd->src_data)
2017 IDataObject_AddRef(clipbrd->src_data);
2018 set_src_dataobject(clipbrd, NULL);
2021 if ( clipbrd->window )
2023 DestroyWindow(clipbrd->window);
2024 UnregisterClassW( clipbrd_wndclass, GetModuleHandleW(L"ole32") );
2025 clipbrd->window = NULL;
2030 /***********************************************************************
2031 * clipbrd_destroy()
2032 * Destroy the OLE clipboard
2034 void clipbrd_destroy(void)
2036 ole_clipbrd *clipbrd = theOleClipboard;
2038 if (!clipbrd) return;
2040 clipbrd_uninitialize();
2042 IStream_Release(clipbrd->marshal_data);
2043 HeapFree(GetProcessHeap(), 0, clipbrd);
2044 theOleClipboard = NULL;
2047 /***********************************************************************
2048 * clipbrd_wndproc
2050 static LRESULT CALLBACK clipbrd_wndproc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
2052 ole_clipbrd *clipbrd;
2054 get_ole_clipbrd(&clipbrd);
2056 switch (message)
2058 case WM_RENDERFORMAT:
2060 UINT cf = wparam;
2061 ole_priv_data_entry *entry;
2063 TRACE("(): WM_RENDERFORMAT(cfFormat=%x)\n", cf);
2065 if (!clipbrd || !clipbrd->cached_enum) break;
2066 entry = find_format_in_list(clipbrd->cached_enum->entries, clipbrd->cached_enum->count, cf);
2068 if(entry)
2069 render_format(clipbrd->src_data, &entry->fmtetc);
2071 break;
2074 case WM_RENDERALLFORMATS:
2076 DWORD i;
2077 ole_priv_data_entry *entries;
2079 TRACE("(): WM_RENDERALLFORMATS\n");
2081 if (!clipbrd || !clipbrd->cached_enum) break;
2082 entries = clipbrd->cached_enum->entries;
2083 for(i = 0; i < clipbrd->cached_enum->count; i++)
2085 if(entries[i].first_use)
2086 render_format(clipbrd->src_data, &entries[i].fmtetc);
2088 break;
2091 case WM_DESTROYCLIPBOARD:
2093 TRACE("(): WM_DESTROYCLIPBOARD\n");
2095 set_src_dataobject(clipbrd, NULL);
2096 break;
2099 default:
2100 return DefWindowProcW(hwnd, message, wparam, lparam);
2103 return 0;
2107 /***********************************************************************
2108 * create_clipbrd_window
2110 static HWND create_clipbrd_window(void)
2112 WNDCLASSEXW class;
2113 HINSTANCE hinst = GetModuleHandleW(L"ole32");
2115 class.cbSize = sizeof(class);
2116 class.style = 0;
2117 class.lpfnWndProc = clipbrd_wndproc;
2118 class.cbClsExtra = 0;
2119 class.cbWndExtra = 0;
2120 class.hInstance = hinst;
2121 class.hIcon = 0;
2122 class.hCursor = 0;
2123 class.hbrBackground = 0;
2124 class.lpszMenuName = NULL;
2125 class.lpszClassName = clipbrd_wndclass;
2126 class.hIconSm = NULL;
2128 RegisterClassExW(&class);
2130 return CreateWindowW(clipbrd_wndclass, L"ClipboardWindow", WS_POPUP | WS_CLIPSIBLINGS | WS_OVERLAPPED,
2131 0, 0, 0, 0, HWND_MESSAGE, NULL, hinst, 0);
2134 /*********************************************************************
2135 * set_dataobject_format
2137 * Windows creates a 'DataObject' clipboard format that contains the
2138 * clipboard window's HWND or NULL if the Ole clipboard has been flushed.
2140 static HRESULT set_dataobject_format(HWND hwnd)
2142 HGLOBAL h = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE, sizeof(hwnd));
2143 HWND *data;
2145 if(!h) return E_OUTOFMEMORY;
2147 data = GlobalLock(h);
2148 *data = hwnd;
2149 GlobalUnlock(h);
2151 if(!SetClipboardData(dataobject_clipboard_format, h))
2153 GlobalFree(h);
2154 return CLIPBRD_E_CANT_SET;
2157 return S_OK;
2160 /*---------------------------------------------------------------------*
2161 * Win32 OLE clipboard API
2162 *---------------------------------------------------------------------*/
2164 /***********************************************************************
2165 * OleSetClipboard [OLE32.@]
2166 * Places a pointer to the specified data object onto the clipboard,
2167 * making the data object accessible to the OleGetClipboard function.
2169 * RETURNS
2171 * S_OK IDataObject pointer placed on the clipboard
2172 * CLIPBRD_E_CANT_OPEN OpenClipboard failed
2173 * CLIPBRD_E_CANT_EMPTY EmptyClipboard failed
2174 * CLIPBRD_E_CANT_CLOSE CloseClipboard failed
2175 * CLIPBRD_E_CANT_SET SetClipboard failed
2178 HRESULT WINAPI OleSetClipboard(IDataObject* data)
2180 struct oletls *info = COM_CurrentInfo();
2181 HRESULT hr;
2182 ole_clipbrd *clipbrd;
2183 HWND wnd;
2185 TRACE("(%p)\n", data);
2187 if(!info->ole_inits)
2188 return CO_E_NOTINITIALIZED;
2190 if(FAILED(hr = get_ole_clipbrd(&clipbrd))) return hr;
2192 if(FAILED(hr = get_clipbrd_window(clipbrd, &wnd))) return hr;
2194 if ( !OpenClipboard(wnd) ) return CLIPBRD_E_CANT_OPEN;
2196 if ( !EmptyClipboard() )
2198 hr = CLIPBRD_E_CANT_EMPTY;
2199 goto end;
2202 hr = set_src_dataobject(clipbrd, data);
2203 if(FAILED(hr)) goto end;
2205 if(data)
2207 hr = expose_marshalled_dataobject(clipbrd, data);
2208 if(FAILED(hr)) goto end;
2209 hr = set_dataobject_format(wnd);
2212 end:
2214 if ( !CloseClipboard() ) hr = CLIPBRD_E_CANT_CLOSE;
2216 if ( FAILED(hr) )
2218 expose_marshalled_dataobject(clipbrd, NULL);
2219 set_src_dataobject(clipbrd, NULL);
2222 return hr;
2226 /***********************************************************************
2227 * OleGetClipboard [OLE32.@]
2228 * Returns a pointer to our internal IDataObject which represents the conceptual
2229 * state of the Windows clipboard. If the current clipboard already contains
2230 * an IDataObject, our internal IDataObject will delegate to this object.
2232 HRESULT WINAPI OleGetClipboard(IDataObject **obj)
2234 HRESULT hr;
2235 ole_clipbrd *clipbrd;
2236 DWORD seq_no;
2238 TRACE("(%p)\n", obj);
2240 if(!obj) return E_INVALIDARG;
2241 *obj = NULL;
2243 if(FAILED(hr = get_ole_clipbrd(&clipbrd))) return hr;
2245 seq_no = GetClipboardSequenceNumber();
2246 EnterCriticalSection(&latest_snapshot_cs);
2247 if(clipbrd->latest_snapshot && clipbrd->latest_snapshot->seq_no != seq_no)
2248 clipbrd->latest_snapshot = NULL;
2250 if(!clipbrd->latest_snapshot)
2252 clipbrd->latest_snapshot = snapshot_construct(seq_no);
2253 if(!clipbrd->latest_snapshot)
2255 LeaveCriticalSection(&latest_snapshot_cs);
2256 return E_OUTOFMEMORY;
2260 *obj = &clipbrd->latest_snapshot->IDataObject_iface;
2261 IDataObject_AddRef(*obj);
2262 LeaveCriticalSection(&latest_snapshot_cs);
2264 return S_OK;
2267 /******************************************************************************
2268 * OleFlushClipboard [OLE32.@]
2269 * Renders the data from the source IDataObject into the windows clipboard
2271 * TODO: OleFlushClipboard needs to additionally handle TYMED_IStorage media
2272 * by copying the storage into global memory. Subsequently the default
2273 * data object exposed through OleGetClipboard must convert this TYMED_HGLOBAL
2274 * back to TYMED_IStorage.
2276 HRESULT WINAPI OleFlushClipboard(void)
2278 struct oletls *info = COM_CurrentInfo();
2279 HRESULT hr;
2280 ole_clipbrd *clipbrd;
2281 HWND wnd;
2283 TRACE("()\n");
2285 if(FAILED(hr = get_ole_clipbrd(&clipbrd))) return hr;
2287 if(!info->ole_inits)
2288 return E_FAIL;
2290 if(FAILED(hr = get_clipbrd_window(clipbrd, &wnd))) return hr;
2293 * Already flushed or no source DataObject? Nothing to do.
2295 if (!clipbrd->src_data) return S_OK;
2297 if (!OpenClipboard(wnd)) return CLIPBRD_E_CANT_OPEN;
2299 SendMessageW(wnd, WM_RENDERALLFORMATS, 0, 0);
2301 hr = set_dataobject_format(NULL);
2303 expose_marshalled_dataobject(clipbrd, NULL);
2304 set_src_dataobject(clipbrd, NULL);
2306 if ( !CloseClipboard() ) hr = CLIPBRD_E_CANT_CLOSE;
2308 return hr;
2312 /***********************************************************************
2313 * OleIsCurrentClipboard [OLE32.@]
2315 HRESULT WINAPI OleIsCurrentClipboard(IDataObject *data)
2317 HRESULT hr;
2318 ole_clipbrd *clipbrd;
2319 TRACE("()\n");
2321 if(FAILED(hr = get_ole_clipbrd(&clipbrd))) return hr;
2323 if (data == NULL) return S_FALSE;
2325 return (data == clipbrd->src_data) ? S_OK : S_FALSE;