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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
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
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.
65 #define NONAMELESSUNION
66 #define NONAMELESSSTRUCT
74 #include "wine/debug.h"
77 #include "storage32.h"
79 #define HANDLE_ERROR(err) { hr = err; TRACE("(HRESULT=%lx)\n", (HRESULT)err); goto CLEANUP; }
81 /* For CoGetMalloc (MEMCTX_TASK is currently ignored) */
83 #define MEMCTX_TASK -1
86 WINE_DEFAULT_DEBUG_CHANNEL(ole);
88 /****************************************************************************
90 * DO NOT add any members before the VTables declaration!
95 * List all interface VTables here
97 ICOM_VTABLE(IDataObject)* lpvtbl1; /* IDataObject VTable */
100 * The hidden OLE clipboard window. This window is used as the bridge between the
101 * the OLE and windows clipboard API. (Windows creates one such window per process)
106 * Pointer to the source data object (via OleSetClipboard)
108 IDataObject* pIDataObjectSrc;
111 * The registered DataObject clipboard format
116 * The handle to ourself
121 * Reference count of this object
126 typedef struct OLEClipbrd OLEClipbrd;
129 /****************************************************************************
130 * IEnumFORMATETC implementation
131 * DO NOT add any members before the VTables declaration!
135 /* IEnumFORMATETC VTable */
136 ICOM_VFIELD(IEnumFORMATETC);
138 /* IEnumFORMATETC fields */
139 UINT posFmt; /* current enumerator position */
140 UINT countFmt; /* number of EnumFORMATETC's in array */
141 LPFORMATETC pFmt; /* array of EnumFORMATETC's */
144 * Reference count of this object
149 * IUnknown implementation of the parent data object.
151 IUnknown* pUnkDataObj;
153 } IEnumFORMATETCImpl;
155 typedef struct PresentationDataHeader
158 DWORD dwObjectExtentX;
159 DWORD dwObjectExtentY;
161 } PresentationDataHeader;
164 * The one and only OLEClipbrd object which is created by OLEClipbrd_Initialize()
166 static HGLOBAL hTheOleClipboard = 0;
167 static OLEClipbrd* theOleClipboard = NULL;
171 * Prototypes for the methods of the OLEClipboard class.
173 extern void OLEClipbrd_Initialize();
174 extern void OLEClipbrd_UnInitialize();
175 static OLEClipbrd* OLEClipbrd_Construct();
176 static void OLEClipbrd_Destroy(OLEClipbrd* ptrToDestroy);
177 static HWND OLEClipbrd_CreateWindow();
178 static void OLEClipbrd_DestroyWindow(HWND hwnd);
179 LRESULT CALLBACK OLEClipbrd_WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
180 static HRESULT OLEClipbrd_RenderFormat( IDataObject *pIDataObject, LPFORMATETC pFormatetc );
181 static HGLOBAL OLEClipbrd_GlobalDupMem( HGLOBAL hGlobalSrc );
184 * Prototypes for the methods of the OLEClipboard class
185 * that implement IDataObject methods.
187 static HRESULT WINAPI OLEClipbrd_IDataObject_QueryInterface(
191 static ULONG WINAPI OLEClipbrd_IDataObject_AddRef(
193 static ULONG WINAPI OLEClipbrd_IDataObject_Release(
195 static HRESULT WINAPI OLEClipbrd_IDataObject_GetData(
197 LPFORMATETC pformatetcIn,
199 static HRESULT WINAPI OLEClipbrd_IDataObject_GetDataHere(
201 LPFORMATETC pformatetc,
203 static HRESULT WINAPI OLEClipbrd_IDataObject_QueryGetData(
205 LPFORMATETC pformatetc);
206 static HRESULT WINAPI OLEClipbrd_IDataObject_GetCanonicalFormatEtc(
208 LPFORMATETC pformatectIn,
209 LPFORMATETC pformatetcOut);
210 static HRESULT WINAPI OLEClipbrd_IDataObject_SetData(
212 LPFORMATETC pformatetc,
215 static HRESULT WINAPI OLEClipbrd_IDataObject_EnumFormatEtc(
218 IEnumFORMATETC** ppenumFormatEtc);
219 static HRESULT WINAPI OLEClipbrd_IDataObject_DAdvise(
221 FORMATETC* pformatetc,
223 IAdviseSink* pAdvSink,
224 DWORD* pdwConnection);
225 static HRESULT WINAPI OLEClipbrd_IDataObject_DUnadvise(
228 static HRESULT WINAPI OLEClipbrd_IDataObject_EnumDAdvise(
230 IEnumSTATDATA** ppenumAdvise);
233 * Prototypes for the IEnumFORMATETC methods.
235 static LPENUMFORMATETC OLEClipbrd_IEnumFORMATETC_Construct(UINT cfmt, const FORMATETC afmt[],
236 LPUNKNOWN pUnkDataObj);
237 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_QueryInterface(LPENUMFORMATETC iface, REFIID riid,
239 static ULONG WINAPI OLEClipbrd_IEnumFORMATETC_AddRef(LPENUMFORMATETC iface);
240 static ULONG WINAPI OLEClipbrd_IEnumFORMATETC_Release(LPENUMFORMATETC iface);
241 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Next(LPENUMFORMATETC iface, ULONG celt,
242 FORMATETC* rgelt, ULONG* pceltFethed);
243 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Skip(LPENUMFORMATETC iface, ULONG celt);
244 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Reset(LPENUMFORMATETC iface);
245 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Clone(LPENUMFORMATETC iface, LPENUMFORMATETC* ppenum);
249 * Virtual function table for the OLEClipbrd's exposed IDataObject interface
251 static ICOM_VTABLE(IDataObject) OLEClipbrd_IDataObject_VTable =
253 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
254 OLEClipbrd_IDataObject_QueryInterface,
255 OLEClipbrd_IDataObject_AddRef,
256 OLEClipbrd_IDataObject_Release,
257 OLEClipbrd_IDataObject_GetData,
258 OLEClipbrd_IDataObject_GetDataHere,
259 OLEClipbrd_IDataObject_QueryGetData,
260 OLEClipbrd_IDataObject_GetCanonicalFormatEtc,
261 OLEClipbrd_IDataObject_SetData,
262 OLEClipbrd_IDataObject_EnumFormatEtc,
263 OLEClipbrd_IDataObject_DAdvise,
264 OLEClipbrd_IDataObject_DUnadvise,
265 OLEClipbrd_IDataObject_EnumDAdvise
269 * Virtual function table for IEnumFORMATETC interface
271 static struct ICOM_VTABLE(IEnumFORMATETC) efvt =
273 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
274 OLEClipbrd_IEnumFORMATETC_QueryInterface,
275 OLEClipbrd_IEnumFORMATETC_AddRef,
276 OLEClipbrd_IEnumFORMATETC_Release,
277 OLEClipbrd_IEnumFORMATETC_Next,
278 OLEClipbrd_IEnumFORMATETC_Skip,
279 OLEClipbrd_IEnumFORMATETC_Reset,
280 OLEClipbrd_IEnumFORMATETC_Clone
284 * Name of our registered OLE clipboard window class
286 CHAR OLEClipbrd_WNDCLASS[] = "CLIPBRDWNDCLASS";
289 * If we need to store state info we can store it here.
290 * For now we don't need this functionality.
292 typedef struct tagClipboardWindowInfo
294 } ClipboardWindowInfo;
297 /*---------------------------------------------------------------------*
298 * Win32 OLE clipboard API
299 *---------------------------------------------------------------------*/
301 /***********************************************************************
302 * OleSetClipboard [OLE32.@]
303 * Places a pointer to the specified data object onto the clipboard,
304 * making the data object accessible to the OleGetClipboard function.
308 * S_OK IDataObject pointer placed on the clipboard
309 * CLIPBRD_E_CANT_OPEN OpenClipboard failed
310 * CLIPBRD_E_CANT_EMPTY EmptyClipboard failed
311 * CLIPBRD_E_CANT_CLOSE CloseClipboard failed
312 * CLIPBRD_E_CANT_SET SetClipboard failed
315 HRESULT WINAPI OleSetClipboard(IDataObject* pDataObj)
318 IEnumFORMATETC* penumFormatetc = NULL;
320 BOOL bClipboardOpen = FALSE;
322 HGLOBAL hDataObject = 0;
323 OLEClipbrd **ppDataObject;
326 TRACE("(%p)\n", pDataObj);
329 * Make sure we have a clipboard object
331 OLEClipbrd_Initialize();
334 * If the Ole clipboard window hasn't been created yet, create it now.
336 if ( !theOleClipboard->hWndClipboard )
337 theOleClipboard->hWndClipboard = OLEClipbrd_CreateWindow();
339 if ( !theOleClipboard->hWndClipboard ) /* sanity check */
340 HANDLE_ERROR( E_FAIL );
343 * Open the Windows clipboard, associating it with our hidden window
345 if ( !(bClipboardOpen = OpenClipboard(theOleClipboard->hWndClipboard)) )
346 HANDLE_ERROR( CLIPBRD_E_CANT_OPEN );
349 * Empty the current clipboard and make our window the clipboard owner
350 * NOTE: This will trigger a WM_DESTROYCLIPBOARD message
352 if ( !EmptyClipboard() )
353 HANDLE_ERROR( CLIPBRD_E_CANT_EMPTY );
356 * If we are already holding on to an IDataObject first release that.
358 if ( theOleClipboard->pIDataObjectSrc )
360 IDataObject_Release(theOleClipboard->pIDataObjectSrc);
361 theOleClipboard->pIDataObjectSrc = NULL;
365 * AddRef the data object passed in and save its pointer.
366 * A NULL value indicates that the clipboard should be emptied.
368 theOleClipboard->pIDataObjectSrc = pDataObj;
371 IDataObject_AddRef(theOleClipboard->pIDataObjectSrc);
375 * Enumerate all HGLOBAL formats supported by the source and make
376 * those formats available using delayed rendering using SetClipboardData.
377 * Only global memory based data items may be made available to non-OLE
378 * applications via the standard Windows clipboard API. Data based on other
379 * mediums(non TYMED_HGLOBAL) can only be accessed via the Ole Clipboard API.
381 * TODO: Do we need to additionally handle TYMED_IStorage media by copying
382 * the storage into global memory?
386 if ( FAILED(hr = IDataObject_EnumFormatEtc( pDataObj,
393 while ( S_OK == IEnumFORMATETC_Next(penumFormatetc, 1, &rgelt, NULL) )
395 if ( rgelt.tymed == TYMED_HGLOBAL )
398 TRACE("(cfFormat=%d:%s)\n", rgelt.cfFormat,
399 GetClipboardFormatNameA(rgelt.cfFormat, szFmtName, sizeof(szFmtName)-1)
402 SetClipboardData( rgelt.cfFormat, NULL);
405 IEnumFORMATETC_Release(penumFormatetc);
409 * Windows additionally creates a new "DataObject" clipboard format
410 * and stores in on the clipboard. We could possibly store a pointer
411 * to our internal IDataObject interface on the clipboard. I'm not
412 * sure what the use of this is though.
413 * Enable the code below for this functionality.
416 theOleClipboard->cfDataObj = RegisterClipboardFormatA("DataObject");
417 hDataObject = GlobalAlloc( GMEM_DDESHARE|GMEM_MOVEABLE|GMEM_ZEROINIT,
418 sizeof(OLEClipbrd *));
420 HANDLE_ERROR( E_OUTOFMEMORY );
422 ppDataObject = (OLEClipbrd**)GlobalLock(hDataObject);
423 *ppDataObject = theOleClipboard;
424 GlobalUnlock(hDataObject);
426 if ( !SetClipboardData( theOleClipboard->cfDataObj, hDataObject ) )
427 HANDLE_ERROR( CLIPBRD_E_CANT_SET );
435 * Close Windows clipboard (It remains associated with our window)
437 if ( bClipboardOpen && !CloseClipboard() )
438 hr = CLIPBRD_E_CANT_CLOSE;
441 * Release the source IDataObject if something failed
445 if (theOleClipboard->pIDataObjectSrc)
447 IDataObject_Release(theOleClipboard->pIDataObjectSrc);
448 theOleClipboard->pIDataObjectSrc = NULL;
456 /***********************************************************************
457 * OleGetClipboard [OLE32.@]
458 * Returns a pointer to our internal IDataObject which represents the conceptual
459 * state of the Windows clipboard. If the current clipboard already contains
460 * an IDataObject, our internal IDataObject will delegate to this object.
462 HRESULT WINAPI OleGetClipboard(IDataObject** ppDataObj)
468 * Make sure we have a clipboard object
470 OLEClipbrd_Initialize();
472 if (!theOleClipboard)
473 return E_OUTOFMEMORY;
475 /* Return a reference counted IDataObject */
476 hr = IDataObject_QueryInterface( (IDataObject*)&(theOleClipboard->lpvtbl1),
477 &IID_IDataObject, (void**)ppDataObj);
481 /***********************************************************************
482 * OleFlushClipboard [OLE2.76]
485 HRESULT WINAPI OleFlushClipboard16(void)
487 return OleFlushClipboard();
491 /******************************************************************************
492 * OleFlushClipboard [OLE32.@]
493 * Renders the data from the source IDataObject into the windows clipboard
495 * TODO: OleFlushClipboard needs to additionally handle TYMED_IStorage media
496 * by copying the storage into global memory. Subsequently the default
497 * data object exposed through OleGetClipboard must convert this TYMED_HGLOBAL
498 * back to TYMED_IStorage.
500 HRESULT WINAPI OleFlushClipboard()
502 IEnumFORMATETC* penumFormatetc = NULL;
505 BOOL bClipboardOpen = FALSE;
506 IDataObject* pIDataObjectSrc = NULL;
511 * Make sure we have a clipboard object
513 OLEClipbrd_Initialize();
516 * Already flushed or no source DataObject? Nothing to do.
518 if (!theOleClipboard->pIDataObjectSrc)
522 * Addref and save the source data object we are holding on to temporarily,
523 * since it will be released when we empty the clipboard.
525 pIDataObjectSrc = theOleClipboard->pIDataObjectSrc;
526 IDataObject_AddRef(pIDataObjectSrc);
529 * Open the Windows clipboard
531 if ( !(bClipboardOpen = OpenClipboard(theOleClipboard->hWndClipboard)) )
532 HANDLE_ERROR( CLIPBRD_E_CANT_OPEN );
535 * Empty the current clipboard
537 if ( !EmptyClipboard() )
538 HANDLE_ERROR( CLIPBRD_E_CANT_EMPTY );
541 * Render all HGLOBAL formats supported by the source into
542 * the windows clipboard.
544 if ( FAILED( hr = IDataObject_EnumFormatEtc( pIDataObjectSrc,
551 while ( S_OK == IEnumFORMATETC_Next(penumFormatetc, 1, &rgelt, NULL) )
553 if ( rgelt.tymed == TYMED_HGLOBAL )
556 TRACE("(cfFormat=%d:%s)\n", rgelt.cfFormat,
557 GetClipboardFormatNameA(rgelt.cfFormat, szFmtName, sizeof(szFmtName)-1)
561 * Render the clipboard data
563 if ( FAILED(OLEClipbrd_RenderFormat( pIDataObjectSrc, &rgelt )) )
568 IEnumFORMATETC_Release(penumFormatetc);
571 * Release the source data object we are holding on to
573 IDataObject_Release(pIDataObjectSrc);
578 * Close Windows clipboard (It remains associated with our window)
580 if ( bClipboardOpen && !CloseClipboard() )
581 hr = CLIPBRD_E_CANT_CLOSE;
587 /***********************************************************************
588 * OleIsCurrentClipboard [OLE32.@]
590 HRESULT WINAPI OleIsCurrentClipboard ( IDataObject *pDataObject)
594 * Make sure we have a clipboard object
596 OLEClipbrd_Initialize();
598 if (!theOleClipboard)
599 return E_OUTOFMEMORY;
601 return (pDataObject == theOleClipboard->pIDataObjectSrc) ? S_OK : S_FALSE;
605 /*---------------------------------------------------------------------*
606 * Internal implementation methods for the OLE clipboard
607 *---------------------------------------------------------------------*/
609 /***********************************************************************
610 * OLEClipbrd_Initialize()
611 * Initializes the OLE clipboard.
613 void OLEClipbrd_Initialize()
616 * Create the clipboard if necessary
618 if ( !theOleClipboard )
621 theOleClipboard = OLEClipbrd_Construct();
626 /***********************************************************************
627 * OLEClipbrd_UnInitialize()
628 * Un-Initializes the OLE clipboard
630 void OLEClipbrd_UnInitialize()
634 * Destroy the clipboard if no one holds a reference to us.
635 * Note that the clipboard was created with a reference count of 1.
637 if ( theOleClipboard && (theOleClipboard->ref <= 1) )
639 OLEClipbrd_Destroy( theOleClipboard );
643 WARN( "() : OLEClipbrd_UnInitialize called while client holds an IDataObject reference!\n");
648 /*********************************************************
649 * Construct the OLEClipbrd class.
651 static OLEClipbrd* OLEClipbrd_Construct()
653 OLEClipbrd* newObject = NULL;
654 HGLOBAL hNewObject = 0;
657 * Allocate space for the object. We use GlobalAlloc since we need
658 * an HGLOBAL to expose our DataObject as a registered clipboard type.
660 hNewObject = GlobalAlloc( GMEM_DDESHARE|GMEM_MOVEABLE|GMEM_ZEROINIT,
666 * Lock the handle for the entire lifetime of the clipboard.
668 newObject = GlobalLock(hNewObject);
671 * Initialize the virtual function table.
673 newObject->lpvtbl1 = &OLEClipbrd_IDataObject_VTable;
676 * Start with one reference count. The caller of this function
677 * must release the interface pointer when it is done.
681 newObject->hSelf = hNewObject;
684 * The Ole clipboard is a singleton - save the global handle and pointer
686 theOleClipboard = newObject;
687 hTheOleClipboard = hNewObject;
689 return theOleClipboard;
692 static void OLEClipbrd_Destroy(OLEClipbrd* ptrToDestroy)
700 * Destroy the Ole clipboard window
702 if ( ptrToDestroy->hWndClipboard )
703 OLEClipbrd_DestroyWindow(ptrToDestroy->hWndClipboard);
706 * Free the actual OLE Clipboard structure.
708 TRACE("() - Destroying clipboard data object.\n");
709 GlobalUnlock(ptrToDestroy->hSelf);
710 GlobalFree(ptrToDestroy->hSelf);
713 * The Ole clipboard is a singleton (ptrToDestroy == theOleClipboard)
715 theOleClipboard = NULL;
716 hTheOleClipboard = 0;
720 /***********************************************************************
721 * OLEClipbrd_CreateWindow()
722 * Create the clipboard window
724 static HWND OLEClipbrd_CreateWindow()
730 * Register the clipboard window class if necessary
732 ZeroMemory( &wcex, sizeof(WNDCLASSEXA));
734 wcex.cbSize = sizeof(WNDCLASSEXA);
735 /* Windows creates this class with a style mask of 0
736 * We don't bother doing this since the FindClassByAtom code
737 * would have to be changed to deal with this idiosyncrasy. */
738 wcex.style = CS_GLOBALCLASS;
739 wcex.lpfnWndProc = (WNDPROC)OLEClipbrd_WndProc;
741 wcex.lpszClassName = OLEClipbrd_WNDCLASS;
743 RegisterClassExA(&wcex);
746 * Create a hidden window to receive OLE clipboard messages
750 * If we need to store state info we can store it here.
751 * For now we don't need this functionality.
752 * ClipboardWindowInfo clipboardInfo;
753 * ZeroMemory( &trackerInfo, sizeof(ClipboardWindowInfo));
756 hwnd = CreateWindowA(OLEClipbrd_WNDCLASS,
758 WS_POPUP | WS_CLIPSIBLINGS | WS_OVERLAPPED,
759 CW_USEDEFAULT, CW_USEDEFAULT,
760 CW_USEDEFAULT, CW_USEDEFAULT,
764 0 /*(LPVOID)&clipboardInfo */);
769 /***********************************************************************
770 * OLEClipbrd_DestroyWindow(HWND)
771 * Destroy the clipboard window and unregister its class
773 static void OLEClipbrd_DestroyWindow(HWND hwnd)
776 * Destroy clipboard window and unregister its WNDCLASS
779 UnregisterClassA( OLEClipbrd_WNDCLASS, 0 );
782 /***********************************************************************
783 * OLEClipbrd_WndProc(HWND, unsigned, WORD, LONG)
784 * Processes messages sent to the OLE clipboard window.
785 * Note that we will intercept messages in our WndProc only when data
786 * has been placed in the clipboard via OleSetClipboard().
787 * i.e. Only when OLE owns the windows clipboard.
789 LRESULT CALLBACK OLEClipbrd_WndProc
790 (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
796 * We receive this message to allow us to handle delayed rendering of
797 * a specific clipboard format when an application requests data in
798 * that format by calling GetClipboardData.
799 * (Recall that in OleSetClipboard, we used SetClipboardData to
800 * make all HGLOBAL formats supported by the source IDataObject
801 * available using delayed rendering)
802 * On receiving this mesage we must actually render the data in the
803 * specified format and place it on the clipboard by calling the
804 * SetClipboardData function.
806 case WM_RENDERFORMAT:
810 ZeroMemory( &rgelt, sizeof(FORMATETC));
813 * Initialize FORMATETC to a Windows clipboard friendly format
815 rgelt.cfFormat = (UINT) wParam;
816 rgelt.dwAspect = DVASPECT_CONTENT;
818 rgelt.tymed = TYMED_HGLOBAL;
820 TRACE("(): WM_RENDERFORMAT(cfFormat=%d)\n", rgelt.cfFormat);
823 * Render the clipboard data.
824 * (We must have a source data object or we wouldn't be in this WndProc)
826 OLEClipbrd_RenderFormat( (IDataObject*)&(theOleClipboard->lpvtbl1), &rgelt );
832 * WM_RENDERALLFORMATS
833 * Sent before the clipboard owner window is destroyed.
834 * We should receive this message only when OleUninitialize is called
835 * while we have an IDataObject in the clipboard.
836 * For the content of the clipboard to remain available to other
837 * applications, we must render data in all the formats the source IDataObject
838 * is capable of generating, and place the data on the clipboard by calling
841 case WM_RENDERALLFORMATS:
843 IEnumFORMATETC* penumFormatetc = NULL;
846 TRACE("(): WM_RENDERALLFORMATS\n");
849 * Render all HGLOBAL formats supported by the source into
850 * the windows clipboard.
852 if ( FAILED( IDataObject_EnumFormatEtc( (IDataObject*)&(theOleClipboard->lpvtbl1),
853 DATADIR_GET, &penumFormatetc) ) )
855 WARN("(): WM_RENDERALLFORMATS failed to retrieve EnumFormatEtc!\n");
859 while ( S_OK == IEnumFORMATETC_Next(penumFormatetc, 1, &rgelt, NULL) )
861 if ( rgelt.tymed == TYMED_HGLOBAL )
864 * Render the clipboard data.
866 if ( FAILED(OLEClipbrd_RenderFormat( (IDataObject*)&(theOleClipboard->lpvtbl1), &rgelt )) )
869 TRACE("(): WM_RENDERALLFORMATS(cfFormat=%d)\n", rgelt.cfFormat);
873 IEnumFORMATETC_Release(penumFormatetc);
879 * WM_DESTROYCLIPBOARD
880 * This is sent by EmptyClipboard before the clipboard is emptied.
881 * We should release any IDataObject we are holding onto when we receive
882 * this message, since it indicates that the OLE clipboard should be empty
883 * from this point on.
885 case WM_DESTROYCLIPBOARD:
887 TRACE("(): WM_DESTROYCLIPBOARD\n");
889 * Release the data object we are holding on to
891 if ( theOleClipboard->pIDataObjectSrc )
893 IDataObject_Release(theOleClipboard->pIDataObjectSrc);
894 theOleClipboard->pIDataObjectSrc = NULL;
900 case WM_ASKCBFORMATNAME:
901 case WM_CHANGECBCHAIN:
902 case WM_DRAWCLIPBOARD:
903 case WM_SIZECLIPBOARD:
904 case WM_HSCROLLCLIPBOARD:
905 case WM_VSCROLLCLIPBOARD:
906 case WM_PAINTCLIPBOARD:
909 return DefWindowProcA(hWnd, message, wParam, lParam);
915 #define MAX_CLIPFORMAT_NAME 80
917 /***********************************************************************
918 * OLEClipbrd_RenderFormat(LPFORMATETC)
919 * Render the clipboard data. Note that this call will delegate to the
920 * source data object.
921 * Note: This function assumes it is passed an HGLOBAL format to render.
923 static HRESULT OLEClipbrd_RenderFormat(IDataObject *pIDataObject, LPFORMATETC pFormatetc)
928 char szFmtName[MAX_CLIPFORMAT_NAME];
929 ILockBytes *ptrILockBytes = 0;
930 HGLOBAL hStorage = 0;
932 GetClipboardFormatNameA(pFormatetc->cfFormat, szFmtName, MAX_CLIPFORMAT_NAME);
934 /* If embed source */
935 if (!strcmp(szFmtName, CF_EMBEDSOURCE))
937 memset(&std, 0, sizeof(STGMEDIUM));
938 std.tymed = pFormatetc->tymed = TYMED_ISTORAGE;
940 hStorage = GlobalAlloc(GMEM_SHARE|GMEM_MOVEABLE, 0);
941 hr = CreateILockBytesOnHGlobal(hStorage, FALSE, &ptrILockBytes);
942 hr = StgCreateDocfileOnILockBytes(ptrILockBytes, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &std.u.pstg);
944 if (FAILED(hr = IDataObject_GetDataHere(theOleClipboard->pIDataObjectSrc, pFormatetc, &std)))
946 WARN("() : IDataObject_GetDataHere failed to render clipboard data! (%lx)\n", hr);
950 if (1) /* check whether the presentation data is already -not- present */
954 METAFILEPICT *mfp = 0;
956 fmt2.cfFormat = CF_METAFILEPICT;
958 fmt2.dwAspect = DVASPECT_CONTENT;
960 fmt2.tymed = TYMED_MFPICT;
962 memset(&std2, 0, sizeof(STGMEDIUM));
963 std2.tymed = TYMED_MFPICT;
965 /* Get the metafile picture out of it */
967 if (!FAILED(hr = IDataObject_GetData(theOleClipboard->pIDataObjectSrc, &fmt2, &std2)))
969 mfp = (METAFILEPICT *)GlobalLock(std2.u.hGlobal);
974 OLECHAR name[]={ 2, 'O', 'l', 'e', 'P', 'r', 'e', 's', '0', '0', '0', 0};
975 IStream *pStream = 0;
977 PresentationDataHeader pdh;
981 CHAR strOleTypeName[51];
982 BYTE OlePresStreamHeader [] =
984 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00,
985 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
986 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
987 0x00, 0x00, 0x00, 0x00
990 nSize = GetMetaFileBitsEx(mfp->hMF, 0, NULL);
992 memset(&pdh, 0, sizeof(PresentationDataHeader));
993 memcpy(&pdh, OlePresStreamHeader, sizeof(OlePresStreamHeader));
995 pdh.dwObjectExtentX = mfp->xExt;
996 pdh.dwObjectExtentY = mfp->yExt;
999 hr = IStorage_CreateStream(std.u.pstg, name, STGM_CREATE|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, 0, &pStream);
1001 hr = IStream_Write(pStream, &pdh, sizeof(PresentationDataHeader), NULL);
1003 mfBits = HeapAlloc(GetProcessHeap(), 0, nSize);
1004 nSize = GetMetaFileBitsEx(mfp->hMF, nSize, mfBits);
1006 hr = IStream_Write(pStream, mfBits, nSize, NULL);
1008 IStream_Release(pStream);
1010 HeapFree(GetProcessHeap(), 0, mfBits);
1012 GlobalUnlock(std2.u.hGlobal);
1014 ReadClassStg(std.u.pstg, &clsID);
1015 ProgIDFromCLSID(&clsID, &strProgID);
1017 WideCharToMultiByte( CP_ACP, 0, strProgID, -1, strOleTypeName, sizeof(strOleTypeName), NULL, NULL );
1018 OLECONVERT_CreateOleStream(std.u.pstg);
1019 OLECONVERT_CreateCompObjStream(std.u.pstg, strOleTypeName);
1025 if (FAILED(hr = IDataObject_GetData(pIDataObject, pFormatetc, &std)))
1027 WARN("() : IDataObject_GetData failed to render clipboard data! (%lx)\n", hr);
1031 /* To put a copy back on the clipboard */
1033 hStorage = std.u.hGlobal;
1037 * Put a copy of the rendered data back on the clipboard
1040 if ( !(hDup = OLEClipbrd_GlobalDupMem(hStorage)) )
1041 HANDLE_ERROR( E_OUTOFMEMORY );
1043 if ( !SetClipboardData( pFormatetc->cfFormat, hDup ) )
1046 WARN("() : Failed to set rendered clipboard data into clipboard!\n");
1051 ReleaseStgMedium(&std);
1057 /***********************************************************************
1058 * OLEClipbrd_GlobalDupMem( HGLOBAL )
1059 * Helper method to duplicate an HGLOBAL chunk of memory
1061 static HGLOBAL OLEClipbrd_GlobalDupMem( HGLOBAL hGlobalSrc )
1063 HGLOBAL hGlobalDest;
1064 PVOID pGlobalSrc, pGlobalDest;
1070 cBytes = GlobalSize(hGlobalSrc);
1074 hGlobalDest = GlobalAlloc( GMEM_DDESHARE|GMEM_MOVEABLE,
1079 pGlobalSrc = GlobalLock(hGlobalSrc);
1080 pGlobalDest = GlobalLock(hGlobalDest);
1081 if ( !pGlobalSrc || !pGlobalDest )
1084 memcpy(pGlobalDest, pGlobalSrc, cBytes);
1086 GlobalUnlock(hGlobalSrc);
1087 GlobalUnlock(hGlobalDest);
1093 /*---------------------------------------------------------------------*
1094 * Implementation of the internal IDataObject interface exposed by
1095 * the OLE clipboard.
1096 *---------------------------------------------------------------------*/
1099 /************************************************************************
1100 * OLEClipbrd_IDataObject_QueryInterface (IUnknown)
1102 * See Windows documentation for more details on IUnknown methods.
1104 static HRESULT WINAPI OLEClipbrd_IDataObject_QueryInterface(
1110 * Declare "This" pointer
1112 ICOM_THIS(OLEClipbrd, iface);
1113 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObject);
1116 * Perform a sanity check on the parameters.
1118 if ( (This==0) || (ppvObject==0) )
1119 return E_INVALIDARG;
1122 * Initialize the return parameter.
1127 * Compare the riid with the interface IDs implemented by this object.
1129 if (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0)
1133 else if (memcmp(&IID_IDataObject, riid, sizeof(IID_IDataObject)) == 0)
1135 *ppvObject = (IDataObject*)&(This->lpvtbl1);
1137 else /* We only support IUnknown and IDataObject */
1139 WARN( "() : asking for unsupported interface %s\n", debugstr_guid(riid));
1140 return E_NOINTERFACE;
1144 * Query Interface always increases the reference count by one when it is
1147 IUnknown_AddRef((IUnknown*)*ppvObject);
1152 /************************************************************************
1153 * OLEClipbrd_IDataObject_AddRef (IUnknown)
1155 * See Windows documentation for more details on IUnknown methods.
1157 static ULONG WINAPI OLEClipbrd_IDataObject_AddRef(
1161 * Declare "This" pointer
1163 ICOM_THIS(OLEClipbrd, iface);
1165 TRACE("(%p)->(count=%lu)\n",This, This->ref);
1172 /************************************************************************
1173 * OLEClipbrd_IDataObject_Release (IUnknown)
1175 * See Windows documentation for more details on IUnknown methods.
1177 static ULONG WINAPI OLEClipbrd_IDataObject_Release(
1181 * Declare "This" pointer
1183 ICOM_THIS(OLEClipbrd, iface);
1185 TRACE("(%p)->(count=%lu)\n",This, This->ref);
1188 * Decrease the reference count on this object.
1193 * If the reference count goes down to 0, perform suicide.
1197 OLEClipbrd_Destroy(This);
1204 /************************************************************************
1205 * OLEClipbrd_IDataObject_GetData (IDataObject)
1207 * The OLE Clipboard's implementation of this method delegates to
1208 * a data source if there is one or wraps around the windows clipboard
1210 * See Windows documentation for more details on IDataObject methods.
1212 static HRESULT WINAPI OLEClipbrd_IDataObject_GetData(
1214 LPFORMATETC pformatetcIn,
1218 BOOL bClipboardOpen = FALSE;
1223 * Declare "This" pointer
1225 ICOM_THIS(OLEClipbrd, iface);
1227 TRACE("(%p,%p,%p)\n", iface, pformatetcIn, pmedium);
1229 if ( !pformatetcIn || !pmedium )
1230 return E_INVALIDARG;
1233 * If we have a data source placed on the clipboard (via OleSetClipboard)
1234 * simply delegate to the source object's QueryGetData
1235 * NOTE: This code assumes that the IDataObject is in the same address space!
1236 * We will need to add marshalling support when Wine handles multiple processes.
1238 if ( This->pIDataObjectSrc )
1240 return IDataObject_GetData(This->pIDataObjectSrc, pformatetcIn, pmedium);
1243 if ( pformatetcIn->lindex != -1 )
1245 if ( (pformatetcIn->tymed & TYMED_HGLOBAL) != TYMED_HGLOBAL )
1248 if ( pformatetcIn->dwAspect != DVASPECT_CONTENT )
1249 return DV_E_DVASPECT;
1253 * Otherwise, get the data from the windows clipboard using GetClipboardData
1255 if ( !(bClipboardOpen = OpenClipboard(theOleClipboard->hWndClipboard)) )
1256 HANDLE_ERROR( CLIPBRD_E_CANT_OPEN );
1258 hData = GetClipboardData(pformatetcIn->cfFormat);
1260 /* Must make a copy of global handle returned by GetClipboardData; it
1261 * is not valid after we call CloseClipboard
1262 * Application is responsible for freeing the memory (Forte Agent does this)
1264 src = GlobalLock(hData);
1270 size = GlobalSize(hData);
1271 hDest = GlobalAlloc(GHND, size);
1272 dest = GlobalLock(hDest);
1273 memcpy(dest, src, size);
1274 GlobalUnlock(hDest);
1275 GlobalUnlock(hData);
1280 * Return the clipboard data in the storage medium structure
1282 pmedium->tymed = (hData == 0) ? TYMED_NULL : TYMED_HGLOBAL;
1283 pmedium->u.hGlobal = (HGLOBAL)hData;
1284 pmedium->pUnkForRelease = NULL;
1290 * Close Windows clipboard
1292 if ( bClipboardOpen && !CloseClipboard() )
1293 hr = CLIPBRD_E_CANT_CLOSE;
1297 return (hData == 0) ? DV_E_FORMATETC : S_OK;
1300 static HRESULT WINAPI OLEClipbrd_IDataObject_GetDataHere(
1302 LPFORMATETC pformatetc,
1309 /************************************************************************
1310 * OLEClipbrd_IDataObject_QueryGetData (IDataObject)
1312 * The OLE Clipboard's implementation of this method delegates to
1313 * a data source if there is one or wraps around the windows clipboard
1314 * function IsClipboardFormatAvailable() otherwise.
1316 * See Windows documentation for more details on IDataObject methods.
1318 static HRESULT WINAPI OLEClipbrd_IDataObject_QueryGetData(
1320 LPFORMATETC pformatetc)
1323 * Declare "This" pointer
1325 ICOM_THIS(OLEClipbrd, iface);
1327 TRACE("(%p, %p)\n", iface, pformatetc);
1330 * If we have a data source placed on the clipboard (via OleSetClipboard)
1331 * simply delegate to the source object's QueryGetData
1333 if ( This->pIDataObjectSrc )
1335 return IDataObject_QueryGetData(This->pIDataObjectSrc, pformatetc);
1339 return E_INVALIDARG;
1341 if ( pformatetc->dwAspect != DVASPECT_CONTENT )
1342 return DV_E_DVASPECT;
1344 if ( pformatetc->lindex != -1 )
1347 /* TODO: Handle TYMED_IStorage media which were put on the clipboard
1348 * by copying the storage into global memory. We must convert this
1349 * TYMED_HGLOBAL back to TYMED_IStorage.
1351 if ( pformatetc->tymed != TYMED_HGLOBAL )
1355 * Delegate to the Windows clipboard function IsClipboardFormatAvailable
1357 return (IsClipboardFormatAvailable(pformatetc->cfFormat)) ? S_OK : DV_E_FORMATETC;
1360 /************************************************************************
1361 * OLEClipbrd_IDataObject_GetCanonicalFormatEtc (IDataObject)
1363 * See Windows documentation for more details on IDataObject methods.
1365 static HRESULT WINAPI OLEClipbrd_IDataObject_GetCanonicalFormatEtc(
1367 LPFORMATETC pformatectIn,
1368 LPFORMATETC pformatetcOut)
1370 TRACE("(%p, %p, %p)\n", iface, pformatectIn, pformatetcOut);
1372 if ( !pformatectIn || !pformatetcOut )
1373 return E_INVALIDARG;
1375 memcpy(pformatetcOut, pformatectIn, sizeof(FORMATETC));
1376 return DATA_S_SAMEFORMATETC;
1379 /************************************************************************
1380 * OLEClipbrd_IDataObject_SetData (IDataObject)
1382 * The OLE Clipboard's does not implement this method
1384 * See Windows documentation for more details on IDataObject methods.
1386 static HRESULT WINAPI OLEClipbrd_IDataObject_SetData(
1388 LPFORMATETC pformatetc,
1396 /************************************************************************
1397 * OLEClipbrd_IDataObject_EnumFormatEtc (IDataObject)
1399 * See Windows documentation for more details on IDataObject methods.
1401 static HRESULT WINAPI OLEClipbrd_IDataObject_EnumFormatEtc(
1404 IEnumFORMATETC** ppenumFormatEtc)
1407 FORMATETC *afmt = NULL;
1410 BOOL bClipboardOpen;
1413 * Declare "This" pointer
1415 ICOM_THIS(OLEClipbrd, iface);
1417 TRACE("(%p, %lx, %p)\n", iface, dwDirection, ppenumFormatEtc);
1420 * If we have a data source placed on the clipboard (via OleSetClipboard)
1421 * simply delegate to the source object's EnumFormatEtc
1423 if ( This->pIDataObjectSrc )
1425 return IDataObject_EnumFormatEtc(This->pIDataObjectSrc,
1426 dwDirection, ppenumFormatEtc);
1430 * Otherwise we must provide our own enumerator which wraps around the
1431 * Windows clipboard function EnumClipboardFormats
1433 if ( !ppenumFormatEtc )
1434 return E_INVALIDARG;
1436 if ( dwDirection != DATADIR_GET ) /* IDataObject_SetData not implemented */
1440 * Store all current clipboard formats in an array of FORMATETC's,
1441 * and create an IEnumFORMATETC enumerator from this list.
1443 cfmt = CountClipboardFormats();
1444 afmt = (FORMATETC *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1445 sizeof(FORMATETC) * cfmt);
1447 * Open the Windows clipboard, associating it with our hidden window
1449 if ( !(bClipboardOpen = OpenClipboard(This->hWndClipboard)) )
1450 HANDLE_ERROR( CLIPBRD_E_CANT_OPEN );
1453 * Store all current clipboard formats in an array of FORMATETC's
1454 * TODO: Handle TYMED_IStorage media which were put on the clipboard
1455 * by copying the storage into global memory. We must convert this
1456 * TYMED_HGLOBAL back to TYMED_IStorage.
1458 for (i = 0, format = 0; i < cfmt; i++)
1460 format = EnumClipboardFormats(format);
1461 if (!format) /* Failed! */
1463 ERR("EnumClipboardFormats failed to return format!\n");
1464 HANDLE_ERROR( E_FAIL );
1467 /* Init the FORMATETC struct */
1468 afmt[i].cfFormat = format;
1470 afmt[i].dwAspect = DVASPECT_CONTENT;
1471 afmt[i].lindex = -1;
1472 afmt[i].tymed = TYMED_HGLOBAL;
1476 * Create an EnumFORMATETC enumerator and return an
1477 * EnumFORMATETC after bumping up its ref count
1479 *ppenumFormatEtc = OLEClipbrd_IEnumFORMATETC_Construct( cfmt, afmt, (LPUNKNOWN)iface);
1480 if (!(*ppenumFormatEtc))
1481 HANDLE_ERROR( E_OUTOFMEMORY );
1483 if (FAILED( hr = IEnumFORMATETC_AddRef(*ppenumFormatEtc)))
1490 * Free the array of FORMATETC's
1493 HeapFree(GetProcessHeap(), 0, afmt);
1496 * Close Windows clipboard
1498 if ( bClipboardOpen && !CloseClipboard() )
1499 hr = CLIPBRD_E_CANT_CLOSE;
1504 /************************************************************************
1505 * OLEClipbrd_IDataObject_DAdvise (IDataObject)
1507 * The OLE Clipboard's does not implement this method
1509 * See Windows documentation for more details on IDataObject methods.
1511 static HRESULT WINAPI OLEClipbrd_IDataObject_DAdvise(
1513 FORMATETC* pformatetc,
1515 IAdviseSink* pAdvSink,
1516 DWORD* pdwConnection)
1522 /************************************************************************
1523 * OLEClipbrd_IDataObject_DUnadvise (IDataObject)
1525 * The OLE Clipboard's does not implement this method
1527 * See Windows documentation for more details on IDataObject methods.
1529 static HRESULT WINAPI OLEClipbrd_IDataObject_DUnadvise(
1537 /************************************************************************
1538 * OLEClipbrd_IDataObject_EnumDAdvise (IDataObject)
1540 * The OLE Clipboard does not implement this method
1542 * See Windows documentation for more details on IDataObject methods.
1544 static HRESULT WINAPI OLEClipbrd_IDataObject_EnumDAdvise(
1546 IEnumSTATDATA** ppenumAdvise)
1553 /*---------------------------------------------------------------------*
1554 * Implementation of the internal IEnumFORMATETC interface returned by
1555 * the OLE clipboard's IDataObject.
1556 *---------------------------------------------------------------------*/
1558 /************************************************************************
1559 * OLEClipbrd_IEnumFORMATETC_Construct (UINT, const FORMATETC, LPUNKNOWN)
1561 * Creates an IEnumFORMATETC enumerator from an array of FORMATETC
1562 * Structures. pUnkOuter is the outer unknown for reference counting only.
1563 * NOTE: this does not AddRef the interface.
1566 LPENUMFORMATETC OLEClipbrd_IEnumFORMATETC_Construct(UINT cfmt, const FORMATETC afmt[],
1567 LPUNKNOWN pUnkDataObj)
1569 IEnumFORMATETCImpl* ef;
1570 DWORD size=cfmt * sizeof(FORMATETC);
1573 ef = (IEnumFORMATETCImpl*)HeapAlloc(GetProcessHeap(),
1575 sizeof(IEnumFORMATETCImpl));
1581 ef->pUnkDataObj = pUnkDataObj;
1584 ef->countFmt = cfmt;
1585 if (FAILED(CoGetMalloc(MEMCTX_TASK, &pIMalloc))) {
1586 HeapFree(GetProcessHeap(), 0, ef);
1589 ef->pFmt = (LPFORMATETC)IMalloc_Alloc(pIMalloc, size);
1590 IMalloc_Release(pIMalloc);
1593 memcpy(ef->pFmt, afmt, size);
1595 TRACE("(%p)->()\n",ef);
1596 return (LPENUMFORMATETC)ef;
1600 /************************************************************************
1601 * OLEClipbrd_IEnumFORMATETC_QueryInterface (IUnknown)
1603 * See Windows documentation for more details on IUnknown methods.
1605 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_QueryInterface
1606 (LPENUMFORMATETC iface, REFIID riid, LPVOID* ppvObj)
1608 ICOM_THIS(IEnumFORMATETCImpl,iface);
1610 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
1613 * Since enumerators are separate objects from the parent data object
1614 * we only need to support the IUnknown and IEnumFORMATETC interfaces
1619 if(IsEqualIID(riid, &IID_IUnknown))
1623 else if(IsEqualIID(riid, &IID_IEnumFORMATETC))
1625 *ppvObj = (IDataObject*)This;
1630 IEnumFORMATETC_AddRef((IEnumFORMATETC*)*ppvObj);
1631 TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
1635 TRACE("-- Interface: E_NOINTERFACE\n");
1636 return E_NOINTERFACE;
1639 /************************************************************************
1640 * OLEClipbrd_IEnumFORMATETC_AddRef (IUnknown)
1642 * Since enumerating formats only makes sense when our data object is around,
1643 * we insure that it stays as long as we stay by calling our parents IUnknown
1644 * for AddRef and Release. But since we are not controlled by the lifetime of
1645 * the outer object, we still keep our own reference count in order to
1648 static ULONG WINAPI OLEClipbrd_IEnumFORMATETC_AddRef(LPENUMFORMATETC iface)
1650 ICOM_THIS(IEnumFORMATETCImpl,iface);
1651 TRACE("(%p)->(count=%lu)\n",This, This->ref);
1653 if (This->pUnkDataObj)
1654 IUnknown_AddRef(This->pUnkDataObj);
1656 return ++(This->ref);
1659 /************************************************************************
1660 * OLEClipbrd_IEnumFORMATETC_Release (IUnknown)
1662 * See Windows documentation for more details on IUnknown methods.
1664 static ULONG WINAPI OLEClipbrd_IEnumFORMATETC_Release(LPENUMFORMATETC iface)
1666 ICOM_THIS(IEnumFORMATETCImpl,iface);
1669 TRACE("(%p)->(count=%lu)\n",This, This->ref);
1671 if (This->pUnkDataObj)
1672 IUnknown_Release(This->pUnkDataObj); /* Release parent data object */
1676 TRACE("() - destroying IEnumFORMATETC(%p)\n",This);
1677 if (SUCCEEDED(CoGetMalloc(MEMCTX_TASK, &pIMalloc)))
1679 IMalloc_Free(pIMalloc, This->pFmt);
1680 IMalloc_Release(pIMalloc);
1683 HeapFree(GetProcessHeap(),0,This);
1690 /************************************************************************
1691 * OLEClipbrd_IEnumFORMATETC_Next (IEnumFORMATETC)
1693 * Standard enumerator members for IEnumFORMATETC
1695 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Next
1696 (LPENUMFORMATETC iface, ULONG celt, FORMATETC *rgelt, ULONG *pceltFethed)
1698 ICOM_THIS(IEnumFORMATETCImpl,iface);
1700 HRESULT hres = S_FALSE;
1702 TRACE("(%p)->(pos=%u)\n", This, This->posFmt);
1704 if (This->posFmt < This->countFmt)
1706 cfetch = This->countFmt - This->posFmt;
1713 memcpy(rgelt, &This->pFmt[This->posFmt], cfetch * sizeof(FORMATETC));
1714 This->posFmt += cfetch;
1723 *pceltFethed = cfetch;
1729 /************************************************************************
1730 * OLEClipbrd_IEnumFORMATETC_Skip (IEnumFORMATETC)
1732 * Standard enumerator members for IEnumFORMATETC
1734 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Skip(LPENUMFORMATETC iface, ULONG celt)
1736 ICOM_THIS(IEnumFORMATETCImpl,iface);
1737 TRACE("(%p)->(num=%lu)\n", This, celt);
1739 This->posFmt += celt;
1740 if (This->posFmt > This->countFmt)
1742 This->posFmt = This->countFmt;
1748 /************************************************************************
1749 * OLEClipbrd_IEnumFORMATETC_Reset (IEnumFORMATETC)
1751 * Standard enumerator members for IEnumFORMATETC
1753 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Reset(LPENUMFORMATETC iface)
1755 ICOM_THIS(IEnumFORMATETCImpl,iface);
1756 TRACE("(%p)->()\n", This);
1762 /************************************************************************
1763 * OLEClipbrd_IEnumFORMATETC_Clone (IEnumFORMATETC)
1765 * Standard enumerator members for IEnumFORMATETC
1767 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Clone
1768 (LPENUMFORMATETC iface, LPENUMFORMATETC* ppenum)
1770 ICOM_THIS(IEnumFORMATETCImpl,iface);
1773 TRACE("(%p)->(ppenum=%p)\n", This, ppenum);
1776 return E_INVALIDARG;
1778 *ppenum = OLEClipbrd_IEnumFORMATETC_Construct(This->countFmt,
1782 if (FAILED( hr = IEnumFORMATETC_AddRef(*ppenum)))
1785 return (*ppenum) ? S_OK : E_OUTOFMEMORY;