Added missing prototypes for StrRetToBuf(A|W).
[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_VTABLE(IEnumFORMATETC)* lpvtbl;
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(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   
477   TRACE("()\n");
478
479   /*
480    * Make sure we have a clipboard object
481    */
482   OLEClipbrd_Initialize();
483
484   /*
485    * Already flushed or no source DataObject? Nothing to do.
486    */
487   if (!theOleClipboard->pIDataObjectSrc)
488     return S_OK;
489
490   /*
491    * Open the Windows clipboard
492    */
493   if ( !(bClipboardOpen = OpenClipboard(theOleClipboard->hWndClipboard)) )
494     HANDLE_ERROR( CLIPBRD_E_CANT_OPEN );
495
496   /*
497    * Empty the current clipboard
498    */
499   if ( !EmptyClipboard() )
500     HANDLE_ERROR( CLIPBRD_E_CANT_EMPTY );
501
502   /*
503    * Render all HGLOBAL formats supported by the source into
504    * the windows clipboard.
505    */
506   if ( FAILED( hr = IDataObject_EnumFormatEtc( (IDataObject*)&(theOleClipboard->lpvtbl1),
507                                                DATADIR_GET,
508                                                &penumFormatetc) ))
509   {
510     HANDLE_ERROR( hr );
511   }
512
513   while ( S_OK == IEnumFORMATETC_Next(penumFormatetc, 1, &rgelt, NULL) )
514   {
515     if ( rgelt.tymed == TYMED_HGLOBAL )
516     {
517       CHAR szFmtName[80];
518       TRACE("(cfFormat=%d:%s)\n", rgelt.cfFormat,
519             GetClipboardFormatNameA(rgelt.cfFormat, szFmtName, sizeof(szFmtName)-1)
520               ? szFmtName : "");
521
522       /*
523        * Render the clipboard data
524        */
525       if ( FAILED(OLEClipbrd_RenderFormat( &rgelt )) )
526         continue;
527     }
528   }
529   
530   IEnumFORMATETC_Release(penumFormatetc);
531   
532   /*
533    * Release the data object we are holding on to
534    */
535   if ( theOleClipboard->pIDataObjectSrc )
536   {
537     IDataObject_Release(theOleClipboard->pIDataObjectSrc);
538     theOleClipboard->pIDataObjectSrc = NULL;
539   }
540
541 CLEANUP:
542
543   /*
544    * Close Windows clipboard (It remains associated with our window)
545    */
546   if ( bClipboardOpen && !CloseClipboard() )
547     hr = CLIPBRD_E_CANT_CLOSE;
548
549   return hr;
550 }
551
552
553 /***********************************************************************
554  *           OleIsCurrentClipboard32 [OLE32.110]
555  */
556 HRESULT WINAPI OleIsCurrentClipboard (  IDataObject *pDataObject) 
557 {
558   TRACE("()\n");
559   /*
560    * Make sure we have a clipboard object
561    */
562   OLEClipbrd_Initialize();
563
564   if (!theOleClipboard)
565     return E_OUTOFMEMORY;
566
567   return (pDataObject == theOleClipboard->pIDataObjectSrc) ? S_OK : S_FALSE;
568 }
569
570
571 /*---------------------------------------------------------------------*
572  *           Internal implementation methods for the OLE clipboard 
573  *---------------------------------------------------------------------*/
574
575 /***********************************************************************
576  * OLEClipbrd_Initialize()
577  * Initializes the OLE clipboard. 
578  */
579 void OLEClipbrd_Initialize()
580 {
581   /*
582    * Create the clipboard if necesary 
583    */
584   if ( !theOleClipboard )
585   {
586     TRACE("()\n");
587     theOleClipboard = OLEClipbrd_Construct();
588   }
589 }
590
591
592 /***********************************************************************
593  * OLEClipbrd_UnInitialize()
594  * Un-Initializes the OLE clipboard 
595  */
596 void OLEClipbrd_UnInitialize()
597 {
598   TRACE("()\n");
599   /*
600    * Destroy the clipboard if no one holds a reference to us.
601    * Note that the clipboard was created with a reference count of 1.
602    */
603   if ( theOleClipboard && (theOleClipboard->ref <= 1) )
604   {
605     OLEClipbrd_Destroy( theOleClipboard );
606   }
607   else
608   {
609     WARN( "() : OLEClipbrd_UnInitialize called while client holds an IDataObject reference!\n");
610   }
611 }
612
613
614 /*********************************************************
615  * Construct the OLEClipbrd class.
616  */
617 static OLEClipbrd* OLEClipbrd_Construct()
618 {
619   OLEClipbrd* newObject = NULL;
620   HGLOBAL hNewObject = 0;
621   
622   /*
623    * Allocate space for the object. We use GlobalAlloc since we need
624    * an HGLOBAL to expose our DataObject as a registered clipboard type.
625    */
626   hNewObject = GlobalAlloc( GMEM_DDESHARE|GMEM_MOVEABLE|GMEM_ZEROINIT,
627                            sizeof(OLEClipbrd));
628   if (hNewObject==0)
629     return NULL;
630
631   /*
632    * Lock the handle for the entire lifetime of the clipboard.
633    */
634   newObject = GlobalLock(hNewObject);
635   
636   /*
637    * Initialize the virtual function table.
638    */
639   newObject->lpvtbl1 = &OLEClipbrd_IDataObject_VTable;
640
641   /*
642    * Start with one reference count. The caller of this function 
643    * must release the interface pointer when it is done.
644    */
645   newObject->ref = 1;
646
647   newObject->hSelf = hNewObject;
648   
649   /*
650    * The Ole clipboard is a singleton - save the global handle and pointer
651    */
652   theOleClipboard = newObject;
653   hTheOleClipboard = hNewObject;
654
655   return theOleClipboard;
656 }
657
658 static void OLEClipbrd_Destroy(OLEClipbrd* ptrToDestroy)
659 {
660   TRACE("()\n");
661     
662   if ( !ptrToDestroy )
663     return;
664
665   /*
666    * Destroy the Ole clipboard window 
667    */
668   if ( ptrToDestroy->hWndClipboard )
669     OLEClipbrd_DestroyWindow(ptrToDestroy->hWndClipboard);
670
671   /*
672    * Free the actual OLE Clipboard structure.
673    */
674   TRACE("() - Destroying clipboard data object.\n");
675   GlobalUnlock(ptrToDestroy->hSelf);
676   GlobalFree(ptrToDestroy->hSelf);
677
678   /*
679    * The Ole clipboard is a singleton (ptrToDestroy == theOleClipboard)
680    */
681   theOleClipboard = NULL;
682   hTheOleClipboard = 0;
683 }
684
685
686 /***********************************************************************
687  * OLEClipbrd_CreateWindow()
688  * Create the clipboard window 
689  */
690 static HWND OLEClipbrd_CreateWindow()
691 {
692   HWND hwnd = 0;
693   WNDCLASSEXA wcex;
694   ATOM atom;
695
696   /* 
697    * Register the clipboard window class if necessary 
698    */
699
700   if ( !( atom = GlobalFindAtomA(OLEClipbrd_WNDCLASS) ) ||
701         !( CLASS_FindClassByAtom(atom, 0) ) )
702   {
703     ZeroMemory( &wcex, sizeof(WNDCLASSEXA));
704
705     wcex.cbSize         = sizeof(WNDCLASSEXA);
706     /* Windows creates this class with a style mask of 0
707      * We dont bother doing this since the FindClassByAtom code
708      * would have to be changed to deal with this idiosyncracy. */
709     wcex.style          = CS_GLOBALCLASS;
710     wcex.lpfnWndProc    = (WNDPROC)OLEClipbrd_WndProc;
711     wcex.hInstance      = 0;
712     wcex.lpszClassName  = OLEClipbrd_WNDCLASS;
713
714     RegisterClassExA(&wcex);
715   }
716
717   /*
718    * Create a hidden window to receive OLE clipboard messages 
719    */
720
721 /*
722  *  If we need to store state info we can store it here.
723  *  For now we dont need this functionality.
724  *   ClipboardWindowInfo clipboardInfo;
725  *   ZeroMemory( &trackerInfo, sizeof(ClipboardWindowInfo));
726  */
727
728   hwnd = CreateWindowA(OLEClipbrd_WNDCLASS, 
729                                     "ClipboardWindow",
730                                     WS_POPUP | WS_CLIPSIBLINGS | WS_OVERLAPPED,
731                                     CW_USEDEFAULT, CW_USEDEFAULT,
732                                     CW_USEDEFAULT, CW_USEDEFAULT,
733                                     0,
734                                     0,
735                                     0,
736                                     0 /*(LPVOID)&clipboardInfo */);
737
738   return hwnd;
739 }
740
741 /***********************************************************************
742  * OLEClipbrd_DestroyWindow(HWND)
743  * Destroy the clipboard window and unregister its class
744  */
745 static void OLEClipbrd_DestroyWindow(HWND hwnd)
746 {
747   /* 
748    * Destroy clipboard window and unregister its WNDCLASS 
749    */
750   DestroyWindow(hwnd);
751   UnregisterClassA( OLEClipbrd_WNDCLASS, 0 );
752 }
753
754 /***********************************************************************
755  * OLEClipbrd_WndProc(HWND, unsigned, WORD, LONG)
756  * Processes messages sent to the OLE clipboard window. 
757  * Note that we will intercept messages in our WndProc only when data 
758  * has been placed in the clipboard via OleSetClipboard(). 
759  * i.e. Only when OLE owns the windows clipboard.
760  */
761 LRESULT CALLBACK OLEClipbrd_WndProc
762   (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
763 {
764   switch (message) 
765   {
766     /*
767      * WM_RENDERFORMAT 
768      * We receive this message to allow us to handle delayed rendering of
769      * a specific clipboard format when an application requests data in 
770      * that format by calling GetClipboardData.
771      * (Recall that in OleSetClipboard, we used SetClipboardData to 
772      * make all HGLOBAL formats supported by the source IDataObject
773      * available using delayed rendering)
774      * On receiving this mesage we must actually render the data in the 
775      * specified format and place it on the clipboard by calling the 
776      * SetClipboardData function. 
777      */
778     case WM_RENDERFORMAT:
779     {
780       FORMATETC rgelt;
781         
782       ZeroMemory( &rgelt, sizeof(FORMATETC));
783
784       /*
785        * Initialize FORMATETC to a Windows clipboard friendly format
786        */
787       rgelt.cfFormat = (UINT) wParam;
788       rgelt.dwAspect = DVASPECT_CONTENT;
789       rgelt.lindex = -1;
790       rgelt.tymed = TYMED_HGLOBAL;
791
792       TRACE("(): WM_RENDERFORMAT(cfFormat=%d)\n", rgelt.cfFormat);
793       
794       /*
795        * Render the clipboard data.
796        * (We must have a source data object or we wouldn't be in this WndProc)
797        */
798       OLEClipbrd_RenderFormat( &rgelt );
799
800       break;
801     }
802
803     /*
804      * WM_RENDERALLFORMATS
805      * Sent before the clipboard owner window is destroyed.
806      * We should receive this message only when OleUninitialize is called
807      * while we have an IDataObject in the clipboard.
808      * For the content of the clipboard to remain available to other
809      * applications, we must render data in all the formats the source IDataObject
810      * is capable of generating, and place the data on the clipboard by calling
811      * SetClipboardData.
812      */
813     case WM_RENDERALLFORMATS:
814     {
815       IEnumFORMATETC* penumFormatetc = NULL;
816       FORMATETC rgelt;
817       
818       TRACE("(): WM_RENDERALLFORMATS\n");
819       
820       /*
821        * Render all HGLOBAL formats supported by the source into
822        * the windows clipboard.
823        */
824       if ( FAILED( IDataObject_EnumFormatEtc( (IDataObject*)&(theOleClipboard->lpvtbl1),
825                                  DATADIR_GET, &penumFormatetc) ) )
826       {
827         WARN("(): WM_RENDERALLFORMATS failed to retrieve EnumFormatEtc!\n");
828         return 0;
829       }
830
831       while ( S_OK == IEnumFORMATETC_Next(penumFormatetc, 1, &rgelt, NULL) )
832       {
833         if ( rgelt.tymed == TYMED_HGLOBAL )
834         {
835           /*
836            * Render the clipboard data. 
837            */
838           if ( FAILED(OLEClipbrd_RenderFormat( &rgelt )) )
839             continue;
840         
841           TRACE("(): WM_RENDERALLFORMATS(cfFormat=%d)\n", rgelt.cfFormat);
842         }
843       }
844       
845       IEnumFORMATETC_Release(penumFormatetc);
846
847       break;
848     }
849
850     /*
851      * WM_DESTROYCLIPBOARD
852      * This is sent by EmptyClipboard before the clipboard is emptied.
853      * We should release any IDataObject we are holding onto when we receive
854      * this message, since it indicates that the OLE clipboard should be empty
855      * from this point on.
856      */
857     case WM_DESTROYCLIPBOARD:
858     {
859       TRACE("(): WM_DESTROYCLIPBOARD\n");
860       /*
861        * Release the data object we are holding on to
862        */
863       if ( theOleClipboard->pIDataObjectSrc )
864       {
865         IDataObject_Release(theOleClipboard->pIDataObjectSrc);
866         theOleClipboard->pIDataObjectSrc = NULL;
867       }
868       break;
869     }
870
871 /*
872     case WM_ASKCBFORMATNAME:
873     case WM_CHANGECBCHAIN:
874     case WM_DRAWCLIPBOARD:
875     case WM_SIZECLIPBOARD:
876     case WM_HSCROLLCLIPBOARD:
877     case WM_VSCROLLCLIPBOARD:
878     case WM_PAINTCLIPBOARD:
879 */
880     default:
881       return DefWindowProcA(hWnd, message, wParam, lParam);
882   }
883
884   return 0;
885 }
886
887
888 /***********************************************************************
889  * OLEClipbrd_RenderFormat(LPFORMATETC)
890  * Render the clipboard data. Note that this call will delegate to the
891  * source data object.
892  * Note: This function assumes it is passed an HGLOBAL format to render.
893  */
894 static HRESULT OLEClipbrd_RenderFormat(LPFORMATETC pFormatetc)
895 {
896   STGMEDIUM medium;
897   HGLOBAL hDup;
898   HRESULT hr = S_OK;
899   
900   if ( FAILED(hr = IDataObject_GetData((IDataObject*)&(theOleClipboard->lpvtbl1),
901                                        pFormatetc, &medium)) )
902   {
903     WARN("() : IDataObject_GetData failed to render clipboard data! (%lx)\n", hr);
904     return hr;
905   }
906
907   /*
908    *  Put a copy of the rendered data back on the clipboard
909    */
910   
911   if ( !(hDup = OLEClipbrd_GlobalDupMem(medium.u.hGlobal)) )
912     HANDLE_ERROR( E_OUTOFMEMORY );
913        
914   if ( !SetClipboardData( pFormatetc->cfFormat, hDup ) )
915   {
916     GlobalFree(hDup);
917     WARN("() : Failed to set rendered clipboard data into clipboard!\n");
918   }
919
920 CLEANUP:
921   
922   ReleaseStgMedium(&medium);
923   
924   return hr;
925 }
926
927
928 /***********************************************************************
929  * OLEClipbrd_GlobalDupMem( HGLOBAL )
930  * Helper method to duplicate an HGLOBAL chunk of memory
931  */
932 static HGLOBAL OLEClipbrd_GlobalDupMem( HGLOBAL hGlobalSrc )
933 {
934     HGLOBAL hGlobalDest;
935     PVOID pGlobalSrc, pGlobalDest;
936     DWORD cBytes;
937     
938     if ( !hGlobalSrc )
939       return 0;
940
941     cBytes = GlobalSize(hGlobalSrc);
942     if ( 0 == cBytes )
943       return 0;
944         
945     hGlobalDest = GlobalAlloc( GMEM_DDESHARE|GMEM_MOVEABLE,
946                                cBytes );
947     if ( !hGlobalDest )
948       return 0;
949     
950     pGlobalSrc = GlobalLock(hGlobalSrc);
951     pGlobalDest = GlobalLock(hGlobalDest);
952     if ( !pGlobalSrc || !pGlobalDest )
953       return 0;
954
955     memcpy(pGlobalDest, pGlobalSrc, cBytes);
956         
957     GlobalUnlock(hGlobalSrc);
958     GlobalUnlock(hGlobalDest);
959
960     return hGlobalDest;
961 }
962
963
964 /*---------------------------------------------------------------------*
965  *  Implementation of the internal IDataObject interface exposed by 
966  *  the OLE clipboard.
967  *---------------------------------------------------------------------*/
968
969
970 /************************************************************************
971  * OLEClipbrd_IDataObject_QueryInterface (IUnknown)
972  *
973  * See Windows documentation for more details on IUnknown methods.
974  */
975 static HRESULT WINAPI OLEClipbrd_IDataObject_QueryInterface(
976             IDataObject*     iface,
977             REFIID           riid,
978             void**           ppvObject)
979 {
980   /* 
981    * Declare "This" pointer 
982    */
983   ICOM_THIS(OLEClipbrd, iface);
984   char    xriid[50];
985
986   WINE_StringFromCLSID((LPCLSID)riid,xriid);
987   TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,xriid,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     char clsid[50];
1014
1015     WINE_StringFromCLSID((LPCLSID)riid,clsid);
1016     WARN( "() : asking for unsupported interface %s\n", clsid);
1017
1018     return E_NOINTERFACE;
1019   }
1020   
1021   /*
1022    * Query Interface always increases the reference count by one when it is
1023    * successful. 
1024    */
1025   IUnknown_AddRef((IUnknown*)*ppvObject);
1026
1027   return S_OK;
1028 }
1029
1030 /************************************************************************
1031  * OLEClipbrd_IDataObject_AddRef (IUnknown)
1032  *
1033  * See Windows documentation for more details on IUnknown methods.
1034  */
1035 static ULONG WINAPI OLEClipbrd_IDataObject_AddRef( 
1036             IDataObject*     iface)
1037 {
1038   /* 
1039    * Declare "This" pointer 
1040    */
1041   ICOM_THIS(OLEClipbrd, iface);
1042
1043   TRACE("(%p)->(count=%lu)\n",This, This->ref);
1044   
1045   This->ref++;
1046
1047   return This->ref;
1048 }
1049
1050 /************************************************************************
1051  * OLEClipbrd_IDataObject_Release (IUnknown)
1052  *
1053  * See Windows documentation for more details on IUnknown methods.
1054  */
1055 static ULONG WINAPI OLEClipbrd_IDataObject_Release( 
1056             IDataObject*     iface)
1057 {
1058   /* 
1059    * Declare "This" pointer 
1060    */
1061   ICOM_THIS(OLEClipbrd, iface);
1062
1063   TRACE("(%p)->(count=%lu)\n",This, This->ref);
1064   
1065   /*
1066    * Decrease the reference count on this object.
1067    */
1068   This->ref--;
1069
1070   /*
1071    * If the reference count goes down to 0, perform suicide.
1072    */
1073   if (This->ref==0)
1074   {
1075     OLEClipbrd_Destroy(This);
1076   }
1077   
1078   return This->ref;
1079 }
1080
1081  
1082 /************************************************************************
1083  * OLEClipbrd_IDataObject_GetData (IDataObject)
1084  *
1085  * The OLE Clipboard's implementation of this method delegates to 
1086  * a data source if there is one or wraps around the windows clipboard
1087  *
1088  * See Windows documentation for more details on IDataObject methods.
1089  */
1090 static HRESULT WINAPI OLEClipbrd_IDataObject_GetData(
1091             IDataObject*     iface,
1092             LPFORMATETC      pformatetcIn, 
1093             STGMEDIUM*       pmedium)
1094 {
1095   HANDLE      hData = 0;
1096   BOOL bClipboardOpen = FALSE;
1097   HRESULT hr = S_OK;
1098
1099   /*
1100    * Declare "This" pointer 
1101    */
1102   ICOM_THIS(OLEClipbrd, iface);
1103
1104   if ( !pformatetcIn || !pformatetcIn || !pmedium )
1105     return E_INVALIDARG;
1106
1107   TRACE("(%p, %p)\n", iface, pformatetcIn);
1108
1109   /*
1110    * If we have a data source placed on the clipboard (via OleSetClipboard)
1111    * simply delegate to the source object's QueryGetData
1112    * NOTE: This code assumes that the IDataObject is in the same address space!
1113    * We will need to add marshalling support when Wine handles multiple processes.
1114    */
1115   if ( This->pIDataObjectSrc )
1116   {
1117     return IDataObject_GetData(This->pIDataObjectSrc, pformatetcIn, pmedium);
1118   }
1119
1120   if ( pformatetcIn->lindex != -1 )
1121     return DV_E_LINDEX;
1122   if ( (pformatetcIn->tymed & TYMED_HGLOBAL) != TYMED_HGLOBAL )
1123     return DV_E_TYMED;
1124 /*
1125    if ( pformatetcIn->dwAspect != DVASPECT_CONTENT )
1126      return DV_E_DVASPECT;
1127 */
1128
1129   /* 
1130    * Otherwise, get the data from the windows clipboard using GetClipboardData
1131    */
1132   if ( !(bClipboardOpen = OpenClipboard(theOleClipboard->hWndClipboard)) )
1133     HANDLE_ERROR( CLIPBRD_E_CANT_OPEN );
1134
1135   hData = GetClipboardData(pformatetcIn->cfFormat);
1136
1137   /* 
1138    * Return the clipboard data in the storage medium structure
1139    */
1140   pmedium->tymed = (hData == 0) ? TYMED_NULL : TYMED_HGLOBAL;
1141   pmedium->u.hGlobal = (HGLOBAL)hData;
1142   pmedium->pUnkForRelease = NULL;
1143   
1144   hr = S_OK;
1145   
1146 CLEANUP:
1147   /*
1148    * Close Windows clipboard
1149    */
1150   if ( bClipboardOpen && !CloseClipboard() )
1151      hr = CLIPBRD_E_CANT_CLOSE;
1152
1153   if ( FAILED(hr) )
1154       return hr;
1155   return (hData == 0) ? DV_E_FORMATETC : S_OK;
1156 }
1157
1158 static HRESULT WINAPI OLEClipbrd_IDataObject_GetDataHere(
1159             IDataObject*     iface, 
1160             LPFORMATETC      pformatetc,
1161             STGMEDIUM*       pmedium)
1162 {
1163   FIXME(": Stub\n");
1164   return E_NOTIMPL;
1165 }
1166
1167 /************************************************************************
1168  * OLEClipbrd_IDataObject_QueryGetData (IDataObject)
1169  *
1170  * The OLE Clipboard's implementation of this method delegates to 
1171  * a data source if there is one or wraps around the windows clipboard
1172  * function IsClipboardFormatAvailable() otherwise.
1173  *
1174  * See Windows documentation for more details on IDataObject methods.
1175  */
1176 static HRESULT WINAPI OLEClipbrd_IDataObject_QueryGetData(
1177             IDataObject*     iface,
1178             LPFORMATETC      pformatetc)
1179 {
1180   /* 
1181    * Declare "This" pointer 
1182    */
1183   ICOM_THIS(OLEClipbrd, iface);
1184
1185   TRACE("(%p, %p)\n", iface, pformatetc);
1186
1187   /*
1188    * If we have a data source placed on the clipboard (via OleSetClipboard)
1189    * simply delegate to the source object's QueryGetData
1190    */
1191   if ( This->pIDataObjectSrc )
1192   {
1193     return IDataObject_QueryGetData(This->pIDataObjectSrc, pformatetc);
1194   }
1195
1196   if (!pformatetc)
1197     return E_INVALIDARG;
1198 /*
1199    if ( pformatetc->dwAspect != DVASPECT_CONTENT )
1200      return DV_E_DVASPECT;
1201 */
1202   if ( pformatetc->lindex != -1 )
1203     return DV_E_LINDEX;
1204
1205   /* TODO: Handle TYMED_IStorage media which were put on the clipboard
1206    * by copying the storage into global memory. We must convert this
1207    * TYMED_HGLOBAL back to TYMED_IStorage.
1208    */
1209   if ( pformatetc->tymed != TYMED_HGLOBAL )
1210     return DV_E_TYMED;
1211           
1212   /*
1213    * Delegate to the Windows clipboard function IsClipboardFormatAvailable
1214    */
1215   return (IsClipboardFormatAvailable(pformatetc->cfFormat)) ? S_OK : DV_E_FORMATETC;
1216 }
1217
1218 /************************************************************************
1219  * OLEClipbrd_IDataObject_GetCanonicalFormatEtc (IDataObject)
1220  *
1221  * See Windows documentation for more details on IDataObject methods.
1222  */
1223 static HRESULT WINAPI OLEClipbrd_IDataObject_GetCanonicalFormatEtc(
1224             IDataObject*     iface, 
1225             LPFORMATETC      pformatectIn, 
1226             LPFORMATETC      pformatetcOut)
1227 {
1228   TRACE("(%p, %p, %p)\n", iface, pformatectIn, pformatetcOut);
1229
1230   if ( !pformatectIn || !pformatetcOut )
1231     return E_INVALIDARG;
1232
1233   memcpy(pformatetcOut, pformatectIn, sizeof(FORMATETC));
1234   return DATA_S_SAMEFORMATETC;
1235 }
1236
1237 /************************************************************************
1238  * OLEClipbrd_IDataObject_SetData (IDataObject)
1239  *
1240  * The OLE Clipboard's does not implement this method 
1241  *
1242  * See Windows documentation for more details on IDataObject methods.
1243  */
1244 static HRESULT WINAPI OLEClipbrd_IDataObject_SetData(
1245             IDataObject*     iface,
1246             LPFORMATETC      pformatetc, 
1247             STGMEDIUM*       pmedium, 
1248             BOOL             fRelease)
1249 {
1250   return E_NOTIMPL;
1251 }
1252
1253 /************************************************************************
1254  * OLEClipbrd_IDataObject_EnumFormatEtc (IDataObject)
1255  *
1256  * See Windows documentation for more details on IDataObject methods.
1257  */
1258 static HRESULT WINAPI OLEClipbrd_IDataObject_EnumFormatEtc(
1259             IDataObject*     iface,
1260             DWORD            dwDirection,
1261             IEnumFORMATETC** ppenumFormatEtc)
1262 {
1263   HRESULT hr = S_OK;
1264   FORMATETC *afmt = NULL;
1265   int cfmt, i;
1266   UINT format;
1267   BOOL bClipboardOpen;
1268   
1269   /* 
1270    * Declare "This" pointer 
1271    */
1272   ICOM_THIS(OLEClipbrd, iface);
1273
1274   TRACE("(%p, %lx, %p)\n", iface, dwDirection, ppenumFormatEtc);
1275
1276   /*
1277    * If we have a data source placed on the clipboard (via OleSetClipboard)
1278    * simply delegate to the source object's EnumFormatEtc
1279    */
1280   if ( This->pIDataObjectSrc )
1281   {
1282     return IDataObject_EnumFormatEtc(This->pIDataObjectSrc,
1283                                      dwDirection, ppenumFormatEtc);
1284   }
1285
1286   /*
1287    * Otherwise we must provide our own enumerator which wraps around the
1288    * Windows clipboard function EnumClipboardFormats
1289    */
1290   if ( !ppenumFormatEtc )
1291     return E_INVALIDARG;
1292
1293   if ( dwDirection != DATADIR_GET ) /* IDataObject_SetData not implemented */
1294     return E_NOTIMPL;
1295
1296   /*
1297    * Store all current clipboard formats in an array of FORMATETC's,
1298    * and create an IEnumFORMATETC enumerator from this list.
1299    */
1300   cfmt = CountClipboardFormats();
1301   afmt = (FORMATETC *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1302                                 sizeof(FORMATETC) * cfmt);
1303   /*
1304    * Open the Windows clipboard, associating it with our hidden window
1305    */
1306   if ( !(bClipboardOpen = OpenClipboard(This->hWndClipboard)) )
1307     HANDLE_ERROR( CLIPBRD_E_CANT_OPEN );
1308
1309   /*
1310    * Store all current clipboard formats in an array of FORMATETC's
1311    * TODO: Handle TYMED_IStorage media which were put on the clipboard
1312    * by copying the storage into global memory. We must convert this
1313    * TYMED_HGLOBAL back to TYMED_IStorage.
1314    */
1315   for (i = 0, format = 0; i < cfmt; i++)
1316   {
1317     format = EnumClipboardFormats(format);
1318     if (!format)  /* Failed! */
1319     {
1320       ERR("EnumClipboardFormats failed to return format!\n");
1321       HANDLE_ERROR( E_FAIL );
1322     }
1323     
1324     /* Init the FORMATETC struct */
1325     afmt[i].cfFormat = format;
1326     afmt[i].ptd = NULL;
1327     afmt[i].dwAspect = DVASPECT_CONTENT;
1328     afmt[i].lindex = -1;
1329     afmt[i].tymed = TYMED_HGLOBAL;
1330   }
1331
1332   /*
1333    * Create an EnumFORMATETC enumerator and return an
1334    * EnumFORMATETC after bumping up its ref count
1335    */
1336   *ppenumFormatEtc = OLEClipbrd_IEnumFORMATETC_Construct( cfmt, afmt, (LPUNKNOWN)iface);
1337   if (!(*ppenumFormatEtc))
1338     HANDLE_ERROR( E_OUTOFMEMORY );
1339
1340   if (FAILED( hr = IEnumFORMATETC_AddRef(*ppenumFormatEtc)))
1341     HANDLE_ERROR( hr );
1342       
1343   hr = S_OK;
1344   
1345 CLEANUP:
1346   /*
1347    * Free the array of FORMATETC's
1348    */
1349   if (afmt)
1350     HeapFree(GetProcessHeap(), 0, afmt);
1351   
1352   /*
1353    * Close Windows clipboard
1354    */
1355   if ( bClipboardOpen && !CloseClipboard() )
1356     hr = CLIPBRD_E_CANT_CLOSE;
1357
1358   return hr;
1359 }
1360
1361 /************************************************************************
1362  * OLEClipbrd_IDataObject_DAdvise (IDataObject)
1363  *
1364  * The OLE Clipboard's does not implement this method 
1365  *
1366  * See Windows documentation for more details on IDataObject methods.
1367  */
1368 static HRESULT WINAPI OLEClipbrd_IDataObject_DAdvise(
1369             IDataObject*     iface, 
1370             FORMATETC*       pformatetc, 
1371             DWORD            advf, 
1372             IAdviseSink*     pAdvSink, 
1373             DWORD*           pdwConnection)
1374 {
1375   return E_NOTIMPL;
1376 }
1377
1378 /************************************************************************
1379  * OLEClipbrd_IDataObject_DUnadvise (IDataObject)
1380  *
1381  * The OLE Clipboard's does not implement this method 
1382  *
1383  * See Windows documentation for more details on IDataObject methods.
1384  */
1385 static HRESULT WINAPI OLEClipbrd_IDataObject_DUnadvise(
1386             IDataObject*     iface,
1387             DWORD            dwConnection)
1388 {
1389   return E_NOTIMPL;
1390 }
1391
1392 /************************************************************************
1393  * OLEClipbrd_IDataObject_EnumDAdvise (IDataObject)
1394  *
1395  * The OLE Clipboard does not implement this method
1396  *
1397  * See Windows documentation for more details on IDataObject methods.
1398  */
1399 static HRESULT WINAPI OLEClipbrd_IDataObject_EnumDAdvise(
1400             IDataObject*     iface,
1401             IEnumSTATDATA**  ppenumAdvise)
1402 {
1403   return E_NOTIMPL;
1404 }
1405
1406
1407 /*---------------------------------------------------------------------*
1408  *  Implementation of the internal IEnumFORMATETC interface returned by
1409  *  the OLE clipboard's IDataObject.
1410  *---------------------------------------------------------------------*/
1411
1412 /************************************************************************
1413  * OLEClipbrd_IEnumFORMATETC_Construct (UINT, const FORMATETC, LPUNKNOWN)
1414  *
1415  * Creates an IEnumFORMATETC enumerator from an array of FORMATETC
1416  * Structures. pUnkOuter is the outer unknown for reference counting only.
1417  * NOTE: this does not AddRef the interface.
1418  */
1419
1420 LPENUMFORMATETC OLEClipbrd_IEnumFORMATETC_Construct(UINT cfmt, const FORMATETC afmt[],
1421                                                     LPUNKNOWN pUnkDataObj)
1422 {
1423   IEnumFORMATETCImpl* ef;
1424   DWORD size=cfmt * sizeof(FORMATETC);
1425   LPMALLOC pIMalloc;
1426   
1427   ef = (IEnumFORMATETCImpl*)HeapAlloc(GetProcessHeap(),
1428                                       HEAP_ZERO_MEMORY,
1429                                       sizeof(IEnumFORMATETCImpl));
1430   if (!ef)
1431     return NULL;
1432   
1433   ef->ref = 0;
1434   ef->lpvtbl = &efvt;
1435   ef->pUnkDataObj = pUnkDataObj;
1436   
1437   ef->posFmt = 0;
1438   ef->countFmt = cfmt;
1439   if (FAILED(CoGetMalloc(MEMCTX_TASK, &pIMalloc)))
1440     return NULL;
1441   ef->pFmt = (LPFORMATETC)IMalloc_Alloc(pIMalloc, size);
1442   IMalloc_Release(pIMalloc);
1443   
1444   if (ef->pFmt)
1445     memcpy(ef->pFmt, afmt, size);
1446   
1447   TRACE("(%p)->()\n",ef);
1448   return (LPENUMFORMATETC)ef;
1449 }
1450
1451
1452 /************************************************************************
1453  * OLEClipbrd_IEnumFORMATETC_QueryInterface (IUnknown)
1454  *
1455  * See Windows documentation for more details on IUnknown methods.
1456  */
1457 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_QueryInterface
1458   (LPENUMFORMATETC iface, REFIID riid, LPVOID* ppvObj)
1459 {
1460   ICOM_THIS(IEnumFORMATETCImpl,iface);
1461   char    xriid[50];
1462
1463   WINE_StringFromCLSID((LPCLSID)riid,xriid);
1464   TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,xriid,ppvObj);
1465
1466   /*
1467    * Since enumerators are seperate objects from the parent data object
1468    * we only need to support the IUnknown and IEnumFORMATETC interfaces
1469    */
1470   
1471   *ppvObj = NULL;
1472   
1473   if(IsEqualIID(riid, &IID_IUnknown))
1474   {
1475     *ppvObj = This;
1476   }
1477   else if(IsEqualIID(riid, &IID_IEnumFORMATETC))
1478   {
1479     *ppvObj = (IDataObject*)This;
1480   }   
1481   
1482   if(*ppvObj)
1483   {
1484     IEnumFORMATETC_AddRef((IEnumFORMATETC*)*ppvObj);
1485     TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
1486     return S_OK;
1487   }
1488   
1489   TRACE("-- Interface: E_NOINTERFACE\n");
1490   return E_NOINTERFACE;
1491 }
1492
1493 /************************************************************************
1494  * OLEClipbrd_IEnumFORMATETC_AddRef (IUnknown)
1495  *
1496  * Since enumerating formats only makes sense when our data object is around,
1497  * we insure that it stays as long as we stay by calling our parents IUnknown
1498  * for AddRef and Release. But since we are not controlled by the lifetime of
1499  * the outer object, we still keep our own reference count in order to
1500  * free ourselves.
1501  */
1502 static ULONG WINAPI OLEClipbrd_IEnumFORMATETC_AddRef(LPENUMFORMATETC iface)
1503 {
1504   ICOM_THIS(IEnumFORMATETCImpl,iface);
1505   TRACE("(%p)->(count=%lu)\n",This, This->ref);
1506
1507   if (This->pUnkDataObj)
1508     IUnknown_AddRef(This->pUnkDataObj);
1509   
1510   return ++(This->ref);
1511 }
1512
1513 /************************************************************************
1514  * OLEClipbrd_IEnumFORMATETC_Release (IUnknown)
1515  *
1516  * See Windows documentation for more details on IUnknown methods.
1517  */
1518 static ULONG WINAPI OLEClipbrd_IEnumFORMATETC_Release(LPENUMFORMATETC iface)
1519 {
1520   ICOM_THIS(IEnumFORMATETCImpl,iface);
1521   LPMALLOC pIMalloc;
1522
1523   TRACE("(%p)->(count=%lu)\n",This, This->ref);
1524
1525   if (This->pUnkDataObj)
1526     IUnknown_Release(This->pUnkDataObj);  /* Release parent data object */
1527   
1528   if (!--(This->ref)) 
1529   {
1530     TRACE("() - destroying IEnumFORMATETC(%p)\n",This);
1531     if (SUCCEEDED(CoGetMalloc(MEMCTX_TASK, &pIMalloc)))
1532     {
1533       IMalloc_Free(pIMalloc, This->pFmt);
1534       IMalloc_Release(pIMalloc);
1535     }
1536       
1537     HeapFree(GetProcessHeap(),0,This);
1538     return 0;
1539   }
1540
1541   return This->ref;
1542 }
1543
1544 /************************************************************************
1545  * OLEClipbrd_IEnumFORMATETC_Next (IEnumFORMATETC)
1546  *
1547  * Standard enumerator members for IEnumFORMATETC
1548  */
1549 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Next
1550   (LPENUMFORMATETC iface, ULONG celt, FORMATETC *rgelt, ULONG *pceltFethed)
1551 {
1552   ICOM_THIS(IEnumFORMATETCImpl,iface);
1553   UINT cfetch;
1554   HRESULT hres = S_FALSE;
1555   
1556   TRACE("(%p)->(pos=%u)\n", This, This->posFmt);
1557   
1558   if (This->posFmt < This->countFmt)
1559   {
1560     cfetch = This->countFmt - This->posFmt;
1561     if (cfetch >= celt)
1562     {
1563       cfetch = celt;
1564       hres = S_OK;
1565     }
1566     
1567     memcpy(rgelt, &This->pFmt[This->posFmt], cfetch * sizeof(FORMATETC));
1568     This->posFmt += cfetch;
1569   }
1570   else
1571   {
1572     cfetch = 0;
1573   }
1574   
1575   if (pceltFethed)
1576   {
1577     *pceltFethed = cfetch;
1578   }
1579   
1580   return hres;
1581 }
1582
1583 /************************************************************************
1584  * OLEClipbrd_IEnumFORMATETC_Skip (IEnumFORMATETC)
1585  *
1586  * Standard enumerator members for IEnumFORMATETC
1587  */
1588 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Skip(LPENUMFORMATETC iface, ULONG celt)
1589 {
1590   ICOM_THIS(IEnumFORMATETCImpl,iface);
1591   TRACE("(%p)->(num=%lu)\n", This, celt);
1592   
1593   This->posFmt += celt;
1594   if (This->posFmt > This->countFmt)
1595   {
1596     This->posFmt = This->countFmt;
1597     return S_FALSE;
1598   }
1599   return S_OK;
1600 }
1601
1602 /************************************************************************
1603  * OLEClipbrd_IEnumFORMATETC_Reset (IEnumFORMATETC)
1604  *
1605  * Standard enumerator members for IEnumFORMATETC
1606  */
1607 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Reset(LPENUMFORMATETC iface)
1608 {
1609   ICOM_THIS(IEnumFORMATETCImpl,iface);
1610   TRACE("(%p)->()\n", This);
1611   
1612   This->posFmt = 0;
1613   return S_OK;
1614 }
1615
1616 /************************************************************************
1617  * OLEClipbrd_IEnumFORMATETC_Clone (IEnumFORMATETC)
1618  *
1619  * Standard enumerator members for IEnumFORMATETC
1620  */
1621 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Clone
1622   (LPENUMFORMATETC iface, LPENUMFORMATETC* ppenum)
1623 {
1624   ICOM_THIS(IEnumFORMATETCImpl,iface);
1625   HRESULT hr = S_OK;
1626   
1627   TRACE("(%p)->(ppenum=%p)\n", This, ppenum);
1628
1629   if ( !ppenum )
1630     return E_INVALIDARG;
1631
1632   *ppenum = OLEClipbrd_IEnumFORMATETC_Construct(This->countFmt,
1633                                                 This->pFmt,
1634                                                 This->pUnkDataObj);
1635
1636   if (FAILED( hr = IEnumFORMATETC_AddRef(*ppenum)))
1637     return ( hr );
1638   
1639   return (*ppenum) ? S_OK : E_OUTOFMEMORY;
1640 }
1641