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

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

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

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