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