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