ole32: Store the marshalled IDataObject in a window property of the clipboard window.
[wine] / dlls / ole32 / clipboard.c
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  *           create_empty_priv_data
109  *
110  * Create an empty data structure.  The only thing that really matters
111  * here is setting count and size members.  This is used by the enumerator as a
112  * convenience when there's an empty list.
113  */
114 static HRESULT create_empty_priv_data(ole_priv_data **data)
115 {
116     ole_priv_data *ptr;
117
118     *data = NULL;
119     ptr = HeapAlloc(GetProcessHeap(), 0, sizeof(*ptr));
120     if(!ptr) return E_OUTOFMEMORY;
121     ptr->size = sizeof(*ptr);
122     ptr->count = 0;
123     *data = ptr;
124     return S_OK;
125 }
126
127
128 /****************************************************************************
129  * ole_clipbrd
130  */
131 typedef struct ole_clipbrd
132 {
133     const IDataObjectVtbl* lpvtbl;  /* Exposed IDataObject vtable */
134
135     LONG ref;
136
137     HWND window;                     /* Hidden clipboard window */
138     IDataObject *src_data;           /* Source object passed to OleSetClipboard */
139     ole_priv_data *cached_enum;      /* Cached result from the enumeration of src data object */
140     IStream *marshal_data;           /* Stream onto which to marshal src_data */
141 } ole_clipbrd;
142
143 static inline ole_clipbrd *impl_from_IDataObject(IDataObject *iface)
144 {
145     return (ole_clipbrd*)((char*)iface - FIELD_OFFSET(ole_clipbrd, lpvtbl));
146 }
147
148 typedef struct PresentationDataHeader
149 {
150   BYTE unknown1[28];
151   DWORD dwObjectExtentX;
152   DWORD dwObjectExtentY;
153   DWORD dwSize;
154 } PresentationDataHeader;
155
156 /*
157  * The one and only ole_clipbrd object which is created by OLEClipbrd_Initialize()
158  */
159 static ole_clipbrd* theOleClipboard;
160
161 static inline HRESULT get_ole_clipbrd(ole_clipbrd **clipbrd)
162 {
163     struct oletls *info = COM_CurrentInfo();
164     *clipbrd = NULL;
165
166     if(!info->ole_inits)
167         return CO_E_NOTINITIALIZED;
168     *clipbrd = theOleClipboard;
169
170     return S_OK;
171 }
172
173 /*
174  * Name of our registered OLE clipboard window class
175  */
176 static const WCHAR clipbrd_wndclass[] = {'C','L','I','P','B','R','D','W','N','D','C','L','A','S','S',0};
177
178 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};
179
180 static UINT dataobject_clipboard_format;
181 static UINT ole_priv_data_clipboard_format;
182 static UINT embed_source_clipboard_format;
183
184 static inline char *dump_fmtetc(FORMATETC *fmt)
185 {
186     static char buf[100];
187
188     snprintf(buf, sizeof(buf), "cf %04x ptd %p aspect %x lindex %d tymed %x",
189              fmt->cfFormat, fmt->ptd, fmt->dwAspect, fmt->lindex, fmt->tymed);
190     return buf;
191 }
192
193 /*---------------------------------------------------------------------*
194  *  Implementation of the internal IEnumFORMATETC interface returned by
195  *  the OLE clipboard's IDataObject.
196  *---------------------------------------------------------------------*/
197
198 typedef struct enum_fmtetc
199 {
200     const IEnumFORMATETCVtbl *lpVtbl;
201     LONG ref;
202
203     UINT pos;    /* current enumerator position */
204     ole_priv_data *data;
205 } enum_fmtetc;
206
207 static inline enum_fmtetc *impl_from_IEnumFORMATETC(IEnumFORMATETC *iface)
208 {
209     return (enum_fmtetc*)((char*)iface - FIELD_OFFSET(enum_fmtetc, lpVtbl));
210 }
211
212 /************************************************************************
213  * OLEClipbrd_IEnumFORMATETC_QueryInterface (IUnknown)
214  *
215  * See Windows documentation for more details on IUnknown methods.
216  */
217 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_QueryInterface
218   (LPENUMFORMATETC iface, REFIID riid, LPVOID* ppvObj)
219 {
220   enum_fmtetc *This = impl_from_IEnumFORMATETC(iface);
221
222   TRACE("(%p)->(IID: %s, %p)\n", This, debugstr_guid(riid), ppvObj);
223
224   *ppvObj = NULL;
225
226   if(IsEqualIID(riid, &IID_IUnknown) ||
227      IsEqualIID(riid, &IID_IEnumFORMATETC))
228   {
229     *ppvObj = iface;
230   }
231
232   if(*ppvObj)
233   {
234     IEnumFORMATETC_AddRef((IEnumFORMATETC*)*ppvObj);
235     TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
236     return S_OK;
237   }
238
239   TRACE("-- Interface: E_NOINTERFACE\n");
240   return E_NOINTERFACE;
241 }
242
243 /************************************************************************
244  * OLEClipbrd_IEnumFORMATETC_AddRef (IUnknown)
245  *
246  */
247 static ULONG WINAPI OLEClipbrd_IEnumFORMATETC_AddRef(LPENUMFORMATETC iface)
248 {
249   enum_fmtetc *This = impl_from_IEnumFORMATETC(iface);
250   TRACE("(%p)->(count=%u)\n",This, This->ref);
251
252   return InterlockedIncrement(&This->ref);
253 }
254
255 /************************************************************************
256  * OLEClipbrd_IEnumFORMATETC_Release (IUnknown)
257  *
258  * See Windows documentation for more details on IUnknown methods.
259  */
260 static ULONG WINAPI OLEClipbrd_IEnumFORMATETC_Release(LPENUMFORMATETC iface)
261 {
262   enum_fmtetc *This = impl_from_IEnumFORMATETC(iface);
263   ULONG ref;
264
265   TRACE("(%p)->(count=%u)\n",This, This->ref);
266
267   ref = InterlockedDecrement(&This->ref);
268   if (!ref)
269   {
270     TRACE("() - destroying IEnumFORMATETC(%p)\n",This);
271     HeapFree(GetProcessHeap(), 0, This->data);
272     HeapFree(GetProcessHeap(), 0, This);
273   }
274   return ref;
275 }
276
277 /************************************************************************
278  * OLEClipbrd_IEnumFORMATETC_Next (IEnumFORMATETC)
279  *
280  * Standard enumerator members for IEnumFORMATETC
281  */
282 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Next
283   (LPENUMFORMATETC iface, ULONG celt, FORMATETC *rgelt, ULONG *pceltFethed)
284 {
285   enum_fmtetc *This = impl_from_IEnumFORMATETC(iface);
286   UINT cfetch, i;
287   HRESULT hres = S_FALSE;
288
289   TRACE("(%p)->(pos=%u)\n", This, This->pos);
290
291   if (This->pos < This->data->count)
292   {
293     cfetch = This->data->count - This->pos;
294     if (cfetch >= celt)
295     {
296       cfetch = celt;
297       hres = S_OK;
298     }
299
300     for(i = 0; i < cfetch; i++)
301     {
302       rgelt[i] = This->data->entries[This->pos++].fmtetc;
303       if(rgelt[i].ptd)
304       {
305         DVTARGETDEVICE *target = (DVTARGETDEVICE *)((char *)This->data + (DWORD)rgelt[i].ptd);
306         rgelt[i].ptd = CoTaskMemAlloc(target->tdSize);
307         if(!rgelt[i].ptd) return E_OUTOFMEMORY;
308         memcpy(rgelt[i].ptd, target, target->tdSize);
309       }
310     }
311   }
312   else
313   {
314     cfetch = 0;
315   }
316
317   if (pceltFethed)
318   {
319     *pceltFethed = cfetch;
320   }
321
322   return hres;
323 }
324
325 /************************************************************************
326  * OLEClipbrd_IEnumFORMATETC_Skip (IEnumFORMATETC)
327  *
328  * Standard enumerator members for IEnumFORMATETC
329  */
330 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Skip(LPENUMFORMATETC iface, ULONG celt)
331 {
332   enum_fmtetc *This = impl_from_IEnumFORMATETC(iface);
333   TRACE("(%p)->(num=%u)\n", This, celt);
334
335   This->pos += celt;
336   if (This->pos > This->data->count)
337   {
338     This->pos = This->data->count;
339     return S_FALSE;
340   }
341   return S_OK;
342 }
343
344 /************************************************************************
345  * OLEClipbrd_IEnumFORMATETC_Reset (IEnumFORMATETC)
346  *
347  * Standard enumerator members for IEnumFORMATETC
348  */
349 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Reset(LPENUMFORMATETC iface)
350 {
351   enum_fmtetc *This = impl_from_IEnumFORMATETC(iface);
352   TRACE("(%p)->()\n", This);
353
354   This->pos = 0;
355   return S_OK;
356 }
357
358 static HRESULT enum_fmtetc_construct(ole_priv_data *data, UINT pos, IEnumFORMATETC **obj);
359
360 /************************************************************************
361  * OLEClipbrd_IEnumFORMATETC_Clone (IEnumFORMATETC)
362  *
363  * Standard enumerator members for IEnumFORMATETC
364  */
365 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Clone
366   (LPENUMFORMATETC iface, LPENUMFORMATETC* obj)
367 {
368   enum_fmtetc *This = impl_from_IEnumFORMATETC(iface);
369   ole_priv_data *new_data;
370
371   TRACE("(%p)->(%p)\n", This, obj);
372
373   if ( !obj ) return E_INVALIDARG;
374   *obj = NULL;
375
376   new_data = HeapAlloc(GetProcessHeap(), 0, This->data->size);
377   if(!new_data) return E_OUTOFMEMORY;
378
379   return enum_fmtetc_construct(new_data, This->pos, obj);
380 }
381
382 static const IEnumFORMATETCVtbl efvt =
383 {
384   OLEClipbrd_IEnumFORMATETC_QueryInterface,
385   OLEClipbrd_IEnumFORMATETC_AddRef,
386   OLEClipbrd_IEnumFORMATETC_Release,
387   OLEClipbrd_IEnumFORMATETC_Next,
388   OLEClipbrd_IEnumFORMATETC_Skip,
389   OLEClipbrd_IEnumFORMATETC_Reset,
390   OLEClipbrd_IEnumFORMATETC_Clone
391 };
392
393 /************************************************************************
394  * enum_fmtetc_construct
395  *
396  * Creates an IEnumFORMATETC enumerator from ole_priv_data which it then owns.
397  */
398 static HRESULT enum_fmtetc_construct(ole_priv_data *data, UINT pos, IEnumFORMATETC **obj)
399 {
400   enum_fmtetc* ef;
401
402   *obj = NULL;
403   ef = HeapAlloc(GetProcessHeap(), 0, sizeof(*ef));
404   if (!ef) return E_OUTOFMEMORY;
405
406   ef->ref = 1;
407   ef->lpVtbl = &efvt;
408   ef->data = data;
409   ef->pos = pos;
410
411   TRACE("(%p)->()\n", ef);
412   *obj = (IEnumFORMATETC *)ef;
413   return S_OK;
414 }
415
416 /***********************************************************************
417  *                    dup_global_mem
418  *
419  * Helper method to duplicate an HGLOBAL chunk of memory
420  */
421 static HRESULT dup_global_mem( HGLOBAL src, DWORD flags, HGLOBAL *dst )
422 {
423     void *src_ptr, *dst_ptr;
424     DWORD size;
425
426     *dst = NULL;
427     if ( !src ) return S_FALSE;
428
429     size = GlobalSize(src);
430
431     *dst = GlobalAlloc( flags, size );
432     if ( !*dst ) return E_OUTOFMEMORY;
433
434     src_ptr = GlobalLock(src);
435     dst_ptr = GlobalLock(*dst);
436
437     memcpy(dst_ptr, src_ptr, size);
438
439     GlobalUnlock(*dst);
440     GlobalUnlock(src);
441
442     return S_OK;
443 }
444
445 /************************************************************
446  *              render_embed_source_hack
447  *
448  * This is clearly a hack and has no place in the clipboard code.
449  *
450  */
451 static HRESULT render_embed_source_hack(IDataObject *data, LPFORMATETC fmt)
452 {
453     STGMEDIUM std;
454     HGLOBAL hStorage = 0;
455     HRESULT hr = S_OK;
456     ILockBytes *ptrILockBytes;
457
458     memset(&std, 0, sizeof(STGMEDIUM));
459     std.tymed = fmt->tymed = TYMED_ISTORAGE;
460
461     hStorage = GlobalAlloc(GMEM_SHARE|GMEM_MOVEABLE, 0);
462     if (hStorage == NULL) return E_OUTOFMEMORY;
463     hr = CreateILockBytesOnHGlobal(hStorage, FALSE, &ptrILockBytes);
464     hr = StgCreateDocfileOnILockBytes(ptrILockBytes, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &std.u.pstg);
465     ILockBytes_Release(ptrILockBytes);
466
467     if (FAILED(hr = IDataObject_GetDataHere(theOleClipboard->src_data, fmt, &std)))
468     {
469         WARN("() : IDataObject_GetDataHere failed to render clipboard data! (%x)\n", hr);
470         GlobalFree(hStorage);
471         return hr;
472     }
473
474     if (1) /* check whether the presentation data is already -not- present */
475     {
476         FORMATETC fmt2;
477         STGMEDIUM std2;
478         METAFILEPICT *mfp = 0;
479
480         fmt2.cfFormat = CF_METAFILEPICT;
481         fmt2.ptd = 0;
482         fmt2.dwAspect = DVASPECT_CONTENT;
483         fmt2.lindex = -1;
484         fmt2.tymed = TYMED_MFPICT;
485
486         memset(&std2, 0, sizeof(STGMEDIUM));
487         std2.tymed = TYMED_MFPICT;
488
489         /* Get the metafile picture out of it */
490
491         if (SUCCEEDED(hr = IDataObject_GetData(theOleClipboard->src_data, &fmt2, &std2)))
492         {
493             mfp = GlobalLock(std2.u.hGlobal);
494         }
495
496         if (mfp)
497         {
498             OLECHAR name[]={ 2, 'O', 'l', 'e', 'P', 'r', 'e', 's', '0', '0', '0', 0};
499             IStream *pStream = 0;
500             void *mfBits;
501             PresentationDataHeader pdh;
502             INT nSize;
503             CLSID clsID;
504             LPOLESTR strProgID;
505             CHAR strOleTypeName[51];
506             BYTE OlePresStreamHeader [] =
507             {
508                 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00,
509                 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
510                 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
511                 0x00, 0x00, 0x00, 0x00
512             };
513
514             nSize = GetMetaFileBitsEx(mfp->hMF, 0, NULL);
515
516             memset(&pdh, 0, sizeof(PresentationDataHeader));
517             memcpy(&pdh, OlePresStreamHeader, sizeof(OlePresStreamHeader));
518
519             pdh.dwObjectExtentX = mfp->xExt;
520             pdh.dwObjectExtentY = mfp->yExt;
521             pdh.dwSize = nSize;
522
523             hr = IStorage_CreateStream(std.u.pstg, name, STGM_CREATE|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, 0, &pStream);
524
525             hr = IStream_Write(pStream, &pdh, sizeof(PresentationDataHeader), NULL);
526
527             mfBits = HeapAlloc(GetProcessHeap(), 0, nSize);
528             nSize = GetMetaFileBitsEx(mfp->hMF, nSize, mfBits);
529
530             hr = IStream_Write(pStream, mfBits, nSize, NULL);
531
532             IStream_Release(pStream);
533
534             HeapFree(GetProcessHeap(), 0, mfBits);
535
536             GlobalUnlock(std2.u.hGlobal);
537             ReleaseStgMedium(&std2);
538
539             ReadClassStg(std.u.pstg, &clsID);
540             ProgIDFromCLSID(&clsID, &strProgID);
541
542             WideCharToMultiByte( CP_ACP, 0, strProgID, -1, strOleTypeName, sizeof(strOleTypeName), NULL, NULL );
543             OLECONVERT_CreateOleStream(std.u.pstg);
544             OLECONVERT_CreateCompObjStream(std.u.pstg, strOleTypeName);
545         }
546     }
547
548     if ( !SetClipboardData( fmt->cfFormat, hStorage ) )
549     {
550         WARN("() : Failed to set rendered clipboard data into clipboard!\n");
551         GlobalFree(hStorage);
552         hr = CLIPBRD_E_CANT_SET;
553     }
554
555     ReleaseStgMedium(&std);
556     return hr;
557 }
558
559 /************************************************************************
560  *           find_format_in_list
561  *
562  * Returns the first entry that matches the provided clipboard format.
563  */
564 static inline ole_priv_data_entry *find_format_in_list(ole_priv_data_entry *entries, DWORD num, UINT cf)
565 {
566     DWORD i;
567     for(i = 0; i < num; i++)
568         if(entries[i].fmtetc.cfFormat == cf)
569             return &entries[i];
570
571     return NULL;
572 }
573
574 /***************************************************************************
575  *         get_data_from_storage
576  *
577  * Returns storage data in an HGLOBAL.
578  */
579 static HRESULT get_data_from_storage(IDataObject *data, FORMATETC *fmt, HGLOBAL *mem)
580 {
581     HGLOBAL h;
582     IStorage *stg;
583     HRESULT hr;
584     FORMATETC stg_fmt;
585     STGMEDIUM med;
586     ILockBytes *lbs;
587
588     *mem = NULL;
589
590     h = GlobalAlloc( GMEM_DDESHARE|GMEM_MOVEABLE, 0 );
591     if(!h) return E_OUTOFMEMORY;
592
593     hr = CreateILockBytesOnHGlobal(h, FALSE, &lbs);
594     if(SUCCEEDED(hr))
595     {
596         hr = StgCreateDocfileOnILockBytes(lbs, STGM_CREATE|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &stg);
597         ILockBytes_Release(lbs);
598     }
599     if(FAILED(hr))
600     {
601         GlobalFree(h);
602         return hr;
603     }
604
605     stg_fmt = *fmt;
606     med.tymed = stg_fmt.tymed = TYMED_ISTORAGE;
607     med.u.pstg = stg;
608     med.pUnkForRelease = NULL;
609
610     hr = IDataObject_GetDataHere(data, &stg_fmt, &med);
611     if(FAILED(hr))
612     {
613         med.u.pstg = NULL;
614         hr = IDataObject_GetData(data, &stg_fmt, &med);
615         if(FAILED(hr)) goto end;
616
617         hr = IStorage_CopyTo(med.u.pstg, 0, NULL, NULL, stg);
618         ReleaseStgMedium(&med);
619         if(FAILED(hr)) goto end;
620     }
621     *mem = h;
622
623 end:
624     IStorage_Release(stg);
625     if(FAILED(hr)) GlobalFree(h);
626     return hr;
627 }
628
629 /***************************************************************************
630  *         get_data_from_stream
631  *
632  * Returns stream data in an HGLOBAL.
633  */
634 static HRESULT get_data_from_stream(IDataObject *data, FORMATETC *fmt, HGLOBAL *mem)
635 {
636     HGLOBAL h;
637     IStream *stm = NULL;
638     HRESULT hr;
639     FORMATETC stm_fmt;
640     STGMEDIUM med;
641
642     *mem = NULL;
643
644     h = GlobalAlloc( GMEM_DDESHARE|GMEM_MOVEABLE, 0 );
645     if(!h) return E_OUTOFMEMORY;
646
647     hr = CreateStreamOnHGlobal(h, FALSE, &stm);
648     if(FAILED(hr)) goto error;
649
650     stm_fmt = *fmt;
651     med.tymed = stm_fmt.tymed = TYMED_ISTREAM;
652     med.u.pstm = stm;
653     med.pUnkForRelease = NULL;
654
655     hr = IDataObject_GetDataHere(data, &stm_fmt, &med);
656     if(FAILED(hr))
657     {
658         LARGE_INTEGER offs;
659         ULARGE_INTEGER pos;
660
661         med.u.pstm = NULL;
662         hr = IDataObject_GetData(data, &stm_fmt, &med);
663         if(FAILED(hr)) goto error;
664
665         offs.QuadPart = 0;
666         IStream_Seek(med.u.pstm, offs, STREAM_SEEK_CUR, &pos);
667         IStream_Seek(med.u.pstm, offs, STREAM_SEEK_SET, NULL);
668         hr = IStream_CopyTo(med.u.pstm, stm, pos, NULL, NULL);
669         ReleaseStgMedium(&med);
670         if(FAILED(hr)) goto error;
671     }
672     *mem = h;
673     IStream_Release(stm);
674     return S_OK;
675
676 error:
677     if(stm) IStream_Release(stm);
678     GlobalFree(h);
679     return hr;
680 }
681
682 /***************************************************************************
683  *         get_data_from_global
684  *
685  * Returns global data in an HGLOBAL.
686  */
687 static HRESULT get_data_from_global(IDataObject *data, FORMATETC *fmt, HGLOBAL *mem)
688 {
689     HGLOBAL h;
690     HRESULT hr;
691     FORMATETC mem_fmt;
692     STGMEDIUM med;
693
694     *mem = NULL;
695
696     mem_fmt = *fmt;
697     mem_fmt.tymed = TYMED_HGLOBAL;
698
699     hr = IDataObject_GetData(data, &mem_fmt, &med);
700     if(FAILED(hr)) return hr;
701
702     hr = dup_global_mem(med.u.hGlobal, GMEM_DDESHARE|GMEM_MOVEABLE, &h);
703
704     if(SUCCEEDED(hr)) *mem = h;
705
706     ReleaseStgMedium(&med);
707
708     return hr;
709 }
710
711 /***********************************************************************
712  *                render_format
713  *
714  * Render the clipboard data. Note that this call will delegate to the
715  * source data object.
716  */
717 static HRESULT render_format(IDataObject *data, LPFORMATETC fmt)
718 {
719     HGLOBAL clip_data = NULL;
720     HRESULT hr;
721
722     /* Embed source hack */
723     if(fmt->cfFormat == embed_source_clipboard_format)
724     {
725         return render_embed_source_hack(data, fmt);
726     }
727
728     if(fmt->tymed & TYMED_ISTORAGE)
729     {
730         hr = get_data_from_storage(data, fmt, &clip_data);
731     }
732     else if(fmt->tymed & TYMED_ISTREAM)
733     {
734         hr = get_data_from_stream(data, fmt, &clip_data);
735     }
736     else if(fmt->tymed & TYMED_HGLOBAL)
737     {
738         hr = get_data_from_global(data, fmt, &clip_data);
739     }
740     else
741     {
742         FIXME("Unhandled tymed %x\n", fmt->tymed);
743         hr = DV_E_FORMATETC;
744     }
745
746     if(SUCCEEDED(hr))
747     {
748         if ( !SetClipboardData(fmt->cfFormat, clip_data) )
749         {
750             WARN("() : Failed to set rendered clipboard data into clipboard!\n");
751             GlobalFree(clip_data);
752             hr = CLIPBRD_E_CANT_SET;
753         }
754     }
755
756     return hr;
757 }
758
759 /*---------------------------------------------------------------------*
760  *  Implementation of the internal IDataObject interface exposed by
761  *  the OLE clipboard.
762  *---------------------------------------------------------------------*/
763
764
765 /************************************************************************
766  * OLEClipbrd_IDataObject_QueryInterface (IUnknown)
767  *
768  * See Windows documentation for more details on IUnknown methods.
769  */
770 static HRESULT WINAPI OLEClipbrd_IDataObject_QueryInterface(
771             IDataObject*     iface,
772             REFIID           riid,
773             void**           ppvObject)
774 {
775   ole_clipbrd *This = impl_from_IDataObject(iface);
776   TRACE("(%p)->(IID:%s, %p)\n", This, debugstr_guid(riid), ppvObject);
777
778   if ( (This==0) || (ppvObject==0) )
779     return E_INVALIDARG;
780
781   *ppvObject = 0;
782
783   if (IsEqualIID(&IID_IUnknown, riid) ||
784       IsEqualIID(&IID_IDataObject, riid))
785   {
786     *ppvObject = iface;
787   }
788   else
789   {
790     WARN( "() : asking for unsupported interface %s\n", debugstr_guid(riid));
791     return E_NOINTERFACE;
792   }
793
794   IUnknown_AddRef((IUnknown*)*ppvObject);
795
796   return S_OK;
797 }
798
799 /************************************************************************
800  * OLEClipbrd_IDataObject_AddRef (IUnknown)
801  *
802  * See Windows documentation for more details on IUnknown methods.
803  */
804 static ULONG WINAPI OLEClipbrd_IDataObject_AddRef(
805             IDataObject*     iface)
806 {
807   ole_clipbrd *This = impl_from_IDataObject(iface);
808
809   TRACE("(%p)->(count=%u)\n",This, This->ref);
810
811   return InterlockedIncrement(&This->ref);
812 }
813
814 /***********************************************************************
815  *                 destroy_clipbrd_window
816  * Destroy the clipboard window and unregister its class
817  */
818 static void destroy_clipbrd_window(HWND hwnd)
819 {
820     static const WCHAR ole32W[] = {'o','l','e','3','2',0};
821     HINSTANCE hinst = GetModuleHandleW(ole32W);
822
823     DestroyWindow(hwnd);
824     UnregisterClassW( clipbrd_wndclass, hinst );
825 }
826
827 static void OLEClipbrd_Destroy(ole_clipbrd* This)
828 {
829     TRACE("()\n");
830
831     if (!This) return;
832
833     if ( This->window ) destroy_clipbrd_window(This->window);
834
835     IStream_Release(This->marshal_data);
836     HeapFree(GetProcessHeap(), 0, This);
837 }
838
839 /************************************************************************
840  * OLEClipbrd_IDataObject_Release (IUnknown)
841  *
842  * See Windows documentation for more details on IUnknown methods.
843  */
844 static ULONG WINAPI OLEClipbrd_IDataObject_Release(
845             IDataObject*     iface)
846 {
847   ole_clipbrd *This = impl_from_IDataObject(iface);
848   ULONG ref;
849
850   TRACE("(%p)->(count=%u)\n",This, This->ref);
851
852   ref = InterlockedDecrement(&This->ref);
853
854   if (ref == 0)
855   {
856     OLEClipbrd_Destroy(This);
857   }
858
859   return ref;
860 }
861
862
863 /************************************************************************
864  * OLEClipbrd_IDataObject_GetData (IDataObject)
865  *
866  * The OLE Clipboard's implementation of this method delegates to
867  * a data source if there is one or wraps around the windows clipboard
868  *
869  * See Windows documentation for more details on IDataObject methods.
870  */
871 static HRESULT WINAPI OLEClipbrd_IDataObject_GetData(
872             IDataObject*     iface,
873             LPFORMATETC      pformatetcIn,
874             STGMEDIUM*       pmedium)
875 {
876   HANDLE h, hData = 0;
877   ole_clipbrd *This = impl_from_IDataObject(iface);
878   HRESULT hr;
879
880   TRACE("(%p,%p,%p)\n", iface, pformatetcIn, pmedium);
881
882   if ( !pformatetcIn || !pmedium )
883     return E_INVALIDARG;
884
885   /*
886    * If we have a data source placed on the clipboard (via OleSetClipboard)
887    * simply delegate to the source object's QueryGetData
888    * NOTE: This code assumes that the IDataObject is in the same address space!
889    * We will need to add marshalling support when Wine handles multiple processes.
890    */
891   if ( This->src_data )
892   {
893     return IDataObject_GetData(This->src_data, pformatetcIn, pmedium);
894   }
895
896   if ( pformatetcIn->lindex != -1 )
897     return DV_E_FORMATETC;
898
899   if ( (pformatetcIn->tymed & TYMED_HGLOBAL) != TYMED_HGLOBAL )
900     return DV_E_TYMED;
901 /*
902    if ( pformatetcIn->dwAspect != DVASPECT_CONTENT )
903      return DV_E_DVASPECT;
904 */
905
906   /*
907    * Otherwise, get the data from the windows clipboard using GetClipboardData
908    */
909   if ( !OpenClipboard(NULL)) return CLIPBRD_E_CANT_OPEN;
910
911   h = GetClipboardData(pformatetcIn->cfFormat);
912   hr = dup_global_mem(h, GMEM_MOVEABLE, &hData);
913
914   /*
915    * Return the clipboard data in the storage medium structure
916    */
917   pmedium->tymed = (hData == 0) ? TYMED_NULL : TYMED_HGLOBAL;
918   pmedium->u.hGlobal = hData;
919   pmedium->pUnkForRelease = NULL;
920
921   if ( !CloseClipboard() ) return CLIPBRD_E_CANT_CLOSE;
922
923   if(FAILED(hr)) return hr;
924   return (hData == 0) ? DV_E_FORMATETC : S_OK;
925 }
926
927 static HRESULT WINAPI OLEClipbrd_IDataObject_GetDataHere(
928             IDataObject*     iface,
929             LPFORMATETC      pformatetc,
930             STGMEDIUM*       pmedium)
931 {
932   FIXME(": Stub\n");
933   return E_NOTIMPL;
934 }
935
936 /************************************************************************
937  * OLEClipbrd_IDataObject_QueryGetData (IDataObject)
938  *
939  * The OLE Clipboard's implementation of this method delegates to
940  * a data source if there is one or wraps around the windows clipboard
941  * function IsClipboardFormatAvailable() otherwise.
942  *
943  * See Windows documentation for more details on IDataObject methods.
944  */
945 static HRESULT WINAPI OLEClipbrd_IDataObject_QueryGetData(
946             IDataObject*     iface,
947             LPFORMATETC      pformatetc)
948 {
949   TRACE("(%p, %p)\n", iface, pformatetc);
950
951   if (!pformatetc)
952     return E_INVALIDARG;
953
954   if ( pformatetc->dwAspect != DVASPECT_CONTENT )
955     return DV_E_FORMATETC;
956
957   if ( pformatetc->lindex != -1 )
958     return DV_E_FORMATETC;
959
960   /*
961    * Delegate to the Windows clipboard function IsClipboardFormatAvailable
962    */
963   return (IsClipboardFormatAvailable(pformatetc->cfFormat)) ? S_OK : DV_E_CLIPFORMAT;
964 }
965
966 /************************************************************************
967  * OLEClipbrd_IDataObject_GetCanonicalFormatEtc (IDataObject)
968  *
969  * See Windows documentation for more details on IDataObject methods.
970  */
971 static HRESULT WINAPI OLEClipbrd_IDataObject_GetCanonicalFormatEtc(
972             IDataObject*     iface,
973             LPFORMATETC      pformatectIn,
974             LPFORMATETC      pformatetcOut)
975 {
976   TRACE("(%p, %p, %p)\n", iface, pformatectIn, pformatetcOut);
977
978   if ( !pformatectIn || !pformatetcOut )
979     return E_INVALIDARG;
980
981   *pformatetcOut = *pformatectIn;
982   return DATA_S_SAMEFORMATETC;
983 }
984
985 /************************************************************************
986  * OLEClipbrd_IDataObject_SetData (IDataObject)
987  *
988  * The OLE Clipboard's does not implement this method
989  *
990  * See Windows documentation for more details on IDataObject methods.
991  */
992 static HRESULT WINAPI OLEClipbrd_IDataObject_SetData(
993             IDataObject*     iface,
994             LPFORMATETC      pformatetc,
995             STGMEDIUM*       pmedium,
996             BOOL             fRelease)
997 {
998   TRACE("\n");
999   return E_NOTIMPL;
1000 }
1001
1002 /************************************************************************
1003  * OLEClipbrd_IDataObject_EnumFormatEtc (IDataObject)
1004  *
1005  * See Windows documentation for more details on IDataObject methods.
1006  */
1007 static HRESULT WINAPI OLEClipbrd_IDataObject_EnumFormatEtc(
1008             IDataObject*     iface,
1009             DWORD            dwDirection,
1010             IEnumFORMATETC** enum_fmt)
1011 {
1012     HRESULT hr = S_OK;
1013     HGLOBAL handle;
1014     ole_priv_data *data = NULL;
1015
1016     TRACE("(%p, %x, %p)\n", iface, dwDirection, enum_fmt);
1017
1018     *enum_fmt = NULL;
1019
1020     if ( dwDirection != DATADIR_GET ) return E_NOTIMPL;
1021     if ( !OpenClipboard(NULL) ) return CLIPBRD_E_CANT_OPEN;
1022
1023     handle = GetClipboardData( ole_priv_data_clipboard_format );
1024     if(handle)
1025     {
1026         ole_priv_data *src = GlobalLock(handle);
1027         if(src)
1028         {
1029             /* FIXME: sanity check on size */
1030             data = HeapAlloc(GetProcessHeap(), 0, src->size);
1031             if(!data)
1032             {
1033                 GlobalUnlock(handle);
1034                 hr = E_OUTOFMEMORY;
1035                 goto end;
1036             }
1037             memcpy(data, src, src->size);
1038             GlobalUnlock(handle);
1039         }
1040     }
1041
1042     if(!data) hr = create_empty_priv_data(&data);
1043     if(FAILED(hr)) goto end;
1044
1045     hr = enum_fmtetc_construct( data, 0, enum_fmt );
1046
1047 end:
1048     if ( !CloseClipboard() ) hr = CLIPBRD_E_CANT_CLOSE;
1049     return hr;
1050 }
1051
1052 /************************************************************************
1053  * OLEClipbrd_IDataObject_DAdvise (IDataObject)
1054  *
1055  * The OLE Clipboard's does not implement this method
1056  *
1057  * See Windows documentation for more details on IDataObject methods.
1058  */
1059 static HRESULT WINAPI OLEClipbrd_IDataObject_DAdvise(
1060             IDataObject*     iface,
1061             FORMATETC*       pformatetc,
1062             DWORD            advf,
1063             IAdviseSink*     pAdvSink,
1064             DWORD*           pdwConnection)
1065 {
1066   TRACE("\n");
1067   return E_NOTIMPL;
1068 }
1069
1070 /************************************************************************
1071  * OLEClipbrd_IDataObject_DUnadvise (IDataObject)
1072  *
1073  * The OLE Clipboard's does not implement this method
1074  *
1075  * See Windows documentation for more details on IDataObject methods.
1076  */
1077 static HRESULT WINAPI OLEClipbrd_IDataObject_DUnadvise(
1078             IDataObject*     iface,
1079             DWORD            dwConnection)
1080 {
1081   TRACE("\n");
1082   return E_NOTIMPL;
1083 }
1084
1085 /************************************************************************
1086  * OLEClipbrd_IDataObject_EnumDAdvise (IDataObject)
1087  *
1088  * The OLE Clipboard does not implement this method
1089  *
1090  * See Windows documentation for more details on IDataObject methods.
1091  */
1092 static HRESULT WINAPI OLEClipbrd_IDataObject_EnumDAdvise(
1093             IDataObject*     iface,
1094             IEnumSTATDATA**  ppenumAdvise)
1095 {
1096   TRACE("\n");
1097   return E_NOTIMPL;
1098 }
1099
1100 static const IDataObjectVtbl OLEClipbrd_IDataObject_VTable =
1101 {
1102   OLEClipbrd_IDataObject_QueryInterface,
1103   OLEClipbrd_IDataObject_AddRef,
1104   OLEClipbrd_IDataObject_Release,
1105   OLEClipbrd_IDataObject_GetData,
1106   OLEClipbrd_IDataObject_GetDataHere,
1107   OLEClipbrd_IDataObject_QueryGetData,
1108   OLEClipbrd_IDataObject_GetCanonicalFormatEtc,
1109   OLEClipbrd_IDataObject_SetData,
1110   OLEClipbrd_IDataObject_EnumFormatEtc,
1111   OLEClipbrd_IDataObject_DAdvise,
1112   OLEClipbrd_IDataObject_DUnadvise,
1113   OLEClipbrd_IDataObject_EnumDAdvise
1114 };
1115
1116 /*---------------------------------------------------------------------*
1117  *           Internal implementation methods for the OLE clipboard
1118  *---------------------------------------------------------------------*/
1119
1120 /*********************************************************
1121  * Construct the OLEClipbrd class.
1122  */
1123 static ole_clipbrd* OLEClipbrd_Construct(void)
1124 {
1125     ole_clipbrd* This;
1126     HGLOBAL h;
1127
1128     This = HeapAlloc( GetProcessHeap(), 0, sizeof(*This) );
1129     if (!This) return NULL;
1130
1131     This->lpvtbl = &OLEClipbrd_IDataObject_VTable;
1132     This->ref = 1;
1133
1134     This->window = NULL;
1135     This->src_data = NULL;
1136     This->cached_enum = NULL;
1137
1138     h = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE, 0);
1139     if(!h) goto error;
1140
1141     if(FAILED(CreateStreamOnHGlobal(h, TRUE, &This->marshal_data)))
1142         goto error;
1143
1144     return This;
1145
1146 error:
1147     if(h) GlobalFree(h);
1148     HeapFree(GetProcessHeap(), 0, This);
1149     return NULL;
1150 }
1151
1152 static void register_clipboard_formats(void)
1153 {
1154     static const WCHAR DataObjectW[] = { 'D','a','t','a','O','b','j','e','c','t',0 };
1155     static const WCHAR OlePrivateDataW[] = { 'O','l','e',' ','P','r','i','v','a','t','e',' ','D','a','t','a',0 };
1156     static const WCHAR EmbedSourceW[] = { 'E','m','b','e','d',' ','S','o','u','r','c','e',0 };
1157
1158     if(!dataobject_clipboard_format)
1159         dataobject_clipboard_format = RegisterClipboardFormatW(DataObjectW);
1160     if(!ole_priv_data_clipboard_format)
1161         ole_priv_data_clipboard_format = RegisterClipboardFormatW(OlePrivateDataW);
1162     if(!embed_source_clipboard_format)
1163         embed_source_clipboard_format = RegisterClipboardFormatW(EmbedSourceW);
1164 }
1165
1166 /***********************************************************************
1167  * OLEClipbrd_Initialize()
1168  * Initializes the OLE clipboard.
1169  */
1170 void OLEClipbrd_Initialize(void)
1171 {
1172   register_clipboard_formats();
1173
1174   if ( !theOleClipboard )
1175   {
1176     TRACE("()\n");
1177     theOleClipboard = OLEClipbrd_Construct();
1178   }
1179 }
1180
1181
1182 /***********************************************************************
1183  * OLEClipbrd_UnInitialize()
1184  * Un-Initializes the OLE clipboard
1185  */
1186 void OLEClipbrd_UnInitialize(void)
1187 {
1188   TRACE("()\n");
1189   /*
1190    * Destroy the clipboard if no one holds a reference to us.
1191    * Note that the clipboard was created with a reference count of 1.
1192    */
1193   if ( theOleClipboard && (theOleClipboard->ref <= 1) )
1194   {
1195     OLEClipbrd_Destroy( theOleClipboard );
1196     theOleClipboard = NULL;
1197   }
1198   else
1199   {
1200     WARN( "() : OLEClipbrd_UnInitialize called while client holds an IDataObject reference!\n");
1201   }
1202 }
1203
1204 /*********************************************************************
1205  *          set_clipboard_formats
1206  *
1207  * Enumerate all formats supported by the source and make
1208  * those formats available using delayed rendering using SetClipboardData.
1209  * Cache the enumeration list and make that list visibile as the
1210  * 'Ole Private Data' format on the clipboard.
1211  *
1212  */
1213 static HRESULT set_clipboard_formats(ole_clipbrd *clipbrd, IDataObject *data)
1214 {
1215     HRESULT hr;
1216     FORMATETC fmt;
1217     IEnumFORMATETC *enum_fmt;
1218     HGLOBAL priv_data_handle;
1219     DWORD target_offset;
1220     ole_priv_data *priv_data;
1221     DWORD count = 0, needed = sizeof(*priv_data), idx;
1222
1223     hr = IDataObject_EnumFormatEtc(data, DATADIR_GET, &enum_fmt);
1224     if(FAILED(hr)) return hr;
1225
1226     while(IEnumFORMATETC_Next(enum_fmt, 1, &fmt, NULL) == S_OK)
1227     {
1228         count++;
1229         needed += sizeof(priv_data->entries[0]);
1230         if(fmt.ptd)
1231         {
1232             needed += fmt.ptd->tdSize;
1233             CoTaskMemFree(fmt.ptd);
1234         }
1235     }
1236
1237     /* Windows pads the list with two empty ole_priv_data_entries, one
1238      * after the entries array and one after the target device data.
1239      * Allocating with zero init to zero these pads. */
1240
1241     needed += sizeof(priv_data->entries[0]); /* initialisation of needed includes one of these. */
1242     priv_data_handle = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE | GMEM_ZEROINIT, needed);
1243     priv_data = GlobalLock(priv_data_handle);
1244
1245     priv_data->unk1 = 0;
1246     priv_data->size = needed;
1247     priv_data->unk2 = 1;
1248     priv_data->count = count;
1249     priv_data->unk3[0] = 0;
1250     priv_data->unk3[1] = 0;
1251
1252     IEnumFORMATETC_Reset(enum_fmt);
1253
1254     idx = 0;
1255     target_offset = FIELD_OFFSET(ole_priv_data, entries[count + 1]); /* count entries + one pad. */
1256
1257     while(IEnumFORMATETC_Next(enum_fmt, 1, &fmt, NULL) == S_OK)
1258     {
1259         TRACE("%s\n", dump_fmtetc(&fmt));
1260
1261         priv_data->entries[idx].fmtetc = fmt;
1262         if(fmt.ptd)
1263         {
1264             memcpy((char*)priv_data + target_offset, fmt.ptd, fmt.ptd->tdSize);
1265             priv_data->entries[idx].fmtetc.ptd = (DVTARGETDEVICE*)target_offset;
1266             target_offset += fmt.ptd->tdSize;
1267             CoTaskMemFree(fmt.ptd);
1268         }
1269
1270         priv_data->entries[idx].first_use = !find_format_in_list(priv_data->entries, idx, fmt.cfFormat);
1271         priv_data->entries[idx].unk[0] = 0;
1272         priv_data->entries[idx].unk[1] = 0;
1273
1274         if (priv_data->entries[idx].first_use)
1275             SetClipboardData(fmt.cfFormat, NULL);
1276
1277         idx++;
1278     }
1279
1280     IEnumFORMATETC_Release(enum_fmt);
1281
1282     /* Cache the list and fixup any target device offsets to ptrs */
1283     clipbrd->cached_enum = HeapAlloc(GetProcessHeap(), 0, needed);
1284     memcpy(clipbrd->cached_enum, priv_data, needed);
1285     for(idx = 0; idx < clipbrd->cached_enum->count; idx++)
1286         if(clipbrd->cached_enum->entries[idx].fmtetc.ptd)
1287             clipbrd->cached_enum->entries[idx].fmtetc.ptd =
1288                 (DVTARGETDEVICE *)((char*)clipbrd->cached_enum + (DWORD)clipbrd->cached_enum->entries[idx].fmtetc.ptd);
1289
1290     GlobalUnlock(priv_data_handle);
1291     SetClipboardData(ole_priv_data_clipboard_format, priv_data_handle);
1292
1293     return S_OK;
1294 }
1295
1296 static HWND create_clipbrd_window(void);
1297
1298 /***********************************************************************
1299  *                 get_clipbrd_window
1300  */
1301 static inline HRESULT get_clipbrd_window(ole_clipbrd *clipbrd, HWND *wnd)
1302 {
1303     if ( !clipbrd->window )
1304         clipbrd->window = create_clipbrd_window();
1305
1306     *wnd = clipbrd->window;
1307     return *wnd ? S_OK : E_FAIL;
1308 }
1309
1310
1311 /**********************************************************************
1312  *                  release_marshal_data
1313  *
1314  * Releases the data and sets the stream back to zero size.
1315  */
1316 static inline void release_marshal_data(IStream *stm)
1317 {
1318     LARGE_INTEGER pos;
1319     ULARGE_INTEGER size;
1320     pos.QuadPart = size.QuadPart = 0;
1321
1322     IStream_Seek(stm, pos, STREAM_SEEK_SET, NULL);
1323     CoReleaseMarshalData(stm);
1324     IStream_Seek(stm, pos, STREAM_SEEK_SET, NULL);
1325     IStream_SetSize(stm, size);
1326 }
1327
1328 /***********************************************************************
1329  *                   set_src_dataobject
1330  *
1331  * Clears and sets the clipboard's src IDataObject.
1332  *
1333  * To marshal the source dataobject we do something rather different from Windows.
1334  * We set a window prop which contains the marshalled data.
1335  * Windows set two props one of which is an IID, the other is an endpoint number.
1336  */
1337 static HRESULT set_src_dataobject(ole_clipbrd *clipbrd, IDataObject *data)
1338 {
1339     HRESULT hr;
1340     HWND wnd;
1341
1342     if(FAILED(hr = get_clipbrd_window(clipbrd, &wnd))) return hr;
1343
1344     if(clipbrd->src_data)
1345     {
1346         RemovePropW(wnd, wine_marshal_dataobject);
1347         release_marshal_data(clipbrd->marshal_data);
1348
1349         IDataObject_Release(clipbrd->src_data);
1350         clipbrd->src_data = NULL;
1351         HeapFree(GetProcessHeap(), 0, clipbrd->cached_enum);
1352         clipbrd->cached_enum = NULL;
1353     }
1354
1355     if(data)
1356     {
1357         HGLOBAL h;
1358         IUnknown *unk;
1359
1360         IDataObject_AddRef(data);
1361         clipbrd->src_data = data;
1362
1363         IDataObject_QueryInterface(data, &IID_IUnknown, (void**)&unk);
1364         hr = CoMarshalInterface(clipbrd->marshal_data, &IID_IDataObject, unk,
1365                                 MSHCTX_LOCAL, NULL, MSHLFLAGS_TABLESTRONG);
1366         IUnknown_Release(unk); /* Don't hold a ref on IUnknown, we have one on IDataObject. */
1367         if(FAILED(hr)) return hr;
1368         GetHGlobalFromStream(clipbrd->marshal_data, &h);
1369         SetPropW(wnd, wine_marshal_dataobject, h);
1370         hr = set_clipboard_formats(clipbrd, data);
1371     }
1372     return hr;
1373 }
1374
1375 /***********************************************************************
1376  *                   clipbrd_wndproc
1377  */
1378 static LRESULT CALLBACK clipbrd_wndproc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
1379 {
1380     ole_clipbrd *clipbrd;
1381
1382     get_ole_clipbrd(&clipbrd);
1383
1384     switch (message)
1385     {
1386     case WM_RENDERFORMAT:
1387     {
1388         UINT cf = wparam;
1389         ole_priv_data_entry *entry;
1390
1391         TRACE("(): WM_RENDERFORMAT(cfFormat=%x)\n", cf);
1392         entry = find_format_in_list(clipbrd->cached_enum->entries, clipbrd->cached_enum->count, cf);
1393
1394         if(entry)
1395             render_format(clipbrd->src_data, &entry->fmtetc);
1396
1397         break;
1398     }
1399
1400     case WM_RENDERALLFORMATS:
1401     {
1402         DWORD i;
1403         ole_priv_data_entry *entries = clipbrd->cached_enum->entries;
1404
1405         TRACE("(): WM_RENDERALLFORMATS\n");
1406
1407         for(i = 0; i < clipbrd->cached_enum->count; i++)
1408         {
1409             if(entries[i].first_use)
1410                 render_format(clipbrd->src_data, &entries[i].fmtetc);
1411         }
1412         break;
1413     }
1414
1415     case WM_DESTROYCLIPBOARD:
1416     {
1417         TRACE("(): WM_DESTROYCLIPBOARD\n");
1418
1419         set_src_dataobject(clipbrd, NULL);
1420         break;
1421     }
1422
1423     default:
1424         return DefWindowProcW(hwnd, message, wparam, lparam);
1425     }
1426
1427     return 0;
1428 }
1429
1430
1431 /***********************************************************************
1432  *                 create_clipbrd_window
1433  */
1434 static HWND create_clipbrd_window(void)
1435 {
1436     WNDCLASSEXW class;
1437     static const WCHAR ole32W[] = {'o','l','e','3','2',0};
1438     static const WCHAR title[] = {'C','l','i','p','b','o','a','r','d','W','i','n','d','o','w',0};
1439     HINSTANCE hinst = GetModuleHandleW(ole32W);
1440
1441     class.cbSize         = sizeof(class);
1442     class.style          = 0;
1443     class.lpfnWndProc    = clipbrd_wndproc;
1444     class.cbClsExtra     = 0;
1445     class.cbWndExtra     = 0;
1446     class.hInstance      = hinst;
1447     class.hIcon          = 0;
1448     class.hCursor        = 0;
1449     class.hbrBackground  = 0;
1450     class.lpszMenuName   = NULL;
1451     class.lpszClassName  = clipbrd_wndclass;
1452     class.hIconSm        = NULL;
1453
1454     RegisterClassExW(&class);
1455
1456     return CreateWindowW(clipbrd_wndclass, title, WS_POPUP | WS_CLIPSIBLINGS | WS_OVERLAPPED,
1457                          CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
1458                          NULL, NULL, hinst, 0);
1459 }
1460
1461 /*********************************************************************
1462  *          set_dataobject_format
1463  *
1464  * Windows creates a 'DataObject' clipboard format that contains the
1465  * clipboard window's HWND or NULL if the Ole clipboard has been flushed.
1466  */
1467 static HRESULT set_dataobject_format(HWND hwnd)
1468 {
1469     HGLOBAL h = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE, sizeof(hwnd));
1470     HWND *data;
1471
1472     if(!h) return E_OUTOFMEMORY;
1473
1474     data = GlobalLock(h);
1475     *data = hwnd;
1476     GlobalUnlock(h);
1477
1478     if(!SetClipboardData(dataobject_clipboard_format, h))
1479     {
1480         GlobalFree(h);
1481         return CLIPBRD_E_CANT_SET;
1482     }
1483
1484     return S_OK;
1485 }
1486
1487 /*---------------------------------------------------------------------*
1488  *           Win32 OLE clipboard API
1489  *---------------------------------------------------------------------*/
1490
1491 /***********************************************************************
1492  *           OleSetClipboard     [OLE32.@]
1493  *  Places a pointer to the specified data object onto the clipboard,
1494  *  making the data object accessible to the OleGetClipboard function.
1495  *
1496  * RETURNS
1497  *
1498  *    S_OK                  IDataObject pointer placed on the clipboard
1499  *    CLIPBRD_E_CANT_OPEN   OpenClipboard failed
1500  *    CLIPBRD_E_CANT_EMPTY  EmptyClipboard failed
1501  *    CLIPBRD_E_CANT_CLOSE  CloseClipboard failed
1502  *    CLIPBRD_E_CANT_SET    SetClipboard failed
1503  */
1504
1505 HRESULT WINAPI OleSetClipboard(IDataObject* data)
1506 {
1507   HRESULT hr;
1508   ole_clipbrd *clipbrd;
1509   HWND wnd;
1510
1511   TRACE("(%p)\n", data);
1512
1513   if(FAILED(hr = get_ole_clipbrd(&clipbrd))) return hr;
1514
1515   if(FAILED(hr = get_clipbrd_window(clipbrd, &wnd))) return hr;
1516
1517   if ( !OpenClipboard(wnd) ) return CLIPBRD_E_CANT_OPEN;
1518
1519   if ( !EmptyClipboard() )
1520   {
1521     hr = CLIPBRD_E_CANT_EMPTY;
1522     goto end;
1523   }
1524
1525   hr = set_src_dataobject(clipbrd, data);
1526   if(FAILED(hr)) goto end;
1527
1528   hr = set_dataobject_format(wnd);
1529
1530 end:
1531
1532   if ( !CloseClipboard() ) hr = CLIPBRD_E_CANT_CLOSE;
1533
1534   if ( FAILED(hr) )
1535   {
1536     set_src_dataobject(clipbrd, NULL);
1537   }
1538
1539   return hr;
1540 }
1541
1542
1543 /***********************************************************************
1544  * OleGetClipboard [OLE32.@]
1545  * Returns a pointer to our internal IDataObject which represents the conceptual
1546  * state of the Windows clipboard. If the current clipboard already contains
1547  * an IDataObject, our internal IDataObject will delegate to this object.
1548  */
1549 HRESULT WINAPI OleGetClipboard(IDataObject** ppDataObj)
1550 {
1551     HRESULT hr;
1552     ole_clipbrd *clipbrd;
1553     TRACE("()\n");
1554
1555     if(FAILED(hr = get_ole_clipbrd(&clipbrd))) return hr;
1556
1557     hr = IDataObject_QueryInterface( (IDataObject*)&(clipbrd->lpvtbl),
1558                                      &IID_IDataObject,  (void**)ppDataObj);
1559     return hr;
1560 }
1561
1562 /******************************************************************************
1563  *              OleFlushClipboard        [OLE32.@]
1564  *  Renders the data from the source IDataObject into the windows clipboard
1565  *
1566  *  TODO: OleFlushClipboard needs to additionally handle TYMED_IStorage media
1567  *  by copying the storage into global memory. Subsequently the default
1568  *  data object exposed through OleGetClipboard must convert this TYMED_HGLOBAL
1569  *  back to TYMED_IStorage.
1570  */
1571 HRESULT WINAPI OleFlushClipboard(void)
1572 {
1573   IEnumFORMATETC* penumFormatetc = NULL;
1574   FORMATETC rgelt;
1575   HRESULT hr;
1576   ole_clipbrd *clipbrd;
1577   HWND wnd;
1578
1579   TRACE("()\n");
1580
1581   if(FAILED(hr = get_ole_clipbrd(&clipbrd))) return hr;
1582
1583   if(FAILED(hr = get_clipbrd_window(clipbrd, &wnd))) return hr;
1584
1585   /*
1586    * Already flushed or no source DataObject? Nothing to do.
1587    */
1588   if (!clipbrd->src_data) return S_OK;
1589
1590   if (!OpenClipboard(wnd)) return CLIPBRD_E_CANT_OPEN;
1591
1592   /*
1593    * Render all HGLOBAL formats supported by the source into
1594    * the windows clipboard.
1595    */
1596   if ( FAILED( hr = IDataObject_EnumFormatEtc( clipbrd->src_data,
1597                                                DATADIR_GET,
1598                                                &penumFormatetc) ))
1599     goto end;
1600
1601
1602   while ( S_OK == IEnumFORMATETC_Next(penumFormatetc, 1, &rgelt, NULL) )
1603   {
1604     if ( rgelt.tymed == TYMED_HGLOBAL )
1605     {
1606       CHAR szFmtName[80];
1607       TRACE("(cfFormat=%d:%s)\n", rgelt.cfFormat,
1608             GetClipboardFormatNameA(rgelt.cfFormat, szFmtName, sizeof(szFmtName)-1)
1609               ? szFmtName : "");
1610
1611       if ( FAILED(render_format( clipbrd->src_data, &rgelt )) )
1612         continue;
1613     }
1614   }
1615
1616   IEnumFORMATETC_Release(penumFormatetc);
1617
1618   hr = set_dataobject_format(NULL);
1619
1620   set_src_dataobject(clipbrd, NULL);
1621
1622 end:
1623
1624   if ( !CloseClipboard() ) hr = CLIPBRD_E_CANT_CLOSE;
1625
1626   return hr;
1627 }
1628
1629
1630 /***********************************************************************
1631  *           OleIsCurrentClipboard [OLE32.@]
1632  */
1633 HRESULT WINAPI OleIsCurrentClipboard(IDataObject *data)
1634 {
1635     HRESULT hr;
1636     ole_clipbrd *clipbrd;
1637     TRACE("()\n");
1638
1639     if(FAILED(hr = get_ole_clipbrd(&clipbrd))) return hr;
1640
1641     if (data == NULL) return S_FALSE;
1642
1643     return (data == clipbrd->src_data) ? S_OK : S_FALSE;
1644 }