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