wined3d: Use return type to return result from read_dword.
[wine.git] / dlls / ole32 / clipboard.c
blobc54608985fbd811f746ae08e8568dac5172d1a5e
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 #include "windef.h"
68 #include "winbase.h"
69 #include "wingdi.h"
70 #include "winuser.h"
71 #include "winerror.h"
72 #include "winnls.h"
73 #include "ole2.h"
74 #include "wine/debug.h"
75 #include "olestd.h"
77 #include "storage32.h"
79 #include "compobj_private.h"
81 WINE_DEFAULT_DEBUG_CHANNEL(ole);
83 /* Structure of 'Ole Private Data' clipboard format */
84 typedef struct
86 FORMATETC fmtetc;
87 DWORD first_use; /* Has this cf been added to the list already */
88 DWORD unk[2];
89 } ole_priv_data_entry;
91 typedef struct
93 DWORD unk1;
94 DWORD size; /* in bytes of the entire structure */
95 DWORD unk2;
96 DWORD count; /* no. of format entries */
97 DWORD unk3[2];
98 ole_priv_data_entry entries[1]; /* array of size count */
99 /* then follows any DVTARGETDEVICE structures referenced in the FORMATETCs */
100 } ole_priv_data;
102 /*****************************************************************************
103 * td_offs_to_ptr
105 * Returns a ptr to a target device at a given offset from the
106 * start of the ole_priv_data.
108 * Used when unpacking ole private data from the clipboard.
110 static inline DVTARGETDEVICE *td_offs_to_ptr(ole_priv_data *data, DWORD_PTR off)
112 if(off == 0) return NULL;
113 return (DVTARGETDEVICE*)((char*)data + off);
116 /*****************************************************************************
117 * td_get_offs
119 * Get the offset from the start of the ole_priv_data of the idx'th
120 * target device.
122 * Used when packing ole private data to the clipboard.
124 static inline DWORD_PTR td_get_offs(ole_priv_data *data, DWORD idx)
126 if(data->entries[idx].fmtetc.ptd == NULL) return 0;
127 return (char*)data->entries[idx].fmtetc.ptd - (char*)data;
130 /****************************************************************************
131 * Consumer snapshot. Represents the state of the ole clipboard
132 * returned by OleGetClipboard().
134 typedef struct snapshot
136 IDataObject IDataObject_iface;
137 LONG ref;
139 DWORD seq_no; /* Clipboard sequence number corresponding to this snapshot */
141 IDataObject *data; /* If we unmarshal a remote data object we hold a ref here */
142 } snapshot;
144 /****************************************************************************
145 * ole_clipbrd
147 typedef struct ole_clipbrd
149 snapshot *latest_snapshot; /* Latest consumer snapshot */
151 HWND window; /* Hidden clipboard window */
152 IDataObject *src_data; /* Source object passed to OleSetClipboard */
153 ole_priv_data *cached_enum; /* Cached result from the enumeration of src data object */
154 IStream *marshal_data; /* Stream onto which to marshal src_data */
155 } ole_clipbrd;
157 static inline snapshot *impl_from_IDataObject(IDataObject *iface)
159 return CONTAINING_RECORD(iface, snapshot, IDataObject_iface);
162 typedef struct PresentationDataHeader
164 BYTE unknown1[28];
165 DWORD dwObjectExtentX;
166 DWORD dwObjectExtentY;
167 DWORD dwSize;
168 } PresentationDataHeader;
171 * The one and only ole_clipbrd object which is created by clipbrd_create()
173 static ole_clipbrd* theOleClipboard;
175 static CRITICAL_SECTION latest_snapshot_cs;
176 static CRITICAL_SECTION_DEBUG latest_snapshot_cs_debug =
178 0, 0, &latest_snapshot_cs,
179 { &latest_snapshot_cs_debug.ProcessLocksList, &latest_snapshot_cs_debug.ProcessLocksList },
180 0, 0, { (DWORD_PTR)(__FILE__ ": clipboard last snapshot") }
182 static CRITICAL_SECTION latest_snapshot_cs = { &latest_snapshot_cs_debug, -1, 0, 0, 0, 0 };
185 * Name of our registered OLE clipboard window class
187 static const WCHAR clipbrd_wndclass[] = L"CLIPBRDWNDCLASS";
189 UINT ownerlink_clipboard_format = 0;
190 UINT filename_clipboard_format = 0;
191 UINT filenameW_clipboard_format = 0;
192 UINT dataobject_clipboard_format = 0;
193 UINT embedded_object_clipboard_format = 0;
194 UINT embed_source_clipboard_format = 0;
195 UINT custom_link_source_clipboard_format = 0;
196 UINT link_source_clipboard_format = 0;
197 UINT object_descriptor_clipboard_format = 0;
198 UINT link_source_descriptor_clipboard_format = 0;
199 UINT ole_private_data_clipboard_format = 0;
201 static UINT wine_marshal_clipboard_format;
203 static void register_clipboard_formats(void)
205 ownerlink_clipboard_format = RegisterClipboardFormatW(L"OwnerLink");
206 filename_clipboard_format = RegisterClipboardFormatW(L"FileName");
207 filenameW_clipboard_format = RegisterClipboardFormatW(L"FileNameW");
208 dataobject_clipboard_format = RegisterClipboardFormatW(L"DataObject");
209 embedded_object_clipboard_format = RegisterClipboardFormatW(L"Embedded Object");
210 embed_source_clipboard_format = RegisterClipboardFormatW(L"Embed Source");
211 custom_link_source_clipboard_format = RegisterClipboardFormatW(L"Custom Link Source");
212 link_source_clipboard_format = RegisterClipboardFormatW(L"Link Source");
213 object_descriptor_clipboard_format = RegisterClipboardFormatW(L"Object Descriptor");
214 link_source_descriptor_clipboard_format = RegisterClipboardFormatW(L"Link Source Descriptor");
215 ole_private_data_clipboard_format = RegisterClipboardFormatW(L"Ole Private Data");
217 wine_marshal_clipboard_format = RegisterClipboardFormatW(L"Wine Marshalled DataObject");
220 static BOOL WINAPI clipbrd_create(INIT_ONCE *init_once, void *parameter, void **context)
222 ole_clipbrd* clipbrd;
223 HGLOBAL h;
225 TRACE("()\n");
227 register_clipboard_formats();
229 clipbrd = HeapAlloc( GetProcessHeap(), 0, sizeof(*clipbrd) );
230 if (!clipbrd)
232 ERR("No memory.\n");
233 return FALSE;
236 clipbrd->latest_snapshot = NULL;
237 clipbrd->window = NULL;
238 clipbrd->src_data = NULL;
239 clipbrd->cached_enum = NULL;
241 h = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE, 0);
242 if(!h)
244 ERR("No memory.\n");
245 HeapFree(GetProcessHeap(), 0, clipbrd);
246 return FALSE;
249 if(FAILED(CreateStreamOnHGlobal(h, TRUE, &clipbrd->marshal_data)))
251 ERR("CreateStreamOnHGlobal failed.\n");
252 GlobalFree(h);
253 HeapFree(GetProcessHeap(), 0, clipbrd);
254 return FALSE;
257 theOleClipboard = clipbrd;
258 return TRUE;
261 static inline HRESULT get_ole_clipbrd(ole_clipbrd **clipbrd)
263 static INIT_ONCE init_once = INIT_ONCE_STATIC_INIT;
265 if (!InitOnceExecuteOnce(&init_once, clipbrd_create, NULL, NULL))
267 *clipbrd = NULL;
268 return CO_E_NOTINITIALIZED;
271 *clipbrd = theOleClipboard;
272 return S_OK;
275 static inline const char *dump_fmtetc(FORMATETC *fmt)
277 if (!fmt) return "(null)";
278 return wine_dbg_sprintf("cf %04x ptd %p aspect %lx lindex %ld tymed %lx",
279 fmt->cfFormat, fmt->ptd, fmt->dwAspect, fmt->lindex, fmt->tymed);
282 /*---------------------------------------------------------------------*
283 * Implementation of the internal IEnumFORMATETC interface returned by
284 * the OLE clipboard's IDataObject.
285 *---------------------------------------------------------------------*/
287 typedef struct enum_fmtetc
289 IEnumFORMATETC IEnumFORMATETC_iface;
290 LONG ref;
292 UINT pos; /* current enumerator position */
293 ole_priv_data *data;
294 } enum_fmtetc;
296 static inline enum_fmtetc *impl_from_IEnumFORMATETC(IEnumFORMATETC *iface)
298 return CONTAINING_RECORD(iface, enum_fmtetc, IEnumFORMATETC_iface);
301 /************************************************************************
302 * OLEClipbrd_IEnumFORMATETC_QueryInterface (IUnknown)
304 * See Windows documentation for more details on IUnknown methods.
306 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_QueryInterface
307 (LPENUMFORMATETC iface, REFIID riid, LPVOID* ppvObj)
309 enum_fmtetc *This = impl_from_IEnumFORMATETC(iface);
311 TRACE("(%p)->(IID: %s, %p)\n", This, debugstr_guid(riid), ppvObj);
313 *ppvObj = NULL;
315 if(IsEqualIID(riid, &IID_IUnknown) ||
316 IsEqualIID(riid, &IID_IEnumFORMATETC))
318 *ppvObj = iface;
321 if(*ppvObj)
323 IEnumFORMATETC_AddRef((IEnumFORMATETC*)*ppvObj);
324 TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
325 return S_OK;
328 TRACE("-- Interface: E_NOINTERFACE\n");
329 return E_NOINTERFACE;
332 /************************************************************************
333 * OLEClipbrd_IEnumFORMATETC_AddRef (IUnknown)
336 static ULONG WINAPI OLEClipbrd_IEnumFORMATETC_AddRef(LPENUMFORMATETC iface)
338 enum_fmtetc *This = impl_from_IEnumFORMATETC(iface);
339 ULONG ref = InterlockedIncrement(&This->ref);
341 TRACE("%p, refcount %lu.\n", iface, ref);
343 return ref;
346 /************************************************************************
347 * OLEClipbrd_IEnumFORMATETC_Release (IUnknown)
349 * See Windows documentation for more details on IUnknown methods.
351 static ULONG WINAPI OLEClipbrd_IEnumFORMATETC_Release(LPENUMFORMATETC iface)
353 enum_fmtetc *This = impl_from_IEnumFORMATETC(iface);
354 ULONG ref = InterlockedDecrement(&This->ref);
356 TRACE("%p, refcount %lu.\n", iface, ref);
358 if (!ref)
360 TRACE("() - destroying IEnumFORMATETC(%p)\n",This);
361 HeapFree(GetProcessHeap(), 0, This->data);
362 HeapFree(GetProcessHeap(), 0, This);
364 return ref;
367 /************************************************************************
368 * OLEClipbrd_IEnumFORMATETC_Next (IEnumFORMATETC)
370 * Standard enumerator members for IEnumFORMATETC
372 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Next
373 (LPENUMFORMATETC iface, ULONG celt, FORMATETC *rgelt, ULONG *pceltFethed)
375 enum_fmtetc *This = impl_from_IEnumFORMATETC(iface);
376 UINT cfetch, i;
377 HRESULT hres = S_FALSE;
379 TRACE("(%p)->(pos=%u)\n", This, This->pos);
381 if (This->pos < This->data->count)
383 cfetch = This->data->count - This->pos;
384 if (cfetch >= celt)
386 cfetch = celt;
387 hres = S_OK;
390 for(i = 0; i < cfetch; i++)
392 hres = copy_formatetc(rgelt + i, &This->data->entries[This->pos++].fmtetc);
393 if(FAILED(hres)) return hres;
396 else
398 cfetch = 0;
401 if (pceltFethed)
403 *pceltFethed = cfetch;
406 return hres;
409 /************************************************************************
410 * OLEClipbrd_IEnumFORMATETC_Skip (IEnumFORMATETC)
412 * Standard enumerator members for IEnumFORMATETC
414 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Skip(LPENUMFORMATETC iface, ULONG celt)
416 enum_fmtetc *This = impl_from_IEnumFORMATETC(iface);
417 TRACE("%p, %lu.\n", iface, celt);
419 This->pos += celt;
420 if (This->pos > This->data->count)
422 This->pos = This->data->count;
423 return S_FALSE;
425 return S_OK;
428 /************************************************************************
429 * OLEClipbrd_IEnumFORMATETC_Reset (IEnumFORMATETC)
431 * Standard enumerator members for IEnumFORMATETC
433 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Reset(LPENUMFORMATETC iface)
435 enum_fmtetc *This = impl_from_IEnumFORMATETC(iface);
436 TRACE("(%p)->()\n", This);
438 This->pos = 0;
439 return S_OK;
442 static HRESULT enum_fmtetc_construct(ole_priv_data *data, UINT pos, IEnumFORMATETC **obj);
444 /************************************************************************
445 * OLEClipbrd_IEnumFORMATETC_Clone (IEnumFORMATETC)
447 * Standard enumerator members for IEnumFORMATETC
449 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Clone
450 (LPENUMFORMATETC iface, LPENUMFORMATETC* obj)
452 enum_fmtetc *This = impl_from_IEnumFORMATETC(iface);
453 ole_priv_data *new_data;
454 DWORD i;
456 TRACE("(%p)->(%p)\n", This, obj);
458 if ( !obj ) return E_INVALIDARG;
459 *obj = NULL;
461 new_data = HeapAlloc(GetProcessHeap(), 0, This->data->size);
462 if(!new_data) return E_OUTOFMEMORY;
463 memcpy(new_data, This->data, This->data->size);
465 /* Fixup any target device ptrs */
466 for(i = 0; i < This->data->count; i++)
467 new_data->entries[i].fmtetc.ptd =
468 td_offs_to_ptr(new_data, td_get_offs(This->data, i));
470 return enum_fmtetc_construct(new_data, This->pos, obj);
473 static const IEnumFORMATETCVtbl efvt =
475 OLEClipbrd_IEnumFORMATETC_QueryInterface,
476 OLEClipbrd_IEnumFORMATETC_AddRef,
477 OLEClipbrd_IEnumFORMATETC_Release,
478 OLEClipbrd_IEnumFORMATETC_Next,
479 OLEClipbrd_IEnumFORMATETC_Skip,
480 OLEClipbrd_IEnumFORMATETC_Reset,
481 OLEClipbrd_IEnumFORMATETC_Clone
484 /************************************************************************
485 * enum_fmtetc_construct
487 * Creates an IEnumFORMATETC enumerator from ole_priv_data which it then owns.
489 static HRESULT enum_fmtetc_construct(ole_priv_data *data, UINT pos, IEnumFORMATETC **obj)
491 enum_fmtetc* ef;
493 *obj = NULL;
494 ef = HeapAlloc(GetProcessHeap(), 0, sizeof(*ef));
495 if (!ef) return E_OUTOFMEMORY;
497 ef->ref = 1;
498 ef->IEnumFORMATETC_iface.lpVtbl = &efvt;
499 ef->data = data;
500 ef->pos = pos;
502 TRACE("(%p)->()\n", ef);
503 *obj = &ef->IEnumFORMATETC_iface;
504 return S_OK;
507 /***********************************************************************
508 * dup_global_mem
510 * Helper method to duplicate an HGLOBAL chunk of memory
512 static HRESULT dup_global_mem( HGLOBAL src, DWORD flags, HGLOBAL *dst )
514 void *src_ptr, *dst_ptr;
515 DWORD size;
517 *dst = NULL;
518 if ( !src ) return S_FALSE;
520 size = GlobalSize(src);
522 *dst = GlobalAlloc( flags, size );
523 if ( !*dst ) return E_OUTOFMEMORY;
525 src_ptr = GlobalLock(src);
526 dst_ptr = GlobalLock(*dst);
528 memcpy(dst_ptr, src_ptr, size);
530 GlobalUnlock(*dst);
531 GlobalUnlock(src);
533 return S_OK;
536 /***********************************************************************
537 * dup_metafilepict
539 * Helper function to duplicate a handle to a METAFILEPICT, and the
540 * contained HMETAFILE.
542 static HRESULT dup_metafilepict(HGLOBAL src, HGLOBAL *pdest)
544 HRESULT hr;
545 HGLOBAL dest;
546 METAFILEPICT *dest_ptr;
548 *pdest = NULL;
550 /* Copy the METAFILEPICT structure. */
551 hr = dup_global_mem(src, GMEM_DDESHARE|GMEM_MOVEABLE, &dest);
552 if (FAILED(hr)) return hr;
554 dest_ptr = GlobalLock(dest);
555 if (!dest_ptr) return E_FAIL;
557 /* Give the new METAFILEPICT a separate HMETAFILE. */
558 dest_ptr->hMF = CopyMetaFileW(dest_ptr->hMF, NULL);
559 if (dest_ptr->hMF)
561 GlobalUnlock(dest);
562 *pdest = dest;
563 return S_OK;
565 else
567 GlobalUnlock(dest);
568 GlobalFree(dest);
569 return E_FAIL;
573 /***********************************************************************
574 * free_metafilepict
576 * Helper function to GlobalFree a handle to a METAFILEPICT, and also
577 * free the contained HMETAFILE.
579 static void free_metafilepict(HGLOBAL src)
581 METAFILEPICT *src_ptr;
583 src_ptr = GlobalLock(src);
584 if (src_ptr)
586 DeleteMetaFile(src_ptr->hMF);
587 GlobalUnlock(src);
589 GlobalFree(src);
592 /***********************************************************************
593 * dup_bitmap
595 * Helper function to duplicate an HBITMAP.
597 static HRESULT dup_bitmap(HBITMAP src, HBITMAP *pdest)
599 HDC src_dc;
600 HGDIOBJ orig_src_bitmap;
601 BITMAP bm;
602 HBITMAP dest;
604 src_dc = CreateCompatibleDC(NULL);
605 orig_src_bitmap = SelectObject(src_dc, src);
606 GetObjectW(src, sizeof bm, &bm);
607 dest = CreateCompatibleBitmap(src_dc, bm.bmWidth, bm.bmHeight);
608 if (dest)
610 HDC dest_dc = CreateCompatibleDC(NULL);
611 HGDIOBJ orig_dest_bitmap = SelectObject(dest_dc, dest);
612 BitBlt(dest_dc, 0, 0, bm.bmWidth, bm.bmHeight, src_dc, 0, 0, SRCCOPY);
613 SelectObject(dest_dc, orig_dest_bitmap);
614 DeleteDC(dest_dc);
616 SelectObject(src_dc, orig_src_bitmap);
617 DeleteDC(src_dc);
618 *pdest = dest;
619 return dest ? S_OK : E_FAIL;
622 /************************************************************
623 * render_embed_source_hack
625 * This is clearly a hack and has no place in the clipboard code.
628 static HRESULT render_embed_source_hack(IDataObject *data, LPFORMATETC fmt)
630 STGMEDIUM std;
631 HGLOBAL hStorage = 0;
632 HRESULT hr = S_OK;
633 ILockBytes *ptrILockBytes;
635 memset(&std, 0, sizeof(STGMEDIUM));
636 std.tymed = fmt->tymed = TYMED_ISTORAGE;
638 hStorage = GlobalAlloc(GMEM_SHARE|GMEM_MOVEABLE, 0);
639 if (hStorage == NULL) return E_OUTOFMEMORY;
640 hr = CreateILockBytesOnHGlobal(hStorage, FALSE, &ptrILockBytes);
641 if (FAILED(hr))
643 GlobalFree(hStorage);
644 return hr;
647 hr = StgCreateDocfileOnILockBytes(ptrILockBytes, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &std.pstg);
648 ILockBytes_Release(ptrILockBytes);
650 if (FAILED(hr = IDataObject_GetDataHere(theOleClipboard->src_data, fmt, &std)))
652 WARN("() : IDataObject_GetDataHere failed to render clipboard data! (%lx)\n", hr);
653 GlobalFree(hStorage);
654 return hr;
657 if (1) /* check whether the presentation data is already -not- present */
659 FORMATETC fmt2;
660 STGMEDIUM std2;
661 METAFILEPICT *mfp = 0;
663 fmt2.cfFormat = CF_METAFILEPICT;
664 fmt2.ptd = 0;
665 fmt2.dwAspect = DVASPECT_CONTENT;
666 fmt2.lindex = -1;
667 fmt2.tymed = TYMED_MFPICT;
669 memset(&std2, 0, sizeof(STGMEDIUM));
670 std2.tymed = TYMED_MFPICT;
672 /* Get the metafile picture out of it */
674 if (SUCCEEDED(hr = IDataObject_GetData(theOleClipboard->src_data, &fmt2, &std2)))
676 mfp = GlobalLock(std2.hGlobal);
679 if (mfp)
681 IStream *pStream = 0;
682 void *mfBits;
683 PresentationDataHeader pdh;
684 INT nSize;
685 CLSID clsID;
686 LPOLESTR strProgID;
687 CHAR strOleTypeName[51];
688 BYTE OlePresStreamHeader [] =
690 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00,
691 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
692 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
693 0x00, 0x00, 0x00, 0x00
696 nSize = GetMetaFileBitsEx(mfp->hMF, 0, NULL);
698 memset(&pdh, 0, sizeof(PresentationDataHeader));
699 memcpy(&pdh, OlePresStreamHeader, sizeof(OlePresStreamHeader));
701 pdh.dwObjectExtentX = mfp->xExt;
702 pdh.dwObjectExtentY = mfp->yExt;
703 pdh.dwSize = nSize;
705 hr = IStorage_CreateStream(std.pstg, L"\2OlePres000",
706 STGM_CREATE|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, 0, &pStream);
708 hr = IStream_Write(pStream, &pdh, sizeof(PresentationDataHeader), NULL);
710 mfBits = HeapAlloc(GetProcessHeap(), 0, nSize);
711 nSize = GetMetaFileBitsEx(mfp->hMF, nSize, mfBits);
713 hr = IStream_Write(pStream, mfBits, nSize, NULL);
715 IStream_Release(pStream);
717 HeapFree(GetProcessHeap(), 0, mfBits);
719 GlobalUnlock(std2.hGlobal);
720 ReleaseStgMedium(&std2);
722 ReadClassStg(std.pstg, &clsID);
723 ProgIDFromCLSID(&clsID, &strProgID);
725 WideCharToMultiByte( CP_ACP, 0, strProgID, -1, strOleTypeName, sizeof(strOleTypeName), NULL, NULL );
726 STORAGE_CreateOleStream(std.pstg, 0);
727 OLECONVERT_CreateCompObjStream(std.pstg, strOleTypeName);
728 CoTaskMemFree(strProgID);
732 if ( !SetClipboardData( fmt->cfFormat, hStorage ) )
734 WARN("() : Failed to set rendered clipboard data into clipboard!\n");
735 GlobalFree(hStorage);
736 hr = CLIPBRD_E_CANT_SET;
739 ReleaseStgMedium(&std);
740 return hr;
743 /************************************************************************
744 * find_format_in_list
746 * Returns the first entry that matches the provided clipboard format.
748 static inline ole_priv_data_entry *find_format_in_list(ole_priv_data_entry *entries, DWORD num, UINT cf)
750 DWORD i;
751 for(i = 0; i < num; i++)
752 if(entries[i].fmtetc.cfFormat == cf)
753 return &entries[i];
755 return NULL;
758 /***************************************************************************
759 * get_data_from_storage
761 * Returns storage data in an HGLOBAL.
763 static HRESULT get_data_from_storage(IDataObject *data, FORMATETC *fmt, HGLOBAL *mem)
765 HGLOBAL h;
766 IStorage *stg;
767 HRESULT hr;
768 FORMATETC stg_fmt;
769 STGMEDIUM med;
770 ILockBytes *lbs;
772 *mem = NULL;
774 h = GlobalAlloc( GMEM_DDESHARE|GMEM_MOVEABLE, 0 );
775 if(!h) return E_OUTOFMEMORY;
777 hr = CreateILockBytesOnHGlobal(h, FALSE, &lbs);
778 if(SUCCEEDED(hr))
780 hr = StgCreateDocfileOnILockBytes(lbs, STGM_CREATE|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &stg);
781 ILockBytes_Release(lbs);
783 if(FAILED(hr))
785 GlobalFree(h);
786 return hr;
789 stg_fmt = *fmt;
790 med.tymed = stg_fmt.tymed = TYMED_ISTORAGE;
791 med.pstg = stg;
792 med.pUnkForRelease = NULL;
794 hr = IDataObject_GetDataHere(data, &stg_fmt, &med);
795 if(FAILED(hr))
797 memset(&med, 0, sizeof(med));
798 hr = IDataObject_GetData(data, &stg_fmt, &med);
799 if(FAILED(hr)) goto end;
801 hr = IStorage_CopyTo(med.pstg, 0, NULL, NULL, stg);
802 ReleaseStgMedium(&med);
803 if(FAILED(hr)) goto end;
805 *mem = h;
807 end:
808 IStorage_Release(stg);
809 if(FAILED(hr)) GlobalFree(h);
810 return hr;
813 /***************************************************************************
814 * get_data_from_stream
816 * Returns stream data in an HGLOBAL.
818 static HRESULT get_data_from_stream(IDataObject *data, FORMATETC *fmt, HGLOBAL *mem)
820 HGLOBAL h;
821 IStream *stm = NULL;
822 HRESULT hr;
823 FORMATETC stm_fmt;
824 STGMEDIUM med;
826 *mem = NULL;
828 h = GlobalAlloc( GMEM_DDESHARE|GMEM_MOVEABLE, 0 );
829 if(!h) return E_OUTOFMEMORY;
831 hr = CreateStreamOnHGlobal(h, FALSE, &stm);
832 if(FAILED(hr)) goto error;
834 stm_fmt = *fmt;
835 med.tymed = stm_fmt.tymed = TYMED_ISTREAM;
836 med.pstm = stm;
837 med.pUnkForRelease = NULL;
839 hr = IDataObject_GetDataHere(data, &stm_fmt, &med);
840 if(FAILED(hr))
842 LARGE_INTEGER offs;
843 ULARGE_INTEGER pos;
845 memset(&med, 0, sizeof(med));
846 hr = IDataObject_GetData(data, &stm_fmt, &med);
847 if(FAILED(hr)) goto error;
849 offs.QuadPart = 0;
850 IStream_Seek(med.pstm, offs, STREAM_SEEK_END, &pos);
851 IStream_Seek(med.pstm, offs, STREAM_SEEK_SET, NULL);
852 hr = IStream_CopyTo(med.pstm, stm, pos, NULL, NULL);
853 ReleaseStgMedium(&med);
854 if(FAILED(hr)) goto error;
856 *mem = h;
857 IStream_Release(stm);
858 return S_OK;
860 error:
861 if(stm) IStream_Release(stm);
862 GlobalFree(h);
863 return hr;
866 /***************************************************************************
867 * get_data_from_global
869 * Returns global data in an HGLOBAL.
871 static HRESULT get_data_from_global(IDataObject *data, FORMATETC *fmt, HGLOBAL *mem)
873 HGLOBAL h;
874 HRESULT hr;
875 FORMATETC mem_fmt;
876 STGMEDIUM med;
878 *mem = NULL;
880 mem_fmt = *fmt;
881 mem_fmt.tymed = TYMED_HGLOBAL;
882 memset(&med, 0, sizeof(med));
884 hr = IDataObject_GetData(data, &mem_fmt, &med);
885 if(FAILED(hr)) return hr;
887 hr = dup_global_mem(med.hGlobal, GMEM_DDESHARE|GMEM_MOVEABLE, &h);
889 if(SUCCEEDED(hr)) *mem = h;
891 ReleaseStgMedium(&med);
893 return hr;
896 /***************************************************************************
897 * get_data_from_enhmetafile
899 static HRESULT get_data_from_enhmetafile(IDataObject *data, FORMATETC *fmt, HGLOBAL *mem)
901 HENHMETAFILE copy;
902 HRESULT hr;
903 FORMATETC mem_fmt;
904 STGMEDIUM med;
906 *mem = NULL;
908 mem_fmt = *fmt;
909 mem_fmt.tymed = TYMED_ENHMF;
910 memset(&med, 0, sizeof(med));
912 hr = IDataObject_GetData(data, &mem_fmt, &med);
913 if(FAILED(hr)) return hr;
915 copy = CopyEnhMetaFileW(med.hEnhMetaFile, NULL);
916 if(copy) *mem = (HGLOBAL)copy;
917 else hr = E_FAIL;
919 ReleaseStgMedium(&med);
921 return hr;
924 /***************************************************************************
925 * get_data_from_metafilepict
927 static HRESULT get_data_from_metafilepict(IDataObject *data, FORMATETC *fmt, HGLOBAL *mem)
929 HGLOBAL copy;
930 HRESULT hr;
931 FORMATETC mem_fmt;
932 STGMEDIUM med;
934 *mem = NULL;
936 mem_fmt = *fmt;
937 mem_fmt.tymed = TYMED_MFPICT;
938 memset(&med, 0, sizeof(med));
940 hr = IDataObject_GetData(data, &mem_fmt, &med);
941 if(FAILED(hr)) return hr;
943 hr = dup_metafilepict(med.hMetaFilePict, &copy);
945 if(SUCCEEDED(hr)) *mem = copy;
947 ReleaseStgMedium(&med);
949 return hr;
952 /***************************************************************************
953 * get_data_from_bitmap
955 * Returns bitmap in an HBITMAP.
957 static HRESULT get_data_from_bitmap(IDataObject *data, FORMATETC *fmt, HBITMAP *hbm)
959 HBITMAP copy;
960 HRESULT hr;
961 FORMATETC mem_fmt;
962 STGMEDIUM med;
964 *hbm = NULL;
966 mem_fmt = *fmt;
967 mem_fmt.tymed = TYMED_GDI;
968 memset(&med, 0, sizeof(med));
970 hr = IDataObject_GetData(data, &mem_fmt, &med);
971 if(FAILED(hr)) return hr;
973 hr = dup_bitmap(med.hBitmap, &copy);
975 if(SUCCEEDED(hr)) *hbm = copy;
977 ReleaseStgMedium(&med);
979 return hr;
982 /***********************************************************************
983 * render_format
985 * Render the clipboard data. Note that this call will delegate to the
986 * source data object.
988 static HRESULT render_format(IDataObject *data, LPFORMATETC fmt)
990 HANDLE clip_data = NULL; /* HGLOBAL unless otherwise specified */
991 HRESULT hr;
993 /* Embed source hack */
994 if(fmt->cfFormat == embed_source_clipboard_format)
996 return render_embed_source_hack(data, fmt);
999 if(fmt->tymed & TYMED_ISTORAGE)
1001 hr = get_data_from_storage(data, fmt, &clip_data);
1003 else if(fmt->tymed & TYMED_ISTREAM)
1005 hr = get_data_from_stream(data, fmt, &clip_data);
1007 else if(fmt->tymed & TYMED_HGLOBAL)
1009 hr = get_data_from_global(data, fmt, &clip_data);
1011 else if(fmt->tymed & TYMED_ENHMF)
1013 hr = get_data_from_enhmetafile(data, fmt, &clip_data);
1015 else if(fmt->tymed & TYMED_MFPICT)
1017 /* Returns global handle to METAFILEPICT, containing a copied HMETAFILE */
1018 hr = get_data_from_metafilepict(data, fmt, &clip_data);
1020 else if(fmt->tymed & TYMED_GDI)
1022 /* Returns HBITMAP not HGLOBAL */
1023 hr = get_data_from_bitmap(data, fmt, (HBITMAP *)&clip_data);
1025 else
1027 FIXME("Unhandled tymed %lx\n", fmt->tymed);
1028 hr = DV_E_FORMATETC;
1031 if(SUCCEEDED(hr))
1033 if ( !SetClipboardData(fmt->cfFormat, clip_data) )
1035 WARN("() : Failed to set rendered clipboard data into clipboard!\n");
1036 if(fmt->tymed & TYMED_MFPICT)
1037 free_metafilepict(clip_data);
1038 else if(fmt->tymed & TYMED_GDI)
1039 DeleteObject(clip_data);
1040 else
1041 GlobalFree(clip_data);
1042 hr = CLIPBRD_E_CANT_SET;
1046 return hr;
1049 /*---------------------------------------------------------------------*
1050 * Implementation of the internal IDataObject interface exposed by
1051 * the OLE clipboard.
1052 *---------------------------------------------------------------------*/
1055 /************************************************************************
1056 * snapshot_QueryInterface
1058 static HRESULT WINAPI snapshot_QueryInterface(IDataObject *iface,
1059 REFIID riid, void **ppvObject)
1061 snapshot *This = impl_from_IDataObject(iface);
1062 TRACE("(%p)->(IID:%s, %p)\n", This, debugstr_guid(riid), ppvObject);
1064 if ( (This==0) || (ppvObject==0) )
1065 return E_INVALIDARG;
1067 *ppvObject = 0;
1069 if (IsEqualIID(&IID_IUnknown, riid) ||
1070 IsEqualIID(&IID_IDataObject, riid))
1072 *ppvObject = iface;
1074 else
1076 WARN( "() : asking for unsupported interface %s\n", debugstr_guid(riid));
1077 return E_NOINTERFACE;
1080 IUnknown_AddRef((IUnknown*)*ppvObject);
1082 return S_OK;
1085 /************************************************************************
1086 * snapshot_AddRef
1088 static ULONG WINAPI snapshot_AddRef(IDataObject *iface)
1090 snapshot *This = impl_from_IDataObject(iface);
1091 ULONG ref = InterlockedIncrement(&This->ref);
1093 TRACE("%p, refcount %lu.\n", iface, ref);
1095 return ref;
1098 /************************************************************************
1099 * snapshot_Release
1101 static ULONG WINAPI snapshot_Release(IDataObject *iface)
1103 snapshot *This = impl_from_IDataObject(iface);
1104 ULONG ref = InterlockedDecrement(&This->ref);
1106 TRACE("%p, refcount %lu.\n", iface, ref);
1108 if (ref == 0)
1110 EnterCriticalSection(&latest_snapshot_cs);
1111 if (This->ref)
1113 LeaveCriticalSection(&latest_snapshot_cs);
1114 return ref;
1116 if (theOleClipboard->latest_snapshot == This)
1117 theOleClipboard->latest_snapshot = NULL;
1118 LeaveCriticalSection(&latest_snapshot_cs);
1120 if(This->data) IDataObject_Release(This->data);
1121 HeapFree(GetProcessHeap(), 0, This);
1124 return ref;
1127 /************************************************************
1128 * get_current_ole_clip_window
1130 * Return the window that owns the ole clipboard.
1132 * If the clipboard is flushed or not owned by ole this will
1133 * return NULL.
1135 static HWND get_current_ole_clip_window(void)
1137 HGLOBAL h;
1138 HWND *ptr, wnd;
1140 h = GetClipboardData(dataobject_clipboard_format);
1141 if(!h) return NULL;
1142 ptr = GlobalLock(h);
1143 if(!ptr) return NULL;
1144 wnd = *ptr;
1145 GlobalUnlock(h);
1146 return wnd;
1149 /************************************************************
1150 * get_current_dataobject
1152 * Return an unmarshalled IDataObject if there is a current
1153 * (ie non-flushed) object on the ole clipboard.
1155 static HRESULT get_current_dataobject(IDataObject **data)
1157 HRESULT hr = S_FALSE;
1158 HWND wnd = get_current_ole_clip_window();
1159 HGLOBAL h;
1160 void *ptr;
1161 IStream *stm;
1162 LARGE_INTEGER pos;
1164 *data = NULL;
1165 if(!wnd) return S_FALSE;
1167 h = GetClipboardData(wine_marshal_clipboard_format);
1168 if(!h) return S_FALSE;
1169 if(GlobalSize(h) <= 1) return S_FALSE;
1170 ptr = GlobalLock(h);
1171 if(!ptr) return S_FALSE;
1173 hr = CreateStreamOnHGlobal(NULL, TRUE, &stm);
1174 if(FAILED(hr)) goto end;
1176 hr = IStream_Write(stm, ptr, GlobalSize(h), NULL);
1177 if(SUCCEEDED(hr))
1179 pos.QuadPart = 0;
1180 IStream_Seek(stm, pos, STREAM_SEEK_SET, NULL);
1181 hr = CoUnmarshalInterface(stm, &IID_IDataObject, (void**)data);
1183 IStream_Release(stm);
1185 end:
1186 GlobalUnlock(h);
1187 return hr;
1190 static DWORD get_tymed_from_nonole_cf(UINT cf)
1192 if(cf >= 0xc000) return TYMED_ISTREAM | TYMED_HGLOBAL;
1194 switch(cf)
1196 case CF_TEXT:
1197 case CF_OEMTEXT:
1198 case CF_UNICODETEXT:
1199 case CF_HDROP:
1200 return TYMED_ISTREAM | TYMED_HGLOBAL;
1201 case CF_ENHMETAFILE:
1202 return TYMED_ENHMF;
1203 case CF_METAFILEPICT:
1204 return TYMED_MFPICT;
1205 case CF_BITMAP:
1206 return TYMED_GDI;
1207 default:
1208 FIXME("returning TYMED_NULL for cf %04x\n", cf);
1209 return TYMED_NULL;
1213 /***********************************************************
1214 * get_priv_data
1216 * Returns a copy of the Ole Private Data
1218 static HRESULT get_priv_data(ole_priv_data **data)
1220 HGLOBAL handle;
1221 HRESULT hr = S_OK;
1222 ole_priv_data *ret = NULL;
1224 *data = NULL;
1226 handle = GetClipboardData( ole_private_data_clipboard_format );
1227 if(handle)
1229 ole_priv_data *src = GlobalLock(handle);
1230 if(src)
1232 DWORD i;
1234 /* FIXME: sanity check on size */
1235 ret = HeapAlloc(GetProcessHeap(), 0, src->size);
1236 if(!ret)
1238 GlobalUnlock(handle);
1239 return E_OUTOFMEMORY;
1241 memcpy(ret, src, src->size);
1242 GlobalUnlock(handle);
1244 /* Fixup any target device offsets to ptrs */
1245 for(i = 0; i < ret->count; i++)
1246 ret->entries[i].fmtetc.ptd =
1247 td_offs_to_ptr(ret, (DWORD_PTR) ret->entries[i].fmtetc.ptd);
1251 if(!ret) /* Non-ole data */
1253 UINT cf;
1254 DWORD count = 0, idx, size = FIELD_OFFSET(ole_priv_data, entries);
1256 for(cf = 0; (cf = EnumClipboardFormats(cf)) != 0; count++)
1258 WCHAR buf[256];
1259 if (GetClipboardFormatNameW(cf, buf, ARRAY_SIZE(buf)))
1260 TRACE("cf %04x %s\n", cf, debugstr_w(buf));
1261 else
1262 TRACE("cf %04x\n", cf);
1264 TRACE("count %ld\n", count);
1265 size += count * sizeof(ret->entries[0]);
1267 /* There are holes in fmtetc so zero init */
1268 ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
1269 if(!ret) return E_OUTOFMEMORY;
1270 ret->size = size;
1271 ret->count = count;
1273 for(cf = 0, idx = 0; (cf = EnumClipboardFormats(cf)) != 0; idx++)
1275 ret->entries[idx].fmtetc.cfFormat = cf;
1276 ret->entries[idx].fmtetc.ptd = NULL;
1277 ret->entries[idx].fmtetc.dwAspect = DVASPECT_CONTENT;
1278 ret->entries[idx].fmtetc.lindex = -1;
1279 ret->entries[idx].fmtetc.tymed = get_tymed_from_nonole_cf(cf);
1280 ret->entries[idx].first_use = 1;
1284 *data = ret;
1285 return hr;
1288 /************************************************************************
1289 * get_stgmed_for_global
1291 * Returns a stg medium with a copy of the global handle
1293 static HRESULT get_stgmed_for_global(HGLOBAL h, STGMEDIUM *med)
1295 HRESULT hr;
1297 med->pUnkForRelease = NULL;
1298 med->tymed = TYMED_NULL;
1300 hr = dup_global_mem(h, GMEM_MOVEABLE, &med->hGlobal);
1302 if(SUCCEEDED(hr)) med->tymed = TYMED_HGLOBAL;
1304 return hr;
1307 /************************************************************************
1308 * get_stgmed_for_stream
1310 * Returns a stg medium with a stream based on the handle
1312 static HRESULT get_stgmed_for_stream(HGLOBAL h, STGMEDIUM *med)
1314 HRESULT hr;
1315 HGLOBAL dst;
1317 med->pUnkForRelease = NULL;
1318 med->tymed = TYMED_NULL;
1320 hr = dup_global_mem(h, GMEM_MOVEABLE, &dst);
1321 if(FAILED(hr)) return hr;
1323 hr = CreateStreamOnHGlobal(dst, TRUE, &med->pstm);
1324 if(FAILED(hr))
1326 GlobalFree(dst);
1327 return hr;
1330 med->tymed = TYMED_ISTREAM;
1331 return hr;
1334 /************************************************************************
1335 * get_stgmed_for_storage
1337 * Returns a stg medium with a storage based on the handle
1339 static HRESULT get_stgmed_for_storage(HGLOBAL h, STGMEDIUM *med)
1341 HRESULT hr;
1342 HGLOBAL dst;
1343 ILockBytes *lbs;
1345 med->pUnkForRelease = NULL;
1346 med->tymed = TYMED_NULL;
1348 hr = dup_global_mem(h, GMEM_MOVEABLE, &dst);
1349 if(FAILED(hr)) return hr;
1351 hr = CreateILockBytesOnHGlobal(dst, TRUE, &lbs);
1352 if(FAILED(hr))
1354 GlobalFree(dst);
1355 return hr;
1358 hr = StgIsStorageILockBytes(lbs);
1359 if(hr!=S_OK)
1361 ILockBytes_Release(lbs);
1362 GlobalFree(dst);
1363 return SUCCEEDED(hr) ? E_FAIL : hr;
1366 hr = StgOpenStorageOnILockBytes(lbs, NULL, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, NULL, 0, &med->pstg);
1367 ILockBytes_Release(lbs);
1368 if(FAILED(hr))
1370 GlobalFree(dst);
1371 return hr;
1374 med->tymed = TYMED_ISTORAGE;
1375 return hr;
1378 /************************************************************************
1379 * get_stgmed_for_emf
1381 * Returns a stg medium with an enhanced metafile based on the handle
1383 static HRESULT get_stgmed_for_emf(HENHMETAFILE hemf, STGMEDIUM *med)
1385 med->pUnkForRelease = NULL;
1386 med->tymed = TYMED_NULL;
1388 med->hEnhMetaFile = CopyEnhMetaFileW(hemf, NULL);
1389 if(!med->hEnhMetaFile) return E_OUTOFMEMORY;
1390 med->tymed = TYMED_ENHMF;
1391 return S_OK;
1394 /************************************************************************
1395 * get_stgmed_for_bitmap
1397 * Returns a stg medium with a bitmap based on the handle
1399 static HRESULT get_stgmed_for_bitmap(HBITMAP hbmp, STGMEDIUM *med)
1401 HRESULT hr;
1403 med->pUnkForRelease = NULL;
1404 med->tymed = TYMED_NULL;
1406 hr = dup_bitmap(hbmp, &med->hBitmap);
1408 if (FAILED(hr))
1409 return hr;
1411 med->tymed = TYMED_GDI;
1412 return S_OK;
1415 static inline BOOL string_off_equal(const DVTARGETDEVICE *t1, WORD off1, const DVTARGETDEVICE *t2, WORD off2)
1417 const WCHAR *str1, *str2;
1419 if(off1 == 0 && off2 == 0) return TRUE;
1420 if(off1 == 0 || off2 == 0) return FALSE;
1422 str1 = (const WCHAR*)((const char*)t1 + off1);
1423 str2 = (const WCHAR*)((const char*)t2 + off2);
1425 return !wcscmp(str1, str2);
1428 static inline BOOL td_equal(const DVTARGETDEVICE *t1, const DVTARGETDEVICE *t2)
1430 if(t1 == NULL && t2 == NULL) return TRUE;
1431 if(t1 == NULL || t2 == NULL) return FALSE;
1433 if(!string_off_equal(t1, t1->tdDriverNameOffset, t2, t2->tdDriverNameOffset))
1434 return FALSE;
1435 if(!string_off_equal(t1, t1->tdDeviceNameOffset, t2, t2->tdDeviceNameOffset))
1436 return FALSE;
1437 if(!string_off_equal(t1, t1->tdPortNameOffset, t2, t2->tdPortNameOffset))
1438 return FALSE;
1440 /* FIXME check devmode? */
1442 return TRUE;
1445 /************************************************************************
1446 * snapshot_GetData
1448 static HRESULT WINAPI snapshot_GetData(IDataObject *iface, FORMATETC *fmt,
1449 STGMEDIUM *med)
1451 snapshot *This = impl_from_IDataObject(iface);
1452 HANDLE h;
1453 HRESULT hr;
1454 ole_priv_data *enum_data = NULL;
1455 ole_priv_data_entry *entry;
1456 DWORD mask;
1458 TRACE("(%p, %p {%s}, %p)\n", iface, fmt, dump_fmtetc(fmt), med);
1460 if ( !fmt || !med ) return E_INVALIDARG;
1462 memset(med, 0, sizeof(*med));
1464 if ( !OpenClipboard(NULL)) return CLIPBRD_E_CANT_OPEN;
1466 if(!This->data)
1467 hr = get_current_dataobject(&This->data);
1469 if(This->data)
1471 hr = IDataObject_GetData(This->data, fmt, med);
1472 if(SUCCEEDED(hr))
1474 CloseClipboard();
1475 return hr;
1478 if(fmt->lindex != -1)
1480 hr = DV_E_FORMATETC;
1481 goto end;
1484 if(!IsClipboardFormatAvailable(fmt->cfFormat))
1486 hr = DV_E_FORMATETC;
1487 goto end;
1490 hr = get_priv_data(&enum_data);
1491 if(FAILED(hr)) goto end;
1493 entry = find_format_in_list(enum_data->entries, enum_data->count, fmt->cfFormat);
1494 if(entry)
1496 if(!td_equal(fmt->ptd, entry->fmtetc.ptd))
1498 hr = DV_E_FORMATETC;
1499 goto end;
1501 mask = fmt->tymed & entry->fmtetc.tymed;
1502 if(!mask && (entry->fmtetc.tymed & (TYMED_ISTREAM | TYMED_HGLOBAL | TYMED_ISTORAGE)))
1503 mask = fmt->tymed & (TYMED_ISTREAM | TYMED_HGLOBAL | TYMED_ISTORAGE);
1505 else /* non-Ole format */
1506 mask = fmt->tymed & get_tymed_from_nonole_cf(fmt->cfFormat);
1508 if(!mask)
1510 hr = DV_E_TYMED;
1511 goto end;
1514 h = GetClipboardData(fmt->cfFormat);
1515 if(!h)
1517 hr = DV_E_FORMATETC;
1518 goto end;
1521 if(mask & TYMED_HGLOBAL)
1522 hr = get_stgmed_for_global(h, med);
1523 else if(mask & TYMED_ISTREAM)
1524 hr = get_stgmed_for_stream(h, med);
1525 else if(mask & TYMED_ISTORAGE)
1526 hr = get_stgmed_for_storage(h, med);
1527 else if(mask & TYMED_ENHMF)
1528 hr = get_stgmed_for_emf((HENHMETAFILE)h, med);
1529 else if(mask & TYMED_GDI)
1530 hr = get_stgmed_for_bitmap((HBITMAP)h, med);
1531 else
1533 FIXME("Unhandled tymed - mask %lx req tymed %lx\n", mask, fmt->tymed);
1534 hr = E_FAIL;
1535 goto end;
1538 end:
1539 HeapFree(GetProcessHeap(), 0, enum_data);
1540 if ( !CloseClipboard() ) hr = CLIPBRD_E_CANT_CLOSE;
1541 return hr;
1544 /************************************************************************
1545 * snapshot_GetDataHere
1547 static HRESULT WINAPI snapshot_GetDataHere(IDataObject *iface, FORMATETC *fmt,
1548 STGMEDIUM *med)
1550 snapshot *This = impl_from_IDataObject(iface);
1551 HANDLE h;
1552 HRESULT hr;
1553 ole_priv_data *enum_data = NULL;
1554 ole_priv_data_entry *entry;
1555 TYMED supported;
1557 if ( !fmt || !med ) return E_INVALIDARG;
1559 TRACE("%p, %p {%s}, %p (tymed %lx)\n", iface, fmt, dump_fmtetc(fmt), med, med->tymed);
1561 if ( !OpenClipboard(NULL)) return CLIPBRD_E_CANT_OPEN;
1563 if(!This->data)
1564 hr = get_current_dataobject(&This->data);
1566 if(This->data)
1568 hr = IDataObject_GetDataHere(This->data, fmt, med);
1569 if(SUCCEEDED(hr))
1571 CloseClipboard();
1572 return hr;
1576 h = GetClipboardData(fmt->cfFormat);
1577 if(!h)
1579 hr = DV_E_FORMATETC;
1580 goto end;
1583 hr = get_priv_data(&enum_data);
1584 if(FAILED(hr)) goto end;
1586 entry = find_format_in_list(enum_data->entries, enum_data->count, fmt->cfFormat);
1587 if(entry)
1589 if(!td_equal(fmt->ptd, entry->fmtetc.ptd))
1591 hr = DV_E_FORMATETC;
1592 goto end;
1594 supported = entry->fmtetc.tymed;
1596 else /* non-Ole format */
1597 supported = TYMED_HGLOBAL;
1599 switch(med->tymed)
1601 case TYMED_HGLOBAL:
1603 DWORD src_size = GlobalSize(h);
1604 DWORD dst_size = GlobalSize(med->hGlobal);
1605 hr = E_FAIL;
1606 if(dst_size >= src_size)
1608 void *src = GlobalLock(h);
1609 void *dst = GlobalLock(med->hGlobal);
1611 memcpy(dst, src, src_size);
1612 GlobalUnlock(med->hGlobal);
1613 GlobalUnlock(h);
1614 hr = S_OK;
1616 break;
1618 case TYMED_ISTREAM:
1620 DWORD src_size = GlobalSize(h);
1621 void *src = GlobalLock(h);
1622 hr = IStream_Write(med->pstm, src, src_size, NULL);
1623 GlobalUnlock(h);
1624 break;
1626 case TYMED_ISTORAGE:
1628 STGMEDIUM copy;
1629 if(!(supported & TYMED_ISTORAGE))
1631 hr = E_FAIL;
1632 goto end;
1634 hr = get_stgmed_for_storage(h, &copy);
1635 if(SUCCEEDED(hr))
1637 hr = IStorage_CopyTo(copy.pstg, 0, NULL, NULL, med->pstg);
1638 ReleaseStgMedium(&copy);
1640 break;
1642 default:
1643 FIXME("Unhandled tymed - supported %x req tymed %lx\n", supported, med->tymed);
1644 hr = E_FAIL;
1645 goto end;
1648 end:
1649 HeapFree(GetProcessHeap(), 0, enum_data);
1650 if ( !CloseClipboard() ) hr = CLIPBRD_E_CANT_CLOSE;
1651 return hr;
1654 /************************************************************************
1655 * snapshot_QueryGetData
1657 * The OLE Clipboard's implementation of this method delegates to
1658 * a data source if there is one or wraps around the windows clipboard
1659 * function IsClipboardFormatAvailable() otherwise.
1662 static HRESULT WINAPI snapshot_QueryGetData(IDataObject *iface, FORMATETC *fmt)
1664 TRACE("(%p, %p {%s})\n", iface, fmt, dump_fmtetc(fmt));
1666 if (!fmt) return E_INVALIDARG;
1668 if ( fmt->dwAspect != DVASPECT_CONTENT ) return DV_E_FORMATETC;
1670 if ( fmt->lindex != -1 ) return DV_E_FORMATETC;
1672 return (IsClipboardFormatAvailable(fmt->cfFormat)) ? S_OK : DV_E_CLIPFORMAT;
1675 /************************************************************************
1676 * snapshot_GetCanonicalFormatEtc
1678 static HRESULT WINAPI snapshot_GetCanonicalFormatEtc(IDataObject *iface, FORMATETC *fmt_in,
1679 FORMATETC *fmt_out)
1681 TRACE("(%p, %p, %p)\n", iface, fmt_in, fmt_out);
1683 if ( !fmt_in || !fmt_out ) return E_INVALIDARG;
1685 *fmt_out = *fmt_in;
1686 return DATA_S_SAMEFORMATETC;
1689 /************************************************************************
1690 * snapshot_SetData
1692 * The OLE Clipboard does not implement this method
1694 static HRESULT WINAPI snapshot_SetData(IDataObject *iface, FORMATETC *fmt,
1695 STGMEDIUM *med, BOOL release)
1697 TRACE("(%p, %p, %p, %d): not implemented\n", iface, fmt, med, release);
1698 return E_NOTIMPL;
1701 /************************************************************************
1702 * snapshot_EnumFormatEtc
1705 static HRESULT WINAPI snapshot_EnumFormatEtc(IDataObject *iface, DWORD dir,
1706 IEnumFORMATETC **enum_fmt)
1708 HRESULT hr;
1709 ole_priv_data *data = NULL;
1711 TRACE("%p, %lx, %p.\n", iface, dir, enum_fmt);
1713 *enum_fmt = NULL;
1715 if ( dir != DATADIR_GET ) return E_NOTIMPL;
1716 if ( !OpenClipboard(NULL) ) return CLIPBRD_E_CANT_OPEN;
1718 hr = get_priv_data(&data);
1720 if(FAILED(hr)) goto end;
1722 hr = enum_fmtetc_construct( data, 0, enum_fmt );
1724 end:
1725 if ( !CloseClipboard() ) hr = CLIPBRD_E_CANT_CLOSE;
1726 return hr;
1729 /************************************************************************
1730 * snapshot_DAdvise
1732 * The OLE Clipboard does not implement this method
1734 static HRESULT WINAPI snapshot_DAdvise(IDataObject *iface, FORMATETC *fmt,
1735 DWORD flags, IAdviseSink *sink,
1736 DWORD *conn)
1738 TRACE("%p, %p, %lx, %p, %p.\n", iface, fmt, flags, sink, conn);
1739 return E_NOTIMPL;
1742 /************************************************************************
1743 * snapshot_DUnadvise
1745 * The OLE Clipboard does not implement this method
1747 static HRESULT WINAPI snapshot_DUnadvise(IDataObject* iface, DWORD conn)
1749 TRACE("%p, %ld.\n", iface, conn);
1750 return E_NOTIMPL;
1753 /************************************************************************
1754 * snapshot_EnumDAdvise
1756 * The OLE Clipboard does not implement this method
1758 static HRESULT WINAPI snapshot_EnumDAdvise(IDataObject* iface,
1759 IEnumSTATDATA** enum_advise)
1761 TRACE("(%p, %p): not implemented\n", iface, enum_advise);
1762 return E_NOTIMPL;
1765 static const IDataObjectVtbl snapshot_vtable =
1767 snapshot_QueryInterface,
1768 snapshot_AddRef,
1769 snapshot_Release,
1770 snapshot_GetData,
1771 snapshot_GetDataHere,
1772 snapshot_QueryGetData,
1773 snapshot_GetCanonicalFormatEtc,
1774 snapshot_SetData,
1775 snapshot_EnumFormatEtc,
1776 snapshot_DAdvise,
1777 snapshot_DUnadvise,
1778 snapshot_EnumDAdvise
1781 /*---------------------------------------------------------------------*
1782 * Internal implementation methods for the OLE clipboard
1783 *---------------------------------------------------------------------*/
1785 static snapshot *snapshot_construct(DWORD seq_no)
1787 snapshot *This;
1789 This = HeapAlloc( GetProcessHeap(), 0, sizeof(*This) );
1790 if (!This) return NULL;
1792 This->IDataObject_iface.lpVtbl = &snapshot_vtable;
1793 This->ref = 0;
1794 This->seq_no = seq_no;
1795 This->data = NULL;
1797 return This;
1800 /*********************************************************************
1801 * set_clipboard_formats
1803 * Enumerate all formats supported by the source and make
1804 * those formats available using delayed rendering using SetClipboardData.
1805 * Cache the enumeration list and make that list visible as the
1806 * 'Ole Private Data' format on the clipboard.
1809 static HRESULT set_clipboard_formats(ole_clipbrd *clipbrd, IDataObject *data)
1811 HRESULT hr;
1812 FORMATETC fmt;
1813 IEnumFORMATETC *enum_fmt;
1814 HGLOBAL priv_data_handle;
1815 DWORD_PTR target_offset;
1816 ole_priv_data *priv_data;
1817 DWORD count = 0, needed = sizeof(*priv_data), idx;
1819 hr = IDataObject_EnumFormatEtc(data, DATADIR_GET, &enum_fmt);
1820 if(FAILED(hr)) return hr;
1822 while(IEnumFORMATETC_Next(enum_fmt, 1, &fmt, NULL) == S_OK)
1824 count++;
1825 needed += sizeof(priv_data->entries[0]);
1826 if(fmt.ptd)
1828 needed += fmt.ptd->tdSize;
1829 CoTaskMemFree(fmt.ptd);
1833 /* Windows pads the list with two empty ole_priv_data_entries, one
1834 * after the entries array and one after the target device data.
1835 * Allocating with zero init to zero these pads. */
1837 needed += sizeof(priv_data->entries[0]); /* initialisation of needed includes one of these. */
1838 priv_data_handle = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE | GMEM_ZEROINIT, needed);
1839 priv_data = GlobalLock(priv_data_handle);
1841 priv_data->unk1 = 0;
1842 priv_data->size = needed;
1843 priv_data->unk2 = 1;
1844 priv_data->count = count;
1845 priv_data->unk3[0] = 0;
1846 priv_data->unk3[1] = 0;
1848 IEnumFORMATETC_Reset(enum_fmt);
1850 idx = 0;
1851 target_offset = FIELD_OFFSET(ole_priv_data, entries[count + 1]); /* count entries + one pad. */
1853 while(IEnumFORMATETC_Next(enum_fmt, 1, &fmt, NULL) == S_OK)
1855 TRACE("%s\n", dump_fmtetc(&fmt));
1857 priv_data->entries[idx].fmtetc = fmt;
1858 if(fmt.ptd)
1860 memcpy((char*)priv_data + target_offset, fmt.ptd, fmt.ptd->tdSize);
1861 priv_data->entries[idx].fmtetc.ptd = (DVTARGETDEVICE*)target_offset;
1862 target_offset += fmt.ptd->tdSize;
1863 CoTaskMemFree(fmt.ptd);
1866 priv_data->entries[idx].first_use = !find_format_in_list(priv_data->entries, idx, fmt.cfFormat);
1867 priv_data->entries[idx].unk[0] = 0;
1868 priv_data->entries[idx].unk[1] = 0;
1870 if (priv_data->entries[idx].first_use)
1871 SetClipboardData(fmt.cfFormat, NULL);
1873 idx++;
1876 IEnumFORMATETC_Release(enum_fmt);
1878 /* Cache the list and fixup any target device offsets to ptrs */
1879 clipbrd->cached_enum = HeapAlloc(GetProcessHeap(), 0, needed);
1880 memcpy(clipbrd->cached_enum, priv_data, needed);
1881 for(idx = 0; idx < clipbrd->cached_enum->count; idx++)
1882 clipbrd->cached_enum->entries[idx].fmtetc.ptd =
1883 td_offs_to_ptr(clipbrd->cached_enum, (DWORD_PTR)clipbrd->cached_enum->entries[idx].fmtetc.ptd);
1885 GlobalUnlock(priv_data_handle);
1886 if(!SetClipboardData(ole_private_data_clipboard_format, priv_data_handle))
1888 GlobalFree(priv_data_handle);
1889 return CLIPBRD_E_CANT_SET;
1892 return S_OK;
1895 static HWND create_clipbrd_window(void);
1897 /***********************************************************************
1898 * get_clipbrd_window
1900 static inline HRESULT get_clipbrd_window(ole_clipbrd *clipbrd, HWND *wnd)
1902 if ( !clipbrd->window )
1903 clipbrd->window = create_clipbrd_window();
1905 *wnd = clipbrd->window;
1906 return *wnd ? S_OK : E_FAIL;
1910 /**********************************************************************
1911 * release_marshal_data
1913 * Releases the data and sets the stream back to zero size.
1915 static inline void release_marshal_data(IStream *stm)
1917 LARGE_INTEGER pos;
1918 ULARGE_INTEGER size;
1919 pos.QuadPart = size.QuadPart = 0;
1921 IStream_Seek(stm, pos, STREAM_SEEK_SET, NULL);
1922 CoReleaseMarshalData(stm);
1923 IStream_Seek(stm, pos, STREAM_SEEK_SET, NULL);
1924 IStream_SetSize(stm, size);
1927 /***********************************************************************
1928 * expose_marshalled_dataobject
1930 * Sets the marshalled dataobject to the clipboard. In the flushed case
1931 * we set a zero sized HGLOBAL to clear the old marshalled data.
1933 static HRESULT expose_marshalled_dataobject(ole_clipbrd *clipbrd, IDataObject *data)
1935 HGLOBAL h;
1937 if(data)
1939 HGLOBAL h_stm;
1940 GetHGlobalFromStream(clipbrd->marshal_data, &h_stm);
1941 dup_global_mem(h_stm, GMEM_DDESHARE|GMEM_MOVEABLE, &h);
1943 else /* flushed */
1944 h = GlobalAlloc(GMEM_DDESHARE|GMEM_MOVEABLE, 1);
1946 if(!h) return E_OUTOFMEMORY;
1948 if(!SetClipboardData(wine_marshal_clipboard_format, h))
1950 GlobalFree(h);
1951 return CLIPBRD_E_CANT_SET;
1953 return S_OK;
1956 /***********************************************************************
1957 * set_src_dataobject
1959 * Clears and sets the clipboard's src IDataObject.
1961 * To marshal the source dataobject we do something rather different from Windows.
1962 * We set a clipboard format which contains the marshalled data.
1963 * Windows sets two window props one of which is an IID, the other is an endpoint number.
1965 static HRESULT set_src_dataobject(ole_clipbrd *clipbrd, IDataObject *data)
1967 HRESULT hr;
1968 HWND wnd;
1970 if(FAILED(hr = get_clipbrd_window(clipbrd, &wnd))) return hr;
1972 if(clipbrd->src_data)
1974 release_marshal_data(clipbrd->marshal_data);
1976 IDataObject_Release(clipbrd->src_data);
1977 clipbrd->src_data = NULL;
1978 HeapFree(GetProcessHeap(), 0, clipbrd->cached_enum);
1979 clipbrd->cached_enum = NULL;
1982 if(data)
1984 IUnknown *unk;
1986 IDataObject_AddRef(data);
1987 clipbrd->src_data = data;
1989 IDataObject_QueryInterface(data, &IID_IUnknown, (void**)&unk);
1990 hr = CoMarshalInterface(clipbrd->marshal_data, &IID_IDataObject, unk,
1991 MSHCTX_LOCAL, NULL, MSHLFLAGS_TABLESTRONG);
1992 IUnknown_Release(unk); /* Don't hold a ref on IUnknown, we have one on IDataObject. */
1993 if(FAILED(hr)) return hr;
1994 hr = set_clipboard_formats(clipbrd, data);
1996 return hr;
1999 /***********************************************************************
2000 * clipbrd_uninitialize()
2001 * Un-Initializes the OLE clipboard
2003 void clipbrd_uninitialize(void)
2005 ole_clipbrd *clipbrd = theOleClipboard;
2007 TRACE("()\n");
2009 if ( clipbrd )
2011 /* OleUninitialize() does not release the reference to the dataobject, so
2012 take an additional reference here. This reference is then leaked. */
2013 if (clipbrd->src_data)
2015 IDataObject_AddRef(clipbrd->src_data);
2016 set_src_dataobject(clipbrd, NULL);
2019 if ( clipbrd->window )
2021 DestroyWindow(clipbrd->window);
2022 UnregisterClassW( clipbrd_wndclass, GetModuleHandleW(L"ole32") );
2023 clipbrd->window = NULL;
2028 /***********************************************************************
2029 * clipbrd_destroy()
2030 * Destroy the OLE clipboard
2032 void clipbrd_destroy(void)
2034 ole_clipbrd *clipbrd = theOleClipboard;
2036 if (!clipbrd) return;
2038 clipbrd_uninitialize();
2040 IStream_Release(clipbrd->marshal_data);
2041 HeapFree(GetProcessHeap(), 0, clipbrd);
2042 theOleClipboard = NULL;
2045 /***********************************************************************
2046 * clipbrd_wndproc
2048 static LRESULT CALLBACK clipbrd_wndproc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
2050 ole_clipbrd *clipbrd;
2052 get_ole_clipbrd(&clipbrd);
2054 switch (message)
2056 case WM_RENDERFORMAT:
2058 UINT cf = wparam;
2059 ole_priv_data_entry *entry;
2061 TRACE("(): WM_RENDERFORMAT(cfFormat=%x)\n", cf);
2063 if (!clipbrd || !clipbrd->cached_enum) break;
2064 entry = find_format_in_list(clipbrd->cached_enum->entries, clipbrd->cached_enum->count, cf);
2066 if(entry)
2067 render_format(clipbrd->src_data, &entry->fmtetc);
2069 break;
2072 case WM_RENDERALLFORMATS:
2074 DWORD i;
2075 ole_priv_data_entry *entries;
2077 TRACE("(): WM_RENDERALLFORMATS\n");
2079 if (!clipbrd || !clipbrd->cached_enum) break;
2080 entries = clipbrd->cached_enum->entries;
2081 for(i = 0; i < clipbrd->cached_enum->count; i++)
2083 if(entries[i].first_use)
2084 render_format(clipbrd->src_data, &entries[i].fmtetc);
2086 break;
2089 case WM_DESTROYCLIPBOARD:
2091 TRACE("(): WM_DESTROYCLIPBOARD\n");
2093 set_src_dataobject(clipbrd, NULL);
2094 break;
2097 default:
2098 return DefWindowProcW(hwnd, message, wparam, lparam);
2101 return 0;
2105 /***********************************************************************
2106 * create_clipbrd_window
2108 static HWND create_clipbrd_window(void)
2110 WNDCLASSEXW class;
2111 HINSTANCE hinst = GetModuleHandleW(L"ole32");
2113 class.cbSize = sizeof(class);
2114 class.style = 0;
2115 class.lpfnWndProc = clipbrd_wndproc;
2116 class.cbClsExtra = 0;
2117 class.cbWndExtra = 0;
2118 class.hInstance = hinst;
2119 class.hIcon = 0;
2120 class.hCursor = 0;
2121 class.hbrBackground = 0;
2122 class.lpszMenuName = NULL;
2123 class.lpszClassName = clipbrd_wndclass;
2124 class.hIconSm = NULL;
2126 RegisterClassExW(&class);
2128 return CreateWindowW(clipbrd_wndclass, L"ClipboardWindow", WS_POPUP | WS_CLIPSIBLINGS | WS_OVERLAPPED,
2129 0, 0, 0, 0, HWND_MESSAGE, NULL, hinst, 0);
2132 /*********************************************************************
2133 * set_dataobject_format
2135 * Windows creates a 'DataObject' clipboard format that contains the
2136 * clipboard window's HWND or NULL if the Ole clipboard has been flushed.
2138 static HRESULT set_dataobject_format(HWND hwnd)
2140 HGLOBAL h = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE, sizeof(hwnd));
2141 HWND *data;
2143 if(!h) return E_OUTOFMEMORY;
2145 data = GlobalLock(h);
2146 *data = hwnd;
2147 GlobalUnlock(h);
2149 if(!SetClipboardData(dataobject_clipboard_format, h))
2151 GlobalFree(h);
2152 return CLIPBRD_E_CANT_SET;
2155 return S_OK;
2158 /*---------------------------------------------------------------------*
2159 * Win32 OLE clipboard API
2160 *---------------------------------------------------------------------*/
2162 /***********************************************************************
2163 * OleSetClipboard [OLE32.@]
2164 * Places a pointer to the specified data object onto the clipboard,
2165 * making the data object accessible to the OleGetClipboard function.
2167 * RETURNS
2169 * S_OK IDataObject pointer placed on the clipboard
2170 * CLIPBRD_E_CANT_OPEN OpenClipboard failed
2171 * CLIPBRD_E_CANT_EMPTY EmptyClipboard failed
2172 * CLIPBRD_E_CANT_CLOSE CloseClipboard failed
2173 * CLIPBRD_E_CANT_SET SetClipboard failed
2176 HRESULT WINAPI OleSetClipboard(IDataObject* data)
2178 struct oletls *info = COM_CurrentInfo();
2179 HRESULT hr;
2180 ole_clipbrd *clipbrd;
2181 HWND wnd;
2183 TRACE("(%p)\n", data);
2185 if(!info->ole_inits)
2186 return CO_E_NOTINITIALIZED;
2188 if(FAILED(hr = get_ole_clipbrd(&clipbrd))) return hr;
2190 if(FAILED(hr = get_clipbrd_window(clipbrd, &wnd))) return hr;
2192 if ( !OpenClipboard(wnd) ) return CLIPBRD_E_CANT_OPEN;
2194 if ( !EmptyClipboard() )
2196 hr = CLIPBRD_E_CANT_EMPTY;
2197 goto end;
2200 hr = set_src_dataobject(clipbrd, data);
2201 if(FAILED(hr)) goto end;
2203 if(data)
2205 hr = expose_marshalled_dataobject(clipbrd, data);
2206 if(FAILED(hr)) goto end;
2207 hr = set_dataobject_format(wnd);
2210 end:
2212 if ( !CloseClipboard() ) hr = CLIPBRD_E_CANT_CLOSE;
2214 if ( FAILED(hr) )
2216 expose_marshalled_dataobject(clipbrd, NULL);
2217 set_src_dataobject(clipbrd, NULL);
2220 return hr;
2224 /***********************************************************************
2225 * OleGetClipboard [OLE32.@]
2226 * Returns a pointer to our internal IDataObject which represents the conceptual
2227 * state of the Windows clipboard. If the current clipboard already contains
2228 * an IDataObject, our internal IDataObject will delegate to this object.
2230 HRESULT WINAPI OleGetClipboard(IDataObject **obj)
2232 HRESULT hr;
2233 ole_clipbrd *clipbrd;
2234 DWORD seq_no;
2236 TRACE("(%p)\n", obj);
2238 if(!obj) return E_INVALIDARG;
2239 *obj = NULL;
2241 if(FAILED(hr = get_ole_clipbrd(&clipbrd))) return hr;
2243 seq_no = GetClipboardSequenceNumber();
2244 EnterCriticalSection(&latest_snapshot_cs);
2245 if(clipbrd->latest_snapshot && clipbrd->latest_snapshot->seq_no != seq_no)
2246 clipbrd->latest_snapshot = NULL;
2248 if(!clipbrd->latest_snapshot)
2250 clipbrd->latest_snapshot = snapshot_construct(seq_no);
2251 if(!clipbrd->latest_snapshot)
2253 LeaveCriticalSection(&latest_snapshot_cs);
2254 return E_OUTOFMEMORY;
2258 *obj = &clipbrd->latest_snapshot->IDataObject_iface;
2259 IDataObject_AddRef(*obj);
2260 LeaveCriticalSection(&latest_snapshot_cs);
2262 return S_OK;
2265 /******************************************************************************
2266 * OleFlushClipboard [OLE32.@]
2267 * Renders the data from the source IDataObject into the windows clipboard
2269 * TODO: OleFlushClipboard needs to additionally handle TYMED_IStorage media
2270 * by copying the storage into global memory. Subsequently the default
2271 * data object exposed through OleGetClipboard must convert this TYMED_HGLOBAL
2272 * back to TYMED_IStorage.
2274 HRESULT WINAPI OleFlushClipboard(void)
2276 struct oletls *info = COM_CurrentInfo();
2277 HRESULT hr;
2278 ole_clipbrd *clipbrd;
2279 HWND wnd;
2281 TRACE("()\n");
2283 if(FAILED(hr = get_ole_clipbrd(&clipbrd))) return hr;
2285 if(!info->ole_inits)
2286 return E_FAIL;
2288 if(FAILED(hr = get_clipbrd_window(clipbrd, &wnd))) return hr;
2291 * Already flushed or no source DataObject? Nothing to do.
2293 if (!clipbrd->src_data) return S_OK;
2295 if (!OpenClipboard(wnd)) return CLIPBRD_E_CANT_OPEN;
2297 SendMessageW(wnd, WM_RENDERALLFORMATS, 0, 0);
2299 hr = set_dataobject_format(NULL);
2301 expose_marshalled_dataobject(clipbrd, NULL);
2302 set_src_dataobject(clipbrd, NULL);
2304 if ( !CloseClipboard() ) hr = CLIPBRD_E_CANT_CLOSE;
2306 return hr;
2310 /***********************************************************************
2311 * OleIsCurrentClipboard [OLE32.@]
2313 HRESULT WINAPI OleIsCurrentClipboard(IDataObject *data)
2315 HRESULT hr;
2316 ole_clipbrd *clipbrd;
2317 TRACE("()\n");
2319 if(FAILED(hr = get_ole_clipbrd(&clipbrd))) return hr;
2321 if (data == NULL) return S_FALSE;
2323 return (data == clipbrd->src_data) ? S_OK : S_FALSE;