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