Moved libuuid to the dlls directory, and moved the DirectX GUIDs into
[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 NONAMELESSUNION
66 #define NONAMELESSSTRUCT
67 #include "windef.h"
68 #include "winbase.h"
69 #include "wingdi.h"
70 #include "winuser.h"
71 #include "winerror.h"
72 #include "winnls.h"
73 #include "ole2.h"
74 #include "wine/debug.h"
75 #include "olestd.h"
76
77 #include "storage32.h"
78
79 #define HANDLE_ERROR(err) { hr = err; TRACE("(HRESULT=%lx)\n", (HRESULT)err); goto CLEANUP; }
80
81 /* For CoGetMalloc (MEMCTX_TASK is currently ignored) */
82 #ifndef MEMCTX_TASK
83   #define MEMCTX_TASK -1
84 #endif
85
86 WINE_DEFAULT_DEBUG_CHANNEL(ole);
87
88 /****************************************************************************
89  * OLEClipbrd
90  * DO NOT add any members before the VTables declaration!
91  */
92 struct OLEClipbrd
93 {
94   /*
95    * List all interface VTables here
96    */
97   ICOM_VTABLE(IDataObject)*  lpvtbl1;  /* IDataObject VTable */
98
99   /*
100    * The hidden OLE clipboard window. This window is used as the bridge between the
101    * the OLE and windows clipboard API. (Windows creates one such window per process)
102    */
103   HWND                       hWndClipboard;
104
105   /*
106    * Pointer to the source data object (via OleSetClipboard)
107    */
108   IDataObject*               pIDataObjectSrc;
109
110   /*
111    * The registered DataObject clipboard format
112    */
113   UINT                       cfDataObj;
114
115   /*
116    * The handle to ourself
117    */
118   HGLOBAL                    hSelf;
119
120   /*
121    * Reference count of this object
122    */
123   ULONG                      ref;
124 };
125
126 typedef struct OLEClipbrd OLEClipbrd;
127
128
129 /****************************************************************************
130 *   IEnumFORMATETC implementation
131 *   DO NOT add any members before the VTables declaration!
132 */
133 typedef struct
134 {
135   /* IEnumFORMATETC VTable */
136   ICOM_VFIELD(IEnumFORMATETC);
137
138   /* IEnumFORMATETC fields */
139   UINT                         posFmt;    /* current enumerator position */
140   UINT                         countFmt;  /* number of EnumFORMATETC's in array */
141   LPFORMATETC                  pFmt;      /* array of EnumFORMATETC's */
142
143   /*
144    * Reference count of this object
145    */
146   DWORD                        ref;
147
148   /*
149    * IUnknown implementation of the parent data object.
150    */
151   IUnknown*                    pUnkDataObj;
152
153 } IEnumFORMATETCImpl;
154
155 typedef struct PresentationDataHeader
156 {
157   BYTE unknown1[28];
158   DWORD dwObjectExtentX;
159   DWORD dwObjectExtentY;
160   DWORD dwSize;
161 } PresentationDataHeader;
162
163 /*
164  * The one and only OLEClipbrd object which is created by OLEClipbrd_Initialize()
165  */
166 static HGLOBAL hTheOleClipboard = 0;
167 static OLEClipbrd* theOleClipboard = NULL;
168
169
170 /*
171  * Prototypes for the methods of the OLEClipboard class.
172  */
173 extern void OLEClipbrd_Initialize();
174 extern void OLEClipbrd_UnInitialize();
175 static OLEClipbrd* OLEClipbrd_Construct();
176 static void OLEClipbrd_Destroy(OLEClipbrd* ptrToDestroy);
177 static HWND OLEClipbrd_CreateWindow();
178 static void OLEClipbrd_DestroyWindow(HWND hwnd);
179 LRESULT CALLBACK OLEClipbrd_WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
180 static HRESULT OLEClipbrd_RenderFormat( IDataObject *pIDataObject, LPFORMATETC pFormatetc );
181 static HGLOBAL OLEClipbrd_GlobalDupMem( HGLOBAL hGlobalSrc );
182
183 /*
184  * Prototypes for the methods of the OLEClipboard class
185  * that implement IDataObject methods.
186  */
187 static HRESULT WINAPI OLEClipbrd_IDataObject_QueryInterface(
188             IDataObject*     iface,
189             REFIID           riid,
190             void**           ppvObject);
191 static ULONG WINAPI OLEClipbrd_IDataObject_AddRef(
192             IDataObject*     iface);
193 static ULONG WINAPI OLEClipbrd_IDataObject_Release(
194             IDataObject*     iface);
195 static HRESULT WINAPI OLEClipbrd_IDataObject_GetData(
196             IDataObject*     iface,
197             LPFORMATETC      pformatetcIn,
198             STGMEDIUM*       pmedium);
199 static HRESULT WINAPI OLEClipbrd_IDataObject_GetDataHere(
200             IDataObject*     iface,
201             LPFORMATETC      pformatetc,
202             STGMEDIUM*       pmedium);
203 static HRESULT WINAPI OLEClipbrd_IDataObject_QueryGetData(
204             IDataObject*     iface,
205             LPFORMATETC      pformatetc);
206 static HRESULT WINAPI OLEClipbrd_IDataObject_GetCanonicalFormatEtc(
207             IDataObject*     iface,
208             LPFORMATETC      pformatectIn,
209             LPFORMATETC      pformatetcOut);
210 static HRESULT WINAPI OLEClipbrd_IDataObject_SetData(
211             IDataObject*     iface,
212             LPFORMATETC      pformatetc,
213             STGMEDIUM*       pmedium,
214             BOOL             fRelease);
215 static HRESULT WINAPI OLEClipbrd_IDataObject_EnumFormatEtc(
216             IDataObject*     iface,
217             DWORD            dwDirection,
218             IEnumFORMATETC** ppenumFormatEtc);
219 static HRESULT WINAPI OLEClipbrd_IDataObject_DAdvise(
220             IDataObject*     iface,
221             FORMATETC*       pformatetc,
222             DWORD            advf,
223             IAdviseSink*     pAdvSink,
224             DWORD*           pdwConnection);
225 static HRESULT WINAPI OLEClipbrd_IDataObject_DUnadvise(
226             IDataObject*     iface,
227             DWORD            dwConnection);
228 static HRESULT WINAPI OLEClipbrd_IDataObject_EnumDAdvise(
229             IDataObject*     iface,
230             IEnumSTATDATA**  ppenumAdvise);
231
232 /*
233  * Prototypes for the IEnumFORMATETC methods.
234  */
235 static LPENUMFORMATETC OLEClipbrd_IEnumFORMATETC_Construct(UINT cfmt, const FORMATETC afmt[],
236                                                            LPUNKNOWN pUnkDataObj);
237 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_QueryInterface(LPENUMFORMATETC iface, REFIID riid,
238                                                                LPVOID* ppvObj);
239 static ULONG WINAPI OLEClipbrd_IEnumFORMATETC_AddRef(LPENUMFORMATETC iface);
240 static ULONG WINAPI OLEClipbrd_IEnumFORMATETC_Release(LPENUMFORMATETC iface);
241 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Next(LPENUMFORMATETC iface, ULONG celt,
242                                                      FORMATETC* rgelt, ULONG* pceltFethed);
243 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Skip(LPENUMFORMATETC iface, ULONG celt);
244 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Reset(LPENUMFORMATETC iface);
245 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Clone(LPENUMFORMATETC iface, LPENUMFORMATETC* ppenum);
246
247
248 /*
249  * Virtual function table for the OLEClipbrd's exposed IDataObject interface
250  */
251 static ICOM_VTABLE(IDataObject) OLEClipbrd_IDataObject_VTable =
252 {
253   ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
254   OLEClipbrd_IDataObject_QueryInterface,
255   OLEClipbrd_IDataObject_AddRef,
256   OLEClipbrd_IDataObject_Release,
257   OLEClipbrd_IDataObject_GetData,
258   OLEClipbrd_IDataObject_GetDataHere,
259   OLEClipbrd_IDataObject_QueryGetData,
260   OLEClipbrd_IDataObject_GetCanonicalFormatEtc,
261   OLEClipbrd_IDataObject_SetData,
262   OLEClipbrd_IDataObject_EnumFormatEtc,
263   OLEClipbrd_IDataObject_DAdvise,
264   OLEClipbrd_IDataObject_DUnadvise,
265   OLEClipbrd_IDataObject_EnumDAdvise
266 };
267
268 /*
269  * Virtual function table for IEnumFORMATETC interface
270  */
271 static struct ICOM_VTABLE(IEnumFORMATETC) efvt =
272 {
273   ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
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()
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()
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    = (WNDPROC)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 mesage 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     hr = CreateILockBytesOnHGlobal(hStorage, FALSE, &ptrILockBytes);
942     hr = StgCreateDocfileOnILockBytes(ptrILockBytes, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &std.u.pstg);
943
944     if (FAILED(hr = IDataObject_GetDataHere(theOleClipboard->pIDataObjectSrc, pFormatetc, &std)))
945     {
946       WARN("() : IDataObject_GetDataHere failed to render clipboard data! (%lx)\n", hr);
947       return hr;
948     }
949
950     if (1) /* check whether the presentation data is already -not- present */
951     {
952       FORMATETC fmt2;
953       STGMEDIUM std2;
954       METAFILEPICT *mfp = 0;
955
956       fmt2.cfFormat = CF_METAFILEPICT;
957       fmt2.ptd = 0;
958       fmt2.dwAspect = DVASPECT_CONTENT;
959       fmt2.lindex = -1;
960       fmt2.tymed = TYMED_MFPICT;
961
962       memset(&std2, 0, sizeof(STGMEDIUM));
963       std2.tymed = TYMED_MFPICT;
964
965       /* Get the metafile picture out of it */
966
967       if (!FAILED(hr = IDataObject_GetData(theOleClipboard->pIDataObjectSrc, &fmt2, &std2)))
968       {
969         mfp = (METAFILEPICT *)GlobalLock(std2.u.hGlobal);
970       }
971
972       if (mfp)
973       {
974         OLECHAR name[]={ 2, 'O', 'l', 'e', 'P', 'r', 'e', 's', '0', '0', '0', 0};
975         IStream *pStream = 0;
976         void *mfBits;
977         PresentationDataHeader pdh;
978         INT nSize;
979         CLSID clsID;
980         LPOLESTR strProgID;
981         CHAR strOleTypeName[51];
982         BYTE OlePresStreamHeader [] =
983         {
984             0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00,
985             0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
986             0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
987             0x00, 0x00, 0x00, 0x00
988         };
989
990         nSize = GetMetaFileBitsEx(mfp->hMF, 0, NULL);
991
992         memset(&pdh, 0, sizeof(PresentationDataHeader));
993         memcpy(&pdh, OlePresStreamHeader, sizeof(OlePresStreamHeader));
994
995         pdh.dwObjectExtentX = mfp->xExt;
996         pdh.dwObjectExtentY = mfp->yExt;
997         pdh.dwSize = nSize;
998
999         hr = IStorage_CreateStream(std.u.pstg, name, STGM_CREATE|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, 0, &pStream);
1000
1001         hr = IStream_Write(pStream, &pdh, sizeof(PresentationDataHeader), NULL);
1002
1003         mfBits = HeapAlloc(GetProcessHeap(), 0, nSize);
1004         nSize = GetMetaFileBitsEx(mfp->hMF, nSize, mfBits);
1005
1006         hr = IStream_Write(pStream, mfBits, nSize, NULL);
1007
1008         IStream_Release(pStream);
1009
1010         HeapFree(GetProcessHeap(), 0, mfBits);
1011
1012         GlobalUnlock(std2.u.hGlobal);
1013
1014         ReadClassStg(std.u.pstg, &clsID);
1015         ProgIDFromCLSID(&clsID, &strProgID);
1016
1017         WideCharToMultiByte( CP_ACP, 0, strProgID, -1, strOleTypeName, sizeof(strOleTypeName), NULL, NULL );
1018         OLECONVERT_CreateOleStream(std.u.pstg);
1019         OLECONVERT_CreateCompObjStream(std.u.pstg, strOleTypeName);
1020       }
1021     }
1022   }
1023   else
1024   {
1025     if (FAILED(hr = IDataObject_GetData(pIDataObject, pFormatetc, &std)))
1026   {
1027     WARN("() : IDataObject_GetData failed to render clipboard data! (%lx)\n", hr);
1028     return hr;
1029   }
1030
1031     /* To put a copy back on the clipboard */
1032
1033     hStorage = std.u.hGlobal;
1034   }
1035
1036   /*
1037    *  Put a copy of the rendered data back on the clipboard
1038    */
1039
1040   if ( !(hDup = OLEClipbrd_GlobalDupMem(hStorage)) )
1041     HANDLE_ERROR( E_OUTOFMEMORY );
1042
1043   if ( !SetClipboardData( pFormatetc->cfFormat, hDup ) )
1044   {
1045     GlobalFree(hDup);
1046     WARN("() : Failed to set rendered clipboard data into clipboard!\n");
1047   }
1048
1049 CLEANUP:
1050
1051   ReleaseStgMedium(&std);
1052
1053   return hr;
1054 }
1055
1056
1057 /***********************************************************************
1058  * OLEClipbrd_GlobalDupMem( HGLOBAL )
1059  * Helper method to duplicate an HGLOBAL chunk of memory
1060  */
1061 static HGLOBAL OLEClipbrd_GlobalDupMem( HGLOBAL hGlobalSrc )
1062 {
1063     HGLOBAL hGlobalDest;
1064     PVOID pGlobalSrc, pGlobalDest;
1065     DWORD cBytes;
1066
1067     if ( !hGlobalSrc )
1068       return 0;
1069
1070     cBytes = GlobalSize(hGlobalSrc);
1071     if ( 0 == cBytes )
1072       return 0;
1073
1074     hGlobalDest = GlobalAlloc( GMEM_DDESHARE|GMEM_MOVEABLE,
1075                                cBytes );
1076     if ( !hGlobalDest )
1077       return 0;
1078
1079     pGlobalSrc = GlobalLock(hGlobalSrc);
1080     pGlobalDest = GlobalLock(hGlobalDest);
1081     if ( !pGlobalSrc || !pGlobalDest )
1082       return 0;
1083
1084     memcpy(pGlobalDest, pGlobalSrc, cBytes);
1085
1086     GlobalUnlock(hGlobalSrc);
1087     GlobalUnlock(hGlobalDest);
1088
1089     return hGlobalDest;
1090 }
1091
1092
1093 /*---------------------------------------------------------------------*
1094  *  Implementation of the internal IDataObject interface exposed by
1095  *  the OLE clipboard.
1096  *---------------------------------------------------------------------*/
1097
1098
1099 /************************************************************************
1100  * OLEClipbrd_IDataObject_QueryInterface (IUnknown)
1101  *
1102  * See Windows documentation for more details on IUnknown methods.
1103  */
1104 static HRESULT WINAPI OLEClipbrd_IDataObject_QueryInterface(
1105             IDataObject*     iface,
1106             REFIID           riid,
1107             void**           ppvObject)
1108 {
1109   /*
1110    * Declare "This" pointer
1111    */
1112   ICOM_THIS(OLEClipbrd, iface);
1113   TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObject);
1114
1115   /*
1116    * Perform a sanity check on the parameters.
1117    */
1118   if ( (This==0) || (ppvObject==0) )
1119     return E_INVALIDARG;
1120
1121   /*
1122    * Initialize the return parameter.
1123    */
1124   *ppvObject = 0;
1125
1126   /*
1127    * Compare the riid with the interface IDs implemented by this object.
1128    */
1129   if (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0)
1130   {
1131     *ppvObject = iface;
1132   }
1133   else if (memcmp(&IID_IDataObject, riid, sizeof(IID_IDataObject)) == 0)
1134   {
1135     *ppvObject = (IDataObject*)&(This->lpvtbl1);
1136   }
1137   else  /* We only support IUnknown and IDataObject */
1138   {
1139     WARN( "() : asking for unsupported interface %s\n", debugstr_guid(riid));
1140     return E_NOINTERFACE;
1141   }
1142
1143   /*
1144    * Query Interface always increases the reference count by one when it is
1145    * successful.
1146    */
1147   IUnknown_AddRef((IUnknown*)*ppvObject);
1148
1149   return S_OK;
1150 }
1151
1152 /************************************************************************
1153  * OLEClipbrd_IDataObject_AddRef (IUnknown)
1154  *
1155  * See Windows documentation for more details on IUnknown methods.
1156  */
1157 static ULONG WINAPI OLEClipbrd_IDataObject_AddRef(
1158             IDataObject*     iface)
1159 {
1160   /*
1161    * Declare "This" pointer
1162    */
1163   ICOM_THIS(OLEClipbrd, iface);
1164
1165   TRACE("(%p)->(count=%lu)\n",This, This->ref);
1166
1167   This->ref++;
1168
1169   return This->ref;
1170 }
1171
1172 /************************************************************************
1173  * OLEClipbrd_IDataObject_Release (IUnknown)
1174  *
1175  * See Windows documentation for more details on IUnknown methods.
1176  */
1177 static ULONG WINAPI OLEClipbrd_IDataObject_Release(
1178             IDataObject*     iface)
1179 {
1180   /*
1181    * Declare "This" pointer
1182    */
1183   ICOM_THIS(OLEClipbrd, iface);
1184
1185   TRACE("(%p)->(count=%lu)\n",This, This->ref);
1186
1187   /*
1188    * Decrease the reference count on this object.
1189    */
1190   This->ref--;
1191
1192   /*
1193    * If the reference count goes down to 0, perform suicide.
1194    */
1195   if (This->ref==0)
1196   {
1197     OLEClipbrd_Destroy(This);
1198   }
1199
1200   return This->ref;
1201 }
1202
1203
1204 /************************************************************************
1205  * OLEClipbrd_IDataObject_GetData (IDataObject)
1206  *
1207  * The OLE Clipboard's implementation of this method delegates to
1208  * a data source if there is one or wraps around the windows clipboard
1209  *
1210  * See Windows documentation for more details on IDataObject methods.
1211  */
1212 static HRESULT WINAPI OLEClipbrd_IDataObject_GetData(
1213             IDataObject*     iface,
1214             LPFORMATETC      pformatetcIn,
1215             STGMEDIUM*       pmedium)
1216 {
1217   HANDLE      hData = 0;
1218   BOOL bClipboardOpen = FALSE;
1219   HRESULT hr = S_OK;
1220   LPVOID src;
1221
1222   /*
1223    * Declare "This" pointer
1224    */
1225   ICOM_THIS(OLEClipbrd, iface);
1226
1227   TRACE("(%p,%p,%p)\n", iface, pformatetcIn, pmedium);
1228
1229   if ( !pformatetcIn || !pmedium )
1230     return E_INVALIDARG;
1231
1232   /*
1233    * If we have a data source placed on the clipboard (via OleSetClipboard)
1234    * simply delegate to the source object's QueryGetData
1235    * NOTE: This code assumes that the IDataObject is in the same address space!
1236    * We will need to add marshalling support when Wine handles multiple processes.
1237    */
1238   if ( This->pIDataObjectSrc )
1239   {
1240     return IDataObject_GetData(This->pIDataObjectSrc, pformatetcIn, pmedium);
1241   }
1242
1243   if ( pformatetcIn->lindex != -1 )
1244     return DV_E_LINDEX;
1245   if ( (pformatetcIn->tymed & TYMED_HGLOBAL) != TYMED_HGLOBAL )
1246     return DV_E_TYMED;
1247 /*
1248    if ( pformatetcIn->dwAspect != DVASPECT_CONTENT )
1249      return DV_E_DVASPECT;
1250 */
1251
1252   /*
1253    * Otherwise, get the data from the windows clipboard using GetClipboardData
1254    */
1255   if ( !(bClipboardOpen = OpenClipboard(theOleClipboard->hWndClipboard)) )
1256     HANDLE_ERROR( CLIPBRD_E_CANT_OPEN );
1257
1258   hData = GetClipboardData(pformatetcIn->cfFormat);
1259
1260   /* Must make a copy of global handle returned by GetClipboardData; it
1261    * is not valid after we call CloseClipboard
1262    * Application is responsible for freeing the memory (Forte Agent does this)
1263    */
1264   src = GlobalLock(hData);
1265   if(src) {
1266       LPVOID dest;
1267       ULONG  size;
1268       HANDLE hDest;
1269
1270       size = GlobalSize(hData);
1271       hDest = GlobalAlloc(GHND, size);
1272       dest  = GlobalLock(hDest);
1273       memcpy(dest, src, size);
1274       GlobalUnlock(hDest);
1275       GlobalUnlock(hData);
1276       hData = hDest;
1277   }
1278
1279   /*
1280    * Return the clipboard data in the storage medium structure
1281    */
1282   pmedium->tymed = (hData == 0) ? TYMED_NULL : TYMED_HGLOBAL;
1283   pmedium->u.hGlobal = (HGLOBAL)hData;
1284   pmedium->pUnkForRelease = NULL;
1285
1286   hr = S_OK;
1287
1288 CLEANUP:
1289   /*
1290    * Close Windows clipboard
1291    */
1292   if ( bClipboardOpen && !CloseClipboard() )
1293      hr = CLIPBRD_E_CANT_CLOSE;
1294
1295   if ( FAILED(hr) )
1296       return hr;
1297   return (hData == 0) ? DV_E_FORMATETC : S_OK;
1298 }
1299
1300 static HRESULT WINAPI OLEClipbrd_IDataObject_GetDataHere(
1301             IDataObject*     iface,
1302             LPFORMATETC      pformatetc,
1303             STGMEDIUM*       pmedium)
1304 {
1305   FIXME(": Stub\n");
1306   return E_NOTIMPL;
1307 }
1308
1309 /************************************************************************
1310  * OLEClipbrd_IDataObject_QueryGetData (IDataObject)
1311  *
1312  * The OLE Clipboard's implementation of this method delegates to
1313  * a data source if there is one or wraps around the windows clipboard
1314  * function IsClipboardFormatAvailable() otherwise.
1315  *
1316  * See Windows documentation for more details on IDataObject methods.
1317  */
1318 static HRESULT WINAPI OLEClipbrd_IDataObject_QueryGetData(
1319             IDataObject*     iface,
1320             LPFORMATETC      pformatetc)
1321 {
1322   /*
1323    * Declare "This" pointer
1324    */
1325   ICOM_THIS(OLEClipbrd, iface);
1326
1327   TRACE("(%p, %p)\n", iface, pformatetc);
1328
1329   /*
1330    * If we have a data source placed on the clipboard (via OleSetClipboard)
1331    * simply delegate to the source object's QueryGetData
1332    */
1333   if ( This->pIDataObjectSrc )
1334   {
1335     return IDataObject_QueryGetData(This->pIDataObjectSrc, pformatetc);
1336   }
1337
1338   if (!pformatetc)
1339     return E_INVALIDARG;
1340 /*
1341    if ( pformatetc->dwAspect != DVASPECT_CONTENT )
1342      return DV_E_DVASPECT;
1343 */
1344   if ( pformatetc->lindex != -1 )
1345     return DV_E_LINDEX;
1346
1347   /* TODO: Handle TYMED_IStorage media which were put on the clipboard
1348    * by copying the storage into global memory. We must convert this
1349    * TYMED_HGLOBAL back to TYMED_IStorage.
1350    */
1351   if ( pformatetc->tymed != TYMED_HGLOBAL )
1352     return DV_E_TYMED;
1353
1354   /*
1355    * Delegate to the Windows clipboard function IsClipboardFormatAvailable
1356    */
1357   return (IsClipboardFormatAvailable(pformatetc->cfFormat)) ? S_OK : DV_E_FORMATETC;
1358 }
1359
1360 /************************************************************************
1361  * OLEClipbrd_IDataObject_GetCanonicalFormatEtc (IDataObject)
1362  *
1363  * See Windows documentation for more details on IDataObject methods.
1364  */
1365 static HRESULT WINAPI OLEClipbrd_IDataObject_GetCanonicalFormatEtc(
1366             IDataObject*     iface,
1367             LPFORMATETC      pformatectIn,
1368             LPFORMATETC      pformatetcOut)
1369 {
1370   TRACE("(%p, %p, %p)\n", iface, pformatectIn, pformatetcOut);
1371
1372   if ( !pformatectIn || !pformatetcOut )
1373     return E_INVALIDARG;
1374
1375   memcpy(pformatetcOut, pformatectIn, sizeof(FORMATETC));
1376   return DATA_S_SAMEFORMATETC;
1377 }
1378
1379 /************************************************************************
1380  * OLEClipbrd_IDataObject_SetData (IDataObject)
1381  *
1382  * The OLE Clipboard's does not implement this method
1383  *
1384  * See Windows documentation for more details on IDataObject methods.
1385  */
1386 static HRESULT WINAPI OLEClipbrd_IDataObject_SetData(
1387             IDataObject*     iface,
1388             LPFORMATETC      pformatetc,
1389             STGMEDIUM*       pmedium,
1390             BOOL             fRelease)
1391 {
1392   TRACE("\n");
1393   return E_NOTIMPL;
1394 }
1395
1396 /************************************************************************
1397  * OLEClipbrd_IDataObject_EnumFormatEtc (IDataObject)
1398  *
1399  * See Windows documentation for more details on IDataObject methods.
1400  */
1401 static HRESULT WINAPI OLEClipbrd_IDataObject_EnumFormatEtc(
1402             IDataObject*     iface,
1403             DWORD            dwDirection,
1404             IEnumFORMATETC** ppenumFormatEtc)
1405 {
1406   HRESULT hr = S_OK;
1407   FORMATETC *afmt = NULL;
1408   int cfmt, i;
1409   UINT format;
1410   BOOL bClipboardOpen;
1411
1412   /*
1413    * Declare "This" pointer
1414    */
1415   ICOM_THIS(OLEClipbrd, iface);
1416
1417   TRACE("(%p, %lx, %p)\n", iface, dwDirection, ppenumFormatEtc);
1418
1419   /*
1420    * If we have a data source placed on the clipboard (via OleSetClipboard)
1421    * simply delegate to the source object's EnumFormatEtc
1422    */
1423   if ( This->pIDataObjectSrc )
1424   {
1425     return IDataObject_EnumFormatEtc(This->pIDataObjectSrc,
1426                                      dwDirection, ppenumFormatEtc);
1427   }
1428
1429   /*
1430    * Otherwise we must provide our own enumerator which wraps around the
1431    * Windows clipboard function EnumClipboardFormats
1432    */
1433   if ( !ppenumFormatEtc )
1434     return E_INVALIDARG;
1435
1436   if ( dwDirection != DATADIR_GET ) /* IDataObject_SetData not implemented */
1437     return E_NOTIMPL;
1438
1439   /*
1440    * Store all current clipboard formats in an array of FORMATETC's,
1441    * and create an IEnumFORMATETC enumerator from this list.
1442    */
1443   cfmt = CountClipboardFormats();
1444   afmt = (FORMATETC *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1445                                 sizeof(FORMATETC) * cfmt);
1446   /*
1447    * Open the Windows clipboard, associating it with our hidden window
1448    */
1449   if ( !(bClipboardOpen = OpenClipboard(This->hWndClipboard)) )
1450     HANDLE_ERROR( CLIPBRD_E_CANT_OPEN );
1451
1452   /*
1453    * Store all current clipboard formats in an array of FORMATETC's
1454    * TODO: Handle TYMED_IStorage media which were put on the clipboard
1455    * by copying the storage into global memory. We must convert this
1456    * TYMED_HGLOBAL back to TYMED_IStorage.
1457    */
1458   for (i = 0, format = 0; i < cfmt; i++)
1459   {
1460     format = EnumClipboardFormats(format);
1461     if (!format)  /* Failed! */
1462     {
1463       ERR("EnumClipboardFormats failed to return format!\n");
1464       HANDLE_ERROR( E_FAIL );
1465     }
1466
1467     /* Init the FORMATETC struct */
1468     afmt[i].cfFormat = format;
1469     afmt[i].ptd = NULL;
1470     afmt[i].dwAspect = DVASPECT_CONTENT;
1471     afmt[i].lindex = -1;
1472     afmt[i].tymed = TYMED_HGLOBAL;
1473   }
1474
1475   /*
1476    * Create an EnumFORMATETC enumerator and return an
1477    * EnumFORMATETC after bumping up its ref count
1478    */
1479   *ppenumFormatEtc = OLEClipbrd_IEnumFORMATETC_Construct( cfmt, afmt, (LPUNKNOWN)iface);
1480   if (!(*ppenumFormatEtc))
1481     HANDLE_ERROR( E_OUTOFMEMORY );
1482
1483   if (FAILED( hr = IEnumFORMATETC_AddRef(*ppenumFormatEtc)))
1484     HANDLE_ERROR( hr );
1485
1486   hr = S_OK;
1487
1488 CLEANUP:
1489   /*
1490    * Free the array of FORMATETC's
1491    */
1492   if (afmt)
1493     HeapFree(GetProcessHeap(), 0, afmt);
1494
1495   /*
1496    * Close Windows clipboard
1497    */
1498   if ( bClipboardOpen && !CloseClipboard() )
1499     hr = CLIPBRD_E_CANT_CLOSE;
1500
1501   return hr;
1502 }
1503
1504 /************************************************************************
1505  * OLEClipbrd_IDataObject_DAdvise (IDataObject)
1506  *
1507  * The OLE Clipboard's does not implement this method
1508  *
1509  * See Windows documentation for more details on IDataObject methods.
1510  */
1511 static HRESULT WINAPI OLEClipbrd_IDataObject_DAdvise(
1512             IDataObject*     iface,
1513             FORMATETC*       pformatetc,
1514             DWORD            advf,
1515             IAdviseSink*     pAdvSink,
1516             DWORD*           pdwConnection)
1517 {
1518   TRACE("\n");
1519   return E_NOTIMPL;
1520 }
1521
1522 /************************************************************************
1523  * OLEClipbrd_IDataObject_DUnadvise (IDataObject)
1524  *
1525  * The OLE Clipboard's does not implement this method
1526  *
1527  * See Windows documentation for more details on IDataObject methods.
1528  */
1529 static HRESULT WINAPI OLEClipbrd_IDataObject_DUnadvise(
1530             IDataObject*     iface,
1531             DWORD            dwConnection)
1532 {
1533   TRACE("\n");
1534   return E_NOTIMPL;
1535 }
1536
1537 /************************************************************************
1538  * OLEClipbrd_IDataObject_EnumDAdvise (IDataObject)
1539  *
1540  * The OLE Clipboard does not implement this method
1541  *
1542  * See Windows documentation for more details on IDataObject methods.
1543  */
1544 static HRESULT WINAPI OLEClipbrd_IDataObject_EnumDAdvise(
1545             IDataObject*     iface,
1546             IEnumSTATDATA**  ppenumAdvise)
1547 {
1548   TRACE("\n");
1549   return E_NOTIMPL;
1550 }
1551
1552
1553 /*---------------------------------------------------------------------*
1554  *  Implementation of the internal IEnumFORMATETC interface returned by
1555  *  the OLE clipboard's IDataObject.
1556  *---------------------------------------------------------------------*/
1557
1558 /************************************************************************
1559  * OLEClipbrd_IEnumFORMATETC_Construct (UINT, const FORMATETC, LPUNKNOWN)
1560  *
1561  * Creates an IEnumFORMATETC enumerator from an array of FORMATETC
1562  * Structures. pUnkOuter is the outer unknown for reference counting only.
1563  * NOTE: this does not AddRef the interface.
1564  */
1565
1566 LPENUMFORMATETC OLEClipbrd_IEnumFORMATETC_Construct(UINT cfmt, const FORMATETC afmt[],
1567                                                     LPUNKNOWN pUnkDataObj)
1568 {
1569   IEnumFORMATETCImpl* ef;
1570   DWORD size=cfmt * sizeof(FORMATETC);
1571   LPMALLOC pIMalloc;
1572
1573   ef = (IEnumFORMATETCImpl*)HeapAlloc(GetProcessHeap(),
1574                                       HEAP_ZERO_MEMORY,
1575                                       sizeof(IEnumFORMATETCImpl));
1576   if (!ef)
1577     return NULL;
1578
1579   ef->ref = 0;
1580   ef->lpVtbl = &efvt;
1581   ef->pUnkDataObj = pUnkDataObj;
1582
1583   ef->posFmt = 0;
1584   ef->countFmt = cfmt;
1585   if (FAILED(CoGetMalloc(MEMCTX_TASK, &pIMalloc))) {
1586     HeapFree(GetProcessHeap(), 0, ef);
1587     return NULL;
1588   }
1589   ef->pFmt = (LPFORMATETC)IMalloc_Alloc(pIMalloc, size);
1590   IMalloc_Release(pIMalloc);
1591
1592   if (ef->pFmt)
1593     memcpy(ef->pFmt, afmt, size);
1594
1595   TRACE("(%p)->()\n",ef);
1596   return (LPENUMFORMATETC)ef;
1597 }
1598
1599
1600 /************************************************************************
1601  * OLEClipbrd_IEnumFORMATETC_QueryInterface (IUnknown)
1602  *
1603  * See Windows documentation for more details on IUnknown methods.
1604  */
1605 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_QueryInterface
1606   (LPENUMFORMATETC iface, REFIID riid, LPVOID* ppvObj)
1607 {
1608   ICOM_THIS(IEnumFORMATETCImpl,iface);
1609
1610   TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
1611
1612   /*
1613    * Since enumerators are separate objects from the parent data object
1614    * we only need to support the IUnknown and IEnumFORMATETC interfaces
1615    */
1616
1617   *ppvObj = NULL;
1618
1619   if(IsEqualIID(riid, &IID_IUnknown))
1620   {
1621     *ppvObj = This;
1622   }
1623   else if(IsEqualIID(riid, &IID_IEnumFORMATETC))
1624   {
1625     *ppvObj = (IDataObject*)This;
1626   }
1627
1628   if(*ppvObj)
1629   {
1630     IEnumFORMATETC_AddRef((IEnumFORMATETC*)*ppvObj);
1631     TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
1632     return S_OK;
1633   }
1634
1635   TRACE("-- Interface: E_NOINTERFACE\n");
1636   return E_NOINTERFACE;
1637 }
1638
1639 /************************************************************************
1640  * OLEClipbrd_IEnumFORMATETC_AddRef (IUnknown)
1641  *
1642  * Since enumerating formats only makes sense when our data object is around,
1643  * we insure that it stays as long as we stay by calling our parents IUnknown
1644  * for AddRef and Release. But since we are not controlled by the lifetime of
1645  * the outer object, we still keep our own reference count in order to
1646  * free ourselves.
1647  */
1648 static ULONG WINAPI OLEClipbrd_IEnumFORMATETC_AddRef(LPENUMFORMATETC iface)
1649 {
1650   ICOM_THIS(IEnumFORMATETCImpl,iface);
1651   TRACE("(%p)->(count=%lu)\n",This, This->ref);
1652
1653   if (This->pUnkDataObj)
1654     IUnknown_AddRef(This->pUnkDataObj);
1655
1656   return ++(This->ref);
1657 }
1658
1659 /************************************************************************
1660  * OLEClipbrd_IEnumFORMATETC_Release (IUnknown)
1661  *
1662  * See Windows documentation for more details on IUnknown methods.
1663  */
1664 static ULONG WINAPI OLEClipbrd_IEnumFORMATETC_Release(LPENUMFORMATETC iface)
1665 {
1666   ICOM_THIS(IEnumFORMATETCImpl,iface);
1667   LPMALLOC pIMalloc;
1668
1669   TRACE("(%p)->(count=%lu)\n",This, This->ref);
1670
1671   if (This->pUnkDataObj)
1672     IUnknown_Release(This->pUnkDataObj);  /* Release parent data object */
1673
1674   if (!--(This->ref))
1675   {
1676     TRACE("() - destroying IEnumFORMATETC(%p)\n",This);
1677     if (SUCCEEDED(CoGetMalloc(MEMCTX_TASK, &pIMalloc)))
1678     {
1679       IMalloc_Free(pIMalloc, This->pFmt);
1680       IMalloc_Release(pIMalloc);
1681     }
1682
1683     HeapFree(GetProcessHeap(),0,This);
1684     return 0;
1685   }
1686
1687   return This->ref;
1688 }
1689
1690 /************************************************************************
1691  * OLEClipbrd_IEnumFORMATETC_Next (IEnumFORMATETC)
1692  *
1693  * Standard enumerator members for IEnumFORMATETC
1694  */
1695 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Next
1696   (LPENUMFORMATETC iface, ULONG celt, FORMATETC *rgelt, ULONG *pceltFethed)
1697 {
1698   ICOM_THIS(IEnumFORMATETCImpl,iface);
1699   UINT cfetch;
1700   HRESULT hres = S_FALSE;
1701
1702   TRACE("(%p)->(pos=%u)\n", This, This->posFmt);
1703
1704   if (This->posFmt < This->countFmt)
1705   {
1706     cfetch = This->countFmt - This->posFmt;
1707     if (cfetch >= celt)
1708     {
1709       cfetch = celt;
1710       hres = S_OK;
1711     }
1712
1713     memcpy(rgelt, &This->pFmt[This->posFmt], cfetch * sizeof(FORMATETC));
1714     This->posFmt += cfetch;
1715   }
1716   else
1717   {
1718     cfetch = 0;
1719   }
1720
1721   if (pceltFethed)
1722   {
1723     *pceltFethed = cfetch;
1724   }
1725
1726   return hres;
1727 }
1728
1729 /************************************************************************
1730  * OLEClipbrd_IEnumFORMATETC_Skip (IEnumFORMATETC)
1731  *
1732  * Standard enumerator members for IEnumFORMATETC
1733  */
1734 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Skip(LPENUMFORMATETC iface, ULONG celt)
1735 {
1736   ICOM_THIS(IEnumFORMATETCImpl,iface);
1737   TRACE("(%p)->(num=%lu)\n", This, celt);
1738
1739   This->posFmt += celt;
1740   if (This->posFmt > This->countFmt)
1741   {
1742     This->posFmt = This->countFmt;
1743     return S_FALSE;
1744   }
1745   return S_OK;
1746 }
1747
1748 /************************************************************************
1749  * OLEClipbrd_IEnumFORMATETC_Reset (IEnumFORMATETC)
1750  *
1751  * Standard enumerator members for IEnumFORMATETC
1752  */
1753 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Reset(LPENUMFORMATETC iface)
1754 {
1755   ICOM_THIS(IEnumFORMATETCImpl,iface);
1756   TRACE("(%p)->()\n", This);
1757
1758   This->posFmt = 0;
1759   return S_OK;
1760 }
1761
1762 /************************************************************************
1763  * OLEClipbrd_IEnumFORMATETC_Clone (IEnumFORMATETC)
1764  *
1765  * Standard enumerator members for IEnumFORMATETC
1766  */
1767 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Clone
1768   (LPENUMFORMATETC iface, LPENUMFORMATETC* ppenum)
1769 {
1770   ICOM_THIS(IEnumFORMATETCImpl,iface);
1771   HRESULT hr = S_OK;
1772
1773   TRACE("(%p)->(ppenum=%p)\n", This, ppenum);
1774
1775   if ( !ppenum )
1776     return E_INVALIDARG;
1777
1778   *ppenum = OLEClipbrd_IEnumFORMATETC_Construct(This->countFmt,
1779                                                 This->pFmt,
1780                                                 This->pUnkDataObj);
1781
1782   if (FAILED( hr = IEnumFORMATETC_AddRef(*ppenum)))
1783     return ( hr );
1784
1785   return (*ppenum) ? S_OK : E_OUTOFMEMORY;
1786 }