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