include: Get rid of the definitions for the pthread emulation.
[wine/hacks.git] / dlls / ole32 / clipboard.c
blob008e35bde251cc3c17685b54730b1e6831b19fa0
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 /****************************************************************************
109 * IEnumFORMATETC implementation
110 * DO NOT add any members before the VTables declaration!
112 typedef struct
114 /* IEnumFORMATETC VTable */
115 const IEnumFORMATETCVtbl *lpVtbl;
117 /* IEnumFORMATETC fields */
118 UINT posFmt; /* current enumerator position */
119 UINT countFmt; /* number of EnumFORMATETC's in array */
120 LPFORMATETC pFmt; /* array of EnumFORMATETC's */
123 * Reference count of this object
125 LONG ref;
128 * IUnknown implementation of the parent data object.
130 IUnknown* pUnkDataObj;
132 } IEnumFORMATETCImpl;
134 typedef struct PresentationDataHeader
136 BYTE unknown1[28];
137 DWORD dwObjectExtentX;
138 DWORD dwObjectExtentY;
139 DWORD dwSize;
140 } PresentationDataHeader;
143 * The one and only ole_clipbrd object which is created by OLEClipbrd_Initialize()
145 static ole_clipbrd* theOleClipboard;
149 * Name of our registered OLE clipboard window class
151 static const CHAR OLEClipbrd_WNDCLASS[] = "CLIPBRDWNDCLASS";
153 static UINT dataobject_clipboard_format;
156 * If we need to store state info we can store it here.
157 * For now we don't need this functionality.
159 typedef struct tagClipboardWindowInfo
161 } ClipboardWindowInfo;
164 /*---------------------------------------------------------------------*
165 * Implementation of the internal IEnumFORMATETC interface returned by
166 * the OLE clipboard's IDataObject.
167 *---------------------------------------------------------------------*/
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 IEnumFORMATETCImpl *This = (IEnumFORMATETCImpl *)iface;
179 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
182 * Since enumerators are separate objects from the parent data object
183 * we only need to support the IUnknown and IEnumFORMATETC interfaces
186 *ppvObj = NULL;
188 if(IsEqualIID(riid, &IID_IUnknown) ||
189 IsEqualIID(riid, &IID_IEnumFORMATETC))
191 *ppvObj = This;
194 if(*ppvObj)
196 IEnumFORMATETC_AddRef((IEnumFORMATETC*)*ppvObj);
197 TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
198 return S_OK;
201 TRACE("-- Interface: E_NOINTERFACE\n");
202 return E_NOINTERFACE;
205 /************************************************************************
206 * OLEClipbrd_IEnumFORMATETC_AddRef (IUnknown)
208 * Since enumerating formats only makes sense when our data object is around,
209 * we insure that it stays as long as we stay by calling our parents IUnknown
210 * for AddRef and Release. But since we are not controlled by the lifetime of
211 * the outer object, we still keep our own reference count in order to
212 * free ourselves.
214 static ULONG WINAPI OLEClipbrd_IEnumFORMATETC_AddRef(LPENUMFORMATETC iface)
216 IEnumFORMATETCImpl *This = (IEnumFORMATETCImpl *)iface;
217 TRACE("(%p)->(count=%u)\n",This, This->ref);
219 if (This->pUnkDataObj)
220 IUnknown_AddRef(This->pUnkDataObj);
222 return InterlockedIncrement(&This->ref);
225 /************************************************************************
226 * OLEClipbrd_IEnumFORMATETC_Release (IUnknown)
228 * See Windows documentation for more details on IUnknown methods.
230 static ULONG WINAPI OLEClipbrd_IEnumFORMATETC_Release(LPENUMFORMATETC iface)
232 IEnumFORMATETCImpl *This = (IEnumFORMATETCImpl *)iface;
233 ULONG ref;
235 TRACE("(%p)->(count=%u)\n",This, This->ref);
237 if (This->pUnkDataObj)
238 IUnknown_Release(This->pUnkDataObj); /* Release parent data object */
240 ref = InterlockedDecrement(&This->ref);
241 if (!ref)
243 TRACE("() - destroying IEnumFORMATETC(%p)\n",This);
244 HeapFree(GetProcessHeap(), 0, This->pFmt);
245 HeapFree(GetProcessHeap(),0,This);
247 return ref;
250 /************************************************************************
251 * OLEClipbrd_IEnumFORMATETC_Next (IEnumFORMATETC)
253 * Standard enumerator members for IEnumFORMATETC
255 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Next
256 (LPENUMFORMATETC iface, ULONG celt, FORMATETC *rgelt, ULONG *pceltFethed)
258 IEnumFORMATETCImpl *This = (IEnumFORMATETCImpl *)iface;
259 UINT cfetch;
260 HRESULT hres = S_FALSE;
262 TRACE("(%p)->(pos=%u)\n", This, This->posFmt);
264 if (This->posFmt < This->countFmt)
266 cfetch = This->countFmt - This->posFmt;
267 if (cfetch >= celt)
269 cfetch = celt;
270 hres = S_OK;
273 memcpy(rgelt, &This->pFmt[This->posFmt], cfetch * sizeof(FORMATETC));
274 This->posFmt += cfetch;
276 else
278 cfetch = 0;
281 if (pceltFethed)
283 *pceltFethed = cfetch;
286 return hres;
289 /************************************************************************
290 * OLEClipbrd_IEnumFORMATETC_Skip (IEnumFORMATETC)
292 * Standard enumerator members for IEnumFORMATETC
294 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Skip(LPENUMFORMATETC iface, ULONG celt)
296 IEnumFORMATETCImpl *This = (IEnumFORMATETCImpl *)iface;
297 TRACE("(%p)->(num=%u)\n", This, celt);
299 This->posFmt += celt;
300 if (This->posFmt > This->countFmt)
302 This->posFmt = This->countFmt;
303 return S_FALSE;
305 return S_OK;
308 /************************************************************************
309 * OLEClipbrd_IEnumFORMATETC_Reset (IEnumFORMATETC)
311 * Standard enumerator members for IEnumFORMATETC
313 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Reset(LPENUMFORMATETC iface)
315 IEnumFORMATETCImpl *This = (IEnumFORMATETCImpl *)iface;
316 TRACE("(%p)->()\n", This);
318 This->posFmt = 0;
319 return S_OK;
322 static LPENUMFORMATETC OLEClipbrd_IEnumFORMATETC_Construct(UINT cfmt, const FORMATETC afmt[],
323 LPUNKNOWN pUnkDataObj);
325 /************************************************************************
326 * OLEClipbrd_IEnumFORMATETC_Clone (IEnumFORMATETC)
328 * Standard enumerator members for IEnumFORMATETC
330 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Clone
331 (LPENUMFORMATETC iface, LPENUMFORMATETC* ppenum)
333 IEnumFORMATETCImpl *This = (IEnumFORMATETCImpl *)iface;
334 HRESULT hr = S_OK;
336 TRACE("(%p)->(ppenum=%p)\n", This, ppenum);
338 if ( !ppenum )
339 return E_INVALIDARG;
341 *ppenum = OLEClipbrd_IEnumFORMATETC_Construct(This->countFmt,
342 This->pFmt,
343 This->pUnkDataObj);
345 if (FAILED( hr = IEnumFORMATETC_AddRef(*ppenum)))
346 return ( hr );
348 return (*ppenum) ? S_OK : E_OUTOFMEMORY;
351 static const IEnumFORMATETCVtbl efvt =
353 OLEClipbrd_IEnumFORMATETC_QueryInterface,
354 OLEClipbrd_IEnumFORMATETC_AddRef,
355 OLEClipbrd_IEnumFORMATETC_Release,
356 OLEClipbrd_IEnumFORMATETC_Next,
357 OLEClipbrd_IEnumFORMATETC_Skip,
358 OLEClipbrd_IEnumFORMATETC_Reset,
359 OLEClipbrd_IEnumFORMATETC_Clone
362 /************************************************************************
363 * OLEClipbrd_IEnumFORMATETC_Construct (UINT, const FORMATETC, LPUNKNOWN)
365 * Creates an IEnumFORMATETC enumerator from an array of FORMATETC
366 * Structures. pUnkOuter is the outer unknown for reference counting only.
367 * NOTE: this does not AddRef the interface.
370 static LPENUMFORMATETC OLEClipbrd_IEnumFORMATETC_Construct(UINT cfmt, const FORMATETC afmt[],
371 LPUNKNOWN pUnkDataObj)
373 IEnumFORMATETCImpl* ef;
374 DWORD size=cfmt * sizeof(FORMATETC);
376 ef = HeapAlloc(GetProcessHeap(), 0, sizeof(IEnumFORMATETCImpl));
377 if (!ef)
378 return NULL;
380 ef->ref = 0;
381 ef->lpVtbl = &efvt;
382 ef->pUnkDataObj = pUnkDataObj;
384 ef->posFmt = 0;
385 ef->countFmt = cfmt;
386 ef->pFmt = HeapAlloc(GetProcessHeap(), 0, size);
387 if (ef->pFmt)
388 memcpy(ef->pFmt, afmt, size);
389 else
391 HeapFree(GetProcessHeap(), 0, ef);
392 return NULL;
395 TRACE("(%p)->()\n",ef);
396 return (LPENUMFORMATETC)ef;
399 /***********************************************************************
400 * OLEClipbrd_GlobalDupMem( HGLOBAL )
401 * Helper method to duplicate an HGLOBAL chunk of memory
403 static HGLOBAL OLEClipbrd_GlobalDupMem( HGLOBAL hGlobalSrc )
405 HGLOBAL hGlobalDest;
406 PVOID pGlobalSrc, pGlobalDest;
407 DWORD cBytes;
409 if ( !hGlobalSrc )
410 return 0;
412 cBytes = GlobalSize(hGlobalSrc);
413 if ( 0 == cBytes )
414 return 0;
416 hGlobalDest = GlobalAlloc( GMEM_DDESHARE|GMEM_MOVEABLE,
417 cBytes );
418 if ( !hGlobalDest )
419 return 0;
421 pGlobalSrc = GlobalLock(hGlobalSrc);
422 pGlobalDest = GlobalLock(hGlobalDest);
423 if ( !pGlobalSrc || !pGlobalDest )
425 GlobalFree(hGlobalDest);
426 return 0;
429 memcpy(pGlobalDest, pGlobalSrc, cBytes);
431 GlobalUnlock(hGlobalSrc);
432 GlobalUnlock(hGlobalDest);
434 return hGlobalDest;
437 #define MAX_CLIPFORMAT_NAME 80
439 /***********************************************************************
440 * OLEClipbrd_RenderFormat(LPFORMATETC)
441 * Render the clipboard data. Note that this call will delegate to the
442 * source data object.
443 * Note: This function assumes it is passed an HGLOBAL format to render.
445 static HRESULT OLEClipbrd_RenderFormat(IDataObject *pIDataObject, LPFORMATETC pFormatetc)
447 STGMEDIUM std;
448 HGLOBAL hDup;
449 HRESULT hr = S_OK;
450 char szFmtName[MAX_CLIPFORMAT_NAME];
451 ILockBytes *ptrILockBytes = 0;
452 HGLOBAL hStorage = 0;
454 if (!GetClipboardFormatNameA(pFormatetc->cfFormat, szFmtName, MAX_CLIPFORMAT_NAME))
455 szFmtName[0] = '\0';
457 /* If embed source */
458 if (!strcmp(szFmtName, CF_EMBEDSOURCE))
460 memset(&std, 0, sizeof(STGMEDIUM));
461 std.tymed = pFormatetc->tymed = TYMED_ISTORAGE;
463 hStorage = GlobalAlloc(GMEM_SHARE|GMEM_MOVEABLE, 0);
464 if (hStorage == NULL)
465 HANDLE_ERROR( E_OUTOFMEMORY );
466 hr = CreateILockBytesOnHGlobal(hStorage, FALSE, &ptrILockBytes);
467 hr = StgCreateDocfileOnILockBytes(ptrILockBytes, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &std.u.pstg);
469 if (FAILED(hr = IDataObject_GetDataHere(theOleClipboard->pIDataObjectSrc, pFormatetc, &std)))
471 WARN("() : IDataObject_GetDataHere failed to render clipboard data! (%x)\n", hr);
472 GlobalFree(hStorage);
473 return hr;
476 if (1) /* check whether the presentation data is already -not- present */
478 FORMATETC fmt2;
479 STGMEDIUM std2;
480 METAFILEPICT *mfp = 0;
482 fmt2.cfFormat = CF_METAFILEPICT;
483 fmt2.ptd = 0;
484 fmt2.dwAspect = DVASPECT_CONTENT;
485 fmt2.lindex = -1;
486 fmt2.tymed = TYMED_MFPICT;
488 memset(&std2, 0, sizeof(STGMEDIUM));
489 std2.tymed = TYMED_MFPICT;
491 /* Get the metafile picture out of it */
493 if (SUCCEEDED(hr = IDataObject_GetData(theOleClipboard->pIDataObjectSrc, &fmt2, &std2)))
495 mfp = GlobalLock(std2.u.hGlobal);
498 if (mfp)
500 OLECHAR name[]={ 2, 'O', 'l', 'e', 'P', 'r', 'e', 's', '0', '0', '0', 0};
501 IStream *pStream = 0;
502 void *mfBits;
503 PresentationDataHeader pdh;
504 INT nSize;
505 CLSID clsID;
506 LPOLESTR strProgID;
507 CHAR strOleTypeName[51];
508 BYTE OlePresStreamHeader [] =
510 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00,
511 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
512 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
513 0x00, 0x00, 0x00, 0x00
516 nSize = GetMetaFileBitsEx(mfp->hMF, 0, NULL);
518 memset(&pdh, 0, sizeof(PresentationDataHeader));
519 memcpy(&pdh, OlePresStreamHeader, sizeof(OlePresStreamHeader));
521 pdh.dwObjectExtentX = mfp->xExt;
522 pdh.dwObjectExtentY = mfp->yExt;
523 pdh.dwSize = nSize;
525 hr = IStorage_CreateStream(std.u.pstg, name, STGM_CREATE|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, 0, &pStream);
527 hr = IStream_Write(pStream, &pdh, sizeof(PresentationDataHeader), NULL);
529 mfBits = HeapAlloc(GetProcessHeap(), 0, nSize);
530 nSize = GetMetaFileBitsEx(mfp->hMF, nSize, mfBits);
532 hr = IStream_Write(pStream, mfBits, nSize, NULL);
534 IStream_Release(pStream);
536 HeapFree(GetProcessHeap(), 0, mfBits);
538 GlobalUnlock(std2.u.hGlobal);
540 ReadClassStg(std.u.pstg, &clsID);
541 ProgIDFromCLSID(&clsID, &strProgID);
543 WideCharToMultiByte( CP_ACP, 0, strProgID, -1, strOleTypeName, sizeof(strOleTypeName), NULL, NULL );
544 OLECONVERT_CreateOleStream(std.u.pstg);
545 OLECONVERT_CreateCompObjStream(std.u.pstg, strOleTypeName);
549 else
551 if (FAILED(hr = IDataObject_GetData(pIDataObject, pFormatetc, &std)))
553 WARN("() : IDataObject_GetData failed to render clipboard data! (%x)\n", hr);
554 GlobalFree(hStorage);
555 return hr;
558 /* To put a copy back on the clipboard */
560 hStorage = std.u.hGlobal;
564 * Put a copy of the rendered data back on the clipboard
567 if ( !(hDup = OLEClipbrd_GlobalDupMem(hStorage)) )
568 HANDLE_ERROR( E_OUTOFMEMORY );
570 if ( !SetClipboardData( pFormatetc->cfFormat, hDup ) )
572 GlobalFree(hDup);
573 WARN("() : Failed to set rendered clipboard data into clipboard!\n");
576 CLEANUP:
578 ReleaseStgMedium(&std);
580 return hr;
584 /***********************************************************************
585 * OLEClipbrd_WndProc(HWND, unsigned, WORD, LONG)
586 * Processes messages sent to the OLE clipboard window.
587 * Note that we will intercept messages in our WndProc only when data
588 * has been placed in the clipboard via OleSetClipboard().
589 * i.e. Only when OLE owns the windows clipboard.
591 static LRESULT CALLBACK OLEClipbrd_WndProc
592 (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
594 switch (message)
597 * WM_RENDERFORMAT
598 * We receive this message to allow us to handle delayed rendering of
599 * a specific clipboard format when an application requests data in
600 * that format by calling GetClipboardData.
601 * (Recall that in OleSetClipboard, we used SetClipboardData to
602 * make all HGLOBAL formats supported by the source IDataObject
603 * available using delayed rendering)
604 * On receiving this message we must actually render the data in the
605 * specified format and place it on the clipboard by calling the
606 * SetClipboardData function.
608 case WM_RENDERFORMAT:
610 FORMATETC rgelt;
612 ZeroMemory( &rgelt, sizeof(FORMATETC));
615 * Initialize FORMATETC to a Windows clipboard friendly format
617 rgelt.cfFormat = (UINT) wParam;
618 rgelt.dwAspect = DVASPECT_CONTENT;
619 rgelt.lindex = -1;
620 rgelt.tymed = TYMED_HGLOBAL;
622 TRACE("(): WM_RENDERFORMAT(cfFormat=%d)\n", rgelt.cfFormat);
625 * Render the clipboard data.
626 * (We must have a source data object or we wouldn't be in this WndProc)
628 OLEClipbrd_RenderFormat( (IDataObject*)&(theOleClipboard->lpvtbl), &rgelt );
630 break;
634 * WM_RENDERALLFORMATS
635 * Sent before the clipboard owner window is destroyed.
636 * We should receive this message only when OleUninitialize is called
637 * while we have an IDataObject in the clipboard.
638 * For the content of the clipboard to remain available to other
639 * applications, we must render data in all the formats the source IDataObject
640 * is capable of generating, and place the data on the clipboard by calling
641 * SetClipboardData.
643 case WM_RENDERALLFORMATS:
645 IEnumFORMATETC* penumFormatetc = NULL;
646 FORMATETC rgelt;
648 TRACE("(): WM_RENDERALLFORMATS\n");
651 * Render all HGLOBAL formats supported by the source into
652 * the windows clipboard.
654 if ( FAILED( IDataObject_EnumFormatEtc( (IDataObject*)&(theOleClipboard->lpvtbl),
655 DATADIR_GET, &penumFormatetc) ) )
657 WARN("(): WM_RENDERALLFORMATS failed to retrieve EnumFormatEtc!\n");
658 return 0;
661 while ( S_OK == IEnumFORMATETC_Next(penumFormatetc, 1, &rgelt, NULL) )
663 if ( rgelt.tymed == TYMED_HGLOBAL )
666 * Render the clipboard data.
668 if ( FAILED(OLEClipbrd_RenderFormat( (IDataObject*)&(theOleClipboard->lpvtbl), &rgelt )) )
669 continue;
671 TRACE("(): WM_RENDERALLFORMATS(cfFormat=%d)\n", rgelt.cfFormat);
675 IEnumFORMATETC_Release(penumFormatetc);
677 break;
681 * WM_DESTROYCLIPBOARD
682 * This is sent by EmptyClipboard before the clipboard is emptied.
683 * We should release any IDataObject we are holding onto when we receive
684 * this message, since it indicates that the OLE clipboard should be empty
685 * from this point on.
687 case WM_DESTROYCLIPBOARD:
689 TRACE("(): WM_DESTROYCLIPBOARD\n");
691 * Release the data object we are holding on to
693 if ( theOleClipboard->pIDataObjectSrc )
695 IDataObject_Release(theOleClipboard->pIDataObjectSrc);
696 theOleClipboard->pIDataObjectSrc = NULL;
698 break;
702 case WM_ASKCBFORMATNAME:
703 case WM_CHANGECBCHAIN:
704 case WM_DRAWCLIPBOARD:
705 case WM_SIZECLIPBOARD:
706 case WM_HSCROLLCLIPBOARD:
707 case WM_VSCROLLCLIPBOARD:
708 case WM_PAINTCLIPBOARD:
710 default:
711 return DefWindowProcA(hWnd, message, wParam, lParam);
714 return 0;
718 /*---------------------------------------------------------------------*
719 * Implementation of the internal IDataObject interface exposed by
720 * the OLE clipboard.
721 *---------------------------------------------------------------------*/
724 /************************************************************************
725 * OLEClipbrd_IDataObject_QueryInterface (IUnknown)
727 * See Windows documentation for more details on IUnknown methods.
729 static HRESULT WINAPI OLEClipbrd_IDataObject_QueryInterface(
730 IDataObject* iface,
731 REFIID riid,
732 void** ppvObject)
734 ole_clipbrd *This = impl_from_IDataObject(iface);
735 TRACE("(%p)->(IID:%s, %p)\n", This, debugstr_guid(riid), ppvObject);
737 if ( (This==0) || (ppvObject==0) )
738 return E_INVALIDARG;
740 *ppvObject = 0;
742 if (IsEqualIID(&IID_IUnknown, riid) ||
743 IsEqualIID(&IID_IDataObject, riid))
745 *ppvObject = iface;
747 else
749 WARN( "() : asking for unsupported interface %s\n", debugstr_guid(riid));
750 return E_NOINTERFACE;
753 IUnknown_AddRef((IUnknown*)*ppvObject);
755 return S_OK;
758 /************************************************************************
759 * OLEClipbrd_IDataObject_AddRef (IUnknown)
761 * See Windows documentation for more details on IUnknown methods.
763 static ULONG WINAPI OLEClipbrd_IDataObject_AddRef(
764 IDataObject* iface)
766 ole_clipbrd *This = impl_from_IDataObject(iface);
768 TRACE("(%p)->(count=%u)\n",This, This->ref);
770 return InterlockedIncrement(&This->ref);
773 /***********************************************************************
774 * OLEClipbrd_DestroyWindow(HWND)
775 * Destroy the clipboard window and unregister its class
777 static void OLEClipbrd_DestroyWindow(HWND hwnd)
779 DestroyWindow(hwnd);
780 UnregisterClassA( OLEClipbrd_WNDCLASS, 0 );
783 static void OLEClipbrd_Destroy(ole_clipbrd* This)
785 TRACE("()\n");
787 if (!This) return;
789 theOleClipboard = NULL;
791 if ( This->hWndClipboard )
792 OLEClipbrd_DestroyWindow(This->hWndClipboard);
794 HeapFree(GetProcessHeap(), 0, This);
797 /************************************************************************
798 * OLEClipbrd_IDataObject_Release (IUnknown)
800 * See Windows documentation for more details on IUnknown methods.
802 static ULONG WINAPI OLEClipbrd_IDataObject_Release(
803 IDataObject* iface)
805 ole_clipbrd *This = impl_from_IDataObject(iface);
806 ULONG ref;
808 TRACE("(%p)->(count=%u)\n",This, This->ref);
810 ref = InterlockedDecrement(&This->ref);
812 if (ref == 0)
814 OLEClipbrd_Destroy(This);
817 return ref;
821 /************************************************************************
822 * OLEClipbrd_IDataObject_GetData (IDataObject)
824 * The OLE Clipboard's implementation of this method delegates to
825 * a data source if there is one or wraps around the windows clipboard
827 * See Windows documentation for more details on IDataObject methods.
829 static HRESULT WINAPI OLEClipbrd_IDataObject_GetData(
830 IDataObject* iface,
831 LPFORMATETC pformatetcIn,
832 STGMEDIUM* pmedium)
834 HANDLE hData = 0;
835 BOOL bClipboardOpen = FALSE;
836 HRESULT hr = S_OK;
837 LPVOID src;
838 ole_clipbrd *This = impl_from_IDataObject(iface);
840 TRACE("(%p,%p,%p)\n", iface, pformatetcIn, pmedium);
842 if ( !pformatetcIn || !pmedium )
843 return E_INVALIDARG;
846 * If we have a data source placed on the clipboard (via OleSetClipboard)
847 * simply delegate to the source object's QueryGetData
848 * NOTE: This code assumes that the IDataObject is in the same address space!
849 * We will need to add marshalling support when Wine handles multiple processes.
851 if ( This->pIDataObjectSrc )
853 return IDataObject_GetData(This->pIDataObjectSrc, pformatetcIn, pmedium);
856 if ( pformatetcIn->lindex != -1 )
857 return DV_E_FORMATETC;
859 if ( (pformatetcIn->tymed & TYMED_HGLOBAL) != TYMED_HGLOBAL )
860 return DV_E_TYMED;
862 if ( pformatetcIn->dwAspect != DVASPECT_CONTENT )
863 return DV_E_DVASPECT;
867 * Otherwise, get the data from the windows clipboard using GetClipboardData
869 if ( !(bClipboardOpen = OpenClipboard(theOleClipboard->hWndClipboard)) )
870 HANDLE_ERROR( CLIPBRD_E_CANT_OPEN );
872 hData = GetClipboardData(pformatetcIn->cfFormat);
874 /* Must make a copy of global handle returned by GetClipboardData; it
875 * is not valid after we call CloseClipboard
876 * Application is responsible for freeing the memory (Forte Agent does this)
878 src = GlobalLock(hData);
879 if(src) {
880 LPVOID dest;
881 ULONG size;
882 HANDLE hDest;
884 size = GlobalSize(hData);
885 hDest = GlobalAlloc(GHND, size);
886 dest = GlobalLock(hDest);
887 memcpy(dest, src, size);
888 GlobalUnlock(hDest);
889 GlobalUnlock(hData);
890 hData = hDest;
894 * Return the clipboard data in the storage medium structure
896 pmedium->tymed = (hData == 0) ? TYMED_NULL : TYMED_HGLOBAL;
897 pmedium->u.hGlobal = hData;
898 pmedium->pUnkForRelease = NULL;
900 hr = S_OK;
902 CLEANUP:
904 * Close Windows clipboard
906 if ( bClipboardOpen && !CloseClipboard() )
907 hr = CLIPBRD_E_CANT_CLOSE;
909 if ( FAILED(hr) )
910 return hr;
911 return (hData == 0) ? DV_E_FORMATETC : S_OK;
914 static HRESULT WINAPI OLEClipbrd_IDataObject_GetDataHere(
915 IDataObject* iface,
916 LPFORMATETC pformatetc,
917 STGMEDIUM* pmedium)
919 FIXME(": Stub\n");
920 return E_NOTIMPL;
923 /************************************************************************
924 * OLEClipbrd_IDataObject_QueryGetData (IDataObject)
926 * The OLE Clipboard's implementation of this method delegates to
927 * a data source if there is one or wraps around the windows clipboard
928 * function IsClipboardFormatAvailable() otherwise.
930 * See Windows documentation for more details on IDataObject methods.
932 static HRESULT WINAPI OLEClipbrd_IDataObject_QueryGetData(
933 IDataObject* iface,
934 LPFORMATETC pformatetc)
936 TRACE("(%p, %p)\n", iface, pformatetc);
938 if (!pformatetc)
939 return E_INVALIDARG;
941 if ( pformatetc->dwAspect != DVASPECT_CONTENT )
942 return DV_E_FORMATETC;
944 if ( pformatetc->lindex != -1 )
945 return DV_E_FORMATETC;
948 * Delegate to the Windows clipboard function IsClipboardFormatAvailable
950 return (IsClipboardFormatAvailable(pformatetc->cfFormat)) ? S_OK : DV_E_CLIPFORMAT;
953 /************************************************************************
954 * OLEClipbrd_IDataObject_GetCanonicalFormatEtc (IDataObject)
956 * See Windows documentation for more details on IDataObject methods.
958 static HRESULT WINAPI OLEClipbrd_IDataObject_GetCanonicalFormatEtc(
959 IDataObject* iface,
960 LPFORMATETC pformatectIn,
961 LPFORMATETC pformatetcOut)
963 TRACE("(%p, %p, %p)\n", iface, pformatectIn, pformatetcOut);
965 if ( !pformatectIn || !pformatetcOut )
966 return E_INVALIDARG;
968 *pformatetcOut = *pformatectIn;
969 return DATA_S_SAMEFORMATETC;
972 /************************************************************************
973 * OLEClipbrd_IDataObject_SetData (IDataObject)
975 * The OLE Clipboard's does not implement this method
977 * See Windows documentation for more details on IDataObject methods.
979 static HRESULT WINAPI OLEClipbrd_IDataObject_SetData(
980 IDataObject* iface,
981 LPFORMATETC pformatetc,
982 STGMEDIUM* pmedium,
983 BOOL fRelease)
985 TRACE("\n");
986 return E_NOTIMPL;
989 /************************************************************************
990 * OLEClipbrd_IDataObject_EnumFormatEtc (IDataObject)
992 * See Windows documentation for more details on IDataObject methods.
994 static HRESULT WINAPI OLEClipbrd_IDataObject_EnumFormatEtc(
995 IDataObject* iface,
996 DWORD dwDirection,
997 IEnumFORMATETC** ppenumFormatEtc)
999 HRESULT hr = S_OK;
1000 FORMATETC *afmt = NULL;
1001 int cfmt, i;
1002 UINT format;
1003 BOOL bClipboardOpen;
1004 ole_clipbrd *This = impl_from_IDataObject(iface);
1006 TRACE("(%p, %x, %p)\n", iface, dwDirection, ppenumFormatEtc);
1009 * If we have a data source placed on the clipboard (via OleSetClipboard)
1010 * simply delegate to the source object's EnumFormatEtc
1012 if ( This->pIDataObjectSrc )
1014 return IDataObject_EnumFormatEtc(This->pIDataObjectSrc,
1015 dwDirection, ppenumFormatEtc);
1019 * Otherwise we must provide our own enumerator which wraps around the
1020 * Windows clipboard function EnumClipboardFormats
1022 if ( !ppenumFormatEtc )
1023 return E_INVALIDARG;
1025 if ( dwDirection != DATADIR_GET ) /* IDataObject_SetData not implemented */
1026 return E_NOTIMPL;
1029 * Store all current clipboard formats in an array of FORMATETC's,
1030 * and create an IEnumFORMATETC enumerator from this list.
1032 cfmt = CountClipboardFormats();
1033 afmt = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1034 sizeof(FORMATETC) * cfmt);
1036 * Open the Windows clipboard, associating it with our hidden window
1038 if ( !(bClipboardOpen = OpenClipboard(This->hWndClipboard)) )
1039 HANDLE_ERROR( CLIPBRD_E_CANT_OPEN );
1042 * Store all current clipboard formats in an array of FORMATETC's
1043 * TODO: Handle TYMED_IStorage media which were put on the clipboard
1044 * by copying the storage into global memory. We must convert this
1045 * TYMED_HGLOBAL back to TYMED_IStorage.
1047 for (i = 0, format = 0; i < cfmt; i++)
1049 format = EnumClipboardFormats(format);
1050 if (!format) /* Failed! */
1052 ERR("EnumClipboardFormats failed to return format!\n");
1053 HANDLE_ERROR( E_FAIL );
1056 /* Init the FORMATETC struct */
1057 afmt[i].cfFormat = format;
1058 afmt[i].ptd = NULL;
1059 afmt[i].dwAspect = DVASPECT_CONTENT;
1060 afmt[i].lindex = -1;
1061 afmt[i].tymed = TYMED_HGLOBAL;
1065 * Create an EnumFORMATETC enumerator and return an
1066 * EnumFORMATETC after bumping up its ref count
1068 *ppenumFormatEtc = OLEClipbrd_IEnumFORMATETC_Construct( cfmt, afmt, (LPUNKNOWN)iface);
1069 if (!(*ppenumFormatEtc))
1070 HANDLE_ERROR( E_OUTOFMEMORY );
1072 if (FAILED( hr = IEnumFORMATETC_AddRef(*ppenumFormatEtc)))
1073 HANDLE_ERROR( hr );
1075 hr = S_OK;
1077 CLEANUP:
1079 * Free the array of FORMATETC's
1081 HeapFree(GetProcessHeap(), 0, afmt);
1084 * Close Windows clipboard
1086 if ( bClipboardOpen && !CloseClipboard() )
1087 hr = CLIPBRD_E_CANT_CLOSE;
1089 return hr;
1092 /************************************************************************
1093 * OLEClipbrd_IDataObject_DAdvise (IDataObject)
1095 * The OLE Clipboard's does not implement this method
1097 * See Windows documentation for more details on IDataObject methods.
1099 static HRESULT WINAPI OLEClipbrd_IDataObject_DAdvise(
1100 IDataObject* iface,
1101 FORMATETC* pformatetc,
1102 DWORD advf,
1103 IAdviseSink* pAdvSink,
1104 DWORD* pdwConnection)
1106 TRACE("\n");
1107 return E_NOTIMPL;
1110 /************************************************************************
1111 * OLEClipbrd_IDataObject_DUnadvise (IDataObject)
1113 * The OLE Clipboard's does not implement this method
1115 * See Windows documentation for more details on IDataObject methods.
1117 static HRESULT WINAPI OLEClipbrd_IDataObject_DUnadvise(
1118 IDataObject* iface,
1119 DWORD dwConnection)
1121 TRACE("\n");
1122 return E_NOTIMPL;
1125 /************************************************************************
1126 * OLEClipbrd_IDataObject_EnumDAdvise (IDataObject)
1128 * The OLE Clipboard does not implement this method
1130 * See Windows documentation for more details on IDataObject methods.
1132 static HRESULT WINAPI OLEClipbrd_IDataObject_EnumDAdvise(
1133 IDataObject* iface,
1134 IEnumSTATDATA** ppenumAdvise)
1136 TRACE("\n");
1137 return E_NOTIMPL;
1140 static const IDataObjectVtbl OLEClipbrd_IDataObject_VTable =
1142 OLEClipbrd_IDataObject_QueryInterface,
1143 OLEClipbrd_IDataObject_AddRef,
1144 OLEClipbrd_IDataObject_Release,
1145 OLEClipbrd_IDataObject_GetData,
1146 OLEClipbrd_IDataObject_GetDataHere,
1147 OLEClipbrd_IDataObject_QueryGetData,
1148 OLEClipbrd_IDataObject_GetCanonicalFormatEtc,
1149 OLEClipbrd_IDataObject_SetData,
1150 OLEClipbrd_IDataObject_EnumFormatEtc,
1151 OLEClipbrd_IDataObject_DAdvise,
1152 OLEClipbrd_IDataObject_DUnadvise,
1153 OLEClipbrd_IDataObject_EnumDAdvise
1156 /*---------------------------------------------------------------------*
1157 * Internal implementation methods for the OLE clipboard
1158 *---------------------------------------------------------------------*/
1160 /*********************************************************
1161 * Construct the OLEClipbrd class.
1163 static ole_clipbrd* OLEClipbrd_Construct(void)
1165 ole_clipbrd* This;
1167 This = HeapAlloc( GetProcessHeap(), 0, sizeof(*This) );
1168 if (!This) return NULL;
1170 This->lpvtbl = &OLEClipbrd_IDataObject_VTable;
1171 This->ref = 1;
1173 This->hWndClipboard = NULL;
1174 This->pIDataObjectSrc = NULL;
1176 theOleClipboard = This;
1177 return This;
1180 static void register_clipboard_formats(void)
1182 static const WCHAR DataObjectW[] = { 'D','a','t','a','O','b','j','e','c','t',0 };
1184 if(!dataobject_clipboard_format)
1185 dataobject_clipboard_format = RegisterClipboardFormatW(DataObjectW);
1188 /***********************************************************************
1189 * OLEClipbrd_Initialize()
1190 * Initializes the OLE clipboard.
1192 void OLEClipbrd_Initialize(void)
1194 register_clipboard_formats();
1196 if ( !theOleClipboard )
1198 TRACE("()\n");
1199 theOleClipboard = OLEClipbrd_Construct();
1204 /***********************************************************************
1205 * OLEClipbrd_UnInitialize()
1206 * Un-Initializes the OLE clipboard
1208 void OLEClipbrd_UnInitialize(void)
1210 TRACE("()\n");
1212 * Destroy the clipboard if no one holds a reference to us.
1213 * Note that the clipboard was created with a reference count of 1.
1215 if ( theOleClipboard && (theOleClipboard->ref <= 1) )
1217 OLEClipbrd_Destroy( theOleClipboard );
1219 else
1221 WARN( "() : OLEClipbrd_UnInitialize called while client holds an IDataObject reference!\n");
1225 /***********************************************************************
1226 * OLEClipbrd_CreateWindow()
1227 * Create the clipboard window
1229 static HWND OLEClipbrd_CreateWindow(void)
1231 HWND hwnd = 0;
1232 WNDCLASSEXA wcex;
1235 * Register the clipboard window class if necessary
1237 ZeroMemory( &wcex, sizeof(WNDCLASSEXA));
1239 wcex.cbSize = sizeof(WNDCLASSEXA);
1240 /* Windows creates this class with a style mask of 0
1241 * We don't bother doing this since the FindClassByAtom code
1242 * would have to be changed to deal with this idiosyncrasy. */
1243 wcex.style = CS_GLOBALCLASS;
1244 wcex.lpfnWndProc = OLEClipbrd_WndProc;
1245 wcex.hInstance = 0;
1246 wcex.lpszClassName = OLEClipbrd_WNDCLASS;
1248 RegisterClassExA(&wcex);
1251 * Create a hidden window to receive OLE clipboard messages
1255 * If we need to store state info we can store it here.
1256 * For now we don't need this functionality.
1257 * ClipboardWindowInfo clipboardInfo;
1258 * ZeroMemory( &trackerInfo, sizeof(ClipboardWindowInfo));
1261 hwnd = CreateWindowA(OLEClipbrd_WNDCLASS,
1262 "ClipboardWindow",
1263 WS_POPUP | WS_CLIPSIBLINGS | WS_OVERLAPPED,
1264 CW_USEDEFAULT, CW_USEDEFAULT,
1265 CW_USEDEFAULT, CW_USEDEFAULT,
1269 0 /*(LPVOID)&clipboardInfo */);
1271 return hwnd;
1274 /*********************************************************************
1275 * set_clipboard_formats
1277 * Enumerate all HGLOBAL formats supported by the source and make
1278 * those formats available using delayed rendering using SetClipboardData.
1280 * TODO: We need to additionally handle TYMED_IStorage and
1281 * TYMED_IStream data by copying into global memory.
1283 static HRESULT set_clipboard_formats(IDataObject *data)
1285 HRESULT hr;
1286 FORMATETC fmt;
1287 IEnumFORMATETC *enum_fmt;
1289 hr = IDataObject_EnumFormatEtc(data, DATADIR_GET, &enum_fmt);
1290 if(FAILED(hr)) return hr;
1292 while(IEnumFORMATETC_Next(enum_fmt, 1, &fmt, NULL) == S_OK)
1294 if (fmt.tymed == TYMED_HGLOBAL)
1296 char fmt_name[80];
1297 TRACE("(cfFormat=%d:%s)\n", fmt.cfFormat,
1298 GetClipboardFormatNameA(fmt.cfFormat, fmt_name, sizeof(fmt_name)-1) ? fmt_name : "");
1300 SetClipboardData(fmt.cfFormat, NULL);
1304 IEnumFORMATETC_Release(enum_fmt);
1305 return S_OK;
1308 /*********************************************************************
1309 * set_dataobject_format
1311 * Windows creates a 'DataObject' clipboard format that contains the
1312 * clipboard window's HWND or NULL if the Ole clipboard has been flushed.
1314 static HRESULT set_dataobject_format(HWND hwnd)
1316 HGLOBAL h = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE, sizeof(hwnd));
1317 HWND *data;
1319 if(!h) return E_OUTOFMEMORY;
1321 data = GlobalLock(h);
1322 *data = hwnd;
1323 GlobalUnlock(h);
1325 if(!SetClipboardData(dataobject_clipboard_format, h))
1327 GlobalFree(h);
1328 return CLIPBRD_E_CANT_SET;
1331 return S_OK;
1334 /*---------------------------------------------------------------------*
1335 * Win32 OLE clipboard API
1336 *---------------------------------------------------------------------*/
1338 /***********************************************************************
1339 * OleSetClipboard [OLE32.@]
1340 * Places a pointer to the specified data object onto the clipboard,
1341 * making the data object accessible to the OleGetClipboard function.
1343 * RETURNS
1345 * S_OK IDataObject pointer placed on the clipboard
1346 * CLIPBRD_E_CANT_OPEN OpenClipboard failed
1347 * CLIPBRD_E_CANT_EMPTY EmptyClipboard failed
1348 * CLIPBRD_E_CANT_CLOSE CloseClipboard failed
1349 * CLIPBRD_E_CANT_SET SetClipboard failed
1352 HRESULT WINAPI OleSetClipboard(IDataObject* pDataObj)
1354 HRESULT hr = S_OK;
1355 BOOL bClipboardOpen = FALSE;
1356 struct oletls *info = COM_CurrentInfo();
1358 TRACE("(%p)\n", pDataObj);
1360 if(!info)
1361 WARN("Could not allocate tls\n");
1362 else
1363 if(!info->ole_inits)
1364 return CO_E_NOTINITIALIZED;
1367 * Make sure we have a clipboard object
1369 OLEClipbrd_Initialize();
1372 * If the Ole clipboard window hasn't been created yet, create it now.
1374 if ( !theOleClipboard->hWndClipboard )
1375 theOleClipboard->hWndClipboard = OLEClipbrd_CreateWindow();
1377 if ( !theOleClipboard->hWndClipboard ) /* sanity check */
1378 HANDLE_ERROR( E_FAIL );
1381 * Open the Windows clipboard, associating it with our hidden window
1383 if ( !(bClipboardOpen = OpenClipboard(theOleClipboard->hWndClipboard)) )
1384 HANDLE_ERROR( CLIPBRD_E_CANT_OPEN );
1387 * Empty the current clipboard and make our window the clipboard owner
1388 * NOTE: This will trigger a WM_DESTROYCLIPBOARD message
1390 if ( !EmptyClipboard() )
1391 HANDLE_ERROR( CLIPBRD_E_CANT_EMPTY );
1394 * If we are already holding on to an IDataObject first release that.
1396 if ( theOleClipboard->pIDataObjectSrc )
1398 IDataObject_Release(theOleClipboard->pIDataObjectSrc);
1399 theOleClipboard->pIDataObjectSrc = NULL;
1402 /* A NULL value indicates that the clipboard should be emptied. */
1403 theOleClipboard->pIDataObjectSrc = pDataObj;
1404 if ( pDataObj )
1406 IDataObject_AddRef(theOleClipboard->pIDataObjectSrc);
1407 hr = set_clipboard_formats(pDataObj);
1408 if(FAILED(hr)) goto CLEANUP;
1411 hr = set_dataobject_format(theOleClipboard->hWndClipboard);
1413 CLEANUP:
1416 * Close Windows clipboard (It remains associated with our window)
1418 if ( bClipboardOpen && !CloseClipboard() )
1419 hr = CLIPBRD_E_CANT_CLOSE;
1422 * Release the source IDataObject if something failed
1424 if ( FAILED(hr) )
1426 if (theOleClipboard->pIDataObjectSrc)
1428 IDataObject_Release(theOleClipboard->pIDataObjectSrc);
1429 theOleClipboard->pIDataObjectSrc = NULL;
1433 return hr;
1437 /***********************************************************************
1438 * OleGetClipboard [OLE32.@]
1439 * Returns a pointer to our internal IDataObject which represents the conceptual
1440 * state of the Windows clipboard. If the current clipboard already contains
1441 * an IDataObject, our internal IDataObject will delegate to this object.
1443 HRESULT WINAPI OleGetClipboard(IDataObject** ppDataObj)
1445 HRESULT hr = S_OK;
1446 TRACE("()\n");
1449 * Make sure we have a clipboard object
1451 OLEClipbrd_Initialize();
1453 if (!theOleClipboard)
1454 return E_OUTOFMEMORY;
1456 /* Return a reference counted IDataObject */
1457 hr = IDataObject_QueryInterface( (IDataObject*)&(theOleClipboard->lpvtbl),
1458 &IID_IDataObject, (void**)ppDataObj);
1459 return hr;
1462 /******************************************************************************
1463 * OleFlushClipboard [OLE32.@]
1464 * Renders the data from the source IDataObject into the windows clipboard
1466 * TODO: OleFlushClipboard needs to additionally handle TYMED_IStorage media
1467 * by copying the storage into global memory. Subsequently the default
1468 * data object exposed through OleGetClipboard must convert this TYMED_HGLOBAL
1469 * back to TYMED_IStorage.
1471 HRESULT WINAPI OleFlushClipboard(void)
1473 IEnumFORMATETC* penumFormatetc = NULL;
1474 FORMATETC rgelt;
1475 HRESULT hr = S_OK;
1476 BOOL bClipboardOpen = FALSE;
1477 IDataObject* pIDataObjectSrc = NULL;
1479 TRACE("()\n");
1482 * Make sure we have a clipboard object
1484 OLEClipbrd_Initialize();
1487 * Already flushed or no source DataObject? Nothing to do.
1489 if (!theOleClipboard->pIDataObjectSrc)
1490 return S_OK;
1493 * Addref and save the source data object we are holding on to temporarily,
1494 * since it will be released when we empty the clipboard.
1496 pIDataObjectSrc = theOleClipboard->pIDataObjectSrc;
1497 IDataObject_AddRef(pIDataObjectSrc);
1500 * Open the Windows clipboard
1502 if ( !(bClipboardOpen = OpenClipboard(theOleClipboard->hWndClipboard)) )
1503 HANDLE_ERROR( CLIPBRD_E_CANT_OPEN );
1506 * Empty the current clipboard
1508 if ( !EmptyClipboard() )
1509 HANDLE_ERROR( CLIPBRD_E_CANT_EMPTY );
1512 * Render all HGLOBAL formats supported by the source into
1513 * the windows clipboard.
1515 if ( FAILED( hr = IDataObject_EnumFormatEtc( pIDataObjectSrc,
1516 DATADIR_GET,
1517 &penumFormatetc) ))
1519 HANDLE_ERROR( hr );
1522 while ( S_OK == IEnumFORMATETC_Next(penumFormatetc, 1, &rgelt, NULL) )
1524 if ( rgelt.tymed == TYMED_HGLOBAL )
1526 CHAR szFmtName[80];
1527 TRACE("(cfFormat=%d:%s)\n", rgelt.cfFormat,
1528 GetClipboardFormatNameA(rgelt.cfFormat, szFmtName, sizeof(szFmtName)-1)
1529 ? szFmtName : "");
1532 * Render the clipboard data
1534 if ( FAILED(OLEClipbrd_RenderFormat( pIDataObjectSrc, &rgelt )) )
1535 continue;
1539 IEnumFORMATETC_Release(penumFormatetc);
1541 hr = set_dataobject_format(NULL);
1544 * Release the source data object we are holding on to
1546 IDataObject_Release(pIDataObjectSrc);
1548 CLEANUP:
1551 * Close Windows clipboard (It remains associated with our window)
1553 if ( bClipboardOpen && !CloseClipboard() )
1554 hr = CLIPBRD_E_CANT_CLOSE;
1556 return hr;
1560 /***********************************************************************
1561 * OleIsCurrentClipboard [OLE32.@]
1563 HRESULT WINAPI OleIsCurrentClipboard(IDataObject *pDataObject)
1565 TRACE("()\n");
1567 * Make sure we have a clipboard object
1569 OLEClipbrd_Initialize();
1571 if (!theOleClipboard)
1572 return E_OUTOFMEMORY;
1574 if (pDataObject == NULL)
1575 return S_FALSE;
1577 return (pDataObject == theOleClipboard->pIDataObjectSrc) ? S_OK : S_FALSE;