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