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.
71 #include "wine/debug.h"
74 #include "storage32.h"
76 #define HANDLE_ERROR(err) { hr = err; TRACE("(HRESULT=%lx)\n", (HRESULT)err); goto CLEANUP; }
78 /* For CoGetMalloc (MEMCTX_TASK is currently ignored) */
80 #define MEMCTX_TASK -1
83 WINE_DEFAULT_DEBUG_CHANNEL(ole);
85 /****************************************************************************
87 * DO NOT add any members before the VTables declaration!
92 * List all interface VTables here
94 ICOM_VTABLE(IDataObject)* lpvtbl1; /* IDataObject VTable */
97 * The hidden OLE clipboard window. This window is used as the bridge between the
98 * the OLE and windows clipboard API. (Windows creates one such window per process)
103 * Pointer to the source data object (via OleSetClipboard)
105 IDataObject* pIDataObjectSrc;
108 * The registered DataObject clipboard format
113 * The handle to ourself
118 * Reference count of this object
123 typedef struct OLEClipbrd OLEClipbrd;
126 /****************************************************************************
127 * IEnumFORMATETC implementation
128 * DO NOT add any members before the VTables declaration!
132 /* IEnumFORMATETC VTable */
133 ICOM_VFIELD(IEnumFORMATETC);
135 /* IEnumFORMATETC fields */
136 UINT posFmt; /* current enumerator position */
137 UINT countFmt; /* number of EnumFORMATETC's in array */
138 LPFORMATETC pFmt; /* array of EnumFORMATETC's */
141 * Reference count of this object
146 * IUnknown implementation of the parent data object.
148 IUnknown* pUnkDataObj;
150 } IEnumFORMATETCImpl;
152 typedef struct PresentationDataHeader
155 DWORD dwObjectExtentX;
156 DWORD dwObjectExtentY;
158 } PresentationDataHeader;
161 * The one and only OLEClipbrd object which is created by OLEClipbrd_Initialize()
163 static HGLOBAL hTheOleClipboard = 0;
164 static OLEClipbrd* theOleClipboard = NULL;
168 * Prototypes for the methods of the OLEClipboard class.
170 extern void OLEClipbrd_Initialize();
171 extern void OLEClipbrd_UnInitialize();
172 static OLEClipbrd* OLEClipbrd_Construct();
173 static void OLEClipbrd_Destroy(OLEClipbrd* ptrToDestroy);
174 static HWND OLEClipbrd_CreateWindow();
175 static void OLEClipbrd_DestroyWindow(HWND hwnd);
176 LRESULT CALLBACK OLEClipbrd_WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
177 static HRESULT OLEClipbrd_RenderFormat( IDataObject *pIDataObject, LPFORMATETC pFormatetc );
178 static HGLOBAL OLEClipbrd_GlobalDupMem( HGLOBAL hGlobalSrc );
181 * Prototypes for the methods of the OLEClipboard class
182 * that implement IDataObject methods.
184 static HRESULT WINAPI OLEClipbrd_IDataObject_QueryInterface(
188 static ULONG WINAPI OLEClipbrd_IDataObject_AddRef(
190 static ULONG WINAPI OLEClipbrd_IDataObject_Release(
192 static HRESULT WINAPI OLEClipbrd_IDataObject_GetData(
194 LPFORMATETC pformatetcIn,
196 static HRESULT WINAPI OLEClipbrd_IDataObject_GetDataHere(
198 LPFORMATETC pformatetc,
200 static HRESULT WINAPI OLEClipbrd_IDataObject_QueryGetData(
202 LPFORMATETC pformatetc);
203 static HRESULT WINAPI OLEClipbrd_IDataObject_GetCanonicalFormatEtc(
205 LPFORMATETC pformatectIn,
206 LPFORMATETC pformatetcOut);
207 static HRESULT WINAPI OLEClipbrd_IDataObject_SetData(
209 LPFORMATETC pformatetc,
212 static HRESULT WINAPI OLEClipbrd_IDataObject_EnumFormatEtc(
215 IEnumFORMATETC** ppenumFormatEtc);
216 static HRESULT WINAPI OLEClipbrd_IDataObject_DAdvise(
218 FORMATETC* pformatetc,
220 IAdviseSink* pAdvSink,
221 DWORD* pdwConnection);
222 static HRESULT WINAPI OLEClipbrd_IDataObject_DUnadvise(
225 static HRESULT WINAPI OLEClipbrd_IDataObject_EnumDAdvise(
227 IEnumSTATDATA** ppenumAdvise);
230 * Prototypes for the IEnumFORMATETC methods.
232 static LPENUMFORMATETC OLEClipbrd_IEnumFORMATETC_Construct(UINT cfmt, const FORMATETC afmt[],
233 LPUNKNOWN pUnkDataObj);
234 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_QueryInterface(LPENUMFORMATETC iface, REFIID riid,
236 static ULONG WINAPI OLEClipbrd_IEnumFORMATETC_AddRef(LPENUMFORMATETC iface);
237 static ULONG WINAPI OLEClipbrd_IEnumFORMATETC_Release(LPENUMFORMATETC iface);
238 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Next(LPENUMFORMATETC iface, ULONG celt,
239 FORMATETC* rgelt, ULONG* pceltFethed);
240 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Skip(LPENUMFORMATETC iface, ULONG celt);
241 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Reset(LPENUMFORMATETC iface);
242 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Clone(LPENUMFORMATETC iface, LPENUMFORMATETC* ppenum);
246 * Virtual function table for the OLEClipbrd's exposed IDataObject interface
248 static ICOM_VTABLE(IDataObject) OLEClipbrd_IDataObject_VTable =
250 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
251 OLEClipbrd_IDataObject_QueryInterface,
252 OLEClipbrd_IDataObject_AddRef,
253 OLEClipbrd_IDataObject_Release,
254 OLEClipbrd_IDataObject_GetData,
255 OLEClipbrd_IDataObject_GetDataHere,
256 OLEClipbrd_IDataObject_QueryGetData,
257 OLEClipbrd_IDataObject_GetCanonicalFormatEtc,
258 OLEClipbrd_IDataObject_SetData,
259 OLEClipbrd_IDataObject_EnumFormatEtc,
260 OLEClipbrd_IDataObject_DAdvise,
261 OLEClipbrd_IDataObject_DUnadvise,
262 OLEClipbrd_IDataObject_EnumDAdvise
266 * Virtual function table for IEnumFORMATETC interface
268 static struct ICOM_VTABLE(IEnumFORMATETC) efvt =
270 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
271 OLEClipbrd_IEnumFORMATETC_QueryInterface,
272 OLEClipbrd_IEnumFORMATETC_AddRef,
273 OLEClipbrd_IEnumFORMATETC_Release,
274 OLEClipbrd_IEnumFORMATETC_Next,
275 OLEClipbrd_IEnumFORMATETC_Skip,
276 OLEClipbrd_IEnumFORMATETC_Reset,
277 OLEClipbrd_IEnumFORMATETC_Clone
281 * Name of our registered OLE clipboard window class
283 CHAR OLEClipbrd_WNDCLASS[] = "CLIPBRDWNDCLASS";
286 * If we need to store state info we can store it here.
287 * For now we dont need this functionality.
289 typedef struct tagClipboardWindowInfo
291 } ClipboardWindowInfo;
294 /*---------------------------------------------------------------------*
295 * Win32 OLE clipboard API
296 *---------------------------------------------------------------------*/
298 /***********************************************************************
299 * OleSetClipboard [OLE32.127]
300 * Places a pointer to the specified data object onto the clipboard,
301 * making the data object accessible to the OleGetClipboard function.
305 * S_OK IDataObject pointer placed on the clipboard
306 * CLIPBRD_E_CANT_OPEN OpenClipboard failed
307 * CLIPBRD_E_CANT_EMPTY EmptyClipboard failed
308 * CLIPBRD_E_CANT_CLOSE CloseClipboard failed
309 * CLIPBRD_E_CANT_SET SetClipboard failed
312 HRESULT WINAPI OleSetClipboard(IDataObject* pDataObj)
315 IEnumFORMATETC* penumFormatetc = NULL;
317 BOOL bClipboardOpen = FALSE;
319 HGLOBAL hDataObject = 0;
320 OLEClipbrd **ppDataObject;
323 TRACE("(%p)\n", pDataObj);
326 * Make sure we have a clipboard object
328 OLEClipbrd_Initialize();
331 * If the Ole clipboard window hasn't been created yet, create it now.
333 if ( !theOleClipboard->hWndClipboard )
334 theOleClipboard->hWndClipboard = OLEClipbrd_CreateWindow();
336 if ( !theOleClipboard->hWndClipboard ) /* sanity check */
337 HANDLE_ERROR( E_FAIL );
340 * Open the Windows clipboard, associating it with our hidden window
342 if ( !(bClipboardOpen = OpenClipboard(theOleClipboard->hWndClipboard)) )
343 HANDLE_ERROR( CLIPBRD_E_CANT_OPEN );
346 * Empty the current clipboard and make our window the clipboard owner
347 * NOTE: This will trigger a WM_DESTROYCLIPBOARD message
349 if ( !EmptyClipboard() )
350 HANDLE_ERROR( CLIPBRD_E_CANT_EMPTY );
353 * If we are already holding on to an IDataObject first release that.
355 if ( theOleClipboard->pIDataObjectSrc )
357 IDataObject_Release(theOleClipboard->pIDataObjectSrc);
358 theOleClipboard->pIDataObjectSrc = NULL;
362 * AddRef the data object passed in and save its pointer.
363 * A NULL value indicates that the clipboard should be emptied.
365 theOleClipboard->pIDataObjectSrc = pDataObj;
368 IDataObject_AddRef(theOleClipboard->pIDataObjectSrc);
372 * Enumerate all HGLOBAL formats supported by the source and make
373 * those formats available using delayed rendering using SetClipboardData.
374 * Only global memory based data items may be made available to non-OLE
375 * applications via the standard Windows clipboard API. Data based on other
376 * mediums(non TYMED_HGLOBAL) can only be accessed via the Ole Clipboard API.
378 * TODO: Do we need to additionally handle TYMED_IStorage media by copying
379 * the storage into global memory?
383 if ( FAILED(hr = IDataObject_EnumFormatEtc( pDataObj,
390 while ( S_OK == IEnumFORMATETC_Next(penumFormatetc, 1, &rgelt, NULL) )
392 if ( rgelt.tymed == TYMED_HGLOBAL )
395 TRACE("(cfFormat=%d:%s)\n", rgelt.cfFormat,
396 GetClipboardFormatNameA(rgelt.cfFormat, szFmtName, sizeof(szFmtName)-1)
399 SetClipboardData( rgelt.cfFormat, (HANDLE)NULL);
402 IEnumFORMATETC_Release(penumFormatetc);
406 * Windows additionally creates a new "DataObject" clipboard format
407 * and stores in on the clipboard. We could possibly store a pointer
408 * to our internal IDataObject interface on the clipboard. I'm not
409 * sure what the use of this is though.
410 * Enable the code below for this functionality.
413 theOleClipboard->cfDataObj = RegisterClipboardFormatA("DataObject");
414 hDataObject = GlobalAlloc( GMEM_DDESHARE|GMEM_MOVEABLE|GMEM_ZEROINIT,
415 sizeof(OLEClipbrd *));
417 HANDLE_ERROR( E_OUTOFMEMORY );
419 ppDataObject = (OLEClipbrd**)GlobalLock(hDataObject);
420 *ppDataObject = theOleClipboard;
421 GlobalUnlock(hDataObject);
423 if ( !SetClipboardData( theOleClipboard->cfDataObj, hDataObject ) )
424 HANDLE_ERROR( CLIPBRD_E_CANT_SET );
432 * Close Windows clipboard (It remains associated with our window)
434 if ( bClipboardOpen && !CloseClipboard() )
435 hr = CLIPBRD_E_CANT_CLOSE;
438 * Release the source IDataObject if something failed
442 if (theOleClipboard->pIDataObjectSrc)
444 IDataObject_Release(theOleClipboard->pIDataObjectSrc);
445 theOleClipboard->pIDataObjectSrc = NULL;
453 /***********************************************************************
454 * OleGetClipboard [OLE32.105]
455 * Returns a pointer to our internal IDataObject which represents the conceptual
456 * state of the Windows clipboard. If the current clipboard already contains
457 * an IDataObject, our internal IDataObject will delegate to this object.
459 HRESULT WINAPI OleGetClipboard(IDataObject** ppDataObj)
465 * Make sure we have a clipboard object
467 OLEClipbrd_Initialize();
469 if (!theOleClipboard)
470 return E_OUTOFMEMORY;
472 /* Return a reference counted IDataObject */
473 hr = IDataObject_QueryInterface( (IDataObject*)&(theOleClipboard->lpvtbl1),
474 &IID_IDataObject, (void**)ppDataObj);
478 /***********************************************************************
479 * OleFlushClipboard [OLE2.76]
482 HRESULT WINAPI OleFlushClipboard16(void)
484 return OleFlushClipboard();
488 /******************************************************************************
489 * OleFlushClipboard [OLE32.103]
490 * Renders the data from the source IDataObject into the windows clipboard
492 * TODO: OleFlushClipboard needs to additionally handle TYMED_IStorage media
493 * by copying the storage into global memory. Subsequently the default
494 * data object exposed through OleGetClipboard must convert this TYMED_HGLOBAL
495 * back to TYMED_IStorage.
497 HRESULT WINAPI OleFlushClipboard()
499 IEnumFORMATETC* penumFormatetc = NULL;
502 BOOL bClipboardOpen = FALSE;
503 IDataObject* pIDataObjectSrc = NULL;
508 * Make sure we have a clipboard object
510 OLEClipbrd_Initialize();
513 * Already flushed or no source DataObject? Nothing to do.
515 if (!theOleClipboard->pIDataObjectSrc)
519 * Addref and save the source data object we are holding on to temporarily,
520 * since it will be released when we empty the clipboard.
522 pIDataObjectSrc = theOleClipboard->pIDataObjectSrc;
523 IDataObject_AddRef(pIDataObjectSrc);
526 * Open the Windows clipboard
528 if ( !(bClipboardOpen = OpenClipboard(theOleClipboard->hWndClipboard)) )
529 HANDLE_ERROR( CLIPBRD_E_CANT_OPEN );
532 * Empty the current clipboard
534 if ( !EmptyClipboard() )
535 HANDLE_ERROR( CLIPBRD_E_CANT_EMPTY );
538 * Render all HGLOBAL formats supported by the source into
539 * the windows clipboard.
541 if ( FAILED( hr = IDataObject_EnumFormatEtc( pIDataObjectSrc,
548 while ( S_OK == IEnumFORMATETC_Next(penumFormatetc, 1, &rgelt, NULL) )
550 if ( rgelt.tymed == TYMED_HGLOBAL )
553 TRACE("(cfFormat=%d:%s)\n", rgelt.cfFormat,
554 GetClipboardFormatNameA(rgelt.cfFormat, szFmtName, sizeof(szFmtName)-1)
558 * Render the clipboard data
560 if ( FAILED(OLEClipbrd_RenderFormat( pIDataObjectSrc, &rgelt )) )
565 IEnumFORMATETC_Release(penumFormatetc);
568 * Release the source data object we are holding on to
570 IDataObject_Release(pIDataObjectSrc);
575 * Close Windows clipboard (It remains associated with our window)
577 if ( bClipboardOpen && !CloseClipboard() )
578 hr = CLIPBRD_E_CANT_CLOSE;
584 /***********************************************************************
585 * OleIsCurrentClipboard [OLE32.110]
587 HRESULT WINAPI OleIsCurrentClipboard ( IDataObject *pDataObject)
591 * Make sure we have a clipboard object
593 OLEClipbrd_Initialize();
595 if (!theOleClipboard)
596 return E_OUTOFMEMORY;
598 return (pDataObject == theOleClipboard->pIDataObjectSrc) ? S_OK : S_FALSE;
602 /*---------------------------------------------------------------------*
603 * Internal implementation methods for the OLE clipboard
604 *---------------------------------------------------------------------*/
606 /***********************************************************************
607 * OLEClipbrd_Initialize()
608 * Initializes the OLE clipboard.
610 void OLEClipbrd_Initialize()
613 * Create the clipboard if necessary
615 if ( !theOleClipboard )
618 theOleClipboard = OLEClipbrd_Construct();
623 /***********************************************************************
624 * OLEClipbrd_UnInitialize()
625 * Un-Initializes the OLE clipboard
627 void OLEClipbrd_UnInitialize()
631 * Destroy the clipboard if no one holds a reference to us.
632 * Note that the clipboard was created with a reference count of 1.
634 if ( theOleClipboard && (theOleClipboard->ref <= 1) )
636 OLEClipbrd_Destroy( theOleClipboard );
640 WARN( "() : OLEClipbrd_UnInitialize called while client holds an IDataObject reference!\n");
645 /*********************************************************
646 * Construct the OLEClipbrd class.
648 static OLEClipbrd* OLEClipbrd_Construct()
650 OLEClipbrd* newObject = NULL;
651 HGLOBAL hNewObject = 0;
654 * Allocate space for the object. We use GlobalAlloc since we need
655 * an HGLOBAL to expose our DataObject as a registered clipboard type.
657 hNewObject = GlobalAlloc( GMEM_DDESHARE|GMEM_MOVEABLE|GMEM_ZEROINIT,
663 * Lock the handle for the entire lifetime of the clipboard.
665 newObject = GlobalLock(hNewObject);
668 * Initialize the virtual function table.
670 newObject->lpvtbl1 = &OLEClipbrd_IDataObject_VTable;
673 * Start with one reference count. The caller of this function
674 * must release the interface pointer when it is done.
678 newObject->hSelf = hNewObject;
681 * The Ole clipboard is a singleton - save the global handle and pointer
683 theOleClipboard = newObject;
684 hTheOleClipboard = hNewObject;
686 return theOleClipboard;
689 static void OLEClipbrd_Destroy(OLEClipbrd* ptrToDestroy)
697 * Destroy the Ole clipboard window
699 if ( ptrToDestroy->hWndClipboard )
700 OLEClipbrd_DestroyWindow(ptrToDestroy->hWndClipboard);
703 * Free the actual OLE Clipboard structure.
705 TRACE("() - Destroying clipboard data object.\n");
706 GlobalUnlock(ptrToDestroy->hSelf);
707 GlobalFree(ptrToDestroy->hSelf);
710 * The Ole clipboard is a singleton (ptrToDestroy == theOleClipboard)
712 theOleClipboard = NULL;
713 hTheOleClipboard = 0;
717 /***********************************************************************
718 * OLEClipbrd_CreateWindow()
719 * Create the clipboard window
721 static HWND OLEClipbrd_CreateWindow()
727 * Register the clipboard window class if necessary
729 ZeroMemory( &wcex, sizeof(WNDCLASSEXA));
731 wcex.cbSize = sizeof(WNDCLASSEXA);
732 /* Windows creates this class with a style mask of 0
733 * We dont bother doing this since the FindClassByAtom code
734 * would have to be changed to deal with this idiosyncracy. */
735 wcex.style = CS_GLOBALCLASS;
736 wcex.lpfnWndProc = (WNDPROC)OLEClipbrd_WndProc;
738 wcex.lpszClassName = OLEClipbrd_WNDCLASS;
740 RegisterClassExA(&wcex);
743 * Create a hidden window to receive OLE clipboard messages
747 * If we need to store state info we can store it here.
748 * For now we dont need this functionality.
749 * ClipboardWindowInfo clipboardInfo;
750 * ZeroMemory( &trackerInfo, sizeof(ClipboardWindowInfo));
753 hwnd = CreateWindowA(OLEClipbrd_WNDCLASS,
755 WS_POPUP | WS_CLIPSIBLINGS | WS_OVERLAPPED,
756 CW_USEDEFAULT, CW_USEDEFAULT,
757 CW_USEDEFAULT, CW_USEDEFAULT,
761 0 /*(LPVOID)&clipboardInfo */);
766 /***********************************************************************
767 * OLEClipbrd_DestroyWindow(HWND)
768 * Destroy the clipboard window and unregister its class
770 static void OLEClipbrd_DestroyWindow(HWND hwnd)
773 * Destroy clipboard window and unregister its WNDCLASS
776 UnregisterClassA( OLEClipbrd_WNDCLASS, 0 );
779 /***********************************************************************
780 * OLEClipbrd_WndProc(HWND, unsigned, WORD, LONG)
781 * Processes messages sent to the OLE clipboard window.
782 * Note that we will intercept messages in our WndProc only when data
783 * has been placed in the clipboard via OleSetClipboard().
784 * i.e. Only when OLE owns the windows clipboard.
786 LRESULT CALLBACK OLEClipbrd_WndProc
787 (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
793 * We receive this message to allow us to handle delayed rendering of
794 * a specific clipboard format when an application requests data in
795 * that format by calling GetClipboardData.
796 * (Recall that in OleSetClipboard, we used SetClipboardData to
797 * make all HGLOBAL formats supported by the source IDataObject
798 * available using delayed rendering)
799 * On receiving this mesage we must actually render the data in the
800 * specified format and place it on the clipboard by calling the
801 * SetClipboardData function.
803 case WM_RENDERFORMAT:
807 ZeroMemory( &rgelt, sizeof(FORMATETC));
810 * Initialize FORMATETC to a Windows clipboard friendly format
812 rgelt.cfFormat = (UINT) wParam;
813 rgelt.dwAspect = DVASPECT_CONTENT;
815 rgelt.tymed = TYMED_HGLOBAL;
817 TRACE("(): WM_RENDERFORMAT(cfFormat=%d)\n", rgelt.cfFormat);
820 * Render the clipboard data.
821 * (We must have a source data object or we wouldn't be in this WndProc)
823 OLEClipbrd_RenderFormat( (IDataObject*)&(theOleClipboard->lpvtbl1), &rgelt );
829 * WM_RENDERALLFORMATS
830 * Sent before the clipboard owner window is destroyed.
831 * We should receive this message only when OleUninitialize is called
832 * while we have an IDataObject in the clipboard.
833 * For the content of the clipboard to remain available to other
834 * applications, we must render data in all the formats the source IDataObject
835 * is capable of generating, and place the data on the clipboard by calling
838 case WM_RENDERALLFORMATS:
840 IEnumFORMATETC* penumFormatetc = NULL;
843 TRACE("(): WM_RENDERALLFORMATS\n");
846 * Render all HGLOBAL formats supported by the source into
847 * the windows clipboard.
849 if ( FAILED( IDataObject_EnumFormatEtc( (IDataObject*)&(theOleClipboard->lpvtbl1),
850 DATADIR_GET, &penumFormatetc) ) )
852 WARN("(): WM_RENDERALLFORMATS failed to retrieve EnumFormatEtc!\n");
856 while ( S_OK == IEnumFORMATETC_Next(penumFormatetc, 1, &rgelt, NULL) )
858 if ( rgelt.tymed == TYMED_HGLOBAL )
861 * Render the clipboard data.
863 if ( FAILED(OLEClipbrd_RenderFormat( (IDataObject*)&(theOleClipboard->lpvtbl1), &rgelt )) )
866 TRACE("(): WM_RENDERALLFORMATS(cfFormat=%d)\n", rgelt.cfFormat);
870 IEnumFORMATETC_Release(penumFormatetc);
876 * WM_DESTROYCLIPBOARD
877 * This is sent by EmptyClipboard before the clipboard is emptied.
878 * We should release any IDataObject we are holding onto when we receive
879 * this message, since it indicates that the OLE clipboard should be empty
880 * from this point on.
882 case WM_DESTROYCLIPBOARD:
884 TRACE("(): WM_DESTROYCLIPBOARD\n");
886 * Release the data object we are holding on to
888 if ( theOleClipboard->pIDataObjectSrc )
890 IDataObject_Release(theOleClipboard->pIDataObjectSrc);
891 theOleClipboard->pIDataObjectSrc = NULL;
897 case WM_ASKCBFORMATNAME:
898 case WM_CHANGECBCHAIN:
899 case WM_DRAWCLIPBOARD:
900 case WM_SIZECLIPBOARD:
901 case WM_HSCROLLCLIPBOARD:
902 case WM_VSCROLLCLIPBOARD:
903 case WM_PAINTCLIPBOARD:
906 return DefWindowProcA(hWnd, message, wParam, lParam);
912 #define MAX_CLIPFORMAT_NAME 80
914 /***********************************************************************
915 * OLEClipbrd_RenderFormat(LPFORMATETC)
916 * Render the clipboard data. Note that this call will delegate to the
917 * source data object.
918 * Note: This function assumes it is passed an HGLOBAL format to render.
920 static HRESULT OLEClipbrd_RenderFormat(IDataObject *pIDataObject, LPFORMATETC pFormatetc)
925 char szFmtName[MAX_CLIPFORMAT_NAME];
926 ILockBytes *ptrILockBytes = 0;
927 HGLOBAL hStorage = 0;
929 GetClipboardFormatNameA(pFormatetc->cfFormat, szFmtName, MAX_CLIPFORMAT_NAME);
931 /* If embed source */
932 if (!strcmp(szFmtName, CF_EMBEDSOURCE))
934 memset(&std, 0, sizeof(STGMEDIUM));
935 std.tymed = pFormatetc->tymed = TYMED_ISTORAGE;
937 hStorage = GlobalAlloc(GMEM_SHARE|GMEM_MOVEABLE, 0);
938 hr = CreateILockBytesOnHGlobal(hStorage, FALSE, &ptrILockBytes);
939 hr = StgCreateDocfileOnILockBytes(ptrILockBytes, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &std.u.pstg);
941 if (FAILED(hr = IDataObject_GetDataHere(theOleClipboard->pIDataObjectSrc, pFormatetc, &std)))
943 WARN("() : IDataObject_GetDataHere failed to render clipboard data! (%lx)\n", hr);
947 if (1) /* check whether the presentation data is already -not- present */
951 METAFILEPICT *mfp = 0;
953 fmt2.cfFormat = CF_METAFILEPICT;
955 fmt2.dwAspect = DVASPECT_CONTENT;
957 fmt2.tymed = TYMED_MFPICT;
959 memset(&std2, 0, sizeof(STGMEDIUM));
960 std2.tymed = TYMED_MFPICT;
962 /* Get the metafile picture out of it */
964 if (!FAILED(hr = IDataObject_GetData(theOleClipboard->pIDataObjectSrc, &fmt2, &std2)))
966 mfp = (METAFILEPICT *)GlobalLock(std2.u.hGlobal);
971 OLECHAR name[]={ 2, 'O', 'l', 'e', 'P', 'r', 'e', 's', '0', '0', '0', 0};
972 IStream *pStream = 0;
974 PresentationDataHeader pdh;
978 CHAR strOleTypeName[51];
979 BYTE OlePresStreamHeader [] =
981 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00,
982 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
983 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
984 0x00, 0x00, 0x00, 0x00
987 nSize = GetMetaFileBitsEx(mfp->hMF, 0, NULL);
989 memset(&pdh, 0, sizeof(PresentationDataHeader));
990 memcpy(&pdh, OlePresStreamHeader, sizeof(OlePresStreamHeader));
992 pdh.dwObjectExtentX = mfp->xExt;
993 pdh.dwObjectExtentY = mfp->yExt;
996 hr = IStorage_CreateStream(std.u.pstg, name, STGM_CREATE|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, 0, &pStream);
998 hr = IStream_Write(pStream, &pdh, sizeof(PresentationDataHeader), NULL);
1000 mfBits = HeapAlloc(GetProcessHeap(), 0, nSize);
1001 nSize = GetMetaFileBitsEx(mfp->hMF, nSize, mfBits);
1003 hr = IStream_Write(pStream, mfBits, nSize, NULL);
1005 IStream_Release(pStream);
1007 HeapFree(GetProcessHeap(), 0, mfBits);
1009 GlobalUnlock(std2.u.hGlobal);
1011 ReadClassStg(std.u.pstg, &clsID);
1012 ProgIDFromCLSID(&clsID, &strProgID);
1014 WideCharToMultiByte( CP_ACP, 0, strProgID, -1, strOleTypeName, sizeof(strOleTypeName), NULL, NULL );
1015 OLECONVERT_CreateOleStream(std.u.pstg);
1016 OLECONVERT_CreateCompObjStream(std.u.pstg, strOleTypeName);
1022 if (FAILED(hr = IDataObject_GetData(pIDataObject, pFormatetc, &std)))
1024 WARN("() : IDataObject_GetData failed to render clipboard data! (%lx)\n", hr);
1028 /* To put a copy back on the clipboard */
1030 hStorage = std.u.hGlobal;
1034 * Put a copy of the rendered data back on the clipboard
1037 if ( !(hDup = OLEClipbrd_GlobalDupMem(hStorage)) )
1038 HANDLE_ERROR( E_OUTOFMEMORY );
1040 if ( !SetClipboardData( pFormatetc->cfFormat, hDup ) )
1043 WARN("() : Failed to set rendered clipboard data into clipboard!\n");
1048 ReleaseStgMedium(&std);
1054 /***********************************************************************
1055 * OLEClipbrd_GlobalDupMem( HGLOBAL )
1056 * Helper method to duplicate an HGLOBAL chunk of memory
1058 static HGLOBAL OLEClipbrd_GlobalDupMem( HGLOBAL hGlobalSrc )
1060 HGLOBAL hGlobalDest;
1061 PVOID pGlobalSrc, pGlobalDest;
1067 cBytes = GlobalSize(hGlobalSrc);
1071 hGlobalDest = GlobalAlloc( GMEM_DDESHARE|GMEM_MOVEABLE,
1076 pGlobalSrc = GlobalLock(hGlobalSrc);
1077 pGlobalDest = GlobalLock(hGlobalDest);
1078 if ( !pGlobalSrc || !pGlobalDest )
1081 memcpy(pGlobalDest, pGlobalSrc, cBytes);
1083 GlobalUnlock(hGlobalSrc);
1084 GlobalUnlock(hGlobalDest);
1090 /*---------------------------------------------------------------------*
1091 * Implementation of the internal IDataObject interface exposed by
1092 * the OLE clipboard.
1093 *---------------------------------------------------------------------*/
1096 /************************************************************************
1097 * OLEClipbrd_IDataObject_QueryInterface (IUnknown)
1099 * See Windows documentation for more details on IUnknown methods.
1101 static HRESULT WINAPI OLEClipbrd_IDataObject_QueryInterface(
1107 * Declare "This" pointer
1109 ICOM_THIS(OLEClipbrd, iface);
1110 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObject);
1113 * Perform a sanity check on the parameters.
1115 if ( (This==0) || (ppvObject==0) )
1116 return E_INVALIDARG;
1119 * Initialize the return parameter.
1124 * Compare the riid with the interface IDs implemented by this object.
1126 if (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0)
1130 else if (memcmp(&IID_IDataObject, riid, sizeof(IID_IDataObject)) == 0)
1132 *ppvObject = (IDataObject*)&(This->lpvtbl1);
1134 else /* We only support IUnknown and IDataObject */
1136 WARN( "() : asking for unsupported interface %s\n", debugstr_guid(riid));
1137 return E_NOINTERFACE;
1141 * Query Interface always increases the reference count by one when it is
1144 IUnknown_AddRef((IUnknown*)*ppvObject);
1149 /************************************************************************
1150 * OLEClipbrd_IDataObject_AddRef (IUnknown)
1152 * See Windows documentation for more details on IUnknown methods.
1154 static ULONG WINAPI OLEClipbrd_IDataObject_AddRef(
1158 * Declare "This" pointer
1160 ICOM_THIS(OLEClipbrd, iface);
1162 TRACE("(%p)->(count=%lu)\n",This, This->ref);
1169 /************************************************************************
1170 * OLEClipbrd_IDataObject_Release (IUnknown)
1172 * See Windows documentation for more details on IUnknown methods.
1174 static ULONG WINAPI OLEClipbrd_IDataObject_Release(
1178 * Declare "This" pointer
1180 ICOM_THIS(OLEClipbrd, iface);
1182 TRACE("(%p)->(count=%lu)\n",This, This->ref);
1185 * Decrease the reference count on this object.
1190 * If the reference count goes down to 0, perform suicide.
1194 OLEClipbrd_Destroy(This);
1201 /************************************************************************
1202 * OLEClipbrd_IDataObject_GetData (IDataObject)
1204 * The OLE Clipboard's implementation of this method delegates to
1205 * a data source if there is one or wraps around the windows clipboard
1207 * See Windows documentation for more details on IDataObject methods.
1209 static HRESULT WINAPI OLEClipbrd_IDataObject_GetData(
1211 LPFORMATETC pformatetcIn,
1215 BOOL bClipboardOpen = FALSE;
1220 * Declare "This" pointer
1222 ICOM_THIS(OLEClipbrd, iface);
1224 TRACE("(%p,%p,%p)\n", iface, pformatetcIn, pmedium);
1226 if ( !pformatetcIn || !pmedium )
1227 return E_INVALIDARG;
1230 * If we have a data source placed on the clipboard (via OleSetClipboard)
1231 * simply delegate to the source object's QueryGetData
1232 * NOTE: This code assumes that the IDataObject is in the same address space!
1233 * We will need to add marshalling support when Wine handles multiple processes.
1235 if ( This->pIDataObjectSrc )
1237 return IDataObject_GetData(This->pIDataObjectSrc, pformatetcIn, pmedium);
1240 if ( pformatetcIn->lindex != -1 )
1242 if ( (pformatetcIn->tymed & TYMED_HGLOBAL) != TYMED_HGLOBAL )
1245 if ( pformatetcIn->dwAspect != DVASPECT_CONTENT )
1246 return DV_E_DVASPECT;
1250 * Otherwise, get the data from the windows clipboard using GetClipboardData
1252 if ( !(bClipboardOpen = OpenClipboard(theOleClipboard->hWndClipboard)) )
1253 HANDLE_ERROR( CLIPBRD_E_CANT_OPEN );
1255 hData = GetClipboardData(pformatetcIn->cfFormat);
1257 /* Must make a copy of global handle returned by GetClipboardData; it
1258 * is not valid after we call CloseClipboard
1259 * Application is responsible for freeing the memory (Forte Agent does this)
1261 src = GlobalLock(hData);
1267 size = GlobalSize(hData);
1268 hDest = GlobalAlloc(GHND, size);
1269 dest = GlobalLock(hDest);
1270 memcpy(dest, src, size);
1271 GlobalUnlock(hDest);
1272 GlobalUnlock(hData);
1277 * Return the clipboard data in the storage medium structure
1279 pmedium->tymed = (hData == 0) ? TYMED_NULL : TYMED_HGLOBAL;
1280 pmedium->u.hGlobal = (HGLOBAL)hData;
1281 pmedium->pUnkForRelease = NULL;
1287 * Close Windows clipboard
1289 if ( bClipboardOpen && !CloseClipboard() )
1290 hr = CLIPBRD_E_CANT_CLOSE;
1294 return (hData == 0) ? DV_E_FORMATETC : S_OK;
1297 static HRESULT WINAPI OLEClipbrd_IDataObject_GetDataHere(
1299 LPFORMATETC pformatetc,
1306 /************************************************************************
1307 * OLEClipbrd_IDataObject_QueryGetData (IDataObject)
1309 * The OLE Clipboard's implementation of this method delegates to
1310 * a data source if there is one or wraps around the windows clipboard
1311 * function IsClipboardFormatAvailable() otherwise.
1313 * See Windows documentation for more details on IDataObject methods.
1315 static HRESULT WINAPI OLEClipbrd_IDataObject_QueryGetData(
1317 LPFORMATETC pformatetc)
1320 * Declare "This" pointer
1322 ICOM_THIS(OLEClipbrd, iface);
1324 TRACE("(%p, %p)\n", iface, pformatetc);
1327 * If we have a data source placed on the clipboard (via OleSetClipboard)
1328 * simply delegate to the source object's QueryGetData
1330 if ( This->pIDataObjectSrc )
1332 return IDataObject_QueryGetData(This->pIDataObjectSrc, pformatetc);
1336 return E_INVALIDARG;
1338 if ( pformatetc->dwAspect != DVASPECT_CONTENT )
1339 return DV_E_DVASPECT;
1341 if ( pformatetc->lindex != -1 )
1344 /* TODO: Handle TYMED_IStorage media which were put on the clipboard
1345 * by copying the storage into global memory. We must convert this
1346 * TYMED_HGLOBAL back to TYMED_IStorage.
1348 if ( pformatetc->tymed != TYMED_HGLOBAL )
1352 * Delegate to the Windows clipboard function IsClipboardFormatAvailable
1354 return (IsClipboardFormatAvailable(pformatetc->cfFormat)) ? S_OK : DV_E_FORMATETC;
1357 /************************************************************************
1358 * OLEClipbrd_IDataObject_GetCanonicalFormatEtc (IDataObject)
1360 * See Windows documentation for more details on IDataObject methods.
1362 static HRESULT WINAPI OLEClipbrd_IDataObject_GetCanonicalFormatEtc(
1364 LPFORMATETC pformatectIn,
1365 LPFORMATETC pformatetcOut)
1367 TRACE("(%p, %p, %p)\n", iface, pformatectIn, pformatetcOut);
1369 if ( !pformatectIn || !pformatetcOut )
1370 return E_INVALIDARG;
1372 memcpy(pformatetcOut, pformatectIn, sizeof(FORMATETC));
1373 return DATA_S_SAMEFORMATETC;
1376 /************************************************************************
1377 * OLEClipbrd_IDataObject_SetData (IDataObject)
1379 * The OLE Clipboard's does not implement this method
1381 * See Windows documentation for more details on IDataObject methods.
1383 static HRESULT WINAPI OLEClipbrd_IDataObject_SetData(
1385 LPFORMATETC pformatetc,
1393 /************************************************************************
1394 * OLEClipbrd_IDataObject_EnumFormatEtc (IDataObject)
1396 * See Windows documentation for more details on IDataObject methods.
1398 static HRESULT WINAPI OLEClipbrd_IDataObject_EnumFormatEtc(
1401 IEnumFORMATETC** ppenumFormatEtc)
1404 FORMATETC *afmt = NULL;
1407 BOOL bClipboardOpen;
1410 * Declare "This" pointer
1412 ICOM_THIS(OLEClipbrd, iface);
1414 TRACE("(%p, %lx, %p)\n", iface, dwDirection, ppenumFormatEtc);
1417 * If we have a data source placed on the clipboard (via OleSetClipboard)
1418 * simply delegate to the source object's EnumFormatEtc
1420 if ( This->pIDataObjectSrc )
1422 return IDataObject_EnumFormatEtc(This->pIDataObjectSrc,
1423 dwDirection, ppenumFormatEtc);
1427 * Otherwise we must provide our own enumerator which wraps around the
1428 * Windows clipboard function EnumClipboardFormats
1430 if ( !ppenumFormatEtc )
1431 return E_INVALIDARG;
1433 if ( dwDirection != DATADIR_GET ) /* IDataObject_SetData not implemented */
1437 * Store all current clipboard formats in an array of FORMATETC's,
1438 * and create an IEnumFORMATETC enumerator from this list.
1440 cfmt = CountClipboardFormats();
1441 afmt = (FORMATETC *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1442 sizeof(FORMATETC) * cfmt);
1444 * Open the Windows clipboard, associating it with our hidden window
1446 if ( !(bClipboardOpen = OpenClipboard(This->hWndClipboard)) )
1447 HANDLE_ERROR( CLIPBRD_E_CANT_OPEN );
1450 * Store all current clipboard formats in an array of FORMATETC's
1451 * TODO: Handle TYMED_IStorage media which were put on the clipboard
1452 * by copying the storage into global memory. We must convert this
1453 * TYMED_HGLOBAL back to TYMED_IStorage.
1455 for (i = 0, format = 0; i < cfmt; i++)
1457 format = EnumClipboardFormats(format);
1458 if (!format) /* Failed! */
1460 ERR("EnumClipboardFormats failed to return format!\n");
1461 HANDLE_ERROR( E_FAIL );
1464 /* Init the FORMATETC struct */
1465 afmt[i].cfFormat = format;
1467 afmt[i].dwAspect = DVASPECT_CONTENT;
1468 afmt[i].lindex = -1;
1469 afmt[i].tymed = TYMED_HGLOBAL;
1473 * Create an EnumFORMATETC enumerator and return an
1474 * EnumFORMATETC after bumping up its ref count
1476 *ppenumFormatEtc = OLEClipbrd_IEnumFORMATETC_Construct( cfmt, afmt, (LPUNKNOWN)iface);
1477 if (!(*ppenumFormatEtc))
1478 HANDLE_ERROR( E_OUTOFMEMORY );
1480 if (FAILED( hr = IEnumFORMATETC_AddRef(*ppenumFormatEtc)))
1487 * Free the array of FORMATETC's
1490 HeapFree(GetProcessHeap(), 0, afmt);
1493 * Close Windows clipboard
1495 if ( bClipboardOpen && !CloseClipboard() )
1496 hr = CLIPBRD_E_CANT_CLOSE;
1501 /************************************************************************
1502 * OLEClipbrd_IDataObject_DAdvise (IDataObject)
1504 * The OLE Clipboard's does not implement this method
1506 * See Windows documentation for more details on IDataObject methods.
1508 static HRESULT WINAPI OLEClipbrd_IDataObject_DAdvise(
1510 FORMATETC* pformatetc,
1512 IAdviseSink* pAdvSink,
1513 DWORD* pdwConnection)
1519 /************************************************************************
1520 * OLEClipbrd_IDataObject_DUnadvise (IDataObject)
1522 * The OLE Clipboard's does not implement this method
1524 * See Windows documentation for more details on IDataObject methods.
1526 static HRESULT WINAPI OLEClipbrd_IDataObject_DUnadvise(
1534 /************************************************************************
1535 * OLEClipbrd_IDataObject_EnumDAdvise (IDataObject)
1537 * The OLE Clipboard does not implement this method
1539 * See Windows documentation for more details on IDataObject methods.
1541 static HRESULT WINAPI OLEClipbrd_IDataObject_EnumDAdvise(
1543 IEnumSTATDATA** ppenumAdvise)
1550 /*---------------------------------------------------------------------*
1551 * Implementation of the internal IEnumFORMATETC interface returned by
1552 * the OLE clipboard's IDataObject.
1553 *---------------------------------------------------------------------*/
1555 /************************************************************************
1556 * OLEClipbrd_IEnumFORMATETC_Construct (UINT, const FORMATETC, LPUNKNOWN)
1558 * Creates an IEnumFORMATETC enumerator from an array of FORMATETC
1559 * Structures. pUnkOuter is the outer unknown for reference counting only.
1560 * NOTE: this does not AddRef the interface.
1563 LPENUMFORMATETC OLEClipbrd_IEnumFORMATETC_Construct(UINT cfmt, const FORMATETC afmt[],
1564 LPUNKNOWN pUnkDataObj)
1566 IEnumFORMATETCImpl* ef;
1567 DWORD size=cfmt * sizeof(FORMATETC);
1570 ef = (IEnumFORMATETCImpl*)HeapAlloc(GetProcessHeap(),
1572 sizeof(IEnumFORMATETCImpl));
1577 ICOM_VTBL(ef) = &efvt;
1578 ef->pUnkDataObj = pUnkDataObj;
1581 ef->countFmt = cfmt;
1582 if (FAILED(CoGetMalloc(MEMCTX_TASK, &pIMalloc)))
1584 ef->pFmt = (LPFORMATETC)IMalloc_Alloc(pIMalloc, size);
1585 IMalloc_Release(pIMalloc);
1588 memcpy(ef->pFmt, afmt, size);
1590 TRACE("(%p)->()\n",ef);
1591 return (LPENUMFORMATETC)ef;
1595 /************************************************************************
1596 * OLEClipbrd_IEnumFORMATETC_QueryInterface (IUnknown)
1598 * See Windows documentation for more details on IUnknown methods.
1600 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_QueryInterface
1601 (LPENUMFORMATETC iface, REFIID riid, LPVOID* ppvObj)
1603 ICOM_THIS(IEnumFORMATETCImpl,iface);
1605 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
1608 * Since enumerators are separate objects from the parent data object
1609 * we only need to support the IUnknown and IEnumFORMATETC interfaces
1614 if(IsEqualIID(riid, &IID_IUnknown))
1618 else if(IsEqualIID(riid, &IID_IEnumFORMATETC))
1620 *ppvObj = (IDataObject*)This;
1625 IEnumFORMATETC_AddRef((IEnumFORMATETC*)*ppvObj);
1626 TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
1630 TRACE("-- Interface: E_NOINTERFACE\n");
1631 return E_NOINTERFACE;
1634 /************************************************************************
1635 * OLEClipbrd_IEnumFORMATETC_AddRef (IUnknown)
1637 * Since enumerating formats only makes sense when our data object is around,
1638 * we insure that it stays as long as we stay by calling our parents IUnknown
1639 * for AddRef and Release. But since we are not controlled by the lifetime of
1640 * the outer object, we still keep our own reference count in order to
1643 static ULONG WINAPI OLEClipbrd_IEnumFORMATETC_AddRef(LPENUMFORMATETC iface)
1645 ICOM_THIS(IEnumFORMATETCImpl,iface);
1646 TRACE("(%p)->(count=%lu)\n",This, This->ref);
1648 if (This->pUnkDataObj)
1649 IUnknown_AddRef(This->pUnkDataObj);
1651 return ++(This->ref);
1654 /************************************************************************
1655 * OLEClipbrd_IEnumFORMATETC_Release (IUnknown)
1657 * See Windows documentation for more details on IUnknown methods.
1659 static ULONG WINAPI OLEClipbrd_IEnumFORMATETC_Release(LPENUMFORMATETC iface)
1661 ICOM_THIS(IEnumFORMATETCImpl,iface);
1664 TRACE("(%p)->(count=%lu)\n",This, This->ref);
1666 if (This->pUnkDataObj)
1667 IUnknown_Release(This->pUnkDataObj); /* Release parent data object */
1671 TRACE("() - destroying IEnumFORMATETC(%p)\n",This);
1672 if (SUCCEEDED(CoGetMalloc(MEMCTX_TASK, &pIMalloc)))
1674 IMalloc_Free(pIMalloc, This->pFmt);
1675 IMalloc_Release(pIMalloc);
1678 HeapFree(GetProcessHeap(),0,This);
1685 /************************************************************************
1686 * OLEClipbrd_IEnumFORMATETC_Next (IEnumFORMATETC)
1688 * Standard enumerator members for IEnumFORMATETC
1690 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Next
1691 (LPENUMFORMATETC iface, ULONG celt, FORMATETC *rgelt, ULONG *pceltFethed)
1693 ICOM_THIS(IEnumFORMATETCImpl,iface);
1695 HRESULT hres = S_FALSE;
1697 TRACE("(%p)->(pos=%u)\n", This, This->posFmt);
1699 if (This->posFmt < This->countFmt)
1701 cfetch = This->countFmt - This->posFmt;
1708 memcpy(rgelt, &This->pFmt[This->posFmt], cfetch * sizeof(FORMATETC));
1709 This->posFmt += cfetch;
1718 *pceltFethed = cfetch;
1724 /************************************************************************
1725 * OLEClipbrd_IEnumFORMATETC_Skip (IEnumFORMATETC)
1727 * Standard enumerator members for IEnumFORMATETC
1729 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Skip(LPENUMFORMATETC iface, ULONG celt)
1731 ICOM_THIS(IEnumFORMATETCImpl,iface);
1732 TRACE("(%p)->(num=%lu)\n", This, celt);
1734 This->posFmt += celt;
1735 if (This->posFmt > This->countFmt)
1737 This->posFmt = This->countFmt;
1743 /************************************************************************
1744 * OLEClipbrd_IEnumFORMATETC_Reset (IEnumFORMATETC)
1746 * Standard enumerator members for IEnumFORMATETC
1748 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Reset(LPENUMFORMATETC iface)
1750 ICOM_THIS(IEnumFORMATETCImpl,iface);
1751 TRACE("(%p)->()\n", This);
1757 /************************************************************************
1758 * OLEClipbrd_IEnumFORMATETC_Clone (IEnumFORMATETC)
1760 * Standard enumerator members for IEnumFORMATETC
1762 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Clone
1763 (LPENUMFORMATETC iface, LPENUMFORMATETC* ppenum)
1765 ICOM_THIS(IEnumFORMATETCImpl,iface);
1768 TRACE("(%p)->(ppenum=%p)\n", This, ppenum);
1771 return E_INVALIDARG;
1773 *ppenum = OLEClipbrd_IEnumFORMATETC_Construct(This->countFmt,
1777 if (FAILED( hr = IEnumFORMATETC_AddRef(*ppenum)))
1780 return (*ppenum) ? S_OK : E_OUTOFMEMORY;