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