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.
56 #include "debugtools.h"
59 #include "storage32.h"
61 #define HANDLE_ERROR(err) { hr = err; TRACE("(HRESULT=%lx)\n", (HRESULT)err); goto CLEANUP; }
63 /* For CoGetMalloc (MEMCTX_TASK is currently ignored) */
65 #define MEMCTX_TASK -1
68 DEFAULT_DEBUG_CHANNEL(ole);
70 /****************************************************************************
72 * DO NOT add any members before the VTables declaration!
77 * List all interface VTables here
79 ICOM_VTABLE(IDataObject)* lpvtbl1; /* IDataObject VTable */
82 * The hidden OLE clipboard window. This window is used as the bridge between the
83 * the OLE and windows clipboard API. (Windows creates one such window per process)
88 * Pointer to the source data object (via OleSetClipboard)
90 IDataObject* pIDataObjectSrc;
93 * The registered DataObject clipboard format
98 * The handle to our ourself
103 * Reference count of this object
108 typedef struct OLEClipbrd OLEClipbrd;
111 /****************************************************************************
112 * IEnumFORMATETC implementation
113 * DO NOT add any members before the VTables declaration!
117 /* IEnumFORMATETC VTable */
118 ICOM_VFIELD(IEnumFORMATETC);
120 /* IEnumFORMATETC fields */
121 UINT posFmt; /* current enumerator position */
122 UINT countFmt; /* number of EnumFORMATETC's in array */
123 LPFORMATETC pFmt; /* array of EnumFORMATETC's */
126 * Reference count of this object
131 * IUnknown implementation of the parent data object.
133 IUnknown* pUnkDataObj;
135 } IEnumFORMATETCImpl;
137 typedef struct PresentationDataHeader
140 DWORD dwObjectExtentX;
141 DWORD dwObjectExtentY;
143 } PresentationDataHeader;
146 * The one and only OLEClipbrd object which is created by OLEClipbrd_Initialize()
148 static HGLOBAL hTheOleClipboard = 0;
149 static OLEClipbrd* theOleClipboard = NULL;
153 * Prototypes for the methods of the OLEClipboard class.
155 extern void OLEClipbrd_Initialize();
156 extern void OLEClipbrd_UnInitialize();
157 static OLEClipbrd* OLEClipbrd_Construct();
158 static void OLEClipbrd_Destroy(OLEClipbrd* ptrToDestroy);
159 static HWND OLEClipbrd_CreateWindow();
160 static void OLEClipbrd_DestroyWindow(HWND hwnd);
161 LRESULT CALLBACK OLEClipbrd_WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
162 static HRESULT OLEClipbrd_RenderFormat( IDataObject *pIDataObject, LPFORMATETC pFormatetc );
163 static HGLOBAL OLEClipbrd_GlobalDupMem( HGLOBAL hGlobalSrc );
166 * Prototypes for the methods of the OLEClipboard class
167 * that implement IDataObject methods.
169 static HRESULT WINAPI OLEClipbrd_IDataObject_QueryInterface(
173 static ULONG WINAPI OLEClipbrd_IDataObject_AddRef(
175 static ULONG WINAPI OLEClipbrd_IDataObject_Release(
177 static HRESULT WINAPI OLEClipbrd_IDataObject_GetData(
179 LPFORMATETC pformatetcIn,
181 static HRESULT WINAPI OLEClipbrd_IDataObject_GetDataHere(
183 LPFORMATETC pformatetc,
185 static HRESULT WINAPI OLEClipbrd_IDataObject_QueryGetData(
187 LPFORMATETC pformatetc);
188 static HRESULT WINAPI OLEClipbrd_IDataObject_GetCanonicalFormatEtc(
190 LPFORMATETC pformatectIn,
191 LPFORMATETC pformatetcOut);
192 static HRESULT WINAPI OLEClipbrd_IDataObject_SetData(
194 LPFORMATETC pformatetc,
197 static HRESULT WINAPI OLEClipbrd_IDataObject_EnumFormatEtc(
200 IEnumFORMATETC** ppenumFormatEtc);
201 static HRESULT WINAPI OLEClipbrd_IDataObject_DAdvise(
203 FORMATETC* pformatetc,
205 IAdviseSink* pAdvSink,
206 DWORD* pdwConnection);
207 static HRESULT WINAPI OLEClipbrd_IDataObject_DUnadvise(
210 static HRESULT WINAPI OLEClipbrd_IDataObject_EnumDAdvise(
212 IEnumSTATDATA** ppenumAdvise);
215 * Prototypes for the IEnumFORMATETC methods.
217 static LPENUMFORMATETC OLEClipbrd_IEnumFORMATETC_Construct(UINT cfmt, const FORMATETC afmt[],
218 LPUNKNOWN pUnkDataObj);
219 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_QueryInterface(LPENUMFORMATETC iface, REFIID riid,
221 static ULONG WINAPI OLEClipbrd_IEnumFORMATETC_AddRef(LPENUMFORMATETC iface);
222 static ULONG WINAPI OLEClipbrd_IEnumFORMATETC_Release(LPENUMFORMATETC iface);
223 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Next(LPENUMFORMATETC iface, ULONG celt,
224 FORMATETC* rgelt, ULONG* pceltFethed);
225 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Skip(LPENUMFORMATETC iface, ULONG celt);
226 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Reset(LPENUMFORMATETC iface);
227 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Clone(LPENUMFORMATETC iface, LPENUMFORMATETC* ppenum);
231 * Virtual function table for the OLEClipbrd's exposed IDataObject interface
233 static ICOM_VTABLE(IDataObject) OLEClipbrd_IDataObject_VTable =
235 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
236 OLEClipbrd_IDataObject_QueryInterface,
237 OLEClipbrd_IDataObject_AddRef,
238 OLEClipbrd_IDataObject_Release,
239 OLEClipbrd_IDataObject_GetData,
240 OLEClipbrd_IDataObject_GetDataHere,
241 OLEClipbrd_IDataObject_QueryGetData,
242 OLEClipbrd_IDataObject_GetCanonicalFormatEtc,
243 OLEClipbrd_IDataObject_SetData,
244 OLEClipbrd_IDataObject_EnumFormatEtc,
245 OLEClipbrd_IDataObject_DAdvise,
246 OLEClipbrd_IDataObject_DUnadvise,
247 OLEClipbrd_IDataObject_EnumDAdvise
251 * Virtual function table for IEnumFORMATETC interface
253 static struct ICOM_VTABLE(IEnumFORMATETC) efvt =
255 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
256 OLEClipbrd_IEnumFORMATETC_QueryInterface,
257 OLEClipbrd_IEnumFORMATETC_AddRef,
258 OLEClipbrd_IEnumFORMATETC_Release,
259 OLEClipbrd_IEnumFORMATETC_Next,
260 OLEClipbrd_IEnumFORMATETC_Skip,
261 OLEClipbrd_IEnumFORMATETC_Reset,
262 OLEClipbrd_IEnumFORMATETC_Clone
266 * Name of our registered OLE clipboard window class
268 CHAR OLEClipbrd_WNDCLASS[] = "CLIPBRDWNDCLASS";
271 * If we need to store state info we can store it here.
272 * For now we dont need this functionality.
274 typedef struct tagClipboardWindowInfo
276 } ClipboardWindowInfo;
279 /*---------------------------------------------------------------------*
280 * Win32 OLE clipboard API
281 *---------------------------------------------------------------------*/
283 /***********************************************************************
284 * OleSetClipboard [OLE32.127]
285 * Places a pointer to the specified data object onto the clipboard,
286 * making the data object accessible to the OleGetClipboard function.
290 * S_OK IDataObject pointer placed on the clipboard
291 * CLIPBRD_E_CANT_OPEN OpenClipboard failed
292 * CLIPBRD_E_CANT_EMPTY EmptyClipboard failed
293 * CLIPBRD_E_CANT_CLOSE CloseClipboard failed
294 * CLIPBRD_E_CANT_SET SetClipboard failed
297 HRESULT WINAPI OleSetClipboard(IDataObject* pDataObj)
300 IEnumFORMATETC* penumFormatetc = NULL;
302 BOOL bClipboardOpen = FALSE;
304 HGLOBAL hDataObject = 0;
305 OLEClipbrd **ppDataObject;
308 TRACE("(%p)\n", pDataObj);
311 * Make sure we have a clipboard object
313 OLEClipbrd_Initialize();
316 * If the Ole clipboard window hasn't been created yet, create it now.
318 if ( !theOleClipboard->hWndClipboard )
319 theOleClipboard->hWndClipboard = OLEClipbrd_CreateWindow();
321 if ( !theOleClipboard->hWndClipboard ) /* sanity check */
322 HANDLE_ERROR( E_FAIL );
325 * Open the Windows clipboard, associating it with our hidden window
327 if ( !(bClipboardOpen = OpenClipboard(theOleClipboard->hWndClipboard)) )
328 HANDLE_ERROR( CLIPBRD_E_CANT_OPEN );
331 * Empty the current clipboard and make our window the clipboard owner
332 * NOTE: This will trigger a WM_DESTROYCLIPBOARD message
334 if ( !EmptyClipboard() )
335 HANDLE_ERROR( CLIPBRD_E_CANT_EMPTY );
338 * If we are already holding on to an IDataObject first release that.
340 if ( theOleClipboard->pIDataObjectSrc )
342 IDataObject_Release(theOleClipboard->pIDataObjectSrc);
343 theOleClipboard->pIDataObjectSrc = NULL;
347 * AddRef the data object passed in and save its pointer.
348 * A NULL value indicates that the clipboard should be emptied.
350 theOleClipboard->pIDataObjectSrc = pDataObj;
353 IDataObject_AddRef(theOleClipboard->pIDataObjectSrc);
357 * Enumerate all HGLOBAL formats supported by the source and make
358 * those formats available using delayed rendering using SetClipboardData.
359 * Only global memory based data items may be made available to non-OLE
360 * applications via the standard Windows clipboard API. Data based on other
361 * mediums(non TYMED_HGLOBAL) can only be accessed via the Ole Clipboard API.
363 * TODO: Do we need to additionally handle TYMED_IStorage media by copying
364 * the storage into global memory?
368 if ( FAILED(hr = IDataObject_EnumFormatEtc( pDataObj,
375 while ( S_OK == IEnumFORMATETC_Next(penumFormatetc, 1, &rgelt, NULL) )
377 if ( rgelt.tymed == TYMED_HGLOBAL )
380 TRACE("(cfFormat=%d:%s)\n", rgelt.cfFormat,
381 GetClipboardFormatNameA(rgelt.cfFormat, szFmtName, sizeof(szFmtName)-1)
384 SetClipboardData( rgelt.cfFormat, (HANDLE)NULL);
387 IEnumFORMATETC_Release(penumFormatetc);
391 * Windows additionally creates a new "DataObject" clipboard format
392 * and stores in on the clipboard. We could possibly store a pointer
393 * to our internal IDataObject interface on the clipboard. I'm not
394 * sure what the use of this is though.
395 * Enable the code below for this functionality.
398 theOleClipboard->cfDataObj = RegisterClipboardFormatA("DataObject");
399 hDataObject = GlobalAlloc( GMEM_DDESHARE|GMEM_MOVEABLE|GMEM_ZEROINIT,
400 sizeof(OLEClipbrd *));
402 HANDLE_ERROR( E_OUTOFMEMORY );
404 ppDataObject = (OLEClipbrd**)GlobalLock(hDataObject);
405 *ppDataObject = theOleClipboard;
406 GlobalUnlock(hDataObject);
408 if ( !SetClipboardData( theOleClipboard->cfDataObj, hDataObject ) )
409 HANDLE_ERROR( CLIPBRD_E_CANT_SET );
417 * Close Windows clipboard (It remains associated with our window)
419 if ( bClipboardOpen && !CloseClipboard() )
420 hr = CLIPBRD_E_CANT_CLOSE;
423 * Release the source IDataObject if something failed
427 if (theOleClipboard->pIDataObjectSrc)
429 IDataObject_Release(theOleClipboard->pIDataObjectSrc);
430 theOleClipboard->pIDataObjectSrc = NULL;
438 /***********************************************************************
439 * OleGetClipboard [OLE32.105]
440 * Returns a pointer to our internal IDataObject which represents the conceptual
441 * state of the Windows clipboard. If the current clipboard already contains
442 * an IDataObject, our internal IDataObject will delegate to this object.
444 HRESULT WINAPI OleGetClipboard(IDataObject** ppDataObj)
450 * Make sure we have a clipboard object
452 OLEClipbrd_Initialize();
454 if (!theOleClipboard)
455 return E_OUTOFMEMORY;
457 /* Return a reference counted IDataObject */
458 hr = IDataObject_QueryInterface( (IDataObject*)&(theOleClipboard->lpvtbl1),
459 &IID_IDataObject, (void**)ppDataObj);
463 /***********************************************************************
464 * OleFlushClipboard [OLE2.76]
467 HRESULT WINAPI OleFlushClipboard16(void)
469 return OleFlushClipboard();
473 /******************************************************************************
474 * OleFlushClipboard [OLE32.103]
475 * Renders the data from the source IDataObject into the windows clipboard
477 * TODO: OleFlushClipboard needs to additionally handle TYMED_IStorage media
478 * by copying the storage into global memory. Subsequently the default
479 * data object exposed through OleGetClipboard must convert this TYMED_HGLOBAL
480 * back to TYMED_IStorage.
482 HRESULT WINAPI OleFlushClipboard()
484 IEnumFORMATETC* penumFormatetc = NULL;
487 BOOL bClipboardOpen = FALSE;
488 IDataObject* pIDataObjectSrc = NULL;
493 * Make sure we have a clipboard object
495 OLEClipbrd_Initialize();
498 * Already flushed or no source DataObject? Nothing to do.
500 if (!theOleClipboard->pIDataObjectSrc)
504 * Addref and save the source data object we are holding on to temporarily,
505 * since it will be released when we empty the clipboard.
507 pIDataObjectSrc = theOleClipboard->pIDataObjectSrc;
508 IDataObject_AddRef(pIDataObjectSrc);
511 * Open the Windows clipboard
513 if ( !(bClipboardOpen = OpenClipboard(theOleClipboard->hWndClipboard)) )
514 HANDLE_ERROR( CLIPBRD_E_CANT_OPEN );
517 * Empty the current clipboard
519 if ( !EmptyClipboard() )
520 HANDLE_ERROR( CLIPBRD_E_CANT_EMPTY );
523 * Render all HGLOBAL formats supported by the source into
524 * the windows clipboard.
526 if ( FAILED( hr = IDataObject_EnumFormatEtc( pIDataObjectSrc,
533 while ( S_OK == IEnumFORMATETC_Next(penumFormatetc, 1, &rgelt, NULL) )
535 if ( rgelt.tymed == TYMED_HGLOBAL )
538 TRACE("(cfFormat=%d:%s)\n", rgelt.cfFormat,
539 GetClipboardFormatNameA(rgelt.cfFormat, szFmtName, sizeof(szFmtName)-1)
543 * Render the clipboard data
545 if ( FAILED(OLEClipbrd_RenderFormat( pIDataObjectSrc, &rgelt )) )
550 IEnumFORMATETC_Release(penumFormatetc);
553 * Release the source data object we are holding on to
555 IDataObject_Release(pIDataObjectSrc);
560 * Close Windows clipboard (It remains associated with our window)
562 if ( bClipboardOpen && !CloseClipboard() )
563 hr = CLIPBRD_E_CANT_CLOSE;
569 /***********************************************************************
570 * OleIsCurrentClipboard [OLE32.110]
572 HRESULT WINAPI OleIsCurrentClipboard ( IDataObject *pDataObject)
576 * Make sure we have a clipboard object
578 OLEClipbrd_Initialize();
580 if (!theOleClipboard)
581 return E_OUTOFMEMORY;
583 return (pDataObject == theOleClipboard->pIDataObjectSrc) ? S_OK : S_FALSE;
587 /*---------------------------------------------------------------------*
588 * Internal implementation methods for the OLE clipboard
589 *---------------------------------------------------------------------*/
591 /***********************************************************************
592 * OLEClipbrd_Initialize()
593 * Initializes the OLE clipboard.
595 void OLEClipbrd_Initialize()
598 * Create the clipboard if necesary
600 if ( !theOleClipboard )
603 theOleClipboard = OLEClipbrd_Construct();
608 /***********************************************************************
609 * OLEClipbrd_UnInitialize()
610 * Un-Initializes the OLE clipboard
612 void OLEClipbrd_UnInitialize()
616 * Destroy the clipboard if no one holds a reference to us.
617 * Note that the clipboard was created with a reference count of 1.
619 if ( theOleClipboard && (theOleClipboard->ref <= 1) )
621 OLEClipbrd_Destroy( theOleClipboard );
625 WARN( "() : OLEClipbrd_UnInitialize called while client holds an IDataObject reference!\n");
630 /*********************************************************
631 * Construct the OLEClipbrd class.
633 static OLEClipbrd* OLEClipbrd_Construct()
635 OLEClipbrd* newObject = NULL;
636 HGLOBAL hNewObject = 0;
639 * Allocate space for the object. We use GlobalAlloc since we need
640 * an HGLOBAL to expose our DataObject as a registered clipboard type.
642 hNewObject = GlobalAlloc( GMEM_DDESHARE|GMEM_MOVEABLE|GMEM_ZEROINIT,
648 * Lock the handle for the entire lifetime of the clipboard.
650 newObject = GlobalLock(hNewObject);
653 * Initialize the virtual function table.
655 newObject->lpvtbl1 = &OLEClipbrd_IDataObject_VTable;
658 * Start with one reference count. The caller of this function
659 * must release the interface pointer when it is done.
663 newObject->hSelf = hNewObject;
666 * The Ole clipboard is a singleton - save the global handle and pointer
668 theOleClipboard = newObject;
669 hTheOleClipboard = hNewObject;
671 return theOleClipboard;
674 static void OLEClipbrd_Destroy(OLEClipbrd* ptrToDestroy)
682 * Destroy the Ole clipboard window
684 if ( ptrToDestroy->hWndClipboard )
685 OLEClipbrd_DestroyWindow(ptrToDestroy->hWndClipboard);
688 * Free the actual OLE Clipboard structure.
690 TRACE("() - Destroying clipboard data object.\n");
691 GlobalUnlock(ptrToDestroy->hSelf);
692 GlobalFree(ptrToDestroy->hSelf);
695 * The Ole clipboard is a singleton (ptrToDestroy == theOleClipboard)
697 theOleClipboard = NULL;
698 hTheOleClipboard = 0;
702 /***********************************************************************
703 * OLEClipbrd_CreateWindow()
704 * Create the clipboard window
706 static HWND OLEClipbrd_CreateWindow()
712 * Register the clipboard window class if necessary
714 ZeroMemory( &wcex, sizeof(WNDCLASSEXA));
716 wcex.cbSize = sizeof(WNDCLASSEXA);
717 /* Windows creates this class with a style mask of 0
718 * We dont bother doing this since the FindClassByAtom code
719 * would have to be changed to deal with this idiosyncracy. */
720 wcex.style = CS_GLOBALCLASS;
721 wcex.lpfnWndProc = (WNDPROC)OLEClipbrd_WndProc;
723 wcex.lpszClassName = OLEClipbrd_WNDCLASS;
725 RegisterClassExA(&wcex);
728 * Create a hidden window to receive OLE clipboard messages
732 * If we need to store state info we can store it here.
733 * For now we dont need this functionality.
734 * ClipboardWindowInfo clipboardInfo;
735 * ZeroMemory( &trackerInfo, sizeof(ClipboardWindowInfo));
738 hwnd = CreateWindowA(OLEClipbrd_WNDCLASS,
740 WS_POPUP | WS_CLIPSIBLINGS | WS_OVERLAPPED,
741 CW_USEDEFAULT, CW_USEDEFAULT,
742 CW_USEDEFAULT, CW_USEDEFAULT,
746 0 /*(LPVOID)&clipboardInfo */);
751 /***********************************************************************
752 * OLEClipbrd_DestroyWindow(HWND)
753 * Destroy the clipboard window and unregister its class
755 static void OLEClipbrd_DestroyWindow(HWND hwnd)
758 * Destroy clipboard window and unregister its WNDCLASS
761 UnregisterClassA( OLEClipbrd_WNDCLASS, 0 );
764 /***********************************************************************
765 * OLEClipbrd_WndProc(HWND, unsigned, WORD, LONG)
766 * Processes messages sent to the OLE clipboard window.
767 * Note that we will intercept messages in our WndProc only when data
768 * has been placed in the clipboard via OleSetClipboard().
769 * i.e. Only when OLE owns the windows clipboard.
771 LRESULT CALLBACK OLEClipbrd_WndProc
772 (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
778 * We receive this message to allow us to handle delayed rendering of
779 * a specific clipboard format when an application requests data in
780 * that format by calling GetClipboardData.
781 * (Recall that in OleSetClipboard, we used SetClipboardData to
782 * make all HGLOBAL formats supported by the source IDataObject
783 * available using delayed rendering)
784 * On receiving this mesage we must actually render the data in the
785 * specified format and place it on the clipboard by calling the
786 * SetClipboardData function.
788 case WM_RENDERFORMAT:
792 ZeroMemory( &rgelt, sizeof(FORMATETC));
795 * Initialize FORMATETC to a Windows clipboard friendly format
797 rgelt.cfFormat = (UINT) wParam;
798 rgelt.dwAspect = DVASPECT_CONTENT;
800 rgelt.tymed = TYMED_HGLOBAL;
802 TRACE("(): WM_RENDERFORMAT(cfFormat=%d)\n", rgelt.cfFormat);
805 * Render the clipboard data.
806 * (We must have a source data object or we wouldn't be in this WndProc)
808 OLEClipbrd_RenderFormat( (IDataObject*)&(theOleClipboard->lpvtbl1), &rgelt );
814 * WM_RENDERALLFORMATS
815 * Sent before the clipboard owner window is destroyed.
816 * We should receive this message only when OleUninitialize is called
817 * while we have an IDataObject in the clipboard.
818 * For the content of the clipboard to remain available to other
819 * applications, we must render data in all the formats the source IDataObject
820 * is capable of generating, and place the data on the clipboard by calling
823 case WM_RENDERALLFORMATS:
825 IEnumFORMATETC* penumFormatetc = NULL;
828 TRACE("(): WM_RENDERALLFORMATS\n");
831 * Render all HGLOBAL formats supported by the source into
832 * the windows clipboard.
834 if ( FAILED( IDataObject_EnumFormatEtc( (IDataObject*)&(theOleClipboard->lpvtbl1),
835 DATADIR_GET, &penumFormatetc) ) )
837 WARN("(): WM_RENDERALLFORMATS failed to retrieve EnumFormatEtc!\n");
841 while ( S_OK == IEnumFORMATETC_Next(penumFormatetc, 1, &rgelt, NULL) )
843 if ( rgelt.tymed == TYMED_HGLOBAL )
846 * Render the clipboard data.
848 if ( FAILED(OLEClipbrd_RenderFormat( (IDataObject*)&(theOleClipboard->lpvtbl1), &rgelt )) )
851 TRACE("(): WM_RENDERALLFORMATS(cfFormat=%d)\n", rgelt.cfFormat);
855 IEnumFORMATETC_Release(penumFormatetc);
861 * WM_DESTROYCLIPBOARD
862 * This is sent by EmptyClipboard before the clipboard is emptied.
863 * We should release any IDataObject we are holding onto when we receive
864 * this message, since it indicates that the OLE clipboard should be empty
865 * from this point on.
867 case WM_DESTROYCLIPBOARD:
869 TRACE("(): WM_DESTROYCLIPBOARD\n");
871 * Release the data object we are holding on to
873 if ( theOleClipboard->pIDataObjectSrc )
875 IDataObject_Release(theOleClipboard->pIDataObjectSrc);
876 theOleClipboard->pIDataObjectSrc = NULL;
882 case WM_ASKCBFORMATNAME:
883 case WM_CHANGECBCHAIN:
884 case WM_DRAWCLIPBOARD:
885 case WM_SIZECLIPBOARD:
886 case WM_HSCROLLCLIPBOARD:
887 case WM_VSCROLLCLIPBOARD:
888 case WM_PAINTCLIPBOARD:
891 return DefWindowProcA(hWnd, message, wParam, lParam);
897 #define MAX_CLIPFORMAT_NAME 80
899 /***********************************************************************
900 * OLEClipbrd_RenderFormat(LPFORMATETC)
901 * Render the clipboard data. Note that this call will delegate to the
902 * source data object.
903 * Note: This function assumes it is passed an HGLOBAL format to render.
905 static HRESULT OLEClipbrd_RenderFormat(IDataObject *pIDataObject, LPFORMATETC pFormatetc)
910 char szFmtName[MAX_CLIPFORMAT_NAME];
911 ILockBytes *ptrILockBytes = 0;
912 HGLOBAL hStorage = 0;
914 GetClipboardFormatNameA(pFormatetc->cfFormat, szFmtName, MAX_CLIPFORMAT_NAME);
916 /* If embed source */
917 if (!strcmp(szFmtName, CF_EMBEDSOURCE))
919 memset(&std, 0, sizeof(STGMEDIUM));
920 std.tymed = pFormatetc->tymed = TYMED_ISTORAGE;
922 hStorage = GlobalAlloc(GMEM_SHARE|GMEM_MOVEABLE, 0);
923 hr = CreateILockBytesOnHGlobal(hStorage, FALSE, &ptrILockBytes);
924 hr = StgCreateDocfileOnILockBytes(ptrILockBytes, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &std.u.pstg);
926 if (FAILED(hr = IDataObject_GetDataHere(theOleClipboard->pIDataObjectSrc, pFormatetc, &std)))
928 WARN("() : IDataObject_GetDataHere failed to render clipboard data! (%lx)\n", hr);
932 if (1) /* check whether the presentation data is already -not- present */
936 METAFILEPICT *mfp = 0;
938 fmt2.cfFormat = CF_METAFILEPICT;
940 fmt2.dwAspect = DVASPECT_CONTENT;
942 fmt2.tymed = TYMED_MFPICT;
944 memset(&std2, 0, sizeof(STGMEDIUM));
945 std2.tymed = TYMED_MFPICT;
947 /* Get the metafile picture out of it */
949 if (!FAILED(hr = IDataObject_GetData(theOleClipboard->pIDataObjectSrc, &fmt2, &std2)))
951 mfp = (METAFILEPICT *)GlobalLock(std2.u.hMetaFilePict);
956 OLECHAR name[]={ 2, 'O', 'l', 'e', 'P', 'r', 'e', 's', '0', '0', '0', 0};
957 IStream *pStream = 0;
959 PresentationDataHeader pdh;
963 CHAR strOleTypeName[51];
964 BYTE OlePresStreamHeader [] =
966 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00,
967 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
968 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
969 0x00, 0x00, 0x00, 0x00
972 nSize = GetMetaFileBitsEx(mfp->hMF, 0, NULL);
974 memset(&pdh, 0, sizeof(PresentationDataHeader));
975 memcpy(&pdh, OlePresStreamHeader, sizeof(OlePresStreamHeader));
977 pdh.dwObjectExtentX = mfp->xExt;
978 pdh.dwObjectExtentY = mfp->yExt;
981 hr = IStorage_CreateStream(std.u.pstg, name, STGM_CREATE|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, 0, &pStream);
983 hr = IStream_Write(pStream, &pdh, sizeof(PresentationDataHeader), NULL);
985 mfBits = HeapAlloc(GetProcessHeap(), 0, nSize);
986 nSize = GetMetaFileBitsEx(mfp->hMF, nSize, mfBits);
988 hr = IStream_Write(pStream, mfBits, nSize, NULL);
990 IStream_Release(pStream);
992 HeapFree(GetProcessHeap(), 0, mfBits);
994 GlobalUnlock(std2.u.hMetaFilePict);
996 ReadClassStg(std.u.pstg, &clsID);
997 ProgIDFromCLSID(&clsID, &strProgID);
999 WideCharToMultiByte( CP_ACP, 0, strProgID, -1, strOleTypeName, sizeof(strOleTypeName), NULL, NULL );
1000 OLECONVERT_CreateOleStream(std.u.pstg);
1001 OLECONVERT_CreateCompObjStream(std.u.pstg, strOleTypeName);
1007 if (FAILED(hr = IDataObject_GetData(pIDataObject, pFormatetc, &std)))
1009 WARN("() : IDataObject_GetData failed to render clipboard data! (%lx)\n", hr);
1013 /* To put a copy back on the clipboard */
1015 hStorage = std.u.hGlobal;
1019 * Put a copy of the rendered data back on the clipboard
1022 if ( !(hDup = OLEClipbrd_GlobalDupMem(hStorage)) )
1023 HANDLE_ERROR( E_OUTOFMEMORY );
1025 if ( !SetClipboardData( pFormatetc->cfFormat, hDup ) )
1028 WARN("() : Failed to set rendered clipboard data into clipboard!\n");
1033 ReleaseStgMedium(&std);
1039 /***********************************************************************
1040 * OLEClipbrd_GlobalDupMem( HGLOBAL )
1041 * Helper method to duplicate an HGLOBAL chunk of memory
1043 static HGLOBAL OLEClipbrd_GlobalDupMem( HGLOBAL hGlobalSrc )
1045 HGLOBAL hGlobalDest;
1046 PVOID pGlobalSrc, pGlobalDest;
1052 cBytes = GlobalSize(hGlobalSrc);
1056 hGlobalDest = GlobalAlloc( GMEM_DDESHARE|GMEM_MOVEABLE,
1061 pGlobalSrc = GlobalLock(hGlobalSrc);
1062 pGlobalDest = GlobalLock(hGlobalDest);
1063 if ( !pGlobalSrc || !pGlobalDest )
1066 memcpy(pGlobalDest, pGlobalSrc, cBytes);
1068 GlobalUnlock(hGlobalSrc);
1069 GlobalUnlock(hGlobalDest);
1075 /*---------------------------------------------------------------------*
1076 * Implementation of the internal IDataObject interface exposed by
1077 * the OLE clipboard.
1078 *---------------------------------------------------------------------*/
1081 /************************************************************************
1082 * OLEClipbrd_IDataObject_QueryInterface (IUnknown)
1084 * See Windows documentation for more details on IUnknown methods.
1086 static HRESULT WINAPI OLEClipbrd_IDataObject_QueryInterface(
1092 * Declare "This" pointer
1094 ICOM_THIS(OLEClipbrd, iface);
1095 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObject);
1098 * Perform a sanity check on the parameters.
1100 if ( (This==0) || (ppvObject==0) )
1101 return E_INVALIDARG;
1104 * Initialize the return parameter.
1109 * Compare the riid with the interface IDs implemented by this object.
1111 if (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0)
1115 else if (memcmp(&IID_IDataObject, riid, sizeof(IID_IDataObject)) == 0)
1117 *ppvObject = (IDataObject*)&(This->lpvtbl1);
1119 else /* We only support IUnknown and IDataObject */
1121 WARN( "() : asking for unsupported interface %s\n", debugstr_guid(riid));
1122 return E_NOINTERFACE;
1126 * Query Interface always increases the reference count by one when it is
1129 IUnknown_AddRef((IUnknown*)*ppvObject);
1134 /************************************************************************
1135 * OLEClipbrd_IDataObject_AddRef (IUnknown)
1137 * See Windows documentation for more details on IUnknown methods.
1139 static ULONG WINAPI OLEClipbrd_IDataObject_AddRef(
1143 * Declare "This" pointer
1145 ICOM_THIS(OLEClipbrd, iface);
1147 TRACE("(%p)->(count=%lu)\n",This, This->ref);
1154 /************************************************************************
1155 * OLEClipbrd_IDataObject_Release (IUnknown)
1157 * See Windows documentation for more details on IUnknown methods.
1159 static ULONG WINAPI OLEClipbrd_IDataObject_Release(
1163 * Declare "This" pointer
1165 ICOM_THIS(OLEClipbrd, iface);
1167 TRACE("(%p)->(count=%lu)\n",This, This->ref);
1170 * Decrease the reference count on this object.
1175 * If the reference count goes down to 0, perform suicide.
1179 OLEClipbrd_Destroy(This);
1186 /************************************************************************
1187 * OLEClipbrd_IDataObject_GetData (IDataObject)
1189 * The OLE Clipboard's implementation of this method delegates to
1190 * a data source if there is one or wraps around the windows clipboard
1192 * See Windows documentation for more details on IDataObject methods.
1194 static HRESULT WINAPI OLEClipbrd_IDataObject_GetData(
1196 LPFORMATETC pformatetcIn,
1200 BOOL bClipboardOpen = FALSE;
1204 * Declare "This" pointer
1206 ICOM_THIS(OLEClipbrd, iface);
1208 TRACE("(%p,%p,%p)\n", iface, pformatetcIn, pmedium);
1210 if ( !pformatetcIn || !pmedium )
1211 return E_INVALIDARG;
1214 * If we have a data source placed on the clipboard (via OleSetClipboard)
1215 * simply delegate to the source object's QueryGetData
1216 * NOTE: This code assumes that the IDataObject is in the same address space!
1217 * We will need to add marshalling support when Wine handles multiple processes.
1219 if ( This->pIDataObjectSrc )
1221 return IDataObject_GetData(This->pIDataObjectSrc, pformatetcIn, pmedium);
1224 if ( pformatetcIn->lindex != -1 )
1226 if ( (pformatetcIn->tymed & TYMED_HGLOBAL) != TYMED_HGLOBAL )
1229 if ( pformatetcIn->dwAspect != DVASPECT_CONTENT )
1230 return DV_E_DVASPECT;
1234 * Otherwise, get the data from the windows clipboard using GetClipboardData
1236 if ( !(bClipboardOpen = OpenClipboard(theOleClipboard->hWndClipboard)) )
1237 HANDLE_ERROR( CLIPBRD_E_CANT_OPEN );
1239 hData = GetClipboardData(pformatetcIn->cfFormat);
1242 * Return the clipboard data in the storage medium structure
1244 pmedium->tymed = (hData == 0) ? TYMED_NULL : TYMED_HGLOBAL;
1245 pmedium->u.hGlobal = (HGLOBAL)hData;
1246 pmedium->pUnkForRelease = NULL;
1252 * Close Windows clipboard
1254 if ( bClipboardOpen && !CloseClipboard() )
1255 hr = CLIPBRD_E_CANT_CLOSE;
1259 return (hData == 0) ? DV_E_FORMATETC : S_OK;
1262 static HRESULT WINAPI OLEClipbrd_IDataObject_GetDataHere(
1264 LPFORMATETC pformatetc,
1271 /************************************************************************
1272 * OLEClipbrd_IDataObject_QueryGetData (IDataObject)
1274 * The OLE Clipboard's implementation of this method delegates to
1275 * a data source if there is one or wraps around the windows clipboard
1276 * function IsClipboardFormatAvailable() otherwise.
1278 * See Windows documentation for more details on IDataObject methods.
1280 static HRESULT WINAPI OLEClipbrd_IDataObject_QueryGetData(
1282 LPFORMATETC pformatetc)
1285 * Declare "This" pointer
1287 ICOM_THIS(OLEClipbrd, iface);
1289 TRACE("(%p, %p)\n", iface, pformatetc);
1292 * If we have a data source placed on the clipboard (via OleSetClipboard)
1293 * simply delegate to the source object's QueryGetData
1295 if ( This->pIDataObjectSrc )
1297 return IDataObject_QueryGetData(This->pIDataObjectSrc, pformatetc);
1301 return E_INVALIDARG;
1303 if ( pformatetc->dwAspect != DVASPECT_CONTENT )
1304 return DV_E_DVASPECT;
1306 if ( pformatetc->lindex != -1 )
1309 /* TODO: Handle TYMED_IStorage media which were put on the clipboard
1310 * by copying the storage into global memory. We must convert this
1311 * TYMED_HGLOBAL back to TYMED_IStorage.
1313 if ( pformatetc->tymed != TYMED_HGLOBAL )
1317 * Delegate to the Windows clipboard function IsClipboardFormatAvailable
1319 return (IsClipboardFormatAvailable(pformatetc->cfFormat)) ? S_OK : DV_E_FORMATETC;
1322 /************************************************************************
1323 * OLEClipbrd_IDataObject_GetCanonicalFormatEtc (IDataObject)
1325 * See Windows documentation for more details on IDataObject methods.
1327 static HRESULT WINAPI OLEClipbrd_IDataObject_GetCanonicalFormatEtc(
1329 LPFORMATETC pformatectIn,
1330 LPFORMATETC pformatetcOut)
1332 TRACE("(%p, %p, %p)\n", iface, pformatectIn, pformatetcOut);
1334 if ( !pformatectIn || !pformatetcOut )
1335 return E_INVALIDARG;
1337 memcpy(pformatetcOut, pformatectIn, sizeof(FORMATETC));
1338 return DATA_S_SAMEFORMATETC;
1341 /************************************************************************
1342 * OLEClipbrd_IDataObject_SetData (IDataObject)
1344 * The OLE Clipboard's does not implement this method
1346 * See Windows documentation for more details on IDataObject methods.
1348 static HRESULT WINAPI OLEClipbrd_IDataObject_SetData(
1350 LPFORMATETC pformatetc,
1358 /************************************************************************
1359 * OLEClipbrd_IDataObject_EnumFormatEtc (IDataObject)
1361 * See Windows documentation for more details on IDataObject methods.
1363 static HRESULT WINAPI OLEClipbrd_IDataObject_EnumFormatEtc(
1366 IEnumFORMATETC** ppenumFormatEtc)
1369 FORMATETC *afmt = NULL;
1372 BOOL bClipboardOpen;
1375 * Declare "This" pointer
1377 ICOM_THIS(OLEClipbrd, iface);
1379 TRACE("(%p, %lx, %p)\n", iface, dwDirection, ppenumFormatEtc);
1382 * If we have a data source placed on the clipboard (via OleSetClipboard)
1383 * simply delegate to the source object's EnumFormatEtc
1385 if ( This->pIDataObjectSrc )
1387 return IDataObject_EnumFormatEtc(This->pIDataObjectSrc,
1388 dwDirection, ppenumFormatEtc);
1392 * Otherwise we must provide our own enumerator which wraps around the
1393 * Windows clipboard function EnumClipboardFormats
1395 if ( !ppenumFormatEtc )
1396 return E_INVALIDARG;
1398 if ( dwDirection != DATADIR_GET ) /* IDataObject_SetData not implemented */
1402 * Store all current clipboard formats in an array of FORMATETC's,
1403 * and create an IEnumFORMATETC enumerator from this list.
1405 cfmt = CountClipboardFormats();
1406 afmt = (FORMATETC *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1407 sizeof(FORMATETC) * cfmt);
1409 * Open the Windows clipboard, associating it with our hidden window
1411 if ( !(bClipboardOpen = OpenClipboard(This->hWndClipboard)) )
1412 HANDLE_ERROR( CLIPBRD_E_CANT_OPEN );
1415 * Store all current clipboard formats in an array of FORMATETC's
1416 * TODO: Handle TYMED_IStorage media which were put on the clipboard
1417 * by copying the storage into global memory. We must convert this
1418 * TYMED_HGLOBAL back to TYMED_IStorage.
1420 for (i = 0, format = 0; i < cfmt; i++)
1422 format = EnumClipboardFormats(format);
1423 if (!format) /* Failed! */
1425 ERR("EnumClipboardFormats failed to return format!\n");
1426 HANDLE_ERROR( E_FAIL );
1429 /* Init the FORMATETC struct */
1430 afmt[i].cfFormat = format;
1432 afmt[i].dwAspect = DVASPECT_CONTENT;
1433 afmt[i].lindex = -1;
1434 afmt[i].tymed = TYMED_HGLOBAL;
1438 * Create an EnumFORMATETC enumerator and return an
1439 * EnumFORMATETC after bumping up its ref count
1441 *ppenumFormatEtc = OLEClipbrd_IEnumFORMATETC_Construct( cfmt, afmt, (LPUNKNOWN)iface);
1442 if (!(*ppenumFormatEtc))
1443 HANDLE_ERROR( E_OUTOFMEMORY );
1445 if (FAILED( hr = IEnumFORMATETC_AddRef(*ppenumFormatEtc)))
1452 * Free the array of FORMATETC's
1455 HeapFree(GetProcessHeap(), 0, afmt);
1458 * Close Windows clipboard
1460 if ( bClipboardOpen && !CloseClipboard() )
1461 hr = CLIPBRD_E_CANT_CLOSE;
1466 /************************************************************************
1467 * OLEClipbrd_IDataObject_DAdvise (IDataObject)
1469 * The OLE Clipboard's does not implement this method
1471 * See Windows documentation for more details on IDataObject methods.
1473 static HRESULT WINAPI OLEClipbrd_IDataObject_DAdvise(
1475 FORMATETC* pformatetc,
1477 IAdviseSink* pAdvSink,
1478 DWORD* pdwConnection)
1484 /************************************************************************
1485 * OLEClipbrd_IDataObject_DUnadvise (IDataObject)
1487 * The OLE Clipboard's does not implement this method
1489 * See Windows documentation for more details on IDataObject methods.
1491 static HRESULT WINAPI OLEClipbrd_IDataObject_DUnadvise(
1499 /************************************************************************
1500 * OLEClipbrd_IDataObject_EnumDAdvise (IDataObject)
1502 * The OLE Clipboard does not implement this method
1504 * See Windows documentation for more details on IDataObject methods.
1506 static HRESULT WINAPI OLEClipbrd_IDataObject_EnumDAdvise(
1508 IEnumSTATDATA** ppenumAdvise)
1515 /*---------------------------------------------------------------------*
1516 * Implementation of the internal IEnumFORMATETC interface returned by
1517 * the OLE clipboard's IDataObject.
1518 *---------------------------------------------------------------------*/
1520 /************************************************************************
1521 * OLEClipbrd_IEnumFORMATETC_Construct (UINT, const FORMATETC, LPUNKNOWN)
1523 * Creates an IEnumFORMATETC enumerator from an array of FORMATETC
1524 * Structures. pUnkOuter is the outer unknown for reference counting only.
1525 * NOTE: this does not AddRef the interface.
1528 LPENUMFORMATETC OLEClipbrd_IEnumFORMATETC_Construct(UINT cfmt, const FORMATETC afmt[],
1529 LPUNKNOWN pUnkDataObj)
1531 IEnumFORMATETCImpl* ef;
1532 DWORD size=cfmt * sizeof(FORMATETC);
1535 ef = (IEnumFORMATETCImpl*)HeapAlloc(GetProcessHeap(),
1537 sizeof(IEnumFORMATETCImpl));
1542 ICOM_VTBL(ef) = &efvt;
1543 ef->pUnkDataObj = pUnkDataObj;
1546 ef->countFmt = cfmt;
1547 if (FAILED(CoGetMalloc(MEMCTX_TASK, &pIMalloc)))
1549 ef->pFmt = (LPFORMATETC)IMalloc_Alloc(pIMalloc, size);
1550 IMalloc_Release(pIMalloc);
1553 memcpy(ef->pFmt, afmt, size);
1555 TRACE("(%p)->()\n",ef);
1556 return (LPENUMFORMATETC)ef;
1560 /************************************************************************
1561 * OLEClipbrd_IEnumFORMATETC_QueryInterface (IUnknown)
1563 * See Windows documentation for more details on IUnknown methods.
1565 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_QueryInterface
1566 (LPENUMFORMATETC iface, REFIID riid, LPVOID* ppvObj)
1568 ICOM_THIS(IEnumFORMATETCImpl,iface);
1570 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
1573 * Since enumerators are seperate objects from the parent data object
1574 * we only need to support the IUnknown and IEnumFORMATETC interfaces
1579 if(IsEqualIID(riid, &IID_IUnknown))
1583 else if(IsEqualIID(riid, &IID_IEnumFORMATETC))
1585 *ppvObj = (IDataObject*)This;
1590 IEnumFORMATETC_AddRef((IEnumFORMATETC*)*ppvObj);
1591 TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
1595 TRACE("-- Interface: E_NOINTERFACE\n");
1596 return E_NOINTERFACE;
1599 /************************************************************************
1600 * OLEClipbrd_IEnumFORMATETC_AddRef (IUnknown)
1602 * Since enumerating formats only makes sense when our data object is around,
1603 * we insure that it stays as long as we stay by calling our parents IUnknown
1604 * for AddRef and Release. But since we are not controlled by the lifetime of
1605 * the outer object, we still keep our own reference count in order to
1608 static ULONG WINAPI OLEClipbrd_IEnumFORMATETC_AddRef(LPENUMFORMATETC iface)
1610 ICOM_THIS(IEnumFORMATETCImpl,iface);
1611 TRACE("(%p)->(count=%lu)\n",This, This->ref);
1613 if (This->pUnkDataObj)
1614 IUnknown_AddRef(This->pUnkDataObj);
1616 return ++(This->ref);
1619 /************************************************************************
1620 * OLEClipbrd_IEnumFORMATETC_Release (IUnknown)
1622 * See Windows documentation for more details on IUnknown methods.
1624 static ULONG WINAPI OLEClipbrd_IEnumFORMATETC_Release(LPENUMFORMATETC iface)
1626 ICOM_THIS(IEnumFORMATETCImpl,iface);
1629 TRACE("(%p)->(count=%lu)\n",This, This->ref);
1631 if (This->pUnkDataObj)
1632 IUnknown_Release(This->pUnkDataObj); /* Release parent data object */
1636 TRACE("() - destroying IEnumFORMATETC(%p)\n",This);
1637 if (SUCCEEDED(CoGetMalloc(MEMCTX_TASK, &pIMalloc)))
1639 IMalloc_Free(pIMalloc, This->pFmt);
1640 IMalloc_Release(pIMalloc);
1643 HeapFree(GetProcessHeap(),0,This);
1650 /************************************************************************
1651 * OLEClipbrd_IEnumFORMATETC_Next (IEnumFORMATETC)
1653 * Standard enumerator members for IEnumFORMATETC
1655 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Next
1656 (LPENUMFORMATETC iface, ULONG celt, FORMATETC *rgelt, ULONG *pceltFethed)
1658 ICOM_THIS(IEnumFORMATETCImpl,iface);
1660 HRESULT hres = S_FALSE;
1662 TRACE("(%p)->(pos=%u)\n", This, This->posFmt);
1664 if (This->posFmt < This->countFmt)
1666 cfetch = This->countFmt - This->posFmt;
1673 memcpy(rgelt, &This->pFmt[This->posFmt], cfetch * sizeof(FORMATETC));
1674 This->posFmt += cfetch;
1683 *pceltFethed = cfetch;
1689 /************************************************************************
1690 * OLEClipbrd_IEnumFORMATETC_Skip (IEnumFORMATETC)
1692 * Standard enumerator members for IEnumFORMATETC
1694 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Skip(LPENUMFORMATETC iface, ULONG celt)
1696 ICOM_THIS(IEnumFORMATETCImpl,iface);
1697 TRACE("(%p)->(num=%lu)\n", This, celt);
1699 This->posFmt += celt;
1700 if (This->posFmt > This->countFmt)
1702 This->posFmt = This->countFmt;
1708 /************************************************************************
1709 * OLEClipbrd_IEnumFORMATETC_Reset (IEnumFORMATETC)
1711 * Standard enumerator members for IEnumFORMATETC
1713 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Reset(LPENUMFORMATETC iface)
1715 ICOM_THIS(IEnumFORMATETCImpl,iface);
1716 TRACE("(%p)->()\n", This);
1722 /************************************************************************
1723 * OLEClipbrd_IEnumFORMATETC_Clone (IEnumFORMATETC)
1725 * Standard enumerator members for IEnumFORMATETC
1727 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Clone
1728 (LPENUMFORMATETC iface, LPENUMFORMATETC* ppenum)
1730 ICOM_THIS(IEnumFORMATETCImpl,iface);
1733 TRACE("(%p)->(ppenum=%p)\n", This, ppenum);
1736 return E_INVALIDARG;
1738 *ppenum = OLEClipbrd_IEnumFORMATETC_Construct(This->countFmt,
1742 if (FAILED( hr = IEnumFORMATETC_AddRef(*ppenum)))
1745 return (*ppenum) ? S_OK : E_OUTOFMEMORY;