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

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