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