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