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
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.