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