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