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