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