ole32: AddRef does not return an HRESULT. Have the constructor create the object...
[wine.git] / dlls / ole32 / clipboard.c
blob9815749c94476063f906f748a6e816f63dd4fa16
1 /*
2 * OLE 2 clipboard support
4 * Copyright 1999 Noel Borthwick <noel@macadamian.com>
5 * Copyright 2000 Abey George <abey@macadamian.com>
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.
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.
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
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:
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.
37 * 2. OleGetClipboard called without previous OleSetClipboard. Here the internal
38 * IDataObject functionality wraps around the WIN32 clipboard API.
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.
44 * Implementation references : Inside OLE 2'nd edition by Kraig Brockschmidt
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.
61 #include <assert.h>
62 #include <stdarg.h>
63 #include <string.h>
65 #define COBJMACROS
66 #define NONAMELESSUNION
67 #define NONAMELESSSTRUCT
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"
79 #include "storage32.h"
81 #include "compobj_private.h"
83 WINE_DEFAULT_DEBUG_CHANNEL(ole);
85 #define HANDLE_ERROR(err) do { hr = err; TRACE("(HRESULT=%x)\n", (HRESULT)err); goto CLEANUP; } while (0)
88 /****************************************************************************
89 * ole_clipbrd
91 struct ole_clipbrd
93 const IDataObjectVtbl* lpvtbl; /* Exposed IDataObject vtable */
95 LONG ref;
97 HWND hWndClipboard; /* Hidden clipboard window */
98 IDataObject* pIDataObjectSrc; /* Source object passed to OleSetClipboard */
101 typedef struct ole_clipbrd ole_clipbrd;
103 static inline ole_clipbrd *impl_from_IDataObject(IDataObject *iface)
105 return (ole_clipbrd*)((char*)iface - FIELD_OFFSET(ole_clipbrd, lpvtbl));
108 typedef struct PresentationDataHeader
110 BYTE unknown1[28];
111 DWORD dwObjectExtentX;
112 DWORD dwObjectExtentY;
113 DWORD dwSize;
114 } PresentationDataHeader;
117 * The one and only ole_clipbrd object which is created by OLEClipbrd_Initialize()
119 static ole_clipbrd* theOleClipboard;
123 * Name of our registered OLE clipboard window class
125 static const CHAR OLEClipbrd_WNDCLASS[] = "CLIPBRDWNDCLASS";
127 static UINT dataobject_clipboard_format;
128 static UINT ole_priv_data_clipboard_format;
130 /* Structure of 'Ole Private Data' clipboard format */
131 typedef struct
133 FORMATETC fmtetc;
134 DWORD first_use; /* Has this cf been added to the list already */
135 DWORD unk[2];
136 } ole_priv_data_entry;
138 typedef struct
140 DWORD unk1;
141 DWORD size; /* in bytes of the entire structure */
142 DWORD unk2;
143 DWORD count; /* no. of format entries */
144 DWORD unk3[2];
145 ole_priv_data_entry entries[1]; /* array of size count */
146 /* then follows any DVTARGETDEVICE structures referenced in the FORMATETCs */
147 } ole_priv_data;
149 /*---------------------------------------------------------------------*
150 * Implementation of the internal IEnumFORMATETC interface returned by
151 * the OLE clipboard's IDataObject.
152 *---------------------------------------------------------------------*/
154 typedef struct enum_fmtetc
156 const IEnumFORMATETCVtbl *lpVtbl;
157 LONG ref;
159 UINT pos; /* current enumerator position */
160 UINT countFmt; /* number of EnumFORMATETC's in array */
161 LPFORMATETC pFmt; /* array of EnumFORMATETC's */
162 } enum_fmtetc;
164 static inline enum_fmtetc *impl_from_IEnumFORMATETC(IEnumFORMATETC *iface)
166 return (enum_fmtetc*)((char*)iface - FIELD_OFFSET(enum_fmtetc, lpVtbl));
169 /************************************************************************
170 * OLEClipbrd_IEnumFORMATETC_QueryInterface (IUnknown)
172 * See Windows documentation for more details on IUnknown methods.
174 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_QueryInterface
175 (LPENUMFORMATETC iface, REFIID riid, LPVOID* ppvObj)
177 enum_fmtetc *This = impl_from_IEnumFORMATETC(iface);
179 TRACE("(%p)->(IID: %s, %p)\n", This, debugstr_guid(riid), ppvObj);
181 *ppvObj = NULL;
183 if(IsEqualIID(riid, &IID_IUnknown) ||
184 IsEqualIID(riid, &IID_IEnumFORMATETC))
186 *ppvObj = iface;
189 if(*ppvObj)
191 IEnumFORMATETC_AddRef((IEnumFORMATETC*)*ppvObj);
192 TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
193 return S_OK;
196 TRACE("-- Interface: E_NOINTERFACE\n");
197 return E_NOINTERFACE;
200 /************************************************************************
201 * OLEClipbrd_IEnumFORMATETC_AddRef (IUnknown)
204 static ULONG WINAPI OLEClipbrd_IEnumFORMATETC_AddRef(LPENUMFORMATETC iface)
206 enum_fmtetc *This = impl_from_IEnumFORMATETC(iface);
207 TRACE("(%p)->(count=%u)\n",This, This->ref);
209 return InterlockedIncrement(&This->ref);
212 /************************************************************************
213 * OLEClipbrd_IEnumFORMATETC_Release (IUnknown)
215 * See Windows documentation for more details on IUnknown methods.
217 static ULONG WINAPI OLEClipbrd_IEnumFORMATETC_Release(LPENUMFORMATETC iface)
219 enum_fmtetc *This = impl_from_IEnumFORMATETC(iface);
220 ULONG ref;
222 TRACE("(%p)->(count=%u)\n",This, This->ref);
224 ref = InterlockedDecrement(&This->ref);
225 if (!ref)
227 TRACE("() - destroying IEnumFORMATETC(%p)\n",This);
228 HeapFree(GetProcessHeap(), 0, This->pFmt);
229 HeapFree(GetProcessHeap(),0,This);
231 return ref;
234 /************************************************************************
235 * OLEClipbrd_IEnumFORMATETC_Next (IEnumFORMATETC)
237 * Standard enumerator members for IEnumFORMATETC
239 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Next
240 (LPENUMFORMATETC iface, ULONG celt, FORMATETC *rgelt, ULONG *pceltFethed)
242 enum_fmtetc *This = impl_from_IEnumFORMATETC(iface);
243 UINT cfetch;
244 HRESULT hres = S_FALSE;
246 TRACE("(%p)->(pos=%u)\n", This, This->pos);
248 if (This->pos < This->countFmt)
250 cfetch = This->countFmt - This->pos;
251 if (cfetch >= celt)
253 cfetch = celt;
254 hres = S_OK;
257 memcpy(rgelt, &This->pFmt[This->pos], cfetch * sizeof(FORMATETC));
258 This->pos += cfetch;
260 else
262 cfetch = 0;
265 if (pceltFethed)
267 *pceltFethed = cfetch;
270 return hres;
273 /************************************************************************
274 * OLEClipbrd_IEnumFORMATETC_Skip (IEnumFORMATETC)
276 * Standard enumerator members for IEnumFORMATETC
278 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Skip(LPENUMFORMATETC iface, ULONG celt)
280 enum_fmtetc *This = impl_from_IEnumFORMATETC(iface);
281 TRACE("(%p)->(num=%u)\n", This, celt);
283 This->pos += celt;
284 if (This->pos > This->countFmt)
286 This->pos = This->countFmt;
287 return S_FALSE;
289 return S_OK;
292 /************************************************************************
293 * OLEClipbrd_IEnumFORMATETC_Reset (IEnumFORMATETC)
295 * Standard enumerator members for IEnumFORMATETC
297 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Reset(LPENUMFORMATETC iface)
299 enum_fmtetc *This = impl_from_IEnumFORMATETC(iface);
300 TRACE("(%p)->()\n", This);
302 This->pos = 0;
303 return S_OK;
306 static HRESULT enum_fmtetc_construct(UINT cfmt, const FORMATETC afmt[], IEnumFORMATETC **obj);
308 /************************************************************************
309 * OLEClipbrd_IEnumFORMATETC_Clone (IEnumFORMATETC)
311 * Standard enumerator members for IEnumFORMATETC
313 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Clone
314 (LPENUMFORMATETC iface, LPENUMFORMATETC* ppenum)
316 enum_fmtetc *This = impl_from_IEnumFORMATETC(iface);
317 HRESULT hr = S_OK;
319 TRACE("(%p)->(ppenum=%p)\n", This, ppenum);
321 if ( !ppenum )
322 return E_INVALIDARG;
324 hr = enum_fmtetc_construct(This->countFmt, This->pFmt, ppenum);
326 return hr;
329 static const IEnumFORMATETCVtbl efvt =
331 OLEClipbrd_IEnumFORMATETC_QueryInterface,
332 OLEClipbrd_IEnumFORMATETC_AddRef,
333 OLEClipbrd_IEnumFORMATETC_Release,
334 OLEClipbrd_IEnumFORMATETC_Next,
335 OLEClipbrd_IEnumFORMATETC_Skip,
336 OLEClipbrd_IEnumFORMATETC_Reset,
337 OLEClipbrd_IEnumFORMATETC_Clone
340 /************************************************************************
341 * enum_fmtetc_construct
343 * Creates an IEnumFORMATETC enumerator from an array of FORMATETC
344 * Structures.
346 static HRESULT enum_fmtetc_construct(UINT cfmt, const FORMATETC afmt[], IEnumFORMATETC **obj)
348 enum_fmtetc* ef;
349 DWORD size=cfmt * sizeof(FORMATETC);
351 *obj = NULL;
352 ef = HeapAlloc(GetProcessHeap(), 0, sizeof(*ef));
353 if (!ef) return E_OUTOFMEMORY;
355 ef->ref = 1;
356 ef->lpVtbl = &efvt;
358 ef->pos = 0;
359 ef->countFmt = cfmt;
360 ef->pFmt = HeapAlloc(GetProcessHeap(), 0, size);
361 if (ef->pFmt)
362 memcpy(ef->pFmt, afmt, size);
363 else
365 HeapFree(GetProcessHeap(), 0, ef);
366 return E_OUTOFMEMORY;
369 TRACE("(%p)->()\n",ef);
370 *obj = (IEnumFORMATETC *)ef;
371 return S_OK;
374 /***********************************************************************
375 * OLEClipbrd_GlobalDupMem( HGLOBAL )
376 * Helper method to duplicate an HGLOBAL chunk of memory
378 static HGLOBAL OLEClipbrd_GlobalDupMem( HGLOBAL hGlobalSrc )
380 HGLOBAL hGlobalDest;
381 PVOID pGlobalSrc, pGlobalDest;
382 DWORD cBytes;
384 if ( !hGlobalSrc )
385 return 0;
387 cBytes = GlobalSize(hGlobalSrc);
388 if ( 0 == cBytes )
389 return 0;
391 hGlobalDest = GlobalAlloc( GMEM_DDESHARE|GMEM_MOVEABLE,
392 cBytes );
393 if ( !hGlobalDest )
394 return 0;
396 pGlobalSrc = GlobalLock(hGlobalSrc);
397 pGlobalDest = GlobalLock(hGlobalDest);
398 if ( !pGlobalSrc || !pGlobalDest )
400 GlobalFree(hGlobalDest);
401 return 0;
404 memcpy(pGlobalDest, pGlobalSrc, cBytes);
406 GlobalUnlock(hGlobalSrc);
407 GlobalUnlock(hGlobalDest);
409 return hGlobalDest;
412 #define MAX_CLIPFORMAT_NAME 80
414 /***********************************************************************
415 * OLEClipbrd_RenderFormat(LPFORMATETC)
416 * Render the clipboard data. Note that this call will delegate to the
417 * source data object.
418 * Note: This function assumes it is passed an HGLOBAL format to render.
420 static HRESULT OLEClipbrd_RenderFormat(IDataObject *pIDataObject, LPFORMATETC pFormatetc)
422 STGMEDIUM std;
423 HGLOBAL hDup;
424 HRESULT hr = S_OK;
425 char szFmtName[MAX_CLIPFORMAT_NAME];
426 ILockBytes *ptrILockBytes = 0;
427 HGLOBAL hStorage = 0;
429 if (!GetClipboardFormatNameA(pFormatetc->cfFormat, szFmtName, MAX_CLIPFORMAT_NAME))
430 szFmtName[0] = '\0';
432 /* If embed source */
433 if (!strcmp(szFmtName, CF_EMBEDSOURCE))
435 memset(&std, 0, sizeof(STGMEDIUM));
436 std.tymed = pFormatetc->tymed = TYMED_ISTORAGE;
438 hStorage = GlobalAlloc(GMEM_SHARE|GMEM_MOVEABLE, 0);
439 if (hStorage == NULL)
440 HANDLE_ERROR( E_OUTOFMEMORY );
441 hr = CreateILockBytesOnHGlobal(hStorage, FALSE, &ptrILockBytes);
442 hr = StgCreateDocfileOnILockBytes(ptrILockBytes, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &std.u.pstg);
444 if (FAILED(hr = IDataObject_GetDataHere(theOleClipboard->pIDataObjectSrc, pFormatetc, &std)))
446 WARN("() : IDataObject_GetDataHere failed to render clipboard data! (%x)\n", hr);
447 GlobalFree(hStorage);
448 return hr;
451 if (1) /* check whether the presentation data is already -not- present */
453 FORMATETC fmt2;
454 STGMEDIUM std2;
455 METAFILEPICT *mfp = 0;
457 fmt2.cfFormat = CF_METAFILEPICT;
458 fmt2.ptd = 0;
459 fmt2.dwAspect = DVASPECT_CONTENT;
460 fmt2.lindex = -1;
461 fmt2.tymed = TYMED_MFPICT;
463 memset(&std2, 0, sizeof(STGMEDIUM));
464 std2.tymed = TYMED_MFPICT;
466 /* Get the metafile picture out of it */
468 if (SUCCEEDED(hr = IDataObject_GetData(theOleClipboard->pIDataObjectSrc, &fmt2, &std2)))
470 mfp = GlobalLock(std2.u.hGlobal);
473 if (mfp)
475 OLECHAR name[]={ 2, 'O', 'l', 'e', 'P', 'r', 'e', 's', '0', '0', '0', 0};
476 IStream *pStream = 0;
477 void *mfBits;
478 PresentationDataHeader pdh;
479 INT nSize;
480 CLSID clsID;
481 LPOLESTR strProgID;
482 CHAR strOleTypeName[51];
483 BYTE OlePresStreamHeader [] =
485 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00,
486 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
487 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
488 0x00, 0x00, 0x00, 0x00
491 nSize = GetMetaFileBitsEx(mfp->hMF, 0, NULL);
493 memset(&pdh, 0, sizeof(PresentationDataHeader));
494 memcpy(&pdh, OlePresStreamHeader, sizeof(OlePresStreamHeader));
496 pdh.dwObjectExtentX = mfp->xExt;
497 pdh.dwObjectExtentY = mfp->yExt;
498 pdh.dwSize = nSize;
500 hr = IStorage_CreateStream(std.u.pstg, name, STGM_CREATE|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, 0, &pStream);
502 hr = IStream_Write(pStream, &pdh, sizeof(PresentationDataHeader), NULL);
504 mfBits = HeapAlloc(GetProcessHeap(), 0, nSize);
505 nSize = GetMetaFileBitsEx(mfp->hMF, nSize, mfBits);
507 hr = IStream_Write(pStream, mfBits, nSize, NULL);
509 IStream_Release(pStream);
511 HeapFree(GetProcessHeap(), 0, mfBits);
513 GlobalUnlock(std2.u.hGlobal);
515 ReadClassStg(std.u.pstg, &clsID);
516 ProgIDFromCLSID(&clsID, &strProgID);
518 WideCharToMultiByte( CP_ACP, 0, strProgID, -1, strOleTypeName, sizeof(strOleTypeName), NULL, NULL );
519 OLECONVERT_CreateOleStream(std.u.pstg);
520 OLECONVERT_CreateCompObjStream(std.u.pstg, strOleTypeName);
524 else
526 if (FAILED(hr = IDataObject_GetData(pIDataObject, pFormatetc, &std)))
528 WARN("() : IDataObject_GetData failed to render clipboard data! (%x)\n", hr);
529 GlobalFree(hStorage);
530 return hr;
533 /* To put a copy back on the clipboard */
535 hStorage = std.u.hGlobal;
539 * Put a copy of the rendered data back on the clipboard
542 if ( !(hDup = OLEClipbrd_GlobalDupMem(hStorage)) )
543 HANDLE_ERROR( E_OUTOFMEMORY );
545 if ( !SetClipboardData( pFormatetc->cfFormat, hDup ) )
547 GlobalFree(hDup);
548 WARN("() : Failed to set rendered clipboard data into clipboard!\n");
551 CLEANUP:
553 ReleaseStgMedium(&std);
555 return hr;
559 /***********************************************************************
560 * OLEClipbrd_WndProc(HWND, unsigned, WORD, LONG)
561 * Processes messages sent to the OLE clipboard window.
562 * Note that we will intercept messages in our WndProc only when data
563 * has been placed in the clipboard via OleSetClipboard().
564 * i.e. Only when OLE owns the windows clipboard.
566 static LRESULT CALLBACK OLEClipbrd_WndProc
567 (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
569 switch (message)
572 * WM_RENDERFORMAT
573 * We receive this message to allow us to handle delayed rendering of
574 * a specific clipboard format when an application requests data in
575 * that format by calling GetClipboardData.
576 * (Recall that in OleSetClipboard, we used SetClipboardData to
577 * make all HGLOBAL formats supported by the source IDataObject
578 * available using delayed rendering)
579 * On receiving this message we must actually render the data in the
580 * specified format and place it on the clipboard by calling the
581 * SetClipboardData function.
583 case WM_RENDERFORMAT:
585 FORMATETC rgelt;
587 ZeroMemory( &rgelt, sizeof(FORMATETC));
590 * Initialize FORMATETC to a Windows clipboard friendly format
592 rgelt.cfFormat = (UINT) wParam;
593 rgelt.dwAspect = DVASPECT_CONTENT;
594 rgelt.lindex = -1;
595 rgelt.tymed = TYMED_HGLOBAL;
597 TRACE("(): WM_RENDERFORMAT(cfFormat=%d)\n", rgelt.cfFormat);
600 * Render the clipboard data.
601 * (We must have a source data object or we wouldn't be in this WndProc)
603 OLEClipbrd_RenderFormat( (IDataObject*)&(theOleClipboard->lpvtbl), &rgelt );
605 break;
609 * WM_RENDERALLFORMATS
610 * Sent before the clipboard owner window is destroyed.
611 * We should receive this message only when OleUninitialize is called
612 * while we have an IDataObject in the clipboard.
613 * For the content of the clipboard to remain available to other
614 * applications, we must render data in all the formats the source IDataObject
615 * is capable of generating, and place the data on the clipboard by calling
616 * SetClipboardData.
618 case WM_RENDERALLFORMATS:
620 IEnumFORMATETC* penumFormatetc = NULL;
621 FORMATETC rgelt;
623 TRACE("(): WM_RENDERALLFORMATS\n");
626 * Render all HGLOBAL formats supported by the source into
627 * the windows clipboard.
629 if ( FAILED( IDataObject_EnumFormatEtc( (IDataObject*)&(theOleClipboard->lpvtbl),
630 DATADIR_GET, &penumFormatetc) ) )
632 WARN("(): WM_RENDERALLFORMATS failed to retrieve EnumFormatEtc!\n");
633 return 0;
636 while ( S_OK == IEnumFORMATETC_Next(penumFormatetc, 1, &rgelt, NULL) )
638 if ( rgelt.tymed == TYMED_HGLOBAL )
641 * Render the clipboard data.
643 if ( FAILED(OLEClipbrd_RenderFormat( (IDataObject*)&(theOleClipboard->lpvtbl), &rgelt )) )
644 continue;
646 TRACE("(): WM_RENDERALLFORMATS(cfFormat=%d)\n", rgelt.cfFormat);
650 IEnumFORMATETC_Release(penumFormatetc);
652 break;
656 * WM_DESTROYCLIPBOARD
657 * This is sent by EmptyClipboard before the clipboard is emptied.
658 * We should release any IDataObject we are holding onto when we receive
659 * this message, since it indicates that the OLE clipboard should be empty
660 * from this point on.
662 case WM_DESTROYCLIPBOARD:
664 TRACE("(): WM_DESTROYCLIPBOARD\n");
666 * Release the data object we are holding on to
668 if ( theOleClipboard->pIDataObjectSrc )
670 IDataObject_Release(theOleClipboard->pIDataObjectSrc);
671 theOleClipboard->pIDataObjectSrc = NULL;
673 break;
677 case WM_ASKCBFORMATNAME:
678 case WM_CHANGECBCHAIN:
679 case WM_DRAWCLIPBOARD:
680 case WM_SIZECLIPBOARD:
681 case WM_HSCROLLCLIPBOARD:
682 case WM_VSCROLLCLIPBOARD:
683 case WM_PAINTCLIPBOARD:
685 default:
686 return DefWindowProcA(hWnd, message, wParam, lParam);
689 return 0;
693 /*---------------------------------------------------------------------*
694 * Implementation of the internal IDataObject interface exposed by
695 * the OLE clipboard.
696 *---------------------------------------------------------------------*/
699 /************************************************************************
700 * OLEClipbrd_IDataObject_QueryInterface (IUnknown)
702 * See Windows documentation for more details on IUnknown methods.
704 static HRESULT WINAPI OLEClipbrd_IDataObject_QueryInterface(
705 IDataObject* iface,
706 REFIID riid,
707 void** ppvObject)
709 ole_clipbrd *This = impl_from_IDataObject(iface);
710 TRACE("(%p)->(IID:%s, %p)\n", This, debugstr_guid(riid), ppvObject);
712 if ( (This==0) || (ppvObject==0) )
713 return E_INVALIDARG;
715 *ppvObject = 0;
717 if (IsEqualIID(&IID_IUnknown, riid) ||
718 IsEqualIID(&IID_IDataObject, riid))
720 *ppvObject = iface;
722 else
724 WARN( "() : asking for unsupported interface %s\n", debugstr_guid(riid));
725 return E_NOINTERFACE;
728 IUnknown_AddRef((IUnknown*)*ppvObject);
730 return S_OK;
733 /************************************************************************
734 * OLEClipbrd_IDataObject_AddRef (IUnknown)
736 * See Windows documentation for more details on IUnknown methods.
738 static ULONG WINAPI OLEClipbrd_IDataObject_AddRef(
739 IDataObject* iface)
741 ole_clipbrd *This = impl_from_IDataObject(iface);
743 TRACE("(%p)->(count=%u)\n",This, This->ref);
745 return InterlockedIncrement(&This->ref);
748 /***********************************************************************
749 * OLEClipbrd_DestroyWindow(HWND)
750 * Destroy the clipboard window and unregister its class
752 static void OLEClipbrd_DestroyWindow(HWND hwnd)
754 DestroyWindow(hwnd);
755 UnregisterClassA( OLEClipbrd_WNDCLASS, 0 );
758 static void OLEClipbrd_Destroy(ole_clipbrd* This)
760 TRACE("()\n");
762 if (!This) return;
764 theOleClipboard = NULL;
766 if ( This->hWndClipboard )
767 OLEClipbrd_DestroyWindow(This->hWndClipboard);
769 HeapFree(GetProcessHeap(), 0, This);
772 /************************************************************************
773 * OLEClipbrd_IDataObject_Release (IUnknown)
775 * See Windows documentation for more details on IUnknown methods.
777 static ULONG WINAPI OLEClipbrd_IDataObject_Release(
778 IDataObject* iface)
780 ole_clipbrd *This = impl_from_IDataObject(iface);
781 ULONG ref;
783 TRACE("(%p)->(count=%u)\n",This, This->ref);
785 ref = InterlockedDecrement(&This->ref);
787 if (ref == 0)
789 OLEClipbrd_Destroy(This);
792 return ref;
796 /************************************************************************
797 * OLEClipbrd_IDataObject_GetData (IDataObject)
799 * The OLE Clipboard's implementation of this method delegates to
800 * a data source if there is one or wraps around the windows clipboard
802 * See Windows documentation for more details on IDataObject methods.
804 static HRESULT WINAPI OLEClipbrd_IDataObject_GetData(
805 IDataObject* iface,
806 LPFORMATETC pformatetcIn,
807 STGMEDIUM* pmedium)
809 HANDLE hData = 0;
810 BOOL bClipboardOpen = FALSE;
811 HRESULT hr = S_OK;
812 LPVOID src;
813 ole_clipbrd *This = impl_from_IDataObject(iface);
815 TRACE("(%p,%p,%p)\n", iface, pformatetcIn, pmedium);
817 if ( !pformatetcIn || !pmedium )
818 return E_INVALIDARG;
821 * If we have a data source placed on the clipboard (via OleSetClipboard)
822 * simply delegate to the source object's QueryGetData
823 * NOTE: This code assumes that the IDataObject is in the same address space!
824 * We will need to add marshalling support when Wine handles multiple processes.
826 if ( This->pIDataObjectSrc )
828 return IDataObject_GetData(This->pIDataObjectSrc, pformatetcIn, pmedium);
831 if ( pformatetcIn->lindex != -1 )
832 return DV_E_FORMATETC;
834 if ( (pformatetcIn->tymed & TYMED_HGLOBAL) != TYMED_HGLOBAL )
835 return DV_E_TYMED;
837 if ( pformatetcIn->dwAspect != DVASPECT_CONTENT )
838 return DV_E_DVASPECT;
842 * Otherwise, get the data from the windows clipboard using GetClipboardData
844 if ( !(bClipboardOpen = OpenClipboard(theOleClipboard->hWndClipboard)) )
845 HANDLE_ERROR( CLIPBRD_E_CANT_OPEN );
847 hData = GetClipboardData(pformatetcIn->cfFormat);
849 /* Must make a copy of global handle returned by GetClipboardData; it
850 * is not valid after we call CloseClipboard
851 * Application is responsible for freeing the memory (Forte Agent does this)
853 src = GlobalLock(hData);
854 if(src) {
855 LPVOID dest;
856 ULONG size;
857 HANDLE hDest;
859 size = GlobalSize(hData);
860 hDest = GlobalAlloc(GHND, size);
861 dest = GlobalLock(hDest);
862 memcpy(dest, src, size);
863 GlobalUnlock(hDest);
864 GlobalUnlock(hData);
865 hData = hDest;
869 * Return the clipboard data in the storage medium structure
871 pmedium->tymed = (hData == 0) ? TYMED_NULL : TYMED_HGLOBAL;
872 pmedium->u.hGlobal = hData;
873 pmedium->pUnkForRelease = NULL;
875 hr = S_OK;
877 CLEANUP:
879 * Close Windows clipboard
881 if ( bClipboardOpen && !CloseClipboard() )
882 hr = CLIPBRD_E_CANT_CLOSE;
884 if ( FAILED(hr) )
885 return hr;
886 return (hData == 0) ? DV_E_FORMATETC : S_OK;
889 static HRESULT WINAPI OLEClipbrd_IDataObject_GetDataHere(
890 IDataObject* iface,
891 LPFORMATETC pformatetc,
892 STGMEDIUM* pmedium)
894 FIXME(": Stub\n");
895 return E_NOTIMPL;
898 /************************************************************************
899 * OLEClipbrd_IDataObject_QueryGetData (IDataObject)
901 * The OLE Clipboard's implementation of this method delegates to
902 * a data source if there is one or wraps around the windows clipboard
903 * function IsClipboardFormatAvailable() otherwise.
905 * See Windows documentation for more details on IDataObject methods.
907 static HRESULT WINAPI OLEClipbrd_IDataObject_QueryGetData(
908 IDataObject* iface,
909 LPFORMATETC pformatetc)
911 TRACE("(%p, %p)\n", iface, pformatetc);
913 if (!pformatetc)
914 return E_INVALIDARG;
916 if ( pformatetc->dwAspect != DVASPECT_CONTENT )
917 return DV_E_FORMATETC;
919 if ( pformatetc->lindex != -1 )
920 return DV_E_FORMATETC;
923 * Delegate to the Windows clipboard function IsClipboardFormatAvailable
925 return (IsClipboardFormatAvailable(pformatetc->cfFormat)) ? S_OK : DV_E_CLIPFORMAT;
928 /************************************************************************
929 * OLEClipbrd_IDataObject_GetCanonicalFormatEtc (IDataObject)
931 * See Windows documentation for more details on IDataObject methods.
933 static HRESULT WINAPI OLEClipbrd_IDataObject_GetCanonicalFormatEtc(
934 IDataObject* iface,
935 LPFORMATETC pformatectIn,
936 LPFORMATETC pformatetcOut)
938 TRACE("(%p, %p, %p)\n", iface, pformatectIn, pformatetcOut);
940 if ( !pformatectIn || !pformatetcOut )
941 return E_INVALIDARG;
943 *pformatetcOut = *pformatectIn;
944 return DATA_S_SAMEFORMATETC;
947 /************************************************************************
948 * OLEClipbrd_IDataObject_SetData (IDataObject)
950 * The OLE Clipboard's does not implement this method
952 * See Windows documentation for more details on IDataObject methods.
954 static HRESULT WINAPI OLEClipbrd_IDataObject_SetData(
955 IDataObject* iface,
956 LPFORMATETC pformatetc,
957 STGMEDIUM* pmedium,
958 BOOL fRelease)
960 TRACE("\n");
961 return E_NOTIMPL;
964 /************************************************************************
965 * OLEClipbrd_IDataObject_EnumFormatEtc (IDataObject)
967 * See Windows documentation for more details on IDataObject methods.
969 static HRESULT WINAPI OLEClipbrd_IDataObject_EnumFormatEtc(
970 IDataObject* iface,
971 DWORD dwDirection,
972 IEnumFORMATETC** ppenumFormatEtc)
974 HRESULT hr = S_OK;
975 FORMATETC *afmt = NULL;
976 int cfmt, i;
977 UINT format;
978 BOOL bClipboardOpen;
979 ole_clipbrd *This = impl_from_IDataObject(iface);
981 TRACE("(%p, %x, %p)\n", iface, dwDirection, ppenumFormatEtc);
984 * If we have a data source placed on the clipboard (via OleSetClipboard)
985 * simply delegate to the source object's EnumFormatEtc
987 if ( This->pIDataObjectSrc )
989 return IDataObject_EnumFormatEtc(This->pIDataObjectSrc,
990 dwDirection, ppenumFormatEtc);
994 * Otherwise we must provide our own enumerator which wraps around the
995 * Windows clipboard function EnumClipboardFormats
997 if ( !ppenumFormatEtc )
998 return E_INVALIDARG;
1000 if ( dwDirection != DATADIR_GET ) /* IDataObject_SetData not implemented */
1001 return E_NOTIMPL;
1004 * Store all current clipboard formats in an array of FORMATETC's,
1005 * and create an IEnumFORMATETC enumerator from this list.
1007 cfmt = CountClipboardFormats();
1008 afmt = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1009 sizeof(FORMATETC) * cfmt);
1011 * Open the Windows clipboard, associating it with our hidden window
1013 if ( !(bClipboardOpen = OpenClipboard(This->hWndClipboard)) )
1014 HANDLE_ERROR( CLIPBRD_E_CANT_OPEN );
1017 * Store all current clipboard formats in an array of FORMATETC's
1018 * TODO: Handle TYMED_IStorage media which were put on the clipboard
1019 * by copying the storage into global memory. We must convert this
1020 * TYMED_HGLOBAL back to TYMED_IStorage.
1022 for (i = 0, format = 0; i < cfmt; i++)
1024 format = EnumClipboardFormats(format);
1025 if (!format) /* Failed! */
1027 ERR("EnumClipboardFormats failed to return format!\n");
1028 HANDLE_ERROR( E_FAIL );
1031 /* Init the FORMATETC struct */
1032 afmt[i].cfFormat = format;
1033 afmt[i].ptd = NULL;
1034 afmt[i].dwAspect = DVASPECT_CONTENT;
1035 afmt[i].lindex = -1;
1036 afmt[i].tymed = TYMED_HGLOBAL;
1039 hr = enum_fmtetc_construct( cfmt, afmt, ppenumFormatEtc );
1040 if (FAILED(hr))
1041 HANDLE_ERROR( hr );
1043 CLEANUP:
1045 * Free the array of FORMATETC's
1047 HeapFree(GetProcessHeap(), 0, afmt);
1050 * Close Windows clipboard
1052 if ( bClipboardOpen && !CloseClipboard() )
1053 hr = CLIPBRD_E_CANT_CLOSE;
1055 return hr;
1058 /************************************************************************
1059 * OLEClipbrd_IDataObject_DAdvise (IDataObject)
1061 * The OLE Clipboard's does not implement this method
1063 * See Windows documentation for more details on IDataObject methods.
1065 static HRESULT WINAPI OLEClipbrd_IDataObject_DAdvise(
1066 IDataObject* iface,
1067 FORMATETC* pformatetc,
1068 DWORD advf,
1069 IAdviseSink* pAdvSink,
1070 DWORD* pdwConnection)
1072 TRACE("\n");
1073 return E_NOTIMPL;
1076 /************************************************************************
1077 * OLEClipbrd_IDataObject_DUnadvise (IDataObject)
1079 * The OLE Clipboard's does not implement this method
1081 * See Windows documentation for more details on IDataObject methods.
1083 static HRESULT WINAPI OLEClipbrd_IDataObject_DUnadvise(
1084 IDataObject* iface,
1085 DWORD dwConnection)
1087 TRACE("\n");
1088 return E_NOTIMPL;
1091 /************************************************************************
1092 * OLEClipbrd_IDataObject_EnumDAdvise (IDataObject)
1094 * The OLE Clipboard does not implement this method
1096 * See Windows documentation for more details on IDataObject methods.
1098 static HRESULT WINAPI OLEClipbrd_IDataObject_EnumDAdvise(
1099 IDataObject* iface,
1100 IEnumSTATDATA** ppenumAdvise)
1102 TRACE("\n");
1103 return E_NOTIMPL;
1106 static const IDataObjectVtbl OLEClipbrd_IDataObject_VTable =
1108 OLEClipbrd_IDataObject_QueryInterface,
1109 OLEClipbrd_IDataObject_AddRef,
1110 OLEClipbrd_IDataObject_Release,
1111 OLEClipbrd_IDataObject_GetData,
1112 OLEClipbrd_IDataObject_GetDataHere,
1113 OLEClipbrd_IDataObject_QueryGetData,
1114 OLEClipbrd_IDataObject_GetCanonicalFormatEtc,
1115 OLEClipbrd_IDataObject_SetData,
1116 OLEClipbrd_IDataObject_EnumFormatEtc,
1117 OLEClipbrd_IDataObject_DAdvise,
1118 OLEClipbrd_IDataObject_DUnadvise,
1119 OLEClipbrd_IDataObject_EnumDAdvise
1122 /*---------------------------------------------------------------------*
1123 * Internal implementation methods for the OLE clipboard
1124 *---------------------------------------------------------------------*/
1126 /*********************************************************
1127 * Construct the OLEClipbrd class.
1129 static ole_clipbrd* OLEClipbrd_Construct(void)
1131 ole_clipbrd* This;
1133 This = HeapAlloc( GetProcessHeap(), 0, sizeof(*This) );
1134 if (!This) return NULL;
1136 This->lpvtbl = &OLEClipbrd_IDataObject_VTable;
1137 This->ref = 1;
1139 This->hWndClipboard = NULL;
1140 This->pIDataObjectSrc = NULL;
1142 theOleClipboard = This;
1143 return This;
1146 static void register_clipboard_formats(void)
1148 static const WCHAR DataObjectW[] = { 'D','a','t','a','O','b','j','e','c','t',0 };
1149 static const WCHAR OlePrivateDataW[] = { 'O','l','e',' ','P','r','i','v','a','t','e',' ','D','a','t','a',0 };
1151 if(!dataobject_clipboard_format)
1152 dataobject_clipboard_format = RegisterClipboardFormatW(DataObjectW);
1153 if(!ole_priv_data_clipboard_format)
1154 ole_priv_data_clipboard_format = RegisterClipboardFormatW(OlePrivateDataW);
1157 /***********************************************************************
1158 * OLEClipbrd_Initialize()
1159 * Initializes the OLE clipboard.
1161 void OLEClipbrd_Initialize(void)
1163 register_clipboard_formats();
1165 if ( !theOleClipboard )
1167 TRACE("()\n");
1168 theOleClipboard = OLEClipbrd_Construct();
1173 /***********************************************************************
1174 * OLEClipbrd_UnInitialize()
1175 * Un-Initializes the OLE clipboard
1177 void OLEClipbrd_UnInitialize(void)
1179 TRACE("()\n");
1181 * Destroy the clipboard if no one holds a reference to us.
1182 * Note that the clipboard was created with a reference count of 1.
1184 if ( theOleClipboard && (theOleClipboard->ref <= 1) )
1186 OLEClipbrd_Destroy( theOleClipboard );
1188 else
1190 WARN( "() : OLEClipbrd_UnInitialize called while client holds an IDataObject reference!\n");
1194 /***********************************************************************
1195 * OLEClipbrd_CreateWindow()
1196 * Create the clipboard window
1198 static HWND OLEClipbrd_CreateWindow(void)
1200 HWND hwnd = 0;
1201 WNDCLASSEXA wcex;
1204 * Register the clipboard window class if necessary
1206 ZeroMemory( &wcex, sizeof(WNDCLASSEXA));
1208 wcex.cbSize = sizeof(WNDCLASSEXA);
1209 /* Windows creates this class with a style mask of 0
1210 * We don't bother doing this since the FindClassByAtom code
1211 * would have to be changed to deal with this idiosyncrasy. */
1212 wcex.style = CS_GLOBALCLASS;
1213 wcex.lpfnWndProc = OLEClipbrd_WndProc;
1214 wcex.hInstance = 0;
1215 wcex.lpszClassName = OLEClipbrd_WNDCLASS;
1217 RegisterClassExA(&wcex);
1220 * Create a hidden window to receive OLE clipboard messages
1224 * If we need to store state info we can store it here.
1225 * For now we don't need this functionality.
1226 * ClipboardWindowInfo clipboardInfo;
1227 * ZeroMemory( &trackerInfo, sizeof(ClipboardWindowInfo));
1230 hwnd = CreateWindowA(OLEClipbrd_WNDCLASS,
1231 "ClipboardWindow",
1232 WS_POPUP | WS_CLIPSIBLINGS | WS_OVERLAPPED,
1233 CW_USEDEFAULT, CW_USEDEFAULT,
1234 CW_USEDEFAULT, CW_USEDEFAULT,
1238 0 /*(LPVOID)&clipboardInfo */);
1240 return hwnd;
1243 static inline BOOL is_format_in_list(ole_priv_data_entry *entries, DWORD num, UINT cf)
1245 DWORD i;
1246 for(i = 0; i < num; i++)
1247 if(entries[i].fmtetc.cfFormat == cf)
1248 return TRUE;
1250 return FALSE;
1253 /*********************************************************************
1254 * set_clipboard_formats
1256 * Enumerate all HGLOBAL formats supported by the source and make
1257 * those formats available using delayed rendering using SetClipboardData.
1259 * TODO: We need to additionally handle TYMED_IStorage and
1260 * TYMED_IStream data by copying into global memory.
1262 static HRESULT set_clipboard_formats(IDataObject *data)
1264 HRESULT hr;
1265 FORMATETC fmt;
1266 IEnumFORMATETC *enum_fmt;
1267 HGLOBAL priv_data_handle;
1268 DWORD target_offset;
1269 ole_priv_data *priv_data;
1270 DWORD count = 0, needed = sizeof(*priv_data), idx;
1272 hr = IDataObject_EnumFormatEtc(data, DATADIR_GET, &enum_fmt);
1273 if(FAILED(hr)) return hr;
1275 while(IEnumFORMATETC_Next(enum_fmt, 1, &fmt, NULL) == S_OK)
1277 count++;
1278 needed += sizeof(priv_data->entries[0]);
1279 if(fmt.ptd)
1281 needed += fmt.ptd->tdSize;
1282 CoTaskMemFree(fmt.ptd);
1286 /* Windows pads the list with two empty ole_priv_data_entries, one
1287 * after the entries array and one after the target device data.
1288 * Allocating with zero init to zero these pads. */
1290 needed += sizeof(priv_data->entries[0]); /* initialisation of needed includes one of these. */
1291 priv_data_handle = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE | GMEM_ZEROINIT, needed);
1292 priv_data = GlobalLock(priv_data_handle);
1294 priv_data->unk1 = 0;
1295 priv_data->size = needed;
1296 priv_data->unk2 = 1;
1297 priv_data->count = count;
1298 priv_data->unk3[0] = 0;
1299 priv_data->unk3[1] = 0;
1301 IEnumFORMATETC_Reset(enum_fmt);
1303 idx = 0;
1304 target_offset = FIELD_OFFSET(ole_priv_data, entries[count + 1]); /* count entries + one pad. */
1306 while(IEnumFORMATETC_Next(enum_fmt, 1, &fmt, NULL) == S_OK)
1308 if (fmt.tymed == TYMED_HGLOBAL)
1310 char fmt_name[80];
1311 TRACE("(cfFormat=%d:%s)\n", fmt.cfFormat,
1312 GetClipboardFormatNameA(fmt.cfFormat, fmt_name, sizeof(fmt_name)-1) ? fmt_name : "");
1314 SetClipboardData(fmt.cfFormat, NULL);
1317 priv_data->entries[idx].fmtetc = fmt;
1318 if(fmt.ptd)
1320 memcpy((char*)priv_data + target_offset, fmt.ptd, fmt.ptd->tdSize);
1321 priv_data->entries[idx].fmtetc.ptd = (DVTARGETDEVICE*)target_offset;
1322 target_offset += fmt.ptd->tdSize;
1323 CoTaskMemFree(fmt.ptd);
1326 priv_data->entries[idx].first_use = !is_format_in_list(priv_data->entries, idx, fmt.cfFormat);
1327 priv_data->entries[idx].unk[0] = 0;
1328 priv_data->entries[idx].unk[1] = 0;
1330 idx++;
1333 IEnumFORMATETC_Release(enum_fmt);
1335 GlobalUnlock(priv_data_handle);
1336 SetClipboardData(ole_priv_data_clipboard_format, priv_data_handle);
1338 return S_OK;
1341 /*********************************************************************
1342 * set_dataobject_format
1344 * Windows creates a 'DataObject' clipboard format that contains the
1345 * clipboard window's HWND or NULL if the Ole clipboard has been flushed.
1347 static HRESULT set_dataobject_format(HWND hwnd)
1349 HGLOBAL h = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE, sizeof(hwnd));
1350 HWND *data;
1352 if(!h) return E_OUTOFMEMORY;
1354 data = GlobalLock(h);
1355 *data = hwnd;
1356 GlobalUnlock(h);
1358 if(!SetClipboardData(dataobject_clipboard_format, h))
1360 GlobalFree(h);
1361 return CLIPBRD_E_CANT_SET;
1364 return S_OK;
1367 /*---------------------------------------------------------------------*
1368 * Win32 OLE clipboard API
1369 *---------------------------------------------------------------------*/
1371 /***********************************************************************
1372 * OleSetClipboard [OLE32.@]
1373 * Places a pointer to the specified data object onto the clipboard,
1374 * making the data object accessible to the OleGetClipboard function.
1376 * RETURNS
1378 * S_OK IDataObject pointer placed on the clipboard
1379 * CLIPBRD_E_CANT_OPEN OpenClipboard failed
1380 * CLIPBRD_E_CANT_EMPTY EmptyClipboard failed
1381 * CLIPBRD_E_CANT_CLOSE CloseClipboard failed
1382 * CLIPBRD_E_CANT_SET SetClipboard failed
1385 HRESULT WINAPI OleSetClipboard(IDataObject* pDataObj)
1387 HRESULT hr = S_OK;
1388 BOOL bClipboardOpen = FALSE;
1389 struct oletls *info = COM_CurrentInfo();
1391 TRACE("(%p)\n", pDataObj);
1393 if(!info)
1394 WARN("Could not allocate tls\n");
1395 else
1396 if(!info->ole_inits)
1397 return CO_E_NOTINITIALIZED;
1400 * Make sure we have a clipboard object
1402 OLEClipbrd_Initialize();
1405 * If the Ole clipboard window hasn't been created yet, create it now.
1407 if ( !theOleClipboard->hWndClipboard )
1408 theOleClipboard->hWndClipboard = OLEClipbrd_CreateWindow();
1410 if ( !theOleClipboard->hWndClipboard ) /* sanity check */
1411 HANDLE_ERROR( E_FAIL );
1414 * Open the Windows clipboard, associating it with our hidden window
1416 if ( !(bClipboardOpen = OpenClipboard(theOleClipboard->hWndClipboard)) )
1417 HANDLE_ERROR( CLIPBRD_E_CANT_OPEN );
1420 * Empty the current clipboard and make our window the clipboard owner
1421 * NOTE: This will trigger a WM_DESTROYCLIPBOARD message
1423 if ( !EmptyClipboard() )
1424 HANDLE_ERROR( CLIPBRD_E_CANT_EMPTY );
1427 * If we are already holding on to an IDataObject first release that.
1429 if ( theOleClipboard->pIDataObjectSrc )
1431 IDataObject_Release(theOleClipboard->pIDataObjectSrc);
1432 theOleClipboard->pIDataObjectSrc = NULL;
1435 /* A NULL value indicates that the clipboard should be emptied. */
1436 theOleClipboard->pIDataObjectSrc = pDataObj;
1437 if ( pDataObj )
1439 IDataObject_AddRef(theOleClipboard->pIDataObjectSrc);
1440 hr = set_clipboard_formats(pDataObj);
1441 if(FAILED(hr)) goto CLEANUP;
1444 hr = set_dataobject_format(theOleClipboard->hWndClipboard);
1446 CLEANUP:
1449 * Close Windows clipboard (It remains associated with our window)
1451 if ( bClipboardOpen && !CloseClipboard() )
1452 hr = CLIPBRD_E_CANT_CLOSE;
1455 * Release the source IDataObject if something failed
1457 if ( FAILED(hr) )
1459 if (theOleClipboard->pIDataObjectSrc)
1461 IDataObject_Release(theOleClipboard->pIDataObjectSrc);
1462 theOleClipboard->pIDataObjectSrc = NULL;
1466 return hr;
1470 /***********************************************************************
1471 * OleGetClipboard [OLE32.@]
1472 * Returns a pointer to our internal IDataObject which represents the conceptual
1473 * state of the Windows clipboard. If the current clipboard already contains
1474 * an IDataObject, our internal IDataObject will delegate to this object.
1476 HRESULT WINAPI OleGetClipboard(IDataObject** ppDataObj)
1478 HRESULT hr = S_OK;
1479 TRACE("()\n");
1482 * Make sure we have a clipboard object
1484 OLEClipbrd_Initialize();
1486 if (!theOleClipboard)
1487 return E_OUTOFMEMORY;
1489 /* Return a reference counted IDataObject */
1490 hr = IDataObject_QueryInterface( (IDataObject*)&(theOleClipboard->lpvtbl),
1491 &IID_IDataObject, (void**)ppDataObj);
1492 return hr;
1495 /******************************************************************************
1496 * OleFlushClipboard [OLE32.@]
1497 * Renders the data from the source IDataObject into the windows clipboard
1499 * TODO: OleFlushClipboard needs to additionally handle TYMED_IStorage media
1500 * by copying the storage into global memory. Subsequently the default
1501 * data object exposed through OleGetClipboard must convert this TYMED_HGLOBAL
1502 * back to TYMED_IStorage.
1504 HRESULT WINAPI OleFlushClipboard(void)
1506 IEnumFORMATETC* penumFormatetc = NULL;
1507 FORMATETC rgelt;
1508 HRESULT hr = S_OK;
1509 BOOL bClipboardOpen = FALSE;
1511 TRACE("()\n");
1513 OLEClipbrd_Initialize();
1516 * Already flushed or no source DataObject? Nothing to do.
1518 if (!theOleClipboard->pIDataObjectSrc)
1519 return S_OK;
1521 if ( !(bClipboardOpen = OpenClipboard(theOleClipboard->hWndClipboard)) )
1522 HANDLE_ERROR( CLIPBRD_E_CANT_OPEN );
1525 * Render all HGLOBAL formats supported by the source into
1526 * the windows clipboard.
1528 if ( FAILED( hr = IDataObject_EnumFormatEtc( theOleClipboard->pIDataObjectSrc,
1529 DATADIR_GET,
1530 &penumFormatetc) ))
1532 HANDLE_ERROR( hr );
1535 while ( S_OK == IEnumFORMATETC_Next(penumFormatetc, 1, &rgelt, NULL) )
1537 if ( rgelt.tymed == TYMED_HGLOBAL )
1539 CHAR szFmtName[80];
1540 TRACE("(cfFormat=%d:%s)\n", rgelt.cfFormat,
1541 GetClipboardFormatNameA(rgelt.cfFormat, szFmtName, sizeof(szFmtName)-1)
1542 ? szFmtName : "");
1544 if ( FAILED(OLEClipbrd_RenderFormat( theOleClipboard->pIDataObjectSrc, &rgelt )) )
1545 continue;
1549 IEnumFORMATETC_Release(penumFormatetc);
1551 hr = set_dataobject_format(NULL);
1553 IDataObject_Release(theOleClipboard->pIDataObjectSrc);
1554 theOleClipboard->pIDataObjectSrc = NULL;
1556 CLEANUP:
1558 if ( bClipboardOpen && !CloseClipboard() )
1559 hr = CLIPBRD_E_CANT_CLOSE;
1561 return hr;
1565 /***********************************************************************
1566 * OleIsCurrentClipboard [OLE32.@]
1568 HRESULT WINAPI OleIsCurrentClipboard(IDataObject *pDataObject)
1570 TRACE("()\n");
1572 * Make sure we have a clipboard object
1574 OLEClipbrd_Initialize();
1576 if (!theOleClipboard)
1577 return E_OUTOFMEMORY;
1579 if (pDataObject == NULL)
1580 return S_FALSE;
1582 return (pDataObject == theOleClipboard->pIDataObjectSrc) ? S_OK : S_FALSE;