~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Wine Cross Reference
wine/dlls/ole32/clipboard.c

Version: ~ [ wine-1.1.33 ] ~ [ wine-1.1.32 ] ~ [ wine-1.1.31 ] ~ [ wine-1.1.30 ] ~ [ wine-1.1.29 ] ~ [ wine-1.1.28 ] ~ [ wine-1.1.27 ] ~ [ wine-1.1.26 ] ~ [ wine-1.1.25 ] ~ [ wine-1.1.24 ] ~ [ wine-1.1.23 ] ~ [ wine-1.1.22 ] ~ [ wine-1.1.21 ] ~ [ wine-1.1.20 ] ~ [ wine-1.1.19 ] ~ [ wine-1.1.18 ] ~ [ wine-1.1.17 ] ~ [ wine-1.1.16 ] ~ [ wine-1.1.15 ] ~ [ wine-1.1.14 ] ~ [ wine-1.1.13 ] ~ [ wine-1.1.12 ] ~ [ wine-1.1.11 ] ~ [ wine-1.1.10 ] ~ [ wine-1.1.9 ] ~ [ wine-1.1.8 ] ~ [ wine-1.1.7 ] ~ [ wine-1.0.1 ] ~ [ wine-1.1.6 ] ~ [ wine-1.1.5 ] ~ [ wine-1.1.4 ] ~ [ wine-1.1.3 ] ~ [ wine-1.1.2 ] ~ [ wine-1.1.1 ] ~ [ wine-1.1.0 ] ~ [ wine-1.0 ] ~

  1 /*
  2  *  OLE 2 clipboard support
  3  *
  4  *      Copyright 1999  Noel Borthwick <noel@macadamian.com>
  5  *      Copyright 2000  Abey George <abey@macadamian.com>
  6  *
  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.
 11  *
 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.
 16  *
 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
 20  *
 21  * NOTES:
 22  *    This file contains the implementation for the OLE Clipboard and its
 23  *    internal interfaces. The OLE clipboard interacts with an IDataObject
 24  *    interface via the OleSetClipboard, OleGetClipboard and
 25  *    OleIsCurrentClipboard API's. An internal IDataObject delegates
 26  *    to a client supplied IDataObject or the WIN32 clipboard API depending
 27  *    on whether OleSetClipboard has been invoked.
 28  *    Here are some operating scenarios:
 29  *
 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.
 36  *
 37  *    2. OleGetClipboard called without previous OleSetClipboard. Here the internal
 38  *       IDataObject functionality wraps around the WIN32 clipboard API.
 39  *
 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.
 43  *
 44  *    Implementation references : Inside OLE 2'nd  edition by Kraig Brockschmidt
 45  *
 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.
 58  *
 59  */
 60 
 61 #include <assert.h>
 62 #include <stdarg.h>
 63 #include <string.h>
 64 #include <stdio.h>
 65 
 66 #define COBJMACROS
 67 #define NONAMELESSUNION
 68 #define NONAMELESSSTRUCT
 69 
 70 #include "windef.h"
 71 #include "winbase.h"
 72 #include "wingdi.h"
 73 #include "winuser.h"
 74 #include "winerror.h"
 75 #include "winnls.h"
 76 #include "ole2.h"
 77 #include "wine/debug.h"
 78 #include "olestd.h"
 79 
 80 #include "storage32.h"
 81 
 82 #include "compobj_private.h"
 83 
 84 WINE_DEFAULT_DEBUG_CHANNEL(ole);
 85 
 86 #define HANDLE_ERROR(err) do { hr = err; TRACE("(HRESULT=%x)\n", (HRESULT)err); goto CLEANUP; } while (0)
 87 
 88 /* Structure of 'Ole Private Data' clipboard format */
 89 typedef struct
 90 {
 91     FORMATETC fmtetc;
 92     DWORD first_use;  /* Has this cf been added to the list already */
 93     DWORD unk[2];
 94 } ole_priv_data_entry;
 95 
 96 typedef struct
 97 {
 98     DWORD unk1;
 99     DWORD size; /* in bytes of the entire structure */
100     DWORD unk2;
101     DWORD count; /* no. of format entries */
102     DWORD unk3[2];
103     ole_priv_data_entry entries[1]; /* array of size count */
104     /* then follows any DVTARGETDEVICE structures referenced in the FORMATETCs */
105 } ole_priv_data;
106 
107 /*****************************************************************************
108  *           td_offs_to_ptr
109  *
110  * Returns a ptr to a target device at a given offset from the
111  * start of the ole_priv_data.
112  *
113  * Used when unpacking ole private data from the clipboard.
114  */
115 static inline DVTARGETDEVICE *td_offs_to_ptr(ole_priv_data *data, DWORD_PTR off)
116 {
117     if(off == 0) return NULL;
118     return (DVTARGETDEVICE*)((char*)data + off);
119 }
120 
121 /*****************************************************************************
122  *           td_get_offs
123  *
124  * Get the offset from the start of the ole_priv_data of the idx'th
125  * target device.
126  *
127  * Used when packing ole private data to the clipboard.
128  */
129 static inline DWORD_PTR td_get_offs(ole_priv_data *data, DWORD idx)
130 {
131     if(data->entries[idx].fmtetc.ptd == NULL) return 0;
132     return (char*)data->entries[idx].fmtetc.ptd - (char*)data;
133 }
134 
135 /****************************************************************************
136  * Consumer snapshot.  Represents the state of the ole clipboard
137  * returned by OleGetClipboard().
138  */
139 typedef struct snapshot
140 {
141     const IDataObjectVtbl* lpVtbl;
142     LONG ref;
143 
144     DWORD seq_no;                   /* Clipboard sequence number corresponding to this snapshot */
145 
146     IDataObject *data;              /* If we unmarshal a remote data object we hold a ref here */
147 } snapshot;
148 
149 /****************************************************************************
150  * ole_clipbrd
151  */
152 typedef struct ole_clipbrd
153 {
154     snapshot *latest_snapshot;       /* Latest consumer snapshot */
155 
156     HWND window;                     /* Hidden clipboard window */
157     IDataObject *src_data;           /* Source object passed to OleSetClipboard */
158     ole_priv_data *cached_enum;      /* Cached result from the enumeration of src data object */
159     IStream *marshal_data;           /* Stream onto which to marshal src_data */
160 } ole_clipbrd;
161 
162 static inline snapshot *impl_from_IDataObject(IDataObject *iface)
163 {
164     return (snapshot*)((char*)iface - FIELD_OFFSET(snapshot, lpVtbl));
165 }
166 
167 typedef struct PresentationDataHeader
168 {
169   BYTE unknown1[28];
170   DWORD dwObjectExtentX;
171   DWORD dwObjectExtentY;
172   DWORD dwSize;
173 } PresentationDataHeader;
174 
175 /*
176  * The one and only ole_clipbrd object which is created by OLEClipbrd_Initialize()
177  */
178 static ole_clipbrd* theOleClipboard;
179 
180 static inline HRESULT get_ole_clipbrd(ole_clipbrd **clipbrd)
181 {
182     struct oletls *info = COM_CurrentInfo();
183     *clipbrd = NULL;
184 
185     if(!info->ole_inits)
186         return CO_E_NOTINITIALIZED;
187     *clipbrd = theOleClipboard;
188 
189     return S_OK;
190 }
191 
192 /*
193  * Name of our registered OLE clipboard window class
194  */
195 static const WCHAR clipbrd_wndclass[] = {'C','L','I','P','B','R','D','W','N','D','C','L','A','S','S',0};
196 
197 static const WCHAR wine_marshal_dataobject[] = {'W','i','n','e',' ','m','a','r','s','h','a','l',' ','d','a','t','a','o','b','j','e','c','t',0};
198 
199 UINT ownerlink_clipboard_format = 0;
200 UINT filename_clipboard_format = 0;
201 UINT filenameW_clipboard_format = 0;
202 UINT dataobject_clipboard_format = 0;
203 UINT embedded_object_clipboard_format = 0;
204 UINT embed_source_clipboard_format = 0;
205 UINT custom_link_source_clipboard_format = 0;
206 UINT link_source_clipboard_format = 0;
207 UINT object_descriptor_clipboard_format = 0;
208 UINT link_source_descriptor_clipboard_format = 0;
209 UINT ole_private_data_clipboard_format = 0;
210 
211 static UINT wine_marshal_clipboard_format;
212 
213 static inline char *dump_fmtetc(FORMATETC *fmt)
214 {
215     static char buf[100];
216 
217     snprintf(buf, sizeof(buf), "cf %04x ptd %p aspect %x lindex %d tymed %x",
218              fmt->cfFormat, fmt->ptd, fmt->dwAspect, fmt->lindex, fmt->tymed);
219     return buf;
220 }
221 
222 /*---------------------------------------------------------------------*
223  *  Implementation of the internal IEnumFORMATETC interface returned by
224  *  the OLE clipboard's IDataObject.
225  *---------------------------------------------------------------------*/
226 
227 typedef struct enum_fmtetc
228 {
229     const IEnumFORMATETCVtbl *lpVtbl;
230     LONG ref;
231 
232     UINT pos;    /* current enumerator position */
233     ole_priv_data *data;
234 } enum_fmtetc;
235 
236 static inline enum_fmtetc *impl_from_IEnumFORMATETC(IEnumFORMATETC *iface)
237 {
238     return (enum_fmtetc*)((char*)iface - FIELD_OFFSET(enum_fmtetc, lpVtbl));
239 }
240 
241 /************************************************************************
242  * OLEClipbrd_IEnumFORMATETC_QueryInterface (IUnknown)
243  *
244  * See Windows documentation for more details on IUnknown methods.
245  */
246 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_QueryInterface
247   (LPENUMFORMATETC iface, REFIID riid, LPVOID* ppvObj)
248 {
249   enum_fmtetc *This = impl_from_IEnumFORMATETC(iface);
250 
251   TRACE("(%p)->(IID: %s, %p)\n", This, debugstr_guid(riid), ppvObj);
252 
253   *ppvObj = NULL;
254 
255   if(IsEqualIID(riid, &IID_IUnknown) ||
256      IsEqualIID(riid, &IID_IEnumFORMATETC))
257   {
258     *ppvObj = iface;
259   }
260 
261   if(*ppvObj)
262   {
263     IEnumFORMATETC_AddRef((IEnumFORMATETC*)*ppvObj);
264     TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
265     return S_OK;
266   }
267 
268   TRACE("-- Interface: E_NOINTERFACE\n");
269   return E_NOINTERFACE;
270 }
271 
272 /************************************************************************
273  * OLEClipbrd_IEnumFORMATETC_AddRef (IUnknown)
274  *
275  */
276 static ULONG WINAPI OLEClipbrd_IEnumFORMATETC_AddRef(LPENUMFORMATETC iface)
277 {
278   enum_fmtetc *This = impl_from_IEnumFORMATETC(iface);
279   TRACE("(%p)->(count=%u)\n",This, This->ref);
280 
281   return InterlockedIncrement(&This->ref);
282 }
283 
284 /************************************************************************
285  * OLEClipbrd_IEnumFORMATETC_Release (IUnknown)
286  *
287  * See Windows documentation for more details on IUnknown methods.
288  */
289 static ULONG WINAPI OLEClipbrd_IEnumFORMATETC_Release(LPENUMFORMATETC iface)
290 {
291   enum_fmtetc *This = impl_from_IEnumFORMATETC(iface);
292   ULONG ref;
293 
294   TRACE("(%p)->(count=%u)\n",This, This->ref);
295 
296   ref = InterlockedDecrement(&This->ref);
297   if (!ref)
298   {
299     TRACE("() - destroying IEnumFORMATETC(%p)\n",This);
300     HeapFree(GetProcessHeap(), 0, This->data);
301     HeapFree(GetProcessHeap(), 0, This);
302   }
303   return ref;
304 }
305 
306 /************************************************************************
307  * OLEClipbrd_IEnumFORMATETC_Next (IEnumFORMATETC)
308  *
309  * Standard enumerator members for IEnumFORMATETC
310  */
311 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Next
312   (LPENUMFORMATETC iface, ULONG celt, FORMATETC *rgelt, ULONG *pceltFethed)
313 {
314   enum_fmtetc *This = impl_from_IEnumFORMATETC(iface);
315   UINT cfetch, i;
316   HRESULT hres = S_FALSE;
317 
318   TRACE("(%p)->(pos=%u)\n", This, This->pos);
319 
320   if (This->pos < This->data->count)
321   {
322     cfetch = This->data->count - This->pos;
323     if (cfetch >= celt)
324     {
325       cfetch = celt;
326       hres = S_OK;
327     }
328 
329     for(i = 0; i < cfetch; i++)
330     {
331       rgelt[i] = This->data->entries[This->pos++].fmtetc;
332       if(rgelt[i].ptd)
333       {
334         DVTARGETDEVICE *target = rgelt[i].ptd;
335         rgelt[i].ptd = CoTaskMemAlloc(target->tdSize);
336         if(!rgelt[i].ptd) return E_OUTOFMEMORY;
337         memcpy(rgelt[i].ptd, target, target->tdSize);
338       }
339     }
340   }
341   else
342   {
343     cfetch = 0;
344   }
345 
346   if (pceltFethed)
347   {
348     *pceltFethed = cfetch;
349   }
350 
351   return hres;
352 }
353 
354 /************************************************************************
355  * OLEClipbrd_IEnumFORMATETC_Skip (IEnumFORMATETC)
356  *
357  * Standard enumerator members for IEnumFORMATETC
358  */
359 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Skip(LPENUMFORMATETC iface, ULONG celt)
360 {
361   enum_fmtetc *This = impl_from_IEnumFORMATETC(iface);
362   TRACE("(%p)->(num=%u)\n", This, celt);
363 
364   This->pos += celt;
365   if (This->pos > This->data->count)
366   {
367     This->pos = This->data->count;
368     return S_FALSE;
369   }
370   return S_OK;
371 }
372 
373 /************************************************************************
374  * OLEClipbrd_IEnumFORMATETC_Reset (IEnumFORMATETC)
375  *
376  * Standard enumerator members for IEnumFORMATETC
377  */
378 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Reset(LPENUMFORMATETC iface)
379 {
380   enum_fmtetc *This = impl_from_IEnumFORMATETC(iface);
381   TRACE("(%p)->()\n", This);
382 
383   This->pos = 0;
384   return S_OK;
385 }
386 
387 static HRESULT enum_fmtetc_construct(ole_priv_data *data, UINT pos, IEnumFORMATETC **obj);
388 
389 /************************************************************************
390  * OLEClipbrd_IEnumFORMATETC_Clone (IEnumFORMATETC)
391  *
392  * Standard enumerator members for IEnumFORMATETC
393  */
394 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Clone
395   (LPENUMFORMATETC iface, LPENUMFORMATETC* obj)
396 {
397   enum_fmtetc *This = impl_from_IEnumFORMATETC(iface);
398   ole_priv_data *new_data;
399   DWORD i;
400 
401   TRACE("(%p)->(%p)\n", This, obj);
402 
403   if ( !obj ) return E_INVALIDARG;
404   *obj = NULL;
405 
406   new_data = HeapAlloc(GetProcessHeap(), 0, This->data->size);
407   if(!new_data) return E_OUTOFMEMORY;
408   memcpy(new_data, This->data, This->data->size);
409 
410   /* Fixup any target device ptrs */
411   for(i = 0; i < This->data->count; i++)
412       new_data->entries[i].fmtetc.ptd =
413           td_offs_to_ptr(new_data, td_get_offs(This->data, i));
414 
415   return enum_fmtetc_construct(new_data, This->pos, obj);
416 }
417 
418 static const IEnumFORMATETCVtbl efvt =
419 {
420   OLEClipbrd_IEnumFORMATETC_QueryInterface,
421   OLEClipbrd_IEnumFORMATETC_AddRef,
422   OLEClipbrd_IEnumFORMATETC_Release,
423   OLEClipbrd_IEnumFORMATETC_Next,
424   OLEClipbrd_IEnumFORMATETC_Skip,
425   OLEClipbrd_IEnumFORMATETC_Reset,
426   OLEClipbrd_IEnumFORMATETC_Clone
427 };
428 
429 /************************************************************************
430  * enum_fmtetc_construct
431  *
432  * Creates an IEnumFORMATETC enumerator from ole_priv_data which it then owns.
433  */
434 static HRESULT enum_fmtetc_construct(ole_priv_data *data, UINT pos, IEnumFORMATETC **obj)
435 {
436   enum_fmtetc* ef;
437 
438   *obj = NULL;
439   ef = HeapAlloc(GetProcessHeap(), 0, sizeof(*ef));
440   if (!ef) return E_OUTOFMEMORY;
441 
442   ef->ref = 1;
443   ef->lpVtbl = &efvt;
444   ef->data = data;
445   ef->pos = pos;
446 
447   TRACE("(%p)->()\n", ef);
448   *obj = (IEnumFORMATETC *)ef;
449   return S_OK;
450 }
451 
452 /***********************************************************************
453  *                    dup_global_mem
454  *
455  * Helper method to duplicate an HGLOBAL chunk of memory
456  */
457 static HRESULT dup_global_mem( HGLOBAL src, DWORD flags, HGLOBAL *dst )
458 {
459     void *src_ptr, *dst_ptr;
460     DWORD size;
461 
462     *dst = NULL;
463     if ( !src ) return S_FALSE;
464 
465     size = GlobalSize(src);
466 
467     *dst = GlobalAlloc( flags, size );
468     if ( !*dst ) return E_OUTOFMEMORY;
469 
470     src_ptr = GlobalLock(src);
471     dst_ptr = GlobalLock(*dst);
472 
473     memcpy(dst_ptr, src_ptr, size);
474 
475     GlobalUnlock(*dst);
476     GlobalUnlock(src);
477 
478     return S_OK;
479 }
480 
481 /************************************************************
482  *              render_embed_source_hack
483  *
484  * This is clearly a hack and has no place in the clipboard code.
485  *
486  */
487 static HRESULT render_embed_source_hack(IDataObject *data, LPFORMATETC fmt)
488 {
489     STGMEDIUM std;
490     HGLOBAL hStorage = 0;
491     HRESULT hr = S_OK;
492     ILockBytes *ptrILockBytes;
493 
494     memset(&std, 0, sizeof(STGMEDIUM));
495     std.tymed = fmt->tymed = TYMED_ISTORAGE;
496 
497     hStorage = GlobalAlloc(GMEM_SHARE|GMEM_MOVEABLE, 0);
498     if (hStorage == NULL) return E_OUTOFMEMORY;
499     hr = CreateILockBytesOnHGlobal(hStorage, FALSE, &ptrILockBytes);
500     hr = StgCreateDocfileOnILockBytes(ptrILockBytes, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &std.u.pstg);
501     ILockBytes_Release(ptrILockBytes);
502 
503     if (FAILED(hr = IDataObject_GetDataHere(theOleClipboard->src_data, fmt, &std)))
504     {
505         WARN("() : IDataObject_GetDataHere failed to render clipboard data! (%x)\n", hr);
506         GlobalFree(hStorage);
507         return hr;
508     }
509 
510     if (1) /* check whether the presentation data is already -not- present */
511     {
512         FORMATETC fmt2;
513         STGMEDIUM std2;
514         METAFILEPICT *mfp = 0;
515 
516         fmt2.cfFormat = CF_METAFILEPICT;
517         fmt2.ptd = 0;
518         fmt2.dwAspect = DVASPECT_CONTENT;
519         fmt2.lindex = -1;
520         fmt2.tymed = TYMED_MFPICT;
521 
522         memset(&std2, 0, sizeof(STGMEDIUM));
523         std2.tymed = TYMED_MFPICT;
524 
525         /* Get the metafile picture out of it */
526 
527         if (SUCCEEDED(hr = IDataObject_GetData(theOleClipboard->src_data, &fmt2, &std2)))
528         {
529             mfp = GlobalLock(std2.u.hGlobal);
530         }
531 
532         if (mfp)
533         {
534             OLECHAR name[]={ 2, 'O', 'l', 'e', 'P', 'r', 'e', 's', '', '', '', 0};
535             IStream *pStream = 0;
536             void *mfBits;
537             PresentationDataHeader pdh;
538             INT nSize;
539             CLSID clsID;
540             LPOLESTR strProgID;
541             CHAR strOleTypeName[51];
542             BYTE OlePresStreamHeader [] =
543             {
544                 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00,
545                 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
546                 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
547                 0x00, 0x00, 0x00, 0x00
548             };
549 
550             nSize = GetMetaFileBitsEx(mfp->hMF, 0, NULL);
551 
552             memset(&pdh, 0, sizeof(PresentationDataHeader));
553             memcpy(&pdh, OlePresStreamHeader, sizeof(OlePresStreamHeader));
554 
555             pdh.dwObjectExtentX = mfp->xExt;
556             pdh.dwObjectExtentY = mfp->yExt;
557             pdh.dwSize = nSize;
558 
559             hr = IStorage_CreateStream(std.u.pstg, name, STGM_CREATE|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, 0, &pStream);
560 
561             hr = IStream_Write(pStream, &pdh, sizeof(PresentationDataHeader), NULL);
562 
563             mfBits = HeapAlloc(GetProcessHeap(), 0, nSize);
564             nSize = GetMetaFileBitsEx(mfp->hMF, nSize, mfBits);
565 
566             hr = IStream_Write(pStream, mfBits, nSize, NULL);
567 
568             IStream_Release(pStream);
569 
570             HeapFree(GetProcessHeap(), 0, mfBits);
571 
572             GlobalUnlock(std2.u.hGlobal);
573             ReleaseStgMedium(&std2);
574 
575             ReadClassStg(std.u.pstg, &clsID);
576             ProgIDFromCLSID(&clsID, &strProgID);
577 
578             WideCharToMultiByte( CP_ACP, 0, strProgID, -1, strOleTypeName, sizeof(strOleTypeName), NULL, NULL );
579             OLECONVERT_CreateOleStream(std.u.pstg);
580             OLECONVERT_CreateCompObjStream(std.u.pstg, strOleTypeName);
581         }
582     }
583 
584     if ( !SetClipboardData( fmt->cfFormat, hStorage ) )
585     {
586         WARN("() : Failed to set rendered clipboard data into clipboard!\n");
587         GlobalFree(hStorage);
588         hr = CLIPBRD_E_CANT_SET;
589     }
590 
591     ReleaseStgMedium(&std);
592     return hr;
593 }
594 
595 /************************************************************************
596  *           find_format_in_list
597  *
598  * Returns the first entry that matches the provided clipboard format.
599  */
600 static inline ole_priv_data_entry *find_format_in_list(ole_priv_data_entry *entries, DWORD num, UINT cf)
601 {
602     DWORD i;
603     for(i = 0; i < num; i++)
604         if(entries[i].fmtetc.cfFormat == cf)
605             return &entries[i];
606 
607     return NULL;
608 }
609 
610 /***************************************************************************
611  *         get_data_from_storage
612  *
613  * Returns storage data in an HGLOBAL.
614  */
615 static HRESULT get_data_from_storage(IDataObject *data, FORMATETC *fmt, HGLOBAL *mem)
616 {
617     HGLOBAL h;
618     IStorage *stg;
619     HRESULT hr;
620     FORMATETC stg_fmt;
621     STGMEDIUM med;
622     ILockBytes *lbs;
623 
624     *mem = NULL;
625 
626     h = GlobalAlloc( GMEM_DDESHARE|GMEM_MOVEABLE, 0 );
627     if(!h) return E_OUTOFMEMORY;
628 
629     hr = CreateILockBytesOnHGlobal(h, FALSE, &lbs);
630     if(SUCCEEDED(hr))
631     {
632         hr = StgCreateDocfileOnILockBytes(lbs, STGM_CREATE|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &stg);
633         ILockBytes_Release(lbs);
634     }
635     if(FAILED(hr))
636     {
637         GlobalFree(h);
638         return hr;
639     }
640 
641     stg_fmt = *fmt;
642     med.tymed = stg_fmt.tymed = TYMED_ISTORAGE;
643     med.u.pstg = stg;
644     med.pUnkForRelease = NULL;
645 
646     hr = IDataObject_GetDataHere(data, &stg_fmt, &med);
647     if(FAILED(hr))
648     {
649         med.u.pstg = NULL;
650         hr = IDataObject_GetData(data, &stg_fmt, &med);
651         if(FAILED(hr)) goto end;
652 
653         hr = IStorage_CopyTo(med.u.pstg, 0, NULL, NULL, stg);
654         ReleaseStgMedium(&med);
655         if(FAILED(hr)) goto end;
656     }
657     *mem = h;
658 
659 end:
660     IStorage_Release(stg);
661     if(FAILED(hr)) GlobalFree(h);
662     return hr;
663 }
664 
665 /***************************************************************************
666  *         get_data_from_stream
667  *
668  * Returns stream data in an HGLOBAL.
669  */
670 static HRESULT get_data_from_stream(IDataObject *data, FORMATETC *fmt, HGLOBAL *mem)
671 {
672     HGLOBAL h;
673     IStream *stm = NULL;
674     HRESULT hr;
675     FORMATETC stm_fmt;
676     STGMEDIUM med;
677 
678     *mem = NULL;
679 
680     h = GlobalAlloc( GMEM_DDESHARE|GMEM_MOVEABLE, 0 );
681     if(!h) return E_OUTOFMEMORY;
682 
683     hr = CreateStreamOnHGlobal(h, FALSE, &stm);
684     if(FAILED(hr)) goto error;
685 
686     stm_fmt = *fmt;
687     med.tymed = stm_fmt.tymed = TYMED_ISTREAM;
688     med.u.pstm = stm;
689     med.pUnkForRelease = NULL;
690 
691     hr = IDataObject_GetDataHere(data, &stm_fmt, &med);
692     if(FAILED(hr))
693     {
694         LARGE_INTEGER offs;
695         ULARGE_INTEGER pos;
696 
697         med.u.pstm = NULL;
698         hr = IDataObject_GetData(data, &stm_fmt, &med);
699         if(FAILED(hr)) goto error;
700 
701         offs.QuadPart = 0;
702         IStream_Seek(med.u.pstm, offs, STREAM_SEEK_CUR, &pos);
703         IStream_Seek(med.u.pstm, offs, STREAM_SEEK_SET, NULL);
704         hr = IStream_CopyTo(med.u.pstm, stm, pos, NULL, NULL);
705         ReleaseStgMedium(&med);
706         if(FAILED(hr)) goto error;
707     }
708     *mem = h;
709     IStream_Release(stm);
710     return S_OK;
711 
712 error:
713     if(stm) IStream_Release(stm);
714     GlobalFree(h);
715     return hr;
716 }
717 
718 /***************************************************************************
719  *         get_data_from_global
720  *
721  * Returns global data in an HGLOBAL.
722  */
723 static HRESULT get_data_from_global(IDataObject *data, FORMATETC *fmt, HGLOBAL *mem)
724 {
725     HGLOBAL h;
726     HRESULT hr;
727     FORMATETC mem_fmt;
728     STGMEDIUM med;
729 
730     *mem = NULL;
731 
732     mem_fmt = *fmt;
733     mem_fmt.tymed = TYMED_HGLOBAL;
734 
735     hr = IDataObject_GetData(data, &mem_fmt, &med);
736     if(FAILED(hr)) return hr;
737 
738     hr = dup_global_mem(med.u.hGlobal, GMEM_DDESHARE|GMEM_MOVEABLE, &h);
739 
740     if(SUCCEEDED(hr)) *mem = h;
741 
742     ReleaseStgMedium(&med);
743 
744     return hr;
745 }
746 
747 /***********************************************************************
748  *                render_format
749  *
750  * Render the clipboard data. Note that this call will delegate to the
751  * source data object.
752  */
753 static HRESULT render_format(IDataObject *data, LPFORMATETC fmt)
754 {
755     HGLOBAL clip_data = NULL;
756     HRESULT hr;
757 
758     /* Embed source hack */
759     if(fmt->cfFormat == embed_source_clipboard_format)
760     {
761         return render_embed_source_hack(data, fmt);
762     }
763 
764     if(fmt->tymed & TYMED_ISTORAGE)
765     {
766         hr = get_data_from_storage(data, fmt, &clip_data);
767     }
768     else if(fmt->tymed & TYMED_ISTREAM)
769     {
770         hr = get_data_from_stream(data, fmt, &clip_data);
771     }
772     else if(fmt->tymed & TYMED_HGLOBAL)
773     {
774         hr = get_data_from_global(data, fmt, &clip_data);
775     }
776     else
777     {
778         FIXME("Unhandled tymed %x\n", fmt->tymed);
779         hr = DV_E_FORMATETC;
780     }
781 
782     if(SUCCEEDED(hr))
783     {
784         if ( !SetClipboardData(fmt->cfFormat, clip_data) )
785         {
786             WARN("() : Failed to set rendered clipboard data into clipboard!\n");
787             GlobalFree(clip_data);
788             hr = CLIPBRD_E_CANT_SET;
789         }
790     }
791 
792     return hr;
793 }
794 
795 /*---------------------------------------------------------------------*
796  *  Implementation of the internal IDataObject interface exposed by
797  *  the OLE clipboard.
798  *---------------------------------------------------------------------*/
799 
800 
801 /************************************************************************
802  *           snapshot_QueryInterface
803  */
804 static HRESULT WINAPI snapshot_QueryInterface(IDataObject *iface,
805                                               REFIID riid, void **ppvObject)
806 {
807   snapshot *This = impl_from_IDataObject(iface);
808   TRACE("(%p)->(IID:%s, %p)\n", This, debugstr_guid(riid), ppvObject);
809 
810   if ( (This==0) || (ppvObject==0) )
811     return E_INVALIDARG;
812 
813   *ppvObject = 0;
814 
815   if (IsEqualIID(&IID_IUnknown, riid) ||
816       IsEqualIID(&IID_IDataObject, riid))
817   {
818     *ppvObject = iface;
819   }
820   else
821   {
822     WARN( "() : asking for unsupported interface %s\n", debugstr_guid(riid));
823     return E_NOINTERFACE;
824   }
825 
826   IUnknown_AddRef((IUnknown*)*ppvObject);
827 
828   return S_OK;
829 }
830 
831 /************************************************************************
832  *              snapshot_AddRef
833  */
834 static ULONG WINAPI snapshot_AddRef(IDataObject *iface)
835 {
836     snapshot *This = impl_from_IDataObject(iface);
837 
838     TRACE("(%p)->(count=%u)\n", This, This->ref);
839 
840     return InterlockedIncrement(&This->ref);
841 }
842 
843 /************************************************************************
844  *      snapshot_Release
845  */
846 static ULONG WINAPI snapshot_Release(IDataObject *iface)
847 {
848     snapshot *This = impl_from_IDataObject(iface);
849     ULONG ref;
850 
851     TRACE("(%p)->(count=%u)\n", This, This->ref);
852 
853     ref = InterlockedDecrement(&This->ref);
854 
855     if (ref == 0)
856     {
857         ole_clipbrd *clipbrd;
858         HRESULT hr = get_ole_clipbrd(&clipbrd);
859 
860         if(This->data) IDataObject_Release(This->data);
861 
862         if(SUCCEEDED(hr) && clipbrd->latest_snapshot == This)
863             clipbrd->latest_snapshot = NULL;
864         HeapFree(GetProcessHeap(), 0, This);
865     }
866 
867     return ref;
868 }
869 
870 /************************************************************
871  *              get_current_ole_clip_window
872  *
873  * Return the window that owns the ole clipboard.
874  *
875  * If the clipboard is flushed or not owned by ole this will
876  * return NULL.
877  */
878 static HWND get_current_ole_clip_window(void)
879 {
880     HGLOBAL h;
881     HWND *ptr, wnd;
882 
883     h = GetClipboardData(dataobject_clipboard_format);
884     if(!h) return NULL;
885     ptr = GlobalLock(h);
886     if(!ptr) return NULL;
887     wnd = *ptr;
888     GlobalUnlock(h);
889     return wnd;
890 }
891 
892 /************************************************************
893  *              get_current_dataobject
894  *
895  * Return an unmarshalled IDataObject if there is a current
896  * (ie non-flushed) object on the ole clipboard.
897  */
898 static HRESULT get_current_dataobject(IDataObject **data)
899 {
900     HRESULT hr = S_FALSE;
901     HWND wnd = get_current_ole_clip_window();
902     HGLOBAL h;
903     void *ptr;
904     IStream *stm;
905     LARGE_INTEGER pos;
906 
907     *data = NULL;
908     if(!wnd) return S_FALSE;
909 
910     h = GetClipboardData(wine_marshal_clipboard_format);
911     if(!h) return S_FALSE;
912     if(GlobalSize(h) == 0) return S_FALSE;
913     ptr = GlobalLock(h);
914     if(!ptr) return S_FALSE;
915 
916     hr = CreateStreamOnHGlobal(NULL, TRUE, &stm);
917     if(FAILED(hr)) goto end;
918 
919     hr = IStream_Write(stm, ptr, GlobalSize(h), NULL);
920     if(SUCCEEDED(hr))
921     {
922         pos.QuadPart = 0;
923         IStream_Seek(stm, pos, STREAM_SEEK_SET, NULL);
924         hr = CoUnmarshalInterface(stm, &IID_IDataObject, (void**)data);
925     }
926     IStream_Release(stm);
927 
928 end:
929     GlobalUnlock(h);
930     return hr;
931 }
932 
933 static DWORD get_tymed_from_nonole_cf(UINT cf)
934 {
935     if(cf >= 0xc000) return TYMED_ISTREAM | TYMED_HGLOBAL;
936 
937     switch(cf)
938     {
939     case CF_TEXT:
940     case CF_OEMTEXT:
941     case CF_UNICODETEXT:
942         return TYMED_ISTREAM | TYMED_HGLOBAL;
943     case CF_ENHMETAFILE:
944         return TYMED_ENHMF;
945     case CF_METAFILEPICT:
946         return TYMED_MFPICT;
947     default:
948         FIXME("returning TYMED_NULL for cf %04x\n", cf);
949         return TYMED_NULL;
950     }
951 }
952 
953 /***********************************************************
954  *     get_priv_data
955  *
956  * Returns a copy of the Ole Private Data
957  */
958 static HRESULT get_priv_data(ole_priv_data **data)
959 {
960     HGLOBAL handle;
961     HRESULT hr = S_OK;
962     ole_priv_data *ret = NULL;
963 
964     *data = NULL;
965 
966     handle = GetClipboardData( ole_private_data_clipboard_format );
967     if(handle)
968     {
969         ole_priv_data *src = GlobalLock(handle);
970         if(src)
971         {
972             DWORD i;
973 
974             /* FIXME: sanity check on size */
975             ret = HeapAlloc(GetProcessHeap(), 0, src->size);
976             if(!ret)
977             {
978                 GlobalUnlock(handle);
979                 return E_OUTOFMEMORY;
980             }
981             memcpy(ret, src, src->size);
982             GlobalUnlock(handle);
983 
984             /* Fixup any target device offsets to ptrs */
985             for(i = 0; i < ret->count; i++)
986                 ret->entries[i].fmtetc.ptd =
987                     td_offs_to_ptr(ret, (DWORD_PTR) ret->entries[i].fmtetc.ptd);
988         }
989     }
990 
991     if(!ret) /* Non-ole data */
992     {
993         UINT cf;
994         DWORD count = 0, idx, size = FIELD_OFFSET(ole_priv_data, entries);
995 
996         for(cf = 0; (cf = EnumClipboardFormats(cf)) != 0; count++)
997         {
998             char buf[100];
999             GetClipboardFormatNameA(cf, buf, sizeof(buf));
1000             TRACE("cf %04x %s\n", cf, buf);
1001         }
1002         TRACE("count %d\n", count);
1003         size += count * sizeof(ret->entries[0]);
1004 
1005         /* There are holes in fmtetc so zero init */
1006         ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
1007         if(!ret) return E_OUTOFMEMORY;
1008         ret->size = size;
1009         ret->count = count;
1010 
1011         for(cf = 0, idx = 0; (cf = EnumClipboardFormats(cf)) != 0; idx++)
1012         {
1013             ret->entries[idx].fmtetc.cfFormat = cf;
1014             ret->entries[idx].fmtetc.ptd = NULL;
1015             ret->entries[idx].fmtetc.dwAspect = DVASPECT_CONTENT;
1016             ret->entries[idx].fmtetc.lindex = -1;
1017             ret->entries[idx].fmtetc.tymed = get_tymed_from_nonole_cf(cf);
1018             ret->entries[idx].first_use = 1;
1019         }
1020     }
1021 
1022     *data = ret;
1023     return hr;
1024 }
1025 
1026 /************************************************************************
1027  *                    get_stgmed_for_global
1028  *
1029  * Returns a stg medium with a copy of the global handle
1030  */
1031 static HRESULT get_stgmed_for_global(HGLOBAL h, STGMEDIUM *med)
1032 {
1033     HRESULT hr;
1034 
1035     med->pUnkForRelease = NULL;
1036     med->tymed = TYMED_NULL;
1037 
1038     hr = dup_global_mem(h, GMEM_MOVEABLE, &med->u.hGlobal);
1039 
1040     if(SUCCEEDED(hr)) med->tymed = TYMED_HGLOBAL;
1041 
1042     return hr;
1043 }
1044 
1045 /************************************************************************
1046  *                    get_stgmed_for_stream
1047  *
1048  * Returns a stg medium with a stream based on the handle
1049  */
1050 static HRESULT get_stgmed_for_stream(HGLOBAL h, STGMEDIUM *med)
1051 {
1052     HRESULT hr;
1053     HGLOBAL dst;
1054 
1055     med->pUnkForRelease = NULL;
1056     med->tymed = TYMED_NULL;
1057 
1058     hr = dup_global_mem(h, GMEM_MOVEABLE, &dst);
1059     if(FAILED(hr)) return hr;
1060 
1061     hr = CreateStreamOnHGlobal(dst, TRUE, &med->u.pstm);
1062     if(FAILED(hr))
1063     {
1064         GlobalFree(dst);
1065         return hr;
1066     }
1067 
1068     med->tymed = TYMED_ISTREAM;
1069     return hr;
1070 }
1071 
1072 /************************************************************************
1073  *                    get_stgmed_for_storage
1074  *
1075  * Returns a stg medium with a storage based on the handle
1076  */
1077 static HRESULT get_stgmed_for_storage(HGLOBAL h, STGMEDIUM *med)
1078 {
1079     HRESULT hr;
1080     HGLOBAL dst;
1081     ILockBytes *lbs;
1082 
1083     med->pUnkForRelease = NULL;
1084     med->tymed = TYMED_NULL;
1085 
1086     hr = dup_global_mem(h, GMEM_MOVEABLE, &dst);
1087     if(FAILED(hr)) return hr;
1088 
1089     hr = CreateILockBytesOnHGlobal(dst, TRUE, &lbs);
1090     if(FAILED(hr))
1091     {
1092         GlobalFree(dst);
1093         return hr;
1094     }
1095 
1096     hr = StgOpenStorageOnILockBytes(lbs, NULL,  STGM_SHARE_EXCLUSIVE | STGM_READWRITE, NULL, 0, &med->u.pstg);
1097     ILockBytes_Release(lbs);
1098     if(FAILED(hr))
1099     {
1100         GlobalFree(dst);
1101         return hr;
1102     }
1103 
1104     med->tymed = TYMED_ISTORAGE;
1105     return hr;
1106 }
1107 
1108 static inline BOOL string_off_equal(const DVTARGETDEVICE *t1, WORD off1, const DVTARGETDEVICE *t2, WORD off2)
1109 {
1110     const WCHAR *str1, *str2;
1111 
1112     if(off1 == 0 && off2 == 0) return TRUE;
1113     if(off1 == 0 || off2 == 0) return FALSE;
1114 
1115     str1 = (const WCHAR*)((const char*)t1 + off1);
1116     str2 = (const WCHAR*)((const char*)t2 + off2);
1117 
1118     return !lstrcmpW(str1, str2);
1119 }
1120 
1121 static inline BOOL td_equal(const DVTARGETDEVICE *t1, const DVTARGETDEVICE *t2)
1122 {
1123     if(t1 == NULL && t2 == NULL) return TRUE;
1124     if(t1 == NULL || t2 == NULL) return FALSE;
1125 
1126     if(!string_off_equal(t1, t1->tdDriverNameOffset, t2, t2->tdDriverNameOffset))
1127         return FALSE;
1128     if(!string_off_equal(t1, t1->tdDeviceNameOffset, t2, t2->tdDeviceNameOffset))
1129         return FALSE;
1130     if(!string_off_equal(t1, t1->tdPortNameOffset, t2, t2->tdPortNameOffset))
1131         return FALSE;
1132 
1133     /* FIXME check devmode? */
1134 
1135     return TRUE;
1136 }
1137 
1138 /************************************************************************
1139  *         snapshot_GetData
1140  */
1141 static HRESULT WINAPI snapshot_GetData(IDataObject *iface, FORMATETC *fmt,
1142                                        STGMEDIUM *med)
1143 {
1144     snapshot *This = impl_from_IDataObject(iface);
1145     HANDLE h;
1146     HRESULT hr;
1147     ole_priv_data *enum_data = NULL;
1148     ole_priv_data_entry *entry;
1149     DWORD mask;
1150 
1151     TRACE("(%p, %p {%s}, %p)\n", iface, fmt, dump_fmtetc(fmt), med);
1152 
1153     if ( !fmt || !med ) return E_INVALIDARG;
1154 
1155     if ( !OpenClipboard(NULL)) return CLIPBRD_E_CANT_OPEN;
1156 
1157     if(!This->data)
1158         hr = get_current_dataobject(&This->data);
1159 
1160     if(This->data)
1161     {
1162         hr = IDataObject_GetData(This->data, fmt, med);
1163         CloseClipboard();
1164         return hr;
1165     }
1166 
1167     h = GetClipboardData(fmt->cfFormat);
1168     if(!h)
1169     {
1170         hr = DV_E_FORMATETC;
1171         goto end;
1172     }
1173 
1174     hr = get_priv_data(&enum_data);
1175     if(FAILED(hr)) goto end;
1176 
1177     entry = find_format_in_list(enum_data->entries, enum_data->count, fmt->cfFormat);
1178     if(entry)
1179     {
1180         if(!td_equal(fmt->ptd, entry->fmtetc.ptd))
1181         {
1182             hr = DV_E_FORMATETC;
1183             goto end;
1184         }
1185         mask = fmt->tymed & entry->fmtetc.tymed;
1186         if(!mask) mask = fmt->tymed & (TYMED_ISTREAM | TYMED_HGLOBAL);
1187     }
1188     else /* non-Ole format */
1189         mask = fmt->tymed & TYMED_HGLOBAL;
1190 
1191     if(mask & TYMED_ISTORAGE)
1192         hr = get_stgmed_for_storage(h, med);
1193     else if(mask & TYMED_HGLOBAL)
1194         hr = get_stgmed_for_global(h, med);
1195     else if(mask & TYMED_ISTREAM)
1196         hr = get_stgmed_for_stream(h, med);
1197     else
1198     {
1199         FIXME("Unhandled tymed - mask %x req tymed %x\n", mask, fmt->tymed);
1200         hr = E_FAIL;
1201         goto end;
1202     }
1203 
1204 end:
1205     HeapFree(GetProcessHeap(), 0, enum_data);
1206     if ( !CloseClipboard() ) hr = CLIPBRD_E_CANT_CLOSE;
1207     return hr;
1208 }
1209 
1210 /************************************************************************
1211  *          snapshot_GetDataHere
1212  */
1213 static HRESULT WINAPI snapshot_GetDataHere(IDataObject *iface, FORMATETC *fmt,
1214                                            STGMEDIUM *med)
1215 {
1216     snapshot *This = impl_from_IDataObject(iface);
1217     HANDLE h;
1218     HRESULT hr;
1219     ole_priv_data *enum_data = NULL;
1220     ole_priv_data_entry *entry;
1221     TYMED supported;
1222 
1223     TRACE("(%p, %p {%s}, %p (tymed %x)\n", iface, fmt, dump_fmtetc(fmt), med, med->tymed);
1224 
1225     if ( !fmt || !med ) return E_INVALIDARG;
1226 
1227     if ( !OpenClipboard(NULL)) return CLIPBRD_E_CANT_OPEN;
1228 
1229     if(!This->data)
1230         hr = get_current_dataobject(&This->data);
1231 
1232     if(This->data)
1233     {
1234         hr = IDataObject_GetDataHere(This->data, fmt, med);
1235         if(SUCCEEDED(hr))
1236         {
1237             CloseClipboard();
1238             return hr;
1239         }
1240     }
1241 
1242     h = GetClipboardData(fmt->cfFormat);
1243     if(!h)
1244     {
1245         hr = DV_E_FORMATETC;
1246         goto end;
1247     }
1248 
1249     hr = get_priv_data(&enum_data);
1250     if(FAILED(hr)) goto end;
1251 
1252     entry = find_format_in_list(enum_data->entries, enum_data->count, fmt->cfFormat);
1253     if(entry)
1254     {
1255         if(!td_equal(fmt->ptd, entry->fmtetc.ptd))
1256         {
1257             hr = DV_E_FORMATETC;
1258             goto end;
1259         }
1260         supported = entry->fmtetc.tymed;
1261     }
1262     else /* non-Ole format */
1263         supported = TYMED_HGLOBAL;
1264 
1265     switch(med->tymed)
1266     {
1267     case TYMED_HGLOBAL:
1268     {
1269         DWORD src_size = GlobalSize(h);
1270         DWORD dst_size = GlobalSize(med->u.hGlobal);
1271         hr = E_FAIL;
1272         if(dst_size >= src_size)
1273         {
1274             void *src = GlobalLock(h);
1275             void *dst = GlobalLock(med->u.hGlobal);
1276 
1277             memcpy(dst, src, src_size);
1278             GlobalUnlock(med->u.hGlobal);
1279             GlobalUnlock(h);
1280             hr = S_OK;
1281         }
1282         break;
1283     }
1284     case TYMED_ISTREAM:
1285     {
1286         DWORD src_size = GlobalSize(h);
1287         void *src = GlobalLock(h);
1288         hr = IStream_Write(med->u.pstm, src, src_size, NULL);
1289         GlobalUnlock(h);
1290         break;
1291     }
1292     case TYMED_ISTORAGE:
1293     {
1294         STGMEDIUM copy;
1295         if(!(supported & TYMED_ISTORAGE))
1296         {
1297             hr = E_FAIL;
1298             goto end;
1299         }
1300         hr = get_stgmed_for_storage(h, &copy);
1301         if(SUCCEEDED(hr))
1302         {
1303             hr = IStorage_CopyTo(copy.u.pstg, 0, NULL, NULL, med->u.pstg);
1304             ReleaseStgMedium(&copy);
1305         }
1306         break;
1307     }
1308     default:
1309         FIXME("Unhandled tymed - supported %x req tymed %x\n", supported, med->tymed);
1310         hr = E_FAIL;
1311         goto end;
1312     }
1313 
1314 end:
1315     HeapFree(GetProcessHeap(), 0, enum_data);
1316     if ( !CloseClipboard() ) hr = CLIPBRD_E_CANT_CLOSE;
1317     return hr;
1318 }
1319 
1320 /************************************************************************
1321  *           snapshot_QueryGetData
1322  *
1323  * The OLE Clipboard's implementation of this method delegates to
1324  * a data source if there is one or wraps around the windows clipboard
1325  * function IsClipboardFormatAvailable() otherwise.
1326  *
1327  */
1328 static HRESULT WINAPI snapshot_QueryGetData(IDataObject *iface, FORMATETC *fmt)
1329 {
1330     FIXME("(%p, %p {%s})\n", iface, fmt, dump_fmtetc(fmt));
1331 
1332     if (!fmt) return E_INVALIDARG;
1333 
1334     if ( fmt->dwAspect != DVASPECT_CONTENT ) return DV_E_FORMATETC;
1335 
1336     if ( fmt->lindex != -1 ) return DV_E_FORMATETC;
1337 
1338     return (IsClipboardFormatAvailable(fmt->cfFormat)) ? S_OK : DV_E_CLIPFORMAT;
1339 }
1340 
1341 /************************************************************************
1342  *              snapshot_GetCanonicalFormatEtc
1343  */
1344 static HRESULT WINAPI snapshot_GetCanonicalFormatEtc(IDataObject *iface, FORMATETC *fmt_in,
1345                                                      FORMATETC *fmt_out)
1346 {
1347     TRACE("(%p, %p, %p)\n", iface, fmt_in, fmt_out);
1348 
1349     if ( !fmt_in || !fmt_out ) return E_INVALIDARG;
1350 
1351     *fmt_out = *fmt_in;
1352     return DATA_S_SAMEFORMATETC;
1353 }
1354 
1355 /************************************************************************
1356  *              snapshot_SetData
1357  *
1358  * The OLE Clipboard does not implement this method
1359  */
1360 static HRESULT WINAPI snapshot_SetData(IDataObject *iface, FORMATETC *fmt,
1361                                        STGMEDIUM *med, BOOL release)
1362 {
1363     TRACE("(%p, %p, %p, %d): not implemented\n", iface, fmt, med, release);
1364     return E_NOTIMPL;
1365 }
1366 
1367 /************************************************************************
1368  *             snapshot_EnumFormatEtc
1369  *
1370  */
1371 static HRESULT WINAPI snapshot_EnumFormatEtc(IDataObject *iface, DWORD dir,
1372                                              IEnumFORMATETC **enum_fmt)
1373 {
1374     HRESULT hr;
1375     ole_priv_data *data = NULL;
1376 
1377     TRACE("(%p, %x, %p)\n", iface, dir, enum_fmt);
1378 
1379     *enum_fmt = NULL;
1380 
1381     if ( dir != DATADIR_GET ) return E_NOTIMPL;
1382     if ( !OpenClipboard(NULL) ) return CLIPBRD_E_CANT_OPEN;
1383 
1384     hr = get_priv_data(&data);
1385 
1386     if(FAILED(hr)) goto end;
1387 
1388     hr = enum_fmtetc_construct( data, 0, enum_fmt );
1389 
1390 end:
1391     if ( !CloseClipboard() ) hr = CLIPBRD_E_CANT_CLOSE;
1392     return hr;
1393 }
1394 
1395 /************************************************************************
1396  *               snapshot_DAdvise
1397  *
1398  * The OLE Clipboard does not implement this method
1399  */
1400 static HRESULT WINAPI snapshot_DAdvise(IDataObject *iface, FORMATETC *fmt,
1401                                        DWORD flags, IAdviseSink *sink,
1402                                        DWORD *conn)
1403 {
1404     TRACE("(%p, %p, %x, %p, %p): not implemented\n", iface, fmt, flags, sink, conn);
1405     return E_NOTIMPL;
1406 }
1407 
1408 /************************************************************************
1409  *              snapshot_DUnadvise
1410  *
1411  * The OLE Clipboard does not implement this method
1412  */
1413 static HRESULT WINAPI snapshot_DUnadvise(IDataObject* iface, DWORD conn)
1414 {
1415     TRACE("(%p, %d): not implemented\n", iface, conn);
1416     return E_NOTIMPL;
1417 }
1418 
1419 /************************************************************************
1420  *             snapshot_EnumDAdvise
1421  *
1422  * The OLE Clipboard does not implement this method
1423  */
1424 static HRESULT WINAPI snapshot_EnumDAdvise(IDataObject* iface,
1425                                            IEnumSTATDATA** enum_advise)
1426 {
1427     TRACE("(%p, %p): not implemented\n", iface, enum_advise);
1428     return E_NOTIMPL;
1429 }
1430 
1431 static const IDataObjectVtbl snapshot_vtable =
1432 {
1433     snapshot_QueryInterface,
1434     snapshot_AddRef,
1435     snapshot_Release,
1436     snapshot_GetData,
1437     snapshot_GetDataHere,
1438     snapshot_QueryGetData,
1439     snapshot_GetCanonicalFormatEtc,
1440     snapshot_SetData,
1441     snapshot_EnumFormatEtc,
1442     snapshot_DAdvise,
1443     snapshot_DUnadvise,
1444     snapshot_EnumDAdvise
1445 };
1446 
1447 /*---------------------------------------------------------------------*
1448  *           Internal implementation methods for the OLE clipboard
1449  *---------------------------------------------------------------------*/
1450 
1451 static snapshot *snapshot_construct(DWORD seq_no)
1452 {
1453     snapshot *This;
1454 
1455     This = HeapAlloc( GetProcessHeap(), 0, sizeof(*This) );
1456     if (!This) return NULL;
1457 
1458     This->lpVtbl = &snapshot_vtable;
1459     This->ref = 0;
1460     This->seq_no = seq_no;
1461     This->data = NULL;
1462 
1463     return This;
1464 }
1465 
1466 /*********************************************************
1467  *               register_clipboard_formats
1468  */
1469 static void register_clipboard_formats(void)
1470 {
1471     static const WCHAR OwnerLink[] = {'O','w','n','e','r','L','i','n','k',0};
1472     static const WCHAR FileName[] = {'F','i','l','e','N','a','m','e',0};
1473     static const WCHAR FileNameW[] = {'F','i','l','e','N','a','m','e','W',0};
1474     static const WCHAR DataObject[] = {'D','a','t','a','O','b','j','e','c','t',0};
1475     static const WCHAR EmbeddedObject[] = {'E','m','b','e','d','d','e','d',' ','O','b','j','e','c','t',0};
1476     static const WCHAR EmbedSource[] = {'E','m','b','e','d',' ','S','o','u','r','c','e',0};
1477     static const WCHAR CustomLinkSource[] = {'C','u','s','t','o','m',' ','L','i','n','k',' ','S','o','u','r','c','e',0};
1478     static const WCHAR LinkSource[] = {'L','i','n','k',' ','S','o','u','r','c','e',0};
1479     static const WCHAR ObjectDescriptor[] = {'O','b','j','e','c','t',' ','D','e','s','c','r','i','p','t','o','r',0};
1480     static const WCHAR LinkSourceDescriptor[] = {'L','i','n','k',' ','S','o','u','r','c','e',' ',
1481                                                  'D','e','s','c','r','i','p','t','o','r',0};
1482     static const WCHAR OlePrivateData[] = {'O','l','e',' ','P','r','i','v','a','t','e',' ','D','a','t','a',0};
1483 
1484     static const WCHAR WineMarshalledDataObject[] = {'W','i','n','e',' ','M','a','r','s','h','a','l','l','e','d',' ',
1485                                                      'D','a','t','a','O','b','j','e','c','t',0};
1486 
1487     ownerlink_clipboard_format = RegisterClipboardFormatW(OwnerLink);
1488     filename_clipboard_format = RegisterClipboardFormatW(FileName);
1489     filenameW_clipboard_format = RegisterClipboardFormatW(FileNameW);
1490     dataobject_clipboard_format = RegisterClipboardFormatW(DataObject);
1491     embedded_object_clipboard_format = RegisterClipboardFormatW(EmbeddedObject);
1492     embed_source_clipboard_format = RegisterClipboardFormatW(EmbedSource);
1493     custom_link_source_clipboard_format = RegisterClipboardFormatW(CustomLinkSource);
1494     link_source_clipboard_format = RegisterClipboardFormatW(LinkSource);
1495     object_descriptor_clipboard_format = RegisterClipboardFormatW(ObjectDescriptor);
1496     link_source_descriptor_clipboard_format = RegisterClipboardFormatW(LinkSourceDescriptor);
1497     ole_private_data_clipboard_format = RegisterClipboardFormatW(OlePrivateData);
1498 
1499     wine_marshal_clipboard_format = RegisterClipboardFormatW(WineMarshalledDataObject);
1500 }
1501 
1502 /***********************************************************************
1503  * OLEClipbrd_Initialize()
1504  * Initializes the OLE clipboard.
1505  */
1506 void OLEClipbrd_Initialize(void)
1507 {
1508     register_clipboard_formats();
1509 
1510     if ( !theOleClipboard )
1511     {
1512         ole_clipbrd* clipbrd;
1513         HGLOBAL h;
1514 
1515         TRACE("()\n");
1516 
1517         clipbrd = HeapAlloc( GetProcessHeap(), 0, sizeof(*clipbrd) );
1518         if (!clipbrd) return;
1519 
1520         clipbrd->latest_snapshot = NULL;
1521         clipbrd->window = NULL;
1522         clipbrd->src_data = NULL;
1523         clipbrd->cached_enum = NULL;
1524 
1525         h = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE, 0);
1526         if(!h)
1527         {
1528             HeapFree(GetProcessHeap(), 0, clipbrd);
1529             return;
1530         }
1531 
1532         if(FAILED(CreateStreamOnHGlobal(h, TRUE, &clipbrd->marshal_data)))
1533         {
1534             GlobalFree(h);
1535             HeapFree(GetProcessHeap(), 0, clipbrd);
1536             return;
1537         }
1538 
1539         theOleClipboard = clipbrd;
1540     }
1541 }
1542 
1543 /***********************************************************************
1544  * OLEClipbrd_UnInitialize()
1545  * Un-Initializes the OLE clipboard
1546  */
1547 void OLEClipbrd_UnInitialize(void)
1548 {
1549     ole_clipbrd *clipbrd = theOleClipboard;
1550 
1551     TRACE("()\n");
1552 
1553     if ( clipbrd )
1554     {
1555         static const WCHAR ole32W[] = {'o','l','e','3','2',0};
1556         HINSTANCE hinst = GetModuleHandleW(ole32W);
1557 
1558         if ( clipbrd->window )
1559         {
1560             DestroyWindow(clipbrd->window);
1561             UnregisterClassW( clipbrd_wndclass, hinst );
1562         }
1563 
1564         IStream_Release(clipbrd->marshal_data);
1565         HeapFree(GetProcessHeap(), 0, clipbrd);
1566         theOleClipboard = NULL;
1567     }
1568 }
1569 
1570 /*********************************************************************
1571  *          set_clipboard_formats
1572  *
1573  * Enumerate all formats supported by the source and make
1574  * those formats available using delayed rendering using SetClipboardData.
1575  * Cache the enumeration list and make that list visibile as the
1576  * 'Ole Private Data' format on the clipboard.
1577  *
1578  */
1579 static HRESULT set_clipboard_formats(ole_clipbrd *clipbrd, IDataObject *data)
1580 {
1581     HRESULT hr;
1582     FORMATETC fmt;
1583     IEnumFORMATETC *enum_fmt;
1584     HGLOBAL priv_data_handle;
1585     DWORD_PTR target_offset;
1586     ole_priv_data *priv_data;
1587     DWORD count = 0, needed = sizeof(*priv_data), idx;
1588 
1589     hr = IDataObject_EnumFormatEtc(data, DATADIR_GET, &enum_fmt);
1590     if(FAILED(hr)) return hr;
1591 
1592     while(IEnumFORMATETC_Next(enum_fmt, 1, &fmt, NULL) == S_OK)
1593     {
1594         count++;
1595         needed += sizeof(priv_data->entries[0]);
1596         if(fmt.ptd)
1597         {
1598             needed += fmt.ptd->tdSize;
1599             CoTaskMemFree(fmt.ptd);
1600         }
1601     }
1602 
1603     /* Windows pads the list with two empty ole_priv_data_entries, one
1604      * after the entries array and one after the target device data.
1605      * Allocating with zero init to zero these pads. */
1606 
1607     needed += sizeof(priv_data->entries[0]); /* initialisation of needed includes one of these. */
1608     priv_data_handle = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE | GMEM_ZEROINIT, needed);
1609     priv_data = GlobalLock(priv_data_handle);
1610 
1611     priv_data->unk1 = 0;
1612     priv_data->size = needed;
1613     priv_data->unk2 = 1;
1614     priv_data->count = count;
1615     priv_data->unk3[0] = 0;
1616     priv_data->unk3[1] = 0;
1617 
1618     IEnumFORMATETC_Reset(enum_fmt);
1619 
1620     idx = 0;
1621     target_offset = FIELD_OFFSET(ole_priv_data, entries[count + 1]); /* count entries + one pad. */
1622 
1623     while(IEnumFORMATETC_Next(enum_fmt, 1, &fmt, NULL) == S_OK)
1624     {
1625         TRACE("%s\n", dump_fmtetc(&fmt));
1626 
1627         priv_data->entries[idx].fmtetc = fmt;
1628         if(fmt.ptd)
1629         {
1630             memcpy((char*)priv_data + target_offset, fmt.ptd, fmt.ptd->tdSize);
1631             priv_data->entries[idx].fmtetc.ptd = (DVTARGETDEVICE*)target_offset;
1632             target_offset += fmt.ptd->tdSize;
1633             CoTaskMemFree(fmt.ptd);
1634         }
1635 
1636         priv_data->entries[idx].first_use = !find_format_in_list(priv_data->entries, idx, fmt.cfFormat);
1637         priv_data->entries[idx].unk[0] = 0;
1638         priv_data->entries[idx].unk[1] = 0;
1639 
1640         if (priv_data->entries[idx].first_use)
1641             SetClipboardData(fmt.cfFormat, NULL);
1642 
1643         idx++;
1644     }
1645 
1646     IEnumFORMATETC_Release(enum_fmt);
1647 
1648     /* Cache the list and fixup any target device offsets to ptrs */
1649     clipbrd->cached_enum = HeapAlloc(GetProcessHeap(), 0, needed);
1650     memcpy(clipbrd->cached_enum, priv_data, needed);
1651     for(idx = 0; idx < clipbrd->cached_enum->count; idx++)
1652         clipbrd->cached_enum->entries[idx].fmtetc.ptd =
1653             td_offs_to_ptr(clipbrd->cached_enum, (DWORD_PTR)clipbrd->cached_enum->entries[idx].fmtetc.ptd);
1654 
1655     GlobalUnlock(priv_data_handle);
1656     SetClipboardData(ole_private_data_clipboard_format, priv_data_handle);
1657 
1658     return S_OK;
1659 }
1660 
1661 static HWND create_clipbrd_window(void);
1662 
1663 /***********************************************************************
1664  *                 get_clipbrd_window
1665  */
1666 static inline HRESULT get_clipbrd_window(ole_clipbrd *clipbrd, HWND *wnd)
1667 {
1668     if ( !clipbrd->window )
1669         clipbrd->window = create_clipbrd_window();
1670 
1671     *wnd = clipbrd->window;
1672     return *wnd ? S_OK : E_FAIL;
1673 }
1674 
1675 
1676 /**********************************************************************
1677  *                  release_marshal_data
1678  *
1679  * Releases the data and sets the stream back to zero size.
1680  */
1681 static inline void release_marshal_data(IStream *stm)
1682 {
1683     LARGE_INTEGER pos;
1684     ULARGE_INTEGER size;
1685     pos.QuadPart = size.QuadPart = 0;
1686 
1687     IStream_Seek(stm, pos, STREAM_SEEK_SET, NULL);
1688     CoReleaseMarshalData(stm);
1689     IStream_Seek(stm, pos, STREAM_SEEK_SET, NULL);
1690     IStream_SetSize(stm, size);
1691 }
1692 
1693 /***********************************************************************
1694  *   expose_marshalled_dataobject
1695  *
1696  * Sets the marshalled dataobject to the clipboard.  In the flushed case
1697  * we set a zero sized HGLOBAL to clear the old marshalled data.
1698  */
1699 static HRESULT expose_marshalled_dataobject(ole_clipbrd *clipbrd, IDataObject *data)
1700 {
1701     HGLOBAL h;
1702 
1703     if(data)
1704     {
1705         HGLOBAL h_stm;
1706         GetHGlobalFromStream(clipbrd->marshal_data, &h_stm);
1707         dup_global_mem(h_stm, GMEM_DDESHARE|GMEM_MOVEABLE, &h);
1708     }
1709     else /* flushed */
1710         h = GlobalAlloc(GMEM_DDESHARE|GMEM_MOVEABLE, 0);
1711 
1712     if(!h) return E_OUTOFMEMORY;
1713 
1714     SetClipboardData(wine_marshal_clipboard_format, h);
1715     return S_OK;
1716 }
1717 
1718 /***********************************************************************
1719  *                   set_src_dataobject
1720  *
1721  * Clears and sets the clipboard's src IDataObject.
1722  *
1723  * To marshal the source dataobject we do something rather different from Windows.
1724  * We set a clipboard format which contains the marshalled data.
1725  * Windows sets two window props one of which is an IID, the other is an endpoint number.
1726  */
1727 static HRESULT set_src_dataobject(ole_clipbrd *clipbrd, IDataObject *data)
1728 {
1729     HRESULT hr;
1730     HWND wnd;
1731 
1732     if(FAILED(hr = get_clipbrd_window(clipbrd, &wnd))) return hr;
1733 
1734     if(clipbrd->src_data)
1735     {
1736         release_marshal_data(clipbrd->marshal_data);
1737 
1738         IDataObject_Release(clipbrd->src_data);
1739         clipbrd->src_data = NULL;
1740         HeapFree(GetProcessHeap(), 0, clipbrd->cached_enum);
1741         clipbrd->cached_enum = NULL;
1742     }
1743 
1744     if(data)
1745     {
1746         IUnknown *unk;
1747 
1748         IDataObject_AddRef(data);
1749         clipbrd->src_data = data;
1750 
1751         IDataObject_QueryInterface(data, &IID_IUnknown, (void**)&unk);
1752         hr = CoMarshalInterface(clipbrd->marshal_data, &IID_IDataObject, unk,
1753                                 MSHCTX_LOCAL, NULL, MSHLFLAGS_TABLESTRONG);
1754         IUnknown_Release(unk); /* Don't hold a ref on IUnknown, we have one on IDataObject. */
1755         if(FAILED(hr)) return hr;
1756         hr = set_clipboard_formats(clipbrd, data);
1757     }
1758     return hr;
1759 }
1760 
1761 /***********************************************************************
1762  *                   clipbrd_wndproc
1763  */
1764 static LRESULT CALLBACK clipbrd_wndproc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
1765 {
1766     ole_clipbrd *clipbrd;
1767 
1768     get_ole_clipbrd(&clipbrd);
1769 
1770     switch (message)
1771     {
1772     case WM_RENDERFORMAT:
1773     {
1774         UINT cf = wparam;
1775         ole_priv_data_entry *entry;
1776 
1777         TRACE("(): WM_RENDERFORMAT(cfFormat=%x)\n", cf);
1778         entry = find_format_in_list(clipbrd->cached_enum->entries, clipbrd->cached_enum->count, cf);
1779 
1780         if(entry)
1781             render_format(clipbrd->src_data, &entry->fmtetc);
1782 
1783         break;
1784     }
1785 
1786     case WM_RENDERALLFORMATS:
1787     {
1788         DWORD i;
1789         ole_priv_data_entry *entries = clipbrd->cached_enum->entries;
1790 
1791         TRACE("(): WM_RENDERALLFORMATS\n");
1792 
1793         for(i = 0; i < clipbrd->cached_enum->count; i++)
1794         {
1795             if(entries[i].first_use)
1796                 render_format(clipbrd->src_data, &entries[i].fmtetc);
1797         }
1798         break;
1799     }
1800 
1801     case WM_DESTROYCLIPBOARD:
1802     {
1803         TRACE("(): WM_DESTROYCLIPBOARD\n");
1804 
1805         set_src_dataobject(clipbrd, NULL);
1806         break;
1807     }
1808 
1809     default:
1810         return DefWindowProcW(hwnd, message, wparam, lparam);
1811     }
1812 
1813     return 0;
1814 }
1815 
1816 
1817 /***********************************************************************
1818  *                 create_clipbrd_window
1819  */
1820 static HWND create_clipbrd_window(void)
1821 {
1822     WNDCLASSEXW class;
1823     static const WCHAR ole32W[] = {'o','l','e','3','2',0};
1824     static const WCHAR title[] = {'C','l','i','p','b','o','a','r','d','W','i','n','d','o','w',0};
1825     HINSTANCE hinst = GetModuleHandleW(ole32W);
1826 
1827     class.cbSize         = sizeof(class);
1828     class.style          = 0;
1829     class.lpfnWndProc    = clipbrd_wndproc;
1830     class.cbClsExtra     = 0;
1831     class.cbWndExtra     = 0;
1832     class.hInstance      = hinst;
1833     class.hIcon          = 0;
1834     class.hCursor        = 0;
1835     class.hbrBackground  = 0;
1836     class.lpszMenuName   = NULL;
1837     class.lpszClassName  = clipbrd_wndclass;
1838     class.hIconSm        = NULL;
1839 
1840     RegisterClassExW(&class);
1841 
1842     return CreateWindowW(clipbrd_wndclass, title, WS_POPUP | WS_CLIPSIBLINGS | WS_OVERLAPPED,
1843                          CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
1844                          NULL, NULL, hinst, 0);
1845 }
1846 
1847 /*********************************************************************
1848  *          set_dataobject_format
1849  *
1850  * Windows creates a 'DataObject' clipboard format that contains the
1851  * clipboard window's HWND or NULL if the Ole clipboard has been flushed.
1852  */
1853 static HRESULT set_dataobject_format(HWND hwnd)
1854 {
1855     HGLOBAL h = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE, sizeof(hwnd));
1856     HWND *data;
1857 
1858     if(!h) return E_OUTOFMEMORY;
1859 
1860     data = GlobalLock(h);
1861     *data = hwnd;
1862     GlobalUnlock(h);
1863 
1864     if(!SetClipboardData(dataobject_clipboard_format, h))
1865     {
1866         GlobalFree(h);
1867         return CLIPBRD_E_CANT_SET;
1868     }
1869 
1870     return S_OK;
1871 }
1872 
1873 /*---------------------------------------------------------------------*
1874  *           Win32 OLE clipboard API
1875  *---------------------------------------------------------------------*/
1876 
1877 /***********************************************************************
1878  *           OleSetClipboard     [OLE32.@]
1879  *  Places a pointer to the specified data object onto the clipboard,
1880  *  making the data object accessible to the OleGetClipboard function.
1881  *
1882  * RETURNS
1883  *
1884  *    S_OK                  IDataObject pointer placed on the clipboard
1885  *    CLIPBRD_E_CANT_OPEN   OpenClipboard failed
1886  *    CLIPBRD_E_CANT_EMPTY  EmptyClipboard failed
1887  *    CLIPBRD_E_CANT_CLOSE  CloseClipboard failed
1888  *    CLIPBRD_E_CANT_SET    SetClipboard failed
1889  */
1890 
1891 HRESULT WINAPI OleSetClipboard(IDataObject* data)
1892 {
1893   HRESULT hr;
1894   ole_clipbrd *clipbrd;
1895   HWND wnd;
1896 
1897   TRACE("(%p)\n", data);
1898 
1899   if(FAILED(hr = get_ole_clipbrd(&clipbrd))) return hr;
1900 
1901   if(FAILED(hr = get_clipbrd_window(clipbrd, &wnd))) return hr;
1902 
1903   if ( !OpenClipboard(wnd) ) return CLIPBRD_E_CANT_OPEN;
1904 
1905   if ( !EmptyClipboard() )
1906   {
1907     hr = CLIPBRD_E_CANT_EMPTY;
1908     goto end;
1909   }
1910 
1911   hr = set_src_dataobject(clipbrd, data);
1912   if(FAILED(hr)) goto end;
1913 
1914   if(data)
1915   {
1916     hr = expose_marshalled_dataobject(clipbrd, data);
1917     if(FAILED(hr)) goto end;
1918     hr = set_dataobject_format(wnd);
1919   }
1920 
1921 end:
1922 
1923   if ( !CloseClipboard() ) hr = CLIPBRD_E_CANT_CLOSE;
1924 
1925   if ( FAILED(hr) )
1926   {
1927     expose_marshalled_dataobject(clipbrd, NULL);
1928     set_src_dataobject(clipbrd, NULL);
1929   }
1930 
1931   return hr;
1932 }
1933 
1934 
1935 /***********************************************************************
1936  * OleGetClipboard [OLE32.@]
1937  * Returns a pointer to our internal IDataObject which represents the conceptual
1938  * state of the Windows clipboard. If the current clipboard already contains
1939  * an IDataObject, our internal IDataObject will delegate to this object.
1940  */
1941 HRESULT WINAPI OleGetClipboard(IDataObject **obj)
1942 {
1943     HRESULT hr;
1944     ole_clipbrd *clipbrd;
1945     DWORD seq_no;
1946 
1947     TRACE("(%p)\n", obj);
1948 
1949     if(!obj) return E_INVALIDARG;
1950 
1951     if(FAILED(hr = get_ole_clipbrd(&clipbrd))) return hr;
1952 
1953     seq_no = GetClipboardSequenceNumber();
1954     if(clipbrd->latest_snapshot && clipbrd->latest_snapshot->seq_no != seq_no)
1955         clipbrd->latest_snapshot = NULL;
1956 
1957     if(!clipbrd->latest_snapshot)
1958     {
1959         clipbrd->latest_snapshot = snapshot_construct(seq_no);
1960         if(!clipbrd->latest_snapshot) return E_OUTOFMEMORY;
1961     }
1962 
1963     *obj = (IDataObject*)&clipbrd->latest_snapshot->lpVtbl;
1964     IDataObject_AddRef(*obj);
1965 
1966     return S_OK;
1967 }
1968 
1969 /******************************************************************************
1970  *              OleFlushClipboard        [OLE32.@]
1971  *  Renders the data from the source IDataObject into the windows clipboard
1972  *
1973  *  TODO: OleFlushClipboard needs to additionally handle TYMED_IStorage media
1974  *  by copying the storage into global memory. Subsequently the default
1975  *  data object exposed through OleGetClipboard must convert this TYMED_HGLOBAL
1976  *  back to TYMED_IStorage.
1977  */
1978 HRESULT WINAPI OleFlushClipboard(void)
1979 {
1980   HRESULT hr;
1981   ole_clipbrd *clipbrd;
1982   HWND wnd;
1983 
1984   TRACE("()\n");
1985 
1986   if(FAILED(hr = get_ole_clipbrd(&clipbrd))) return hr;
1987 
1988   if(FAILED(hr = get_clipbrd_window(clipbrd, &wnd))) return hr;
1989 
1990   /*
1991    * Already flushed or no source DataObject? Nothing to do.
1992    */
1993   if (!clipbrd->src_data) return S_OK;
1994 
1995   if (!OpenClipboard(wnd)) return CLIPBRD_E_CANT_OPEN;
1996 
1997   SendMessageW(wnd, WM_RENDERALLFORMATS, 0, 0);
1998 
1999   hr = set_dataobject_format(NULL);
2000 
2001   expose_marshalled_dataobject(clipbrd, NULL);
2002   set_src_dataobject(clipbrd, NULL);
2003 
2004   if ( !CloseClipboard() ) hr = CLIPBRD_E_CANT_CLOSE;
2005 
2006   return hr;
2007 }
2008 
2009 
2010 /***********************************************************************
2011  *           OleIsCurrentClipboard [OLE32.@]
2012  */
2013 HRESULT WINAPI OleIsCurrentClipboard(IDataObject *data)
2014 {
2015     HRESULT hr;
2016     ole_clipbrd *clipbrd;
2017     TRACE("()\n");
2018 
2019     if(FAILED(hr = get_ole_clipbrd(&clipbrd))) return hr;
2020 
2021     if (data == NULL) return S_FALSE;
2022 
2023     return (data == clipbrd->src_data) ? S_OK : S_FALSE;
2024 }
2025 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.