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