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