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