2 * OLE 2 clipboard support
4 * Copyright 1999 Noel Borthwick <noel@macadamian.com>
5 * Copyright 2000 Abey George <abey@macadamian.com>
8 * This file contains the implementation for the OLE Clipboard and its
9 * internal interfaces. The OLE clipboard interacts with an IDataObject
10 * interface via the OleSetClipboard, OleGetClipboard and
11 * OleIsCurrentClipboard API's. An internal IDataObject delegates
12 * to a client supplied IDataObject or the WIN32 clipboard API depending
13 * on whether OleSetClipboard has been invoked.
14 * Here are some operating scenarios:
16 * 1. OleSetClipboard called: In this case the internal IDataObject
17 * delegates to the client supplied IDataObject. Additionally OLE takes
18 * ownership of the Windows clipboard and any HGLOCBAL IDataObject
19 * items are placed on the Windows clipboard. This allows non OLE aware
20 * applications to access these. A local WinProc fields WM_RENDERFORMAT
21 * and WM_RENDERALLFORMATS messages in this case.
23 * 2. OleGetClipboard called without previous OleSetClipboard. Here the internal
24 * IDataObject functionality wraps around the WIN32 clipboard API.
26 * 3. OleGetClipboard called after previous OleSetClipboard. Here the internal
27 * IDataObject delegates to the source IDataObjects functionality directly,
28 * thereby bypassing the Windows clipboard.
30 * Implementation references : Inside OLE 2'nd edition by Kraig Brockschmidt
33 * - Support for pasting between different processes. OLE clipboard support
34 * currently works only for in process copy and paste. Since we internally
35 * store a pointer to the source's IDataObject and delegate to that, this
36 * will fail if the IDataObject client belongs to a different process.
37 * - IDataObject::GetDataHere is not implemented
38 * - OleFlushClipboard needs to additionally handle TYMED_IStorage media
39 * by copying the storage into global memory. Subsequently the default
40 * data object exposed through OleGetClipboard must convert this TYMED_HGLOBAL
41 * back to TYMED_IStorage.
42 * - OLE1 compatibility formats to be synthesized from OLE2 formats and put on
43 * clipboard in OleSetClipboard.
54 #include "debugtools.h"
57 #define HANDLE_ERROR(err) { hr = err; TRACE("(HRESULT=%lx)\n", (HRESULT)err); goto CLEANUP; }
59 /* For CoGetMalloc (MEMCTX_TASK is currently ignored) */
61 #define MEMCTX_TASK -1
64 DEFAULT_DEBUG_CHANNEL(ole)
66 /****************************************************************************
68 * DO NOT add any members before the VTables declaration!
73 * List all interface VTables here
75 ICOM_VTABLE(IDataObject)* lpvtbl1; /* IDataObject VTable */
78 * The hidden OLE clipboard window. This window is used as the bridge between the
79 * the OLE and windows clipboard API. (Windows creates one such window per process)
84 * Pointer to the source data object (via OleSetClipboard)
86 IDataObject* pIDataObjectSrc;
89 * The registered DataObject clipboard format
94 * The handle to our ourself
99 * Reference count of this object
104 typedef struct OLEClipbrd OLEClipbrd;
107 /****************************************************************************
108 * IEnumFORMATETC implementation
109 * DO NOT add any members before the VTables declaration!
113 /* IEnumFORMATETC VTable */
114 ICOM_VFIELD(IEnumFORMATETC);
116 /* IEnumFORMATETC fields */
117 UINT posFmt; /* current enumerator position */
118 UINT countFmt; /* number of EnumFORMATETC's in array */
119 LPFORMATETC pFmt; /* array of EnumFORMATETC's */
122 * Reference count of this object
127 * IUnknown implementation of the parent data object.
129 IUnknown* pUnkDataObj;
131 } IEnumFORMATETCImpl;
133 typedef struct PresentationDataHeader
136 DWORD dwObjectExtentX;
137 DWORD dwObjectExtentY;
139 } PresentationDataHeader;
142 * The one and only OLEClipbrd object which is created by OLEClipbrd_Initialize()
144 static HGLOBAL hTheOleClipboard = 0;
145 static OLEClipbrd* theOleClipboard = NULL;
149 * Prototypes for the methods of the OLEClipboard class.
151 extern void OLEClipbrd_Initialize();
152 extern void OLEClipbrd_UnInitialize();
153 static OLEClipbrd* OLEClipbrd_Construct();
154 static void OLEClipbrd_Destroy(OLEClipbrd* ptrToDestroy);
155 static HWND OLEClipbrd_CreateWindow();
156 static void OLEClipbrd_DestroyWindow(HWND hwnd);
157 LRESULT CALLBACK OLEClipbrd_WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
158 static HRESULT OLEClipbrd_RenderFormat( IDataObject *pIDataObject, LPFORMATETC pFormatetc );
159 static HGLOBAL OLEClipbrd_GlobalDupMem( HGLOBAL hGlobalSrc );
162 * Prototypes for the methods of the OLEClipboard class
163 * that implement IDataObject methods.
165 static HRESULT WINAPI OLEClipbrd_IDataObject_QueryInterface(
169 static ULONG WINAPI OLEClipbrd_IDataObject_AddRef(
171 static ULONG WINAPI OLEClipbrd_IDataObject_Release(
173 static HRESULT WINAPI OLEClipbrd_IDataObject_GetData(
175 LPFORMATETC pformatetcIn,
177 static HRESULT WINAPI OLEClipbrd_IDataObject_GetDataHere(
179 LPFORMATETC pformatetc,
181 static HRESULT WINAPI OLEClipbrd_IDataObject_QueryGetData(
183 LPFORMATETC pformatetc);
184 static HRESULT WINAPI OLEClipbrd_IDataObject_GetCanonicalFormatEtc(
186 LPFORMATETC pformatectIn,
187 LPFORMATETC pformatetcOut);
188 static HRESULT WINAPI OLEClipbrd_IDataObject_SetData(
190 LPFORMATETC pformatetc,
193 static HRESULT WINAPI OLEClipbrd_IDataObject_EnumFormatEtc(
196 IEnumFORMATETC** ppenumFormatEtc);
197 static HRESULT WINAPI OLEClipbrd_IDataObject_DAdvise(
199 FORMATETC* pformatetc,
201 IAdviseSink* pAdvSink,
202 DWORD* pdwConnection);
203 static HRESULT WINAPI OLEClipbrd_IDataObject_DUnadvise(
206 static HRESULT WINAPI OLEClipbrd_IDataObject_EnumDAdvise(
208 IEnumSTATDATA** ppenumAdvise);
211 * Prototypes for the IEnumFORMATETC methods.
213 static LPENUMFORMATETC OLEClipbrd_IEnumFORMATETC_Construct(UINT cfmt, const FORMATETC afmt[],
214 LPUNKNOWN pUnkDataObj);
215 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_QueryInterface(LPENUMFORMATETC iface, REFIID riid,
217 static ULONG WINAPI OLEClipbrd_IEnumFORMATETC_AddRef(LPENUMFORMATETC iface);
218 static ULONG WINAPI OLEClipbrd_IEnumFORMATETC_Release(LPENUMFORMATETC iface);
219 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Next(LPENUMFORMATETC iface, ULONG celt,
220 FORMATETC* rgelt, ULONG* pceltFethed);
221 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Skip(LPENUMFORMATETC iface, ULONG celt);
222 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Reset(LPENUMFORMATETC iface);
223 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Clone(LPENUMFORMATETC iface, LPENUMFORMATETC* ppenum);
227 * Virtual function table for the OLEClipbrd's exposed IDataObject interface
229 static ICOM_VTABLE(IDataObject) OLEClipbrd_IDataObject_VTable =
231 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
232 OLEClipbrd_IDataObject_QueryInterface,
233 OLEClipbrd_IDataObject_AddRef,
234 OLEClipbrd_IDataObject_Release,
235 OLEClipbrd_IDataObject_GetData,
236 OLEClipbrd_IDataObject_GetDataHere,
237 OLEClipbrd_IDataObject_QueryGetData,
238 OLEClipbrd_IDataObject_GetCanonicalFormatEtc,
239 OLEClipbrd_IDataObject_SetData,
240 OLEClipbrd_IDataObject_EnumFormatEtc,
241 OLEClipbrd_IDataObject_DAdvise,
242 OLEClipbrd_IDataObject_DUnadvise,
243 OLEClipbrd_IDataObject_EnumDAdvise
247 * Virtual function table for IEnumFORMATETC interface
249 static struct ICOM_VTABLE(IEnumFORMATETC) efvt =
251 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
252 OLEClipbrd_IEnumFORMATETC_QueryInterface,
253 OLEClipbrd_IEnumFORMATETC_AddRef,
254 OLEClipbrd_IEnumFORMATETC_Release,
255 OLEClipbrd_IEnumFORMATETC_Next,
256 OLEClipbrd_IEnumFORMATETC_Skip,
257 OLEClipbrd_IEnumFORMATETC_Reset,
258 OLEClipbrd_IEnumFORMATETC_Clone
262 * Name of our registered OLE clipboard window class
264 CHAR OLEClipbrd_WNDCLASS[] = "CLIPBRDWNDCLASS";
267 * If we need to store state info we can store it here.
268 * For now we dont need this functionality.
270 typedef struct tagClipboardWindowInfo
272 } ClipboardWindowInfo;
275 /*---------------------------------------------------------------------*
276 * Win32 OLE clipboard API
277 *---------------------------------------------------------------------*/
279 /***********************************************************************
280 * OleSetClipboard [OLE32.127]
281 * Places a pointer to the specified data object onto the clipboard,
282 * making the data object accessible to the OleGetClipboard function.
286 * S_OK IDataObject pointer placed on the clipboard
287 * CLIPBRD_E_CANT_OPEN OpenClipboard failed
288 * CLIPBRD_E_CANT_EMPTY EmptyClipboard failed
289 * CLIPBRD_E_CANT_CLOSE CloseClipboard failed
290 * CLIPBRD_E_CANT_SET SetClipboard failed
293 HRESULT WINAPI OleSetClipboard(IDataObject* pDataObj)
296 IEnumFORMATETC* penumFormatetc = NULL;
298 BOOL bClipboardOpen = FALSE;
300 HGLOBAL hDataObject = 0;
301 OLEClipbrd **ppDataObject;
304 TRACE("(%p)\n", pDataObj);
307 * Make sure we have a clipboard object
309 OLEClipbrd_Initialize();
312 * If the Ole clipboard window hasn't been created yet, create it now.
314 if ( !theOleClipboard->hWndClipboard )
315 theOleClipboard->hWndClipboard = OLEClipbrd_CreateWindow();
317 if ( !theOleClipboard->hWndClipboard ) /* sanity check */
318 HANDLE_ERROR( E_FAIL );
321 * Open the Windows clipboard, associating it with our hidden window
323 if ( !(bClipboardOpen = OpenClipboard(theOleClipboard->hWndClipboard)) )
324 HANDLE_ERROR( CLIPBRD_E_CANT_OPEN );
327 * Empty the current clipboard and make our window the clipboard owner
328 * NOTE: This will trigger a WM_DESTROYCLIPBOARD message
330 if ( !EmptyClipboard() )
331 HANDLE_ERROR( CLIPBRD_E_CANT_EMPTY );
334 * If we are already holding on to an IDataObject first release that.
336 if ( theOleClipboard->pIDataObjectSrc )
338 IDataObject_Release(theOleClipboard->pIDataObjectSrc);
339 theOleClipboard->pIDataObjectSrc = NULL;
343 * AddRef the data object passed in and save its pointer.
344 * A NULL value indicates that the clipboard should be emptied.
346 theOleClipboard->pIDataObjectSrc = pDataObj;
349 IDataObject_AddRef(theOleClipboard->pIDataObjectSrc);
353 * Enumerate all HGLOBAL formats supported by the source and make
354 * those formats available using delayed rendering using SetClipboardData.
355 * Only global memory based data items may be made available to non-OLE
356 * applications via the standard Windows clipboard API. Data based on other
357 * mediums(non TYMED_HGLOBAL) can only be accessed via the Ole Clipboard API.
359 * TODO: Do we need to additionally handle TYMED_IStorage media by copying
360 * the storage into global memory?
364 if ( FAILED(hr = IDataObject_EnumFormatEtc( pDataObj,
371 while ( S_OK == IEnumFORMATETC_Next(penumFormatetc, 1, &rgelt, NULL) )
373 if ( rgelt.tymed == TYMED_HGLOBAL )
376 TRACE("(cfFormat=%d:%s)\n", rgelt.cfFormat,
377 GetClipboardFormatNameA(rgelt.cfFormat, szFmtName, sizeof(szFmtName)-1)
380 SetClipboardData( rgelt.cfFormat, (HANDLE)NULL);
383 IEnumFORMATETC_Release(penumFormatetc);
387 * Windows additionally creates a new "DataObject" clipboard format
388 * and stores in on the clipboard. We could possibly store a pointer
389 * to our internal IDataObject interface on the clipboard. I'm not
390 * sure what the use of this is though.
391 * Enable the code below for this functionality.
394 theOleClipboard->cfDataObj = RegisterClipboardFormatA("DataObject");
395 hDataObject = GlobalAlloc( GMEM_DDESHARE|GMEM_MOVEABLE|GMEM_ZEROINIT,
396 sizeof(OLEClipbrd *));
398 HANDLE_ERROR( E_OUTOFMEMORY );
400 ppDataObject = (OLEClipbrd**)GlobalLock(hDataObject);
401 *ppDataObject = theOleClipboard;
402 GlobalUnlock(hDataObject);
404 if ( !SetClipboardData( theOleClipboard->cfDataObj, hDataObject ) )
405 HANDLE_ERROR( CLIPBRD_E_CANT_SET );
413 * Close Windows clipboard (It remains associated with our window)
415 if ( bClipboardOpen && !CloseClipboard() )
416 hr = CLIPBRD_E_CANT_CLOSE;
419 * Release the source IDataObject if something failed
423 if (theOleClipboard->pIDataObjectSrc)
425 IDataObject_Release(theOleClipboard->pIDataObjectSrc);
426 theOleClipboard->pIDataObjectSrc = NULL;
434 /***********************************************************************
435 * OleGetClipboard32 [OLE32.105]
436 * Returns a pointer to our internal IDataObject which represents the conceptual
437 * state of the Windows clipboard. If the current clipboard already contains
438 * an IDataObject, our internal IDataObject will delegate to this object.
440 HRESULT WINAPI OleGetClipboard(IDataObject** ppDataObj)
446 * Make sure we have a clipboard object
448 OLEClipbrd_Initialize();
450 if (!theOleClipboard)
451 return E_OUTOFMEMORY;
453 /* Return a reference counted IDataObject */
454 hr = IDataObject_QueryInterface( (IDataObject*)&(theOleClipboard->lpvtbl1),
455 &IID_IDataObject, (void**)ppDataObj);
459 /***********************************************************************
460 * OleFlushClipboard [OLE2.76]
463 HRESULT WINAPI OleFlushClipboard16(void)
465 return OleFlushClipboard();
469 /******************************************************************************
470 * OleFlushClipboard [OLE32.103]
471 * Renders the data from the source IDataObject into the windows clipboard
473 * TODO: OleFlushClipboard needs to additionally handle TYMED_IStorage media
474 * by copying the storage into global memory. Subsequently the default
475 * data object exposed through OleGetClipboard must convert this TYMED_HGLOBAL
476 * back to TYMED_IStorage.
478 HRESULT WINAPI OleFlushClipboard()
480 IEnumFORMATETC* penumFormatetc = NULL;
483 BOOL bClipboardOpen = FALSE;
484 IDataObject* pIDataObjectSrc = NULL;
489 * Make sure we have a clipboard object
491 OLEClipbrd_Initialize();
494 * Already flushed or no source DataObject? Nothing to do.
496 if (!theOleClipboard->pIDataObjectSrc)
500 * Addref and save the source data object we are holding on to temporarily,
501 * since it will be released when we empty the clipboard.
503 pIDataObjectSrc = theOleClipboard->pIDataObjectSrc;
504 IDataObject_AddRef(pIDataObjectSrc);
507 * Open the Windows clipboard
509 if ( !(bClipboardOpen = OpenClipboard(theOleClipboard->hWndClipboard)) )
510 HANDLE_ERROR( CLIPBRD_E_CANT_OPEN );
513 * Empty the current clipboard
515 if ( !EmptyClipboard() )
516 HANDLE_ERROR( CLIPBRD_E_CANT_EMPTY );
519 * Render all HGLOBAL formats supported by the source into
520 * the windows clipboard.
522 if ( FAILED( hr = IDataObject_EnumFormatEtc( pIDataObjectSrc,
529 while ( S_OK == IEnumFORMATETC_Next(penumFormatetc, 1, &rgelt, NULL) )
531 if ( rgelt.tymed == TYMED_HGLOBAL )
534 TRACE("(cfFormat=%d:%s)\n", rgelt.cfFormat,
535 GetClipboardFormatNameA(rgelt.cfFormat, szFmtName, sizeof(szFmtName)-1)
539 * Render the clipboard data
541 if ( FAILED(OLEClipbrd_RenderFormat( pIDataObjectSrc, &rgelt )) )
546 IEnumFORMATETC_Release(penumFormatetc);
549 * Release the source data object we are holding on to
551 IDataObject_Release(pIDataObjectSrc);
556 * Close Windows clipboard (It remains associated with our window)
558 if ( bClipboardOpen && !CloseClipboard() )
559 hr = CLIPBRD_E_CANT_CLOSE;
565 /***********************************************************************
566 * OleIsCurrentClipboard32 [OLE32.110]
568 HRESULT WINAPI OleIsCurrentClipboard ( IDataObject *pDataObject)
572 * Make sure we have a clipboard object
574 OLEClipbrd_Initialize();
576 if (!theOleClipboard)
577 return E_OUTOFMEMORY;
579 return (pDataObject == theOleClipboard->pIDataObjectSrc) ? S_OK : S_FALSE;
583 /*---------------------------------------------------------------------*
584 * Internal implementation methods for the OLE clipboard
585 *---------------------------------------------------------------------*/
587 /***********************************************************************
588 * OLEClipbrd_Initialize()
589 * Initializes the OLE clipboard.
591 void OLEClipbrd_Initialize()
594 * Create the clipboard if necesary
596 if ( !theOleClipboard )
599 theOleClipboard = OLEClipbrd_Construct();
604 /***********************************************************************
605 * OLEClipbrd_UnInitialize()
606 * Un-Initializes the OLE clipboard
608 void OLEClipbrd_UnInitialize()
612 * Destroy the clipboard if no one holds a reference to us.
613 * Note that the clipboard was created with a reference count of 1.
615 if ( theOleClipboard && (theOleClipboard->ref <= 1) )
617 OLEClipbrd_Destroy( theOleClipboard );
621 WARN( "() : OLEClipbrd_UnInitialize called while client holds an IDataObject reference!\n");
626 /*********************************************************
627 * Construct the OLEClipbrd class.
629 static OLEClipbrd* OLEClipbrd_Construct()
631 OLEClipbrd* newObject = NULL;
632 HGLOBAL hNewObject = 0;
635 * Allocate space for the object. We use GlobalAlloc since we need
636 * an HGLOBAL to expose our DataObject as a registered clipboard type.
638 hNewObject = GlobalAlloc( GMEM_DDESHARE|GMEM_MOVEABLE|GMEM_ZEROINIT,
644 * Lock the handle for the entire lifetime of the clipboard.
646 newObject = GlobalLock(hNewObject);
649 * Initialize the virtual function table.
651 newObject->lpvtbl1 = &OLEClipbrd_IDataObject_VTable;
654 * Start with one reference count. The caller of this function
655 * must release the interface pointer when it is done.
659 newObject->hSelf = hNewObject;
662 * The Ole clipboard is a singleton - save the global handle and pointer
664 theOleClipboard = newObject;
665 hTheOleClipboard = hNewObject;
667 return theOleClipboard;
670 static void OLEClipbrd_Destroy(OLEClipbrd* ptrToDestroy)
678 * Destroy the Ole clipboard window
680 if ( ptrToDestroy->hWndClipboard )
681 OLEClipbrd_DestroyWindow(ptrToDestroy->hWndClipboard);
684 * Free the actual OLE Clipboard structure.
686 TRACE("() - Destroying clipboard data object.\n");
687 GlobalUnlock(ptrToDestroy->hSelf);
688 GlobalFree(ptrToDestroy->hSelf);
691 * The Ole clipboard is a singleton (ptrToDestroy == theOleClipboard)
693 theOleClipboard = NULL;
694 hTheOleClipboard = 0;
698 /***********************************************************************
699 * OLEClipbrd_CreateWindow()
700 * Create the clipboard window
702 static HWND OLEClipbrd_CreateWindow()
708 * Register the clipboard window class if necessary
710 ZeroMemory( &wcex, sizeof(WNDCLASSEXA));
712 wcex.cbSize = sizeof(WNDCLASSEXA);
713 /* Windows creates this class with a style mask of 0
714 * We dont bother doing this since the FindClassByAtom code
715 * would have to be changed to deal with this idiosyncracy. */
716 wcex.style = CS_GLOBALCLASS;
717 wcex.lpfnWndProc = (WNDPROC)OLEClipbrd_WndProc;
719 wcex.lpszClassName = OLEClipbrd_WNDCLASS;
721 RegisterClassExA(&wcex);
724 * Create a hidden window to receive OLE clipboard messages
728 * If we need to store state info we can store it here.
729 * For now we dont need this functionality.
730 * ClipboardWindowInfo clipboardInfo;
731 * ZeroMemory( &trackerInfo, sizeof(ClipboardWindowInfo));
734 hwnd = CreateWindowA(OLEClipbrd_WNDCLASS,
736 WS_POPUP | WS_CLIPSIBLINGS | WS_OVERLAPPED,
737 CW_USEDEFAULT, CW_USEDEFAULT,
738 CW_USEDEFAULT, CW_USEDEFAULT,
742 0 /*(LPVOID)&clipboardInfo */);
747 /***********************************************************************
748 * OLEClipbrd_DestroyWindow(HWND)
749 * Destroy the clipboard window and unregister its class
751 static void OLEClipbrd_DestroyWindow(HWND hwnd)
754 * Destroy clipboard window and unregister its WNDCLASS
757 UnregisterClassA( OLEClipbrd_WNDCLASS, 0 );
760 /***********************************************************************
761 * OLEClipbrd_WndProc(HWND, unsigned, WORD, LONG)
762 * Processes messages sent to the OLE clipboard window.
763 * Note that we will intercept messages in our WndProc only when data
764 * has been placed in the clipboard via OleSetClipboard().
765 * i.e. Only when OLE owns the windows clipboard.
767 LRESULT CALLBACK OLEClipbrd_WndProc
768 (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
774 * We receive this message to allow us to handle delayed rendering of
775 * a specific clipboard format when an application requests data in
776 * that format by calling GetClipboardData.
777 * (Recall that in OleSetClipboard, we used SetClipboardData to
778 * make all HGLOBAL formats supported by the source IDataObject
779 * available using delayed rendering)
780 * On receiving this mesage we must actually render the data in the
781 * specified format and place it on the clipboard by calling the
782 * SetClipboardData function.
784 case WM_RENDERFORMAT:
788 ZeroMemory( &rgelt, sizeof(FORMATETC));
791 * Initialize FORMATETC to a Windows clipboard friendly format
793 rgelt.cfFormat = (UINT) wParam;
794 rgelt.dwAspect = DVASPECT_CONTENT;
796 rgelt.tymed = TYMED_HGLOBAL;
798 TRACE("(): WM_RENDERFORMAT(cfFormat=%d)\n", rgelt.cfFormat);
801 * Render the clipboard data.
802 * (We must have a source data object or we wouldn't be in this WndProc)
804 OLEClipbrd_RenderFormat( (IDataObject*)&(theOleClipboard->lpvtbl1), &rgelt );
810 * WM_RENDERALLFORMATS
811 * Sent before the clipboard owner window is destroyed.
812 * We should receive this message only when OleUninitialize is called
813 * while we have an IDataObject in the clipboard.
814 * For the content of the clipboard to remain available to other
815 * applications, we must render data in all the formats the source IDataObject
816 * is capable of generating, and place the data on the clipboard by calling
819 case WM_RENDERALLFORMATS:
821 IEnumFORMATETC* penumFormatetc = NULL;
824 TRACE("(): WM_RENDERALLFORMATS\n");
827 * Render all HGLOBAL formats supported by the source into
828 * the windows clipboard.
830 if ( FAILED( IDataObject_EnumFormatEtc( (IDataObject*)&(theOleClipboard->lpvtbl1),
831 DATADIR_GET, &penumFormatetc) ) )
833 WARN("(): WM_RENDERALLFORMATS failed to retrieve EnumFormatEtc!\n");
837 while ( S_OK == IEnumFORMATETC_Next(penumFormatetc, 1, &rgelt, NULL) )
839 if ( rgelt.tymed == TYMED_HGLOBAL )
842 * Render the clipboard data.
844 if ( FAILED(OLEClipbrd_RenderFormat( (IDataObject*)&(theOleClipboard->lpvtbl1), &rgelt )) )
847 TRACE("(): WM_RENDERALLFORMATS(cfFormat=%d)\n", rgelt.cfFormat);
851 IEnumFORMATETC_Release(penumFormatetc);
857 * WM_DESTROYCLIPBOARD
858 * This is sent by EmptyClipboard before the clipboard is emptied.
859 * We should release any IDataObject we are holding onto when we receive
860 * this message, since it indicates that the OLE clipboard should be empty
861 * from this point on.
863 case WM_DESTROYCLIPBOARD:
865 TRACE("(): WM_DESTROYCLIPBOARD\n");
867 * Release the data object we are holding on to
869 if ( theOleClipboard->pIDataObjectSrc )
871 IDataObject_Release(theOleClipboard->pIDataObjectSrc);
872 theOleClipboard->pIDataObjectSrc = NULL;
878 case WM_ASKCBFORMATNAME:
879 case WM_CHANGECBCHAIN:
880 case WM_DRAWCLIPBOARD:
881 case WM_SIZECLIPBOARD:
882 case WM_HSCROLLCLIPBOARD:
883 case WM_VSCROLLCLIPBOARD:
884 case WM_PAINTCLIPBOARD:
887 return DefWindowProcA(hWnd, message, wParam, lParam);
893 #define MAX_CLIPFORMAT_NAME 80
895 /***********************************************************************
896 * OLEClipbrd_RenderFormat(LPFORMATETC)
897 * Render the clipboard data. Note that this call will delegate to the
898 * source data object.
899 * Note: This function assumes it is passed an HGLOBAL format to render.
901 static HRESULT OLEClipbrd_RenderFormat(IDataObject *pIDataObject, LPFORMATETC pFormatetc)
906 char szFmtName[MAX_CLIPFORMAT_NAME];
907 ILockBytes *ptrILockBytes = 0;
908 HGLOBAL hStorage = 0;
910 GetClipboardFormatNameA(pFormatetc->cfFormat, szFmtName, MAX_CLIPFORMAT_NAME);
912 /* If embed source */
913 if (!strcmp(szFmtName, CF_EMBEDSOURCE))
915 memset(&std, 0, sizeof(STGMEDIUM));
916 std.tymed = pFormatetc->tymed = TYMED_ISTORAGE;
918 hStorage = GlobalAlloc(GMEM_SHARE|GMEM_MOVEABLE, 0);
919 hr = CreateILockBytesOnHGlobal(hStorage, FALSE, &ptrILockBytes);
920 hr = StgCreateDocfileOnILockBytes(ptrILockBytes, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &std.u.pstg);
922 if (FAILED(hr = IDataObject_GetDataHere(theOleClipboard->pIDataObjectSrc, pFormatetc, &std)))
924 WARN("() : IDataObject_GetDataHere failed to render clipboard data! (%lx)\n", hr);
928 if (1) /* check whether the presentation data is already -not- present */
932 METAFILEPICT *mfp = 0;
934 fmt2.cfFormat = CF_METAFILEPICT;
936 fmt2.dwAspect = DVASPECT_CONTENT;
938 fmt2.tymed = TYMED_MFPICT;
940 memset(&std2, 0, sizeof(STGMEDIUM));
941 std2.tymed = TYMED_MFPICT;
943 /* Get the metafile picture out of it */
945 if (!FAILED(hr = IDataObject_GetData(theOleClipboard->pIDataObjectSrc, &fmt2, &std2)))
947 mfp = (METAFILEPICT *)GlobalLock(std2.u.hMetaFilePict);
952 OLECHAR name[]={ 2, 'O', 'l', 'e', 'P', 'r', 'e', 's', '0', '0', '0', 0};
953 IStream *pStream = 0;
955 PresentationDataHeader pdh;
959 CHAR strOleTypeName[51];
960 BYTE OlePresStreamHeader [] =
962 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00,
963 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
964 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
965 0x00, 0x00, 0x00, 0x00
968 nSize = GetMetaFileBitsEx(mfp->hMF, 0, NULL);
970 memset(&pdh, 0, sizeof(PresentationDataHeader));
971 memcpy(&pdh, OlePresStreamHeader, sizeof(OlePresStreamHeader));
973 pdh.dwObjectExtentX = mfp->xExt;
974 pdh.dwObjectExtentY = mfp->yExt;
977 hr = IStorage_CreateStream(std.u.pstg, name, STGM_CREATE|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, 0, &pStream);
979 hr = IStream_Write(pStream, &pdh, sizeof(PresentationDataHeader), NULL);
981 mfBits = HeapAlloc(GetProcessHeap(), 0, nSize);
982 nSize = GetMetaFileBitsEx(mfp->hMF, nSize, mfBits);
984 hr = IStream_Write(pStream, mfBits, nSize, NULL);
986 IStream_Release(pStream);
988 HeapFree(GetProcessHeap(), 0, mfBits);
990 GlobalUnlock(std2.u.hMetaFilePict);
992 ReadClassStg(std.u.pstg, &clsID);
993 ProgIDFromCLSID(&clsID, &strProgID);
995 lstrcpyWtoA(strOleTypeName, strProgID);
996 OLECONVERT_CreateOleStream(std.u.pstg);
997 OLECONVERT_CreateCompObjStream(std.u.pstg, strOleTypeName);
1003 if (FAILED(hr = IDataObject_GetData(pIDataObject, pFormatetc, &std)))
1005 WARN("() : IDataObject_GetData failed to render clipboard data! (%lx)\n", hr);
1009 /* To put a copy back on the clipboard */
1011 hStorage = std.u.hGlobal;
1015 * Put a copy of the rendered data back on the clipboard
1018 if ( !(hDup = OLEClipbrd_GlobalDupMem(hStorage)) )
1019 HANDLE_ERROR( E_OUTOFMEMORY );
1021 if ( !SetClipboardData( pFormatetc->cfFormat, hDup ) )
1024 WARN("() : Failed to set rendered clipboard data into clipboard!\n");
1029 ReleaseStgMedium(&std);
1035 /***********************************************************************
1036 * OLEClipbrd_GlobalDupMem( HGLOBAL )
1037 * Helper method to duplicate an HGLOBAL chunk of memory
1039 static HGLOBAL OLEClipbrd_GlobalDupMem( HGLOBAL hGlobalSrc )
1041 HGLOBAL hGlobalDest;
1042 PVOID pGlobalSrc, pGlobalDest;
1048 cBytes = GlobalSize(hGlobalSrc);
1052 hGlobalDest = GlobalAlloc( GMEM_DDESHARE|GMEM_MOVEABLE,
1057 pGlobalSrc = GlobalLock(hGlobalSrc);
1058 pGlobalDest = GlobalLock(hGlobalDest);
1059 if ( !pGlobalSrc || !pGlobalDest )
1062 memcpy(pGlobalDest, pGlobalSrc, cBytes);
1064 GlobalUnlock(hGlobalSrc);
1065 GlobalUnlock(hGlobalDest);
1071 /*---------------------------------------------------------------------*
1072 * Implementation of the internal IDataObject interface exposed by
1073 * the OLE clipboard.
1074 *---------------------------------------------------------------------*/
1077 /************************************************************************
1078 * OLEClipbrd_IDataObject_QueryInterface (IUnknown)
1080 * See Windows documentation for more details on IUnknown methods.
1082 static HRESULT WINAPI OLEClipbrd_IDataObject_QueryInterface(
1088 * Declare "This" pointer
1090 ICOM_THIS(OLEClipbrd, iface);
1091 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObject);
1094 * Perform a sanity check on the parameters.
1096 if ( (This==0) || (ppvObject==0) )
1097 return E_INVALIDARG;
1100 * Initialize the return parameter.
1105 * Compare the riid with the interface IDs implemented by this object.
1107 if (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0)
1111 else if (memcmp(&IID_IDataObject, riid, sizeof(IID_IDataObject)) == 0)
1113 *ppvObject = (IDataObject*)&(This->lpvtbl1);
1115 else /* We only support IUnknown and IDataObject */
1117 WARN( "() : asking for unsupported interface %s\n", debugstr_guid(riid));
1118 return E_NOINTERFACE;
1122 * Query Interface always increases the reference count by one when it is
1125 IUnknown_AddRef((IUnknown*)*ppvObject);
1130 /************************************************************************
1131 * OLEClipbrd_IDataObject_AddRef (IUnknown)
1133 * See Windows documentation for more details on IUnknown methods.
1135 static ULONG WINAPI OLEClipbrd_IDataObject_AddRef(
1139 * Declare "This" pointer
1141 ICOM_THIS(OLEClipbrd, iface);
1143 TRACE("(%p)->(count=%lu)\n",This, This->ref);
1150 /************************************************************************
1151 * OLEClipbrd_IDataObject_Release (IUnknown)
1153 * See Windows documentation for more details on IUnknown methods.
1155 static ULONG WINAPI OLEClipbrd_IDataObject_Release(
1159 * Declare "This" pointer
1161 ICOM_THIS(OLEClipbrd, iface);
1163 TRACE("(%p)->(count=%lu)\n",This, This->ref);
1166 * Decrease the reference count on this object.
1171 * If the reference count goes down to 0, perform suicide.
1175 OLEClipbrd_Destroy(This);
1182 /************************************************************************
1183 * OLEClipbrd_IDataObject_GetData (IDataObject)
1185 * The OLE Clipboard's implementation of this method delegates to
1186 * a data source if there is one or wraps around the windows clipboard
1188 * See Windows documentation for more details on IDataObject methods.
1190 static HRESULT WINAPI OLEClipbrd_IDataObject_GetData(
1192 LPFORMATETC pformatetcIn,
1196 BOOL bClipboardOpen = FALSE;
1200 * Declare "This" pointer
1202 ICOM_THIS(OLEClipbrd, iface);
1204 TRACE("(%p,%p,%p)\n", iface, pformatetcIn, pmedium);
1206 if ( !pformatetcIn || !pmedium )
1207 return E_INVALIDARG;
1210 * If we have a data source placed on the clipboard (via OleSetClipboard)
1211 * simply delegate to the source object's QueryGetData
1212 * NOTE: This code assumes that the IDataObject is in the same address space!
1213 * We will need to add marshalling support when Wine handles multiple processes.
1215 if ( This->pIDataObjectSrc )
1217 return IDataObject_GetData(This->pIDataObjectSrc, pformatetcIn, pmedium);
1220 if ( pformatetcIn->lindex != -1 )
1222 if ( (pformatetcIn->tymed & TYMED_HGLOBAL) != TYMED_HGLOBAL )
1225 if ( pformatetcIn->dwAspect != DVASPECT_CONTENT )
1226 return DV_E_DVASPECT;
1230 * Otherwise, get the data from the windows clipboard using GetClipboardData
1232 if ( !(bClipboardOpen = OpenClipboard(theOleClipboard->hWndClipboard)) )
1233 HANDLE_ERROR( CLIPBRD_E_CANT_OPEN );
1235 hData = GetClipboardData(pformatetcIn->cfFormat);
1238 * Return the clipboard data in the storage medium structure
1240 pmedium->tymed = (hData == 0) ? TYMED_NULL : TYMED_HGLOBAL;
1241 pmedium->u.hGlobal = (HGLOBAL)hData;
1242 pmedium->pUnkForRelease = NULL;
1248 * Close Windows clipboard
1250 if ( bClipboardOpen && !CloseClipboard() )
1251 hr = CLIPBRD_E_CANT_CLOSE;
1255 return (hData == 0) ? DV_E_FORMATETC : S_OK;
1258 static HRESULT WINAPI OLEClipbrd_IDataObject_GetDataHere(
1260 LPFORMATETC pformatetc,
1267 /************************************************************************
1268 * OLEClipbrd_IDataObject_QueryGetData (IDataObject)
1270 * The OLE Clipboard's implementation of this method delegates to
1271 * a data source if there is one or wraps around the windows clipboard
1272 * function IsClipboardFormatAvailable() otherwise.
1274 * See Windows documentation for more details on IDataObject methods.
1276 static HRESULT WINAPI OLEClipbrd_IDataObject_QueryGetData(
1278 LPFORMATETC pformatetc)
1281 * Declare "This" pointer
1283 ICOM_THIS(OLEClipbrd, iface);
1285 TRACE("(%p, %p)\n", iface, pformatetc);
1288 * If we have a data source placed on the clipboard (via OleSetClipboard)
1289 * simply delegate to the source object's QueryGetData
1291 if ( This->pIDataObjectSrc )
1293 return IDataObject_QueryGetData(This->pIDataObjectSrc, pformatetc);
1297 return E_INVALIDARG;
1299 if ( pformatetc->dwAspect != DVASPECT_CONTENT )
1300 return DV_E_DVASPECT;
1302 if ( pformatetc->lindex != -1 )
1305 /* TODO: Handle TYMED_IStorage media which were put on the clipboard
1306 * by copying the storage into global memory. We must convert this
1307 * TYMED_HGLOBAL back to TYMED_IStorage.
1309 if ( pformatetc->tymed != TYMED_HGLOBAL )
1313 * Delegate to the Windows clipboard function IsClipboardFormatAvailable
1315 return (IsClipboardFormatAvailable(pformatetc->cfFormat)) ? S_OK : DV_E_FORMATETC;
1318 /************************************************************************
1319 * OLEClipbrd_IDataObject_GetCanonicalFormatEtc (IDataObject)
1321 * See Windows documentation for more details on IDataObject methods.
1323 static HRESULT WINAPI OLEClipbrd_IDataObject_GetCanonicalFormatEtc(
1325 LPFORMATETC pformatectIn,
1326 LPFORMATETC pformatetcOut)
1328 TRACE("(%p, %p, %p)\n", iface, pformatectIn, pformatetcOut);
1330 if ( !pformatectIn || !pformatetcOut )
1331 return E_INVALIDARG;
1333 memcpy(pformatetcOut, pformatectIn, sizeof(FORMATETC));
1334 return DATA_S_SAMEFORMATETC;
1337 /************************************************************************
1338 * OLEClipbrd_IDataObject_SetData (IDataObject)
1340 * The OLE Clipboard's does not implement this method
1342 * See Windows documentation for more details on IDataObject methods.
1344 static HRESULT WINAPI OLEClipbrd_IDataObject_SetData(
1346 LPFORMATETC pformatetc,
1354 /************************************************************************
1355 * OLEClipbrd_IDataObject_EnumFormatEtc (IDataObject)
1357 * See Windows documentation for more details on IDataObject methods.
1359 static HRESULT WINAPI OLEClipbrd_IDataObject_EnumFormatEtc(
1362 IEnumFORMATETC** ppenumFormatEtc)
1365 FORMATETC *afmt = NULL;
1368 BOOL bClipboardOpen;
1371 * Declare "This" pointer
1373 ICOM_THIS(OLEClipbrd, iface);
1375 TRACE("(%p, %lx, %p)\n", iface, dwDirection, ppenumFormatEtc);
1378 * If we have a data source placed on the clipboard (via OleSetClipboard)
1379 * simply delegate to the source object's EnumFormatEtc
1381 if ( This->pIDataObjectSrc )
1383 return IDataObject_EnumFormatEtc(This->pIDataObjectSrc,
1384 dwDirection, ppenumFormatEtc);
1388 * Otherwise we must provide our own enumerator which wraps around the
1389 * Windows clipboard function EnumClipboardFormats
1391 if ( !ppenumFormatEtc )
1392 return E_INVALIDARG;
1394 if ( dwDirection != DATADIR_GET ) /* IDataObject_SetData not implemented */
1398 * Store all current clipboard formats in an array of FORMATETC's,
1399 * and create an IEnumFORMATETC enumerator from this list.
1401 cfmt = CountClipboardFormats();
1402 afmt = (FORMATETC *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1403 sizeof(FORMATETC) * cfmt);
1405 * Open the Windows clipboard, associating it with our hidden window
1407 if ( !(bClipboardOpen = OpenClipboard(This->hWndClipboard)) )
1408 HANDLE_ERROR( CLIPBRD_E_CANT_OPEN );
1411 * Store all current clipboard formats in an array of FORMATETC's
1412 * TODO: Handle TYMED_IStorage media which were put on the clipboard
1413 * by copying the storage into global memory. We must convert this
1414 * TYMED_HGLOBAL back to TYMED_IStorage.
1416 for (i = 0, format = 0; i < cfmt; i++)
1418 format = EnumClipboardFormats(format);
1419 if (!format) /* Failed! */
1421 ERR("EnumClipboardFormats failed to return format!\n");
1422 HANDLE_ERROR( E_FAIL );
1425 /* Init the FORMATETC struct */
1426 afmt[i].cfFormat = format;
1428 afmt[i].dwAspect = DVASPECT_CONTENT;
1429 afmt[i].lindex = -1;
1430 afmt[i].tymed = TYMED_HGLOBAL;
1434 * Create an EnumFORMATETC enumerator and return an
1435 * EnumFORMATETC after bumping up its ref count
1437 *ppenumFormatEtc = OLEClipbrd_IEnumFORMATETC_Construct( cfmt, afmt, (LPUNKNOWN)iface);
1438 if (!(*ppenumFormatEtc))
1439 HANDLE_ERROR( E_OUTOFMEMORY );
1441 if (FAILED( hr = IEnumFORMATETC_AddRef(*ppenumFormatEtc)))
1448 * Free the array of FORMATETC's
1451 HeapFree(GetProcessHeap(), 0, afmt);
1454 * Close Windows clipboard
1456 if ( bClipboardOpen && !CloseClipboard() )
1457 hr = CLIPBRD_E_CANT_CLOSE;
1462 /************************************************************************
1463 * OLEClipbrd_IDataObject_DAdvise (IDataObject)
1465 * The OLE Clipboard's does not implement this method
1467 * See Windows documentation for more details on IDataObject methods.
1469 static HRESULT WINAPI OLEClipbrd_IDataObject_DAdvise(
1471 FORMATETC* pformatetc,
1473 IAdviseSink* pAdvSink,
1474 DWORD* pdwConnection)
1480 /************************************************************************
1481 * OLEClipbrd_IDataObject_DUnadvise (IDataObject)
1483 * The OLE Clipboard's does not implement this method
1485 * See Windows documentation for more details on IDataObject methods.
1487 static HRESULT WINAPI OLEClipbrd_IDataObject_DUnadvise(
1495 /************************************************************************
1496 * OLEClipbrd_IDataObject_EnumDAdvise (IDataObject)
1498 * The OLE Clipboard does not implement this method
1500 * See Windows documentation for more details on IDataObject methods.
1502 static HRESULT WINAPI OLEClipbrd_IDataObject_EnumDAdvise(
1504 IEnumSTATDATA** ppenumAdvise)
1511 /*---------------------------------------------------------------------*
1512 * Implementation of the internal IEnumFORMATETC interface returned by
1513 * the OLE clipboard's IDataObject.
1514 *---------------------------------------------------------------------*/
1516 /************************************************************************
1517 * OLEClipbrd_IEnumFORMATETC_Construct (UINT, const FORMATETC, LPUNKNOWN)
1519 * Creates an IEnumFORMATETC enumerator from an array of FORMATETC
1520 * Structures. pUnkOuter is the outer unknown for reference counting only.
1521 * NOTE: this does not AddRef the interface.
1524 LPENUMFORMATETC OLEClipbrd_IEnumFORMATETC_Construct(UINT cfmt, const FORMATETC afmt[],
1525 LPUNKNOWN pUnkDataObj)
1527 IEnumFORMATETCImpl* ef;
1528 DWORD size=cfmt * sizeof(FORMATETC);
1531 ef = (IEnumFORMATETCImpl*)HeapAlloc(GetProcessHeap(),
1533 sizeof(IEnumFORMATETCImpl));
1538 ICOM_VTBL(ef) = &efvt;
1539 ef->pUnkDataObj = pUnkDataObj;
1542 ef->countFmt = cfmt;
1543 if (FAILED(CoGetMalloc(MEMCTX_TASK, &pIMalloc)))
1545 ef->pFmt = (LPFORMATETC)IMalloc_Alloc(pIMalloc, size);
1546 IMalloc_Release(pIMalloc);
1549 memcpy(ef->pFmt, afmt, size);
1551 TRACE("(%p)->()\n",ef);
1552 return (LPENUMFORMATETC)ef;
1556 /************************************************************************
1557 * OLEClipbrd_IEnumFORMATETC_QueryInterface (IUnknown)
1559 * See Windows documentation for more details on IUnknown methods.
1561 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_QueryInterface
1562 (LPENUMFORMATETC iface, REFIID riid, LPVOID* ppvObj)
1564 ICOM_THIS(IEnumFORMATETCImpl,iface);
1566 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
1569 * Since enumerators are seperate objects from the parent data object
1570 * we only need to support the IUnknown and IEnumFORMATETC interfaces
1575 if(IsEqualIID(riid, &IID_IUnknown))
1579 else if(IsEqualIID(riid, &IID_IEnumFORMATETC))
1581 *ppvObj = (IDataObject*)This;
1586 IEnumFORMATETC_AddRef((IEnumFORMATETC*)*ppvObj);
1587 TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
1591 TRACE("-- Interface: E_NOINTERFACE\n");
1592 return E_NOINTERFACE;
1595 /************************************************************************
1596 * OLEClipbrd_IEnumFORMATETC_AddRef (IUnknown)
1598 * Since enumerating formats only makes sense when our data object is around,
1599 * we insure that it stays as long as we stay by calling our parents IUnknown
1600 * for AddRef and Release. But since we are not controlled by the lifetime of
1601 * the outer object, we still keep our own reference count in order to
1604 static ULONG WINAPI OLEClipbrd_IEnumFORMATETC_AddRef(LPENUMFORMATETC iface)
1606 ICOM_THIS(IEnumFORMATETCImpl,iface);
1607 TRACE("(%p)->(count=%lu)\n",This, This->ref);
1609 if (This->pUnkDataObj)
1610 IUnknown_AddRef(This->pUnkDataObj);
1612 return ++(This->ref);
1615 /************************************************************************
1616 * OLEClipbrd_IEnumFORMATETC_Release (IUnknown)
1618 * See Windows documentation for more details on IUnknown methods.
1620 static ULONG WINAPI OLEClipbrd_IEnumFORMATETC_Release(LPENUMFORMATETC iface)
1622 ICOM_THIS(IEnumFORMATETCImpl,iface);
1625 TRACE("(%p)->(count=%lu)\n",This, This->ref);
1627 if (This->pUnkDataObj)
1628 IUnknown_Release(This->pUnkDataObj); /* Release parent data object */
1632 TRACE("() - destroying IEnumFORMATETC(%p)\n",This);
1633 if (SUCCEEDED(CoGetMalloc(MEMCTX_TASK, &pIMalloc)))
1635 IMalloc_Free(pIMalloc, This->pFmt);
1636 IMalloc_Release(pIMalloc);
1639 HeapFree(GetProcessHeap(),0,This);
1646 /************************************************************************
1647 * OLEClipbrd_IEnumFORMATETC_Next (IEnumFORMATETC)
1649 * Standard enumerator members for IEnumFORMATETC
1651 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Next
1652 (LPENUMFORMATETC iface, ULONG celt, FORMATETC *rgelt, ULONG *pceltFethed)
1654 ICOM_THIS(IEnumFORMATETCImpl,iface);
1656 HRESULT hres = S_FALSE;
1658 TRACE("(%p)->(pos=%u)\n", This, This->posFmt);
1660 if (This->posFmt < This->countFmt)
1662 cfetch = This->countFmt - This->posFmt;
1669 memcpy(rgelt, &This->pFmt[This->posFmt], cfetch * sizeof(FORMATETC));
1670 This->posFmt += cfetch;
1679 *pceltFethed = cfetch;
1685 /************************************************************************
1686 * OLEClipbrd_IEnumFORMATETC_Skip (IEnumFORMATETC)
1688 * Standard enumerator members for IEnumFORMATETC
1690 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Skip(LPENUMFORMATETC iface, ULONG celt)
1692 ICOM_THIS(IEnumFORMATETCImpl,iface);
1693 TRACE("(%p)->(num=%lu)\n", This, celt);
1695 This->posFmt += celt;
1696 if (This->posFmt > This->countFmt)
1698 This->posFmt = This->countFmt;
1704 /************************************************************************
1705 * OLEClipbrd_IEnumFORMATETC_Reset (IEnumFORMATETC)
1707 * Standard enumerator members for IEnumFORMATETC
1709 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Reset(LPENUMFORMATETC iface)
1711 ICOM_THIS(IEnumFORMATETCImpl,iface);
1712 TRACE("(%p)->()\n", This);
1718 /************************************************************************
1719 * OLEClipbrd_IEnumFORMATETC_Clone (IEnumFORMATETC)
1721 * Standard enumerator members for IEnumFORMATETC
1723 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Clone
1724 (LPENUMFORMATETC iface, LPENUMFORMATETC* ppenum)
1726 ICOM_THIS(IEnumFORMATETCImpl,iface);
1729 TRACE("(%p)->(ppenum=%p)\n", This, ppenum);
1732 return E_INVALIDARG;
1734 *ppenum = OLEClipbrd_IEnumFORMATETC_Construct(This->countFmt,
1738 if (FAILED( hr = IEnumFORMATETC_AddRef(*ppenum)))
1741 return (*ppenum) ? S_OK : E_OUTOFMEMORY;