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