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

~ [ 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.