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