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