~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Wine Cross Reference
wine/dlls/ole32/clipboard.c

Version: ~ [ wine-1.1.33 ] ~ [ wine-1.1.32 ] ~ [ wine-1.1.31 ] ~ [ wine-1.1.30 ] ~ [ wine-1.1.29 ] ~ [ wine-1.1.28 ] ~ [ wine-1.1.27 ] ~ [ wine-1.1.26 ] ~ [ wine-1.1.25 ] ~ [ wine-1.1.24 ] ~ [ wine-1.1.23 ] ~ [ wine-1.1.22 ] ~ [ wine-1.1.21 ] ~ [ wine-1.1.20 ] ~ [ wine-1.1.19 ] ~ [ wine-1.1.18 ] ~ [ wine-1.1.17 ] ~ [ wine-1.1.16 ] ~ [ wine-1.1.15 ] ~ [ wine-1.1.14 ] ~ [ wine-1.1.13 ] ~ [ wine-1.1.12 ] ~ [ wine-1.1.11 ] ~ [ wine-1.1.10 ] ~ [ wine-1.1.9 ] ~ [ wine-1.1.8 ] ~ [ wine-1.1.7 ] ~ [ wine-1.0.1 ] ~ [ wine-1.1.6 ] ~ [ wine-1.1.5 ] ~ [ wine-1.1.4 ] ~ [ wine-1.1.3 ] ~ [ wine-1.1.2 ] ~ [ wine-1.1.1 ] ~ [ wine-1.1.0 ] ~ [ wine-1.0 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.