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.
57 #include "debugtools.h"
60 #include "storage32.h"
62 #define HANDLE_ERROR(err) { hr = err; TRACE("(HRESULT=%lx)\n", (HRESULT)err); goto CLEANUP; }
64 /* For CoGetMalloc (MEMCTX_TASK is currently ignored) */
66 #define MEMCTX_TASK -1
69 DEFAULT_DEBUG_CHANNEL(ole
);
71 /****************************************************************************
73 * DO NOT add any members before the VTables declaration!
78 * List all interface VTables here
80 ICOM_VTABLE(IDataObject
)* lpvtbl1
; /* IDataObject VTable */
83 * The hidden OLE clipboard window. This window is used as the bridge between the
84 * the OLE and windows clipboard API. (Windows creates one such window per process)
89 * Pointer to the source data object (via OleSetClipboard)
91 IDataObject
* pIDataObjectSrc
;
94 * The registered DataObject clipboard format
99 * The handle to our ourself
104 * Reference count of this object
109 typedef struct OLEClipbrd OLEClipbrd
;
112 /****************************************************************************
113 * IEnumFORMATETC implementation
114 * DO NOT add any members before the VTables declaration!
118 /* IEnumFORMATETC VTable */
119 ICOM_VFIELD(IEnumFORMATETC
);
121 /* IEnumFORMATETC fields */
122 UINT posFmt
; /* current enumerator position */
123 UINT countFmt
; /* number of EnumFORMATETC's in array */
124 LPFORMATETC pFmt
; /* array of EnumFORMATETC's */
127 * Reference count of this object
132 * IUnknown implementation of the parent data object.
134 IUnknown
* pUnkDataObj
;
136 } IEnumFORMATETCImpl
;
138 typedef struct PresentationDataHeader
141 DWORD dwObjectExtentX
;
142 DWORD dwObjectExtentY
;
144 } PresentationDataHeader
;
147 * The one and only OLEClipbrd object which is created by OLEClipbrd_Initialize()
149 static HGLOBAL hTheOleClipboard
= 0;
150 static OLEClipbrd
* theOleClipboard
= NULL
;
154 * Prototypes for the methods of the OLEClipboard class.
156 extern void OLEClipbrd_Initialize();
157 extern void OLEClipbrd_UnInitialize();
158 static OLEClipbrd
* OLEClipbrd_Construct();
159 static void OLEClipbrd_Destroy(OLEClipbrd
* ptrToDestroy
);
160 static HWND
OLEClipbrd_CreateWindow();
161 static void OLEClipbrd_DestroyWindow(HWND hwnd
);
162 LRESULT CALLBACK
OLEClipbrd_WndProc(HWND hWnd
, UINT message
, WPARAM wParam
, LPARAM lParam
);
163 static HRESULT
OLEClipbrd_RenderFormat( IDataObject
*pIDataObject
, LPFORMATETC pFormatetc
);
164 static HGLOBAL
OLEClipbrd_GlobalDupMem( HGLOBAL hGlobalSrc
);
167 * Prototypes for the methods of the OLEClipboard class
168 * that implement IDataObject methods.
170 static HRESULT WINAPI
OLEClipbrd_IDataObject_QueryInterface(
174 static ULONG WINAPI
OLEClipbrd_IDataObject_AddRef(
176 static ULONG WINAPI
OLEClipbrd_IDataObject_Release(
178 static HRESULT WINAPI
OLEClipbrd_IDataObject_GetData(
180 LPFORMATETC pformatetcIn
,
182 static HRESULT WINAPI
OLEClipbrd_IDataObject_GetDataHere(
184 LPFORMATETC pformatetc
,
186 static HRESULT WINAPI
OLEClipbrd_IDataObject_QueryGetData(
188 LPFORMATETC pformatetc
);
189 static HRESULT WINAPI
OLEClipbrd_IDataObject_GetCanonicalFormatEtc(
191 LPFORMATETC pformatectIn
,
192 LPFORMATETC pformatetcOut
);
193 static HRESULT WINAPI
OLEClipbrd_IDataObject_SetData(
195 LPFORMATETC pformatetc
,
198 static HRESULT WINAPI
OLEClipbrd_IDataObject_EnumFormatEtc(
201 IEnumFORMATETC
** ppenumFormatEtc
);
202 static HRESULT WINAPI
OLEClipbrd_IDataObject_DAdvise(
204 FORMATETC
* pformatetc
,
206 IAdviseSink
* pAdvSink
,
207 DWORD
* pdwConnection
);
208 static HRESULT WINAPI
OLEClipbrd_IDataObject_DUnadvise(
211 static HRESULT WINAPI
OLEClipbrd_IDataObject_EnumDAdvise(
213 IEnumSTATDATA
** ppenumAdvise
);
216 * Prototypes for the IEnumFORMATETC methods.
218 static LPENUMFORMATETC
OLEClipbrd_IEnumFORMATETC_Construct(UINT cfmt
, const FORMATETC afmt
[],
219 LPUNKNOWN pUnkDataObj
);
220 static HRESULT WINAPI
OLEClipbrd_IEnumFORMATETC_QueryInterface(LPENUMFORMATETC iface
, REFIID riid
,
222 static ULONG WINAPI
OLEClipbrd_IEnumFORMATETC_AddRef(LPENUMFORMATETC iface
);
223 static ULONG WINAPI
OLEClipbrd_IEnumFORMATETC_Release(LPENUMFORMATETC iface
);
224 static HRESULT WINAPI
OLEClipbrd_IEnumFORMATETC_Next(LPENUMFORMATETC iface
, ULONG celt
,
225 FORMATETC
* rgelt
, ULONG
* pceltFethed
);
226 static HRESULT WINAPI
OLEClipbrd_IEnumFORMATETC_Skip(LPENUMFORMATETC iface
, ULONG celt
);
227 static HRESULT WINAPI
OLEClipbrd_IEnumFORMATETC_Reset(LPENUMFORMATETC iface
);
228 static HRESULT WINAPI
OLEClipbrd_IEnumFORMATETC_Clone(LPENUMFORMATETC iface
, LPENUMFORMATETC
* ppenum
);
232 * Virtual function table for the OLEClipbrd's exposed IDataObject interface
234 static ICOM_VTABLE(IDataObject
) OLEClipbrd_IDataObject_VTable
=
236 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
237 OLEClipbrd_IDataObject_QueryInterface
,
238 OLEClipbrd_IDataObject_AddRef
,
239 OLEClipbrd_IDataObject_Release
,
240 OLEClipbrd_IDataObject_GetData
,
241 OLEClipbrd_IDataObject_GetDataHere
,
242 OLEClipbrd_IDataObject_QueryGetData
,
243 OLEClipbrd_IDataObject_GetCanonicalFormatEtc
,
244 OLEClipbrd_IDataObject_SetData
,
245 OLEClipbrd_IDataObject_EnumFormatEtc
,
246 OLEClipbrd_IDataObject_DAdvise
,
247 OLEClipbrd_IDataObject_DUnadvise
,
248 OLEClipbrd_IDataObject_EnumDAdvise
252 * Virtual function table for IEnumFORMATETC interface
254 static struct ICOM_VTABLE(IEnumFORMATETC
) efvt
=
256 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
257 OLEClipbrd_IEnumFORMATETC_QueryInterface
,
258 OLEClipbrd_IEnumFORMATETC_AddRef
,
259 OLEClipbrd_IEnumFORMATETC_Release
,
260 OLEClipbrd_IEnumFORMATETC_Next
,
261 OLEClipbrd_IEnumFORMATETC_Skip
,
262 OLEClipbrd_IEnumFORMATETC_Reset
,
263 OLEClipbrd_IEnumFORMATETC_Clone
267 * Name of our registered OLE clipboard window class
269 CHAR OLEClipbrd_WNDCLASS
[] = "CLIPBRDWNDCLASS";
272 * If we need to store state info we can store it here.
273 * For now we dont need this functionality.
275 typedef struct tagClipboardWindowInfo
277 } ClipboardWindowInfo;
280 /*---------------------------------------------------------------------*
281 * Win32 OLE clipboard API
282 *---------------------------------------------------------------------*/
284 /***********************************************************************
285 * OleSetClipboard [OLE32.127]
286 * Places a pointer to the specified data object onto the clipboard,
287 * making the data object accessible to the OleGetClipboard function.
291 * S_OK IDataObject pointer placed on the clipboard
292 * CLIPBRD_E_CANT_OPEN OpenClipboard failed
293 * CLIPBRD_E_CANT_EMPTY EmptyClipboard failed
294 * CLIPBRD_E_CANT_CLOSE CloseClipboard failed
295 * CLIPBRD_E_CANT_SET SetClipboard failed
298 HRESULT WINAPI
OleSetClipboard(IDataObject
* pDataObj
)
301 IEnumFORMATETC
* penumFormatetc
= NULL
;
303 BOOL bClipboardOpen
= FALSE
;
305 HGLOBAL hDataObject = 0;
306 OLEClipbrd **ppDataObject;
309 TRACE("(%p)\n", pDataObj
);
312 * Make sure we have a clipboard object
314 OLEClipbrd_Initialize();
317 * If the Ole clipboard window hasn't been created yet, create it now.
319 if ( !theOleClipboard
->hWndClipboard
)
320 theOleClipboard
->hWndClipboard
= OLEClipbrd_CreateWindow();
322 if ( !theOleClipboard
->hWndClipboard
) /* sanity check */
323 HANDLE_ERROR( E_FAIL
);
326 * Open the Windows clipboard, associating it with our hidden window
328 if ( !(bClipboardOpen
= OpenClipboard(theOleClipboard
->hWndClipboard
)) )
329 HANDLE_ERROR( CLIPBRD_E_CANT_OPEN
);
332 * Empty the current clipboard and make our window the clipboard owner
333 * NOTE: This will trigger a WM_DESTROYCLIPBOARD message
335 if ( !EmptyClipboard() )
336 HANDLE_ERROR( CLIPBRD_E_CANT_EMPTY
);
339 * If we are already holding on to an IDataObject first release that.
341 if ( theOleClipboard
->pIDataObjectSrc
)
343 IDataObject_Release(theOleClipboard
->pIDataObjectSrc
);
344 theOleClipboard
->pIDataObjectSrc
= NULL
;
348 * AddRef the data object passed in and save its pointer.
349 * A NULL value indicates that the clipboard should be emptied.
351 theOleClipboard
->pIDataObjectSrc
= pDataObj
;
354 IDataObject_AddRef(theOleClipboard
->pIDataObjectSrc
);
358 * Enumerate all HGLOBAL formats supported by the source and make
359 * those formats available using delayed rendering using SetClipboardData.
360 * Only global memory based data items may be made available to non-OLE
361 * applications via the standard Windows clipboard API. Data based on other
362 * mediums(non TYMED_HGLOBAL) can only be accessed via the Ole Clipboard API.
364 * TODO: Do we need to additionally handle TYMED_IStorage media by copying
365 * the storage into global memory?
369 if ( FAILED(hr
= IDataObject_EnumFormatEtc( pDataObj
,
376 while ( S_OK
== IEnumFORMATETC_Next(penumFormatetc
, 1, &rgelt
, NULL
) )
378 if ( rgelt
.tymed
== TYMED_HGLOBAL
)
381 TRACE("(cfFormat=%d:%s)\n", rgelt
.cfFormat
,
382 GetClipboardFormatNameA(rgelt
.cfFormat
, szFmtName
, sizeof(szFmtName
)-1)
385 SetClipboardData( rgelt
.cfFormat
, (HANDLE
)NULL
);
388 IEnumFORMATETC_Release(penumFormatetc
);
392 * Windows additionally creates a new "DataObject" clipboard format
393 * and stores in on the clipboard. We could possibly store a pointer
394 * to our internal IDataObject interface on the clipboard. I'm not
395 * sure what the use of this is though.
396 * Enable the code below for this functionality.
399 theOleClipboard->cfDataObj = RegisterClipboardFormatA("DataObject");
400 hDataObject = GlobalAlloc( GMEM_DDESHARE|GMEM_MOVEABLE|GMEM_ZEROINIT,
401 sizeof(OLEClipbrd *));
403 HANDLE_ERROR( E_OUTOFMEMORY );
405 ppDataObject = (OLEClipbrd**)GlobalLock(hDataObject);
406 *ppDataObject = theOleClipboard;
407 GlobalUnlock(hDataObject);
409 if ( !SetClipboardData( theOleClipboard->cfDataObj, hDataObject ) )
410 HANDLE_ERROR( CLIPBRD_E_CANT_SET );
418 * Close Windows clipboard (It remains associated with our window)
420 if ( bClipboardOpen
&& !CloseClipboard() )
421 hr
= CLIPBRD_E_CANT_CLOSE
;
424 * Release the source IDataObject if something failed
428 if (theOleClipboard
->pIDataObjectSrc
)
430 IDataObject_Release(theOleClipboard
->pIDataObjectSrc
);
431 theOleClipboard
->pIDataObjectSrc
= NULL
;
439 /***********************************************************************
440 * OleGetClipboard [OLE32.105]
441 * Returns a pointer to our internal IDataObject which represents the conceptual
442 * state of the Windows clipboard. If the current clipboard already contains
443 * an IDataObject, our internal IDataObject will delegate to this object.
445 HRESULT WINAPI
OleGetClipboard(IDataObject
** ppDataObj
)
451 * Make sure we have a clipboard object
453 OLEClipbrd_Initialize();
455 if (!theOleClipboard
)
456 return E_OUTOFMEMORY
;
458 /* Return a reference counted IDataObject */
459 hr
= IDataObject_QueryInterface( (IDataObject
*)&(theOleClipboard
->lpvtbl1
),
460 &IID_IDataObject
, (void**)ppDataObj
);
464 /***********************************************************************
465 * OleFlushClipboard [OLE2.76]
468 HRESULT WINAPI
OleFlushClipboard16(void)
470 return OleFlushClipboard();
474 /******************************************************************************
475 * OleFlushClipboard [OLE32.103]
476 * Renders the data from the source IDataObject into the windows clipboard
478 * TODO: OleFlushClipboard needs to additionally handle TYMED_IStorage media
479 * by copying the storage into global memory. Subsequently the default
480 * data object exposed through OleGetClipboard must convert this TYMED_HGLOBAL
481 * back to TYMED_IStorage.
483 HRESULT WINAPI
OleFlushClipboard()
485 IEnumFORMATETC
* penumFormatetc
= NULL
;
488 BOOL bClipboardOpen
= FALSE
;
489 IDataObject
* pIDataObjectSrc
= NULL
;
494 * Make sure we have a clipboard object
496 OLEClipbrd_Initialize();
499 * Already flushed or no source DataObject? Nothing to do.
501 if (!theOleClipboard
->pIDataObjectSrc
)
505 * Addref and save the source data object we are holding on to temporarily,
506 * since it will be released when we empty the clipboard.
508 pIDataObjectSrc
= theOleClipboard
->pIDataObjectSrc
;
509 IDataObject_AddRef(pIDataObjectSrc
);
512 * Open the Windows clipboard
514 if ( !(bClipboardOpen
= OpenClipboard(theOleClipboard
->hWndClipboard
)) )
515 HANDLE_ERROR( CLIPBRD_E_CANT_OPEN
);
518 * Empty the current clipboard
520 if ( !EmptyClipboard() )
521 HANDLE_ERROR( CLIPBRD_E_CANT_EMPTY
);
524 * Render all HGLOBAL formats supported by the source into
525 * the windows clipboard.
527 if ( FAILED( hr
= IDataObject_EnumFormatEtc( pIDataObjectSrc
,
534 while ( S_OK
== IEnumFORMATETC_Next(penumFormatetc
, 1, &rgelt
, NULL
) )
536 if ( rgelt
.tymed
== TYMED_HGLOBAL
)
539 TRACE("(cfFormat=%d:%s)\n", rgelt
.cfFormat
,
540 GetClipboardFormatNameA(rgelt
.cfFormat
, szFmtName
, sizeof(szFmtName
)-1)
544 * Render the clipboard data
546 if ( FAILED(OLEClipbrd_RenderFormat( pIDataObjectSrc
, &rgelt
)) )
551 IEnumFORMATETC_Release(penumFormatetc
);
554 * Release the source data object we are holding on to
556 IDataObject_Release(pIDataObjectSrc
);
561 * Close Windows clipboard (It remains associated with our window)
563 if ( bClipboardOpen
&& !CloseClipboard() )
564 hr
= CLIPBRD_E_CANT_CLOSE
;
570 /***********************************************************************
571 * OleIsCurrentClipboard [OLE32.110]
573 HRESULT WINAPI
OleIsCurrentClipboard ( IDataObject
*pDataObject
)
577 * Make sure we have a clipboard object
579 OLEClipbrd_Initialize();
581 if (!theOleClipboard
)
582 return E_OUTOFMEMORY
;
584 return (pDataObject
== theOleClipboard
->pIDataObjectSrc
) ? S_OK
: S_FALSE
;
588 /*---------------------------------------------------------------------*
589 * Internal implementation methods for the OLE clipboard
590 *---------------------------------------------------------------------*/
592 /***********************************************************************
593 * OLEClipbrd_Initialize()
594 * Initializes the OLE clipboard.
596 void OLEClipbrd_Initialize()
599 * Create the clipboard if necessary
601 if ( !theOleClipboard
)
604 theOleClipboard
= OLEClipbrd_Construct();
609 /***********************************************************************
610 * OLEClipbrd_UnInitialize()
611 * Un-Initializes the OLE clipboard
613 void OLEClipbrd_UnInitialize()
617 * Destroy the clipboard if no one holds a reference to us.
618 * Note that the clipboard was created with a reference count of 1.
620 if ( theOleClipboard
&& (theOleClipboard
->ref
<= 1) )
622 OLEClipbrd_Destroy( theOleClipboard
);
626 WARN( "() : OLEClipbrd_UnInitialize called while client holds an IDataObject reference!\n");
631 /*********************************************************
632 * Construct the OLEClipbrd class.
634 static OLEClipbrd
* OLEClipbrd_Construct()
636 OLEClipbrd
* newObject
= NULL
;
637 HGLOBAL hNewObject
= 0;
640 * Allocate space for the object. We use GlobalAlloc since we need
641 * an HGLOBAL to expose our DataObject as a registered clipboard type.
643 hNewObject
= GlobalAlloc( GMEM_DDESHARE
|GMEM_MOVEABLE
|GMEM_ZEROINIT
,
649 * Lock the handle for the entire lifetime of the clipboard.
651 newObject
= GlobalLock(hNewObject
);
654 * Initialize the virtual function table.
656 newObject
->lpvtbl1
= &OLEClipbrd_IDataObject_VTable
;
659 * Start with one reference count. The caller of this function
660 * must release the interface pointer when it is done.
664 newObject
->hSelf
= hNewObject
;
667 * The Ole clipboard is a singleton - save the global handle and pointer
669 theOleClipboard
= newObject
;
670 hTheOleClipboard
= hNewObject
;
672 return theOleClipboard
;
675 static void OLEClipbrd_Destroy(OLEClipbrd
* ptrToDestroy
)
683 * Destroy the Ole clipboard window
685 if ( ptrToDestroy
->hWndClipboard
)
686 OLEClipbrd_DestroyWindow(ptrToDestroy
->hWndClipboard
);
689 * Free the actual OLE Clipboard structure.
691 TRACE("() - Destroying clipboard data object.\n");
692 GlobalUnlock(ptrToDestroy
->hSelf
);
693 GlobalFree(ptrToDestroy
->hSelf
);
696 * The Ole clipboard is a singleton (ptrToDestroy == theOleClipboard)
698 theOleClipboard
= NULL
;
699 hTheOleClipboard
= 0;
703 /***********************************************************************
704 * OLEClipbrd_CreateWindow()
705 * Create the clipboard window
707 static HWND
OLEClipbrd_CreateWindow()
713 * Register the clipboard window class if necessary
715 ZeroMemory( &wcex
, sizeof(WNDCLASSEXA
));
717 wcex
.cbSize
= sizeof(WNDCLASSEXA
);
718 /* Windows creates this class with a style mask of 0
719 * We dont bother doing this since the FindClassByAtom code
720 * would have to be changed to deal with this idiosyncracy. */
721 wcex
.style
= CS_GLOBALCLASS
;
722 wcex
.lpfnWndProc
= (WNDPROC
)OLEClipbrd_WndProc
;
724 wcex
.lpszClassName
= OLEClipbrd_WNDCLASS
;
726 RegisterClassExA(&wcex
);
729 * Create a hidden window to receive OLE clipboard messages
733 * If we need to store state info we can store it here.
734 * For now we dont need this functionality.
735 * ClipboardWindowInfo clipboardInfo;
736 * ZeroMemory( &trackerInfo, sizeof(ClipboardWindowInfo));
739 hwnd
= CreateWindowA(OLEClipbrd_WNDCLASS
,
741 WS_POPUP
| WS_CLIPSIBLINGS
| WS_OVERLAPPED
,
742 CW_USEDEFAULT
, CW_USEDEFAULT
,
743 CW_USEDEFAULT
, CW_USEDEFAULT
,
747 0 /*(LPVOID)&clipboardInfo */);
752 /***********************************************************************
753 * OLEClipbrd_DestroyWindow(HWND)
754 * Destroy the clipboard window and unregister its class
756 static void OLEClipbrd_DestroyWindow(HWND hwnd
)
759 * Destroy clipboard window and unregister its WNDCLASS
762 UnregisterClassA( OLEClipbrd_WNDCLASS
, 0 );
765 /***********************************************************************
766 * OLEClipbrd_WndProc(HWND, unsigned, WORD, LONG)
767 * Processes messages sent to the OLE clipboard window.
768 * Note that we will intercept messages in our WndProc only when data
769 * has been placed in the clipboard via OleSetClipboard().
770 * i.e. Only when OLE owns the windows clipboard.
772 LRESULT CALLBACK OLEClipbrd_WndProc
773 (HWND hWnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
779 * We receive this message to allow us to handle delayed rendering of
780 * a specific clipboard format when an application requests data in
781 * that format by calling GetClipboardData.
782 * (Recall that in OleSetClipboard, we used SetClipboardData to
783 * make all HGLOBAL formats supported by the source IDataObject
784 * available using delayed rendering)
785 * On receiving this mesage we must actually render the data in the
786 * specified format and place it on the clipboard by calling the
787 * SetClipboardData function.
789 case WM_RENDERFORMAT
:
793 ZeroMemory( &rgelt
, sizeof(FORMATETC
));
796 * Initialize FORMATETC to a Windows clipboard friendly format
798 rgelt
.cfFormat
= (UINT
) wParam
;
799 rgelt
.dwAspect
= DVASPECT_CONTENT
;
801 rgelt
.tymed
= TYMED_HGLOBAL
;
803 TRACE("(): WM_RENDERFORMAT(cfFormat=%d)\n", rgelt
.cfFormat
);
806 * Render the clipboard data.
807 * (We must have a source data object or we wouldn't be in this WndProc)
809 OLEClipbrd_RenderFormat( (IDataObject
*)&(theOleClipboard
->lpvtbl1
), &rgelt
);
815 * WM_RENDERALLFORMATS
816 * Sent before the clipboard owner window is destroyed.
817 * We should receive this message only when OleUninitialize is called
818 * while we have an IDataObject in the clipboard.
819 * For the content of the clipboard to remain available to other
820 * applications, we must render data in all the formats the source IDataObject
821 * is capable of generating, and place the data on the clipboard by calling
824 case WM_RENDERALLFORMATS
:
826 IEnumFORMATETC
* penumFormatetc
= NULL
;
829 TRACE("(): WM_RENDERALLFORMATS\n");
832 * Render all HGLOBAL formats supported by the source into
833 * the windows clipboard.
835 if ( FAILED( IDataObject_EnumFormatEtc( (IDataObject
*)&(theOleClipboard
->lpvtbl1
),
836 DATADIR_GET
, &penumFormatetc
) ) )
838 WARN("(): WM_RENDERALLFORMATS failed to retrieve EnumFormatEtc!\n");
842 while ( S_OK
== IEnumFORMATETC_Next(penumFormatetc
, 1, &rgelt
, NULL
) )
844 if ( rgelt
.tymed
== TYMED_HGLOBAL
)
847 * Render the clipboard data.
849 if ( FAILED(OLEClipbrd_RenderFormat( (IDataObject
*)&(theOleClipboard
->lpvtbl1
), &rgelt
)) )
852 TRACE("(): WM_RENDERALLFORMATS(cfFormat=%d)\n", rgelt
.cfFormat
);
856 IEnumFORMATETC_Release(penumFormatetc
);
862 * WM_DESTROYCLIPBOARD
863 * This is sent by EmptyClipboard before the clipboard is emptied.
864 * We should release any IDataObject we are holding onto when we receive
865 * this message, since it indicates that the OLE clipboard should be empty
866 * from this point on.
868 case WM_DESTROYCLIPBOARD
:
870 TRACE("(): WM_DESTROYCLIPBOARD\n");
872 * Release the data object we are holding on to
874 if ( theOleClipboard
->pIDataObjectSrc
)
876 IDataObject_Release(theOleClipboard
->pIDataObjectSrc
);
877 theOleClipboard
->pIDataObjectSrc
= NULL
;
883 case WM_ASKCBFORMATNAME:
884 case WM_CHANGECBCHAIN:
885 case WM_DRAWCLIPBOARD:
886 case WM_SIZECLIPBOARD:
887 case WM_HSCROLLCLIPBOARD:
888 case WM_VSCROLLCLIPBOARD:
889 case WM_PAINTCLIPBOARD:
892 return DefWindowProcA(hWnd
, message
, wParam
, lParam
);
898 #define MAX_CLIPFORMAT_NAME 80
900 /***********************************************************************
901 * OLEClipbrd_RenderFormat(LPFORMATETC)
902 * Render the clipboard data. Note that this call will delegate to the
903 * source data object.
904 * Note: This function assumes it is passed an HGLOBAL format to render.
906 static HRESULT
OLEClipbrd_RenderFormat(IDataObject
*pIDataObject
, LPFORMATETC pFormatetc
)
911 char szFmtName
[MAX_CLIPFORMAT_NAME
];
912 ILockBytes
*ptrILockBytes
= 0;
913 HGLOBAL hStorage
= 0;
915 GetClipboardFormatNameA(pFormatetc
->cfFormat
, szFmtName
, MAX_CLIPFORMAT_NAME
);
917 /* If embed source */
918 if (!strcmp(szFmtName
, CF_EMBEDSOURCE
))
920 memset(&std
, 0, sizeof(STGMEDIUM
));
921 std
.tymed
= pFormatetc
->tymed
= TYMED_ISTORAGE
;
923 hStorage
= GlobalAlloc(GMEM_SHARE
|GMEM_MOVEABLE
, 0);
924 hr
= CreateILockBytesOnHGlobal(hStorage
, FALSE
, &ptrILockBytes
);
925 hr
= StgCreateDocfileOnILockBytes(ptrILockBytes
, STGM_SHARE_EXCLUSIVE
|STGM_READWRITE
, 0, &std
.u
.pstg
);
927 if (FAILED(hr
= IDataObject_GetDataHere(theOleClipboard
->pIDataObjectSrc
, pFormatetc
, &std
)))
929 WARN("() : IDataObject_GetDataHere failed to render clipboard data! (%lx)\n", hr
);
933 if (1) /* check whether the presentation data is already -not- present */
937 METAFILEPICT
*mfp
= 0;
939 fmt2
.cfFormat
= CF_METAFILEPICT
;
941 fmt2
.dwAspect
= DVASPECT_CONTENT
;
943 fmt2
.tymed
= TYMED_MFPICT
;
945 memset(&std2
, 0, sizeof(STGMEDIUM
));
946 std2
.tymed
= TYMED_MFPICT
;
948 /* Get the metafile picture out of it */
950 if (!FAILED(hr
= IDataObject_GetData(theOleClipboard
->pIDataObjectSrc
, &fmt2
, &std2
)))
952 mfp
= (METAFILEPICT
*)GlobalLock(std2
.u
.hGlobal
);
957 OLECHAR name
[]={ 2, 'O', 'l', 'e', 'P', 'r', 'e', 's', '0', '0', '0', 0};
958 IStream
*pStream
= 0;
960 PresentationDataHeader pdh
;
964 CHAR strOleTypeName
[51];
965 BYTE OlePresStreamHeader
[] =
967 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00,
968 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
969 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
970 0x00, 0x00, 0x00, 0x00
973 nSize
= GetMetaFileBitsEx(mfp
->hMF
, 0, NULL
);
975 memset(&pdh
, 0, sizeof(PresentationDataHeader
));
976 memcpy(&pdh
, OlePresStreamHeader
, sizeof(OlePresStreamHeader
));
978 pdh
.dwObjectExtentX
= mfp
->xExt
;
979 pdh
.dwObjectExtentY
= mfp
->yExt
;
982 hr
= IStorage_CreateStream(std
.u
.pstg
, name
, STGM_CREATE
|STGM_SHARE_EXCLUSIVE
|STGM_READWRITE
, 0, 0, &pStream
);
984 hr
= IStream_Write(pStream
, &pdh
, sizeof(PresentationDataHeader
), NULL
);
986 mfBits
= HeapAlloc(GetProcessHeap(), 0, nSize
);
987 nSize
= GetMetaFileBitsEx(mfp
->hMF
, nSize
, mfBits
);
989 hr
= IStream_Write(pStream
, mfBits
, nSize
, NULL
);
991 IStream_Release(pStream
);
993 HeapFree(GetProcessHeap(), 0, mfBits
);
995 GlobalUnlock(std2
.u
.hGlobal
);
997 ReadClassStg(std
.u
.pstg
, &clsID
);
998 ProgIDFromCLSID(&clsID
, &strProgID
);
1000 WideCharToMultiByte( CP_ACP
, 0, strProgID
, -1, strOleTypeName
, sizeof(strOleTypeName
), NULL
, NULL
);
1001 OLECONVERT_CreateOleStream(std
.u
.pstg
);
1002 OLECONVERT_CreateCompObjStream(std
.u
.pstg
, strOleTypeName
);
1008 if (FAILED(hr
= IDataObject_GetData(pIDataObject
, pFormatetc
, &std
)))
1010 WARN("() : IDataObject_GetData failed to render clipboard data! (%lx)\n", hr
);
1014 /* To put a copy back on the clipboard */
1016 hStorage
= std
.u
.hGlobal
;
1020 * Put a copy of the rendered data back on the clipboard
1023 if ( !(hDup
= OLEClipbrd_GlobalDupMem(hStorage
)) )
1024 HANDLE_ERROR( E_OUTOFMEMORY
);
1026 if ( !SetClipboardData( pFormatetc
->cfFormat
, hDup
) )
1029 WARN("() : Failed to set rendered clipboard data into clipboard!\n");
1034 ReleaseStgMedium(&std
);
1040 /***********************************************************************
1041 * OLEClipbrd_GlobalDupMem( HGLOBAL )
1042 * Helper method to duplicate an HGLOBAL chunk of memory
1044 static HGLOBAL
OLEClipbrd_GlobalDupMem( HGLOBAL hGlobalSrc
)
1046 HGLOBAL hGlobalDest
;
1047 PVOID pGlobalSrc
, pGlobalDest
;
1053 cBytes
= GlobalSize(hGlobalSrc
);
1057 hGlobalDest
= GlobalAlloc( GMEM_DDESHARE
|GMEM_MOVEABLE
,
1062 pGlobalSrc
= GlobalLock(hGlobalSrc
);
1063 pGlobalDest
= GlobalLock(hGlobalDest
);
1064 if ( !pGlobalSrc
|| !pGlobalDest
)
1067 memcpy(pGlobalDest
, pGlobalSrc
, cBytes
);
1069 GlobalUnlock(hGlobalSrc
);
1070 GlobalUnlock(hGlobalDest
);
1076 /*---------------------------------------------------------------------*
1077 * Implementation of the internal IDataObject interface exposed by
1078 * the OLE clipboard.
1079 *---------------------------------------------------------------------*/
1082 /************************************************************************
1083 * OLEClipbrd_IDataObject_QueryInterface (IUnknown)
1085 * See Windows documentation for more details on IUnknown methods.
1087 static HRESULT WINAPI
OLEClipbrd_IDataObject_QueryInterface(
1093 * Declare "This" pointer
1095 ICOM_THIS(OLEClipbrd
, iface
);
1096 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This
,debugstr_guid(riid
),ppvObject
);
1099 * Perform a sanity check on the parameters.
1101 if ( (This
==0) || (ppvObject
==0) )
1102 return E_INVALIDARG
;
1105 * Initialize the return parameter.
1110 * Compare the riid with the interface IDs implemented by this object.
1112 if (memcmp(&IID_IUnknown
, riid
, sizeof(IID_IUnknown
)) == 0)
1116 else if (memcmp(&IID_IDataObject
, riid
, sizeof(IID_IDataObject
)) == 0)
1118 *ppvObject
= (IDataObject
*)&(This
->lpvtbl1
);
1120 else /* We only support IUnknown and IDataObject */
1122 WARN( "() : asking for unsupported interface %s\n", debugstr_guid(riid
));
1123 return E_NOINTERFACE
;
1127 * Query Interface always increases the reference count by one when it is
1130 IUnknown_AddRef((IUnknown
*)*ppvObject
);
1135 /************************************************************************
1136 * OLEClipbrd_IDataObject_AddRef (IUnknown)
1138 * See Windows documentation for more details on IUnknown methods.
1140 static ULONG WINAPI
OLEClipbrd_IDataObject_AddRef(
1144 * Declare "This" pointer
1146 ICOM_THIS(OLEClipbrd
, iface
);
1148 TRACE("(%p)->(count=%lu)\n",This
, This
->ref
);
1155 /************************************************************************
1156 * OLEClipbrd_IDataObject_Release (IUnknown)
1158 * See Windows documentation for more details on IUnknown methods.
1160 static ULONG WINAPI
OLEClipbrd_IDataObject_Release(
1164 * Declare "This" pointer
1166 ICOM_THIS(OLEClipbrd
, iface
);
1168 TRACE("(%p)->(count=%lu)\n",This
, This
->ref
);
1171 * Decrease the reference count on this object.
1176 * If the reference count goes down to 0, perform suicide.
1180 OLEClipbrd_Destroy(This
);
1187 /************************************************************************
1188 * OLEClipbrd_IDataObject_GetData (IDataObject)
1190 * The OLE Clipboard's implementation of this method delegates to
1191 * a data source if there is one or wraps around the windows clipboard
1193 * See Windows documentation for more details on IDataObject methods.
1195 static HRESULT WINAPI
OLEClipbrd_IDataObject_GetData(
1197 LPFORMATETC pformatetcIn
,
1201 BOOL bClipboardOpen
= FALSE
;
1205 * Declare "This" pointer
1207 ICOM_THIS(OLEClipbrd
, iface
);
1209 TRACE("(%p,%p,%p)\n", iface
, pformatetcIn
, pmedium
);
1211 if ( !pformatetcIn
|| !pmedium
)
1212 return E_INVALIDARG
;
1215 * If we have a data source placed on the clipboard (via OleSetClipboard)
1216 * simply delegate to the source object's QueryGetData
1217 * NOTE: This code assumes that the IDataObject is in the same address space!
1218 * We will need to add marshalling support when Wine handles multiple processes.
1220 if ( This
->pIDataObjectSrc
)
1222 return IDataObject_GetData(This
->pIDataObjectSrc
, pformatetcIn
, pmedium
);
1225 if ( pformatetcIn
->lindex
!= -1 )
1227 if ( (pformatetcIn
->tymed
& TYMED_HGLOBAL
) != TYMED_HGLOBAL
)
1230 if ( pformatetcIn->dwAspect != DVASPECT_CONTENT )
1231 return DV_E_DVASPECT;
1235 * Otherwise, get the data from the windows clipboard using GetClipboardData
1237 if ( !(bClipboardOpen
= OpenClipboard(theOleClipboard
->hWndClipboard
)) )
1238 HANDLE_ERROR( CLIPBRD_E_CANT_OPEN
);
1240 hData
= GetClipboardData(pformatetcIn
->cfFormat
);
1243 * Return the clipboard data in the storage medium structure
1245 pmedium
->tymed
= (hData
== 0) ? TYMED_NULL
: TYMED_HGLOBAL
;
1246 pmedium
->u
.hGlobal
= (HGLOBAL
)hData
;
1247 pmedium
->pUnkForRelease
= NULL
;
1253 * Close Windows clipboard
1255 if ( bClipboardOpen
&& !CloseClipboard() )
1256 hr
= CLIPBRD_E_CANT_CLOSE
;
1260 return (hData
== 0) ? DV_E_FORMATETC
: S_OK
;
1263 static HRESULT WINAPI
OLEClipbrd_IDataObject_GetDataHere(
1265 LPFORMATETC pformatetc
,
1272 /************************************************************************
1273 * OLEClipbrd_IDataObject_QueryGetData (IDataObject)
1275 * The OLE Clipboard's implementation of this method delegates to
1276 * a data source if there is one or wraps around the windows clipboard
1277 * function IsClipboardFormatAvailable() otherwise.
1279 * See Windows documentation for more details on IDataObject methods.
1281 static HRESULT WINAPI
OLEClipbrd_IDataObject_QueryGetData(
1283 LPFORMATETC pformatetc
)
1286 * Declare "This" pointer
1288 ICOM_THIS(OLEClipbrd
, iface
);
1290 TRACE("(%p, %p)\n", iface
, pformatetc
);
1293 * If we have a data source placed on the clipboard (via OleSetClipboard)
1294 * simply delegate to the source object's QueryGetData
1296 if ( This
->pIDataObjectSrc
)
1298 return IDataObject_QueryGetData(This
->pIDataObjectSrc
, pformatetc
);
1302 return E_INVALIDARG
;
1304 if ( pformatetc->dwAspect != DVASPECT_CONTENT )
1305 return DV_E_DVASPECT;
1307 if ( pformatetc
->lindex
!= -1 )
1310 /* TODO: Handle TYMED_IStorage media which were put on the clipboard
1311 * by copying the storage into global memory. We must convert this
1312 * TYMED_HGLOBAL back to TYMED_IStorage.
1314 if ( pformatetc
->tymed
!= TYMED_HGLOBAL
)
1318 * Delegate to the Windows clipboard function IsClipboardFormatAvailable
1320 return (IsClipboardFormatAvailable(pformatetc
->cfFormat
)) ? S_OK
: DV_E_FORMATETC
;
1323 /************************************************************************
1324 * OLEClipbrd_IDataObject_GetCanonicalFormatEtc (IDataObject)
1326 * See Windows documentation for more details on IDataObject methods.
1328 static HRESULT WINAPI
OLEClipbrd_IDataObject_GetCanonicalFormatEtc(
1330 LPFORMATETC pformatectIn
,
1331 LPFORMATETC pformatetcOut
)
1333 TRACE("(%p, %p, %p)\n", iface
, pformatectIn
, pformatetcOut
);
1335 if ( !pformatectIn
|| !pformatetcOut
)
1336 return E_INVALIDARG
;
1338 memcpy(pformatetcOut
, pformatectIn
, sizeof(FORMATETC
));
1339 return DATA_S_SAMEFORMATETC
;
1342 /************************************************************************
1343 * OLEClipbrd_IDataObject_SetData (IDataObject)
1345 * The OLE Clipboard's does not implement this method
1347 * See Windows documentation for more details on IDataObject methods.
1349 static HRESULT WINAPI
OLEClipbrd_IDataObject_SetData(
1351 LPFORMATETC pformatetc
,
1359 /************************************************************************
1360 * OLEClipbrd_IDataObject_EnumFormatEtc (IDataObject)
1362 * See Windows documentation for more details on IDataObject methods.
1364 static HRESULT WINAPI
OLEClipbrd_IDataObject_EnumFormatEtc(
1367 IEnumFORMATETC
** ppenumFormatEtc
)
1370 FORMATETC
*afmt
= NULL
;
1373 BOOL bClipboardOpen
;
1376 * Declare "This" pointer
1378 ICOM_THIS(OLEClipbrd
, iface
);
1380 TRACE("(%p, %lx, %p)\n", iface
, dwDirection
, ppenumFormatEtc
);
1383 * If we have a data source placed on the clipboard (via OleSetClipboard)
1384 * simply delegate to the source object's EnumFormatEtc
1386 if ( This
->pIDataObjectSrc
)
1388 return IDataObject_EnumFormatEtc(This
->pIDataObjectSrc
,
1389 dwDirection
, ppenumFormatEtc
);
1393 * Otherwise we must provide our own enumerator which wraps around the
1394 * Windows clipboard function EnumClipboardFormats
1396 if ( !ppenumFormatEtc
)
1397 return E_INVALIDARG
;
1399 if ( dwDirection
!= DATADIR_GET
) /* IDataObject_SetData not implemented */
1403 * Store all current clipboard formats in an array of FORMATETC's,
1404 * and create an IEnumFORMATETC enumerator from this list.
1406 cfmt
= CountClipboardFormats();
1407 afmt
= (FORMATETC
*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
1408 sizeof(FORMATETC
) * cfmt
);
1410 * Open the Windows clipboard, associating it with our hidden window
1412 if ( !(bClipboardOpen
= OpenClipboard(This
->hWndClipboard
)) )
1413 HANDLE_ERROR( CLIPBRD_E_CANT_OPEN
);
1416 * Store all current clipboard formats in an array of FORMATETC's
1417 * TODO: Handle TYMED_IStorage media which were put on the clipboard
1418 * by copying the storage into global memory. We must convert this
1419 * TYMED_HGLOBAL back to TYMED_IStorage.
1421 for (i
= 0, format
= 0; i
< cfmt
; i
++)
1423 format
= EnumClipboardFormats(format
);
1424 if (!format
) /* Failed! */
1426 ERR("EnumClipboardFormats failed to return format!\n");
1427 HANDLE_ERROR( E_FAIL
);
1430 /* Init the FORMATETC struct */
1431 afmt
[i
].cfFormat
= format
;
1433 afmt
[i
].dwAspect
= DVASPECT_CONTENT
;
1434 afmt
[i
].lindex
= -1;
1435 afmt
[i
].tymed
= TYMED_HGLOBAL
;
1439 * Create an EnumFORMATETC enumerator and return an
1440 * EnumFORMATETC after bumping up its ref count
1442 *ppenumFormatEtc
= OLEClipbrd_IEnumFORMATETC_Construct( cfmt
, afmt
, (LPUNKNOWN
)iface
);
1443 if (!(*ppenumFormatEtc
))
1444 HANDLE_ERROR( E_OUTOFMEMORY
);
1446 if (FAILED( hr
= IEnumFORMATETC_AddRef(*ppenumFormatEtc
)))
1453 * Free the array of FORMATETC's
1456 HeapFree(GetProcessHeap(), 0, afmt
);
1459 * Close Windows clipboard
1461 if ( bClipboardOpen
&& !CloseClipboard() )
1462 hr
= CLIPBRD_E_CANT_CLOSE
;
1467 /************************************************************************
1468 * OLEClipbrd_IDataObject_DAdvise (IDataObject)
1470 * The OLE Clipboard's does not implement this method
1472 * See Windows documentation for more details on IDataObject methods.
1474 static HRESULT WINAPI
OLEClipbrd_IDataObject_DAdvise(
1476 FORMATETC
* pformatetc
,
1478 IAdviseSink
* pAdvSink
,
1479 DWORD
* pdwConnection
)
1485 /************************************************************************
1486 * OLEClipbrd_IDataObject_DUnadvise (IDataObject)
1488 * The OLE Clipboard's does not implement this method
1490 * See Windows documentation for more details on IDataObject methods.
1492 static HRESULT WINAPI
OLEClipbrd_IDataObject_DUnadvise(
1500 /************************************************************************
1501 * OLEClipbrd_IDataObject_EnumDAdvise (IDataObject)
1503 * The OLE Clipboard does not implement this method
1505 * See Windows documentation for more details on IDataObject methods.
1507 static HRESULT WINAPI
OLEClipbrd_IDataObject_EnumDAdvise(
1509 IEnumSTATDATA
** ppenumAdvise
)
1516 /*---------------------------------------------------------------------*
1517 * Implementation of the internal IEnumFORMATETC interface returned by
1518 * the OLE clipboard's IDataObject.
1519 *---------------------------------------------------------------------*/
1521 /************************************************************************
1522 * OLEClipbrd_IEnumFORMATETC_Construct (UINT, const FORMATETC, LPUNKNOWN)
1524 * Creates an IEnumFORMATETC enumerator from an array of FORMATETC
1525 * Structures. pUnkOuter is the outer unknown for reference counting only.
1526 * NOTE: this does not AddRef the interface.
1529 LPENUMFORMATETC
OLEClipbrd_IEnumFORMATETC_Construct(UINT cfmt
, const FORMATETC afmt
[],
1530 LPUNKNOWN pUnkDataObj
)
1532 IEnumFORMATETCImpl
* ef
;
1533 DWORD size
=cfmt
* sizeof(FORMATETC
);
1536 ef
= (IEnumFORMATETCImpl
*)HeapAlloc(GetProcessHeap(),
1538 sizeof(IEnumFORMATETCImpl
));
1543 ICOM_VTBL(ef
) = &efvt
;
1544 ef
->pUnkDataObj
= pUnkDataObj
;
1547 ef
->countFmt
= cfmt
;
1548 if (FAILED(CoGetMalloc(MEMCTX_TASK
, &pIMalloc
)))
1550 ef
->pFmt
= (LPFORMATETC
)IMalloc_Alloc(pIMalloc
, size
);
1551 IMalloc_Release(pIMalloc
);
1554 memcpy(ef
->pFmt
, afmt
, size
);
1556 TRACE("(%p)->()\n",ef
);
1557 return (LPENUMFORMATETC
)ef
;
1561 /************************************************************************
1562 * OLEClipbrd_IEnumFORMATETC_QueryInterface (IUnknown)
1564 * See Windows documentation for more details on IUnknown methods.
1566 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_QueryInterface
1567 (LPENUMFORMATETC iface
, REFIID riid
, LPVOID
* ppvObj
)
1569 ICOM_THIS(IEnumFORMATETCImpl
,iface
);
1571 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This
,debugstr_guid(riid
),ppvObj
);
1574 * Since enumerators are separate objects from the parent data object
1575 * we only need to support the IUnknown and IEnumFORMATETC interfaces
1580 if(IsEqualIID(riid
, &IID_IUnknown
))
1584 else if(IsEqualIID(riid
, &IID_IEnumFORMATETC
))
1586 *ppvObj
= (IDataObject
*)This
;
1591 IEnumFORMATETC_AddRef((IEnumFORMATETC
*)*ppvObj
);
1592 TRACE("-- Interface: (%p)->(%p)\n",ppvObj
,*ppvObj
);
1596 TRACE("-- Interface: E_NOINTERFACE\n");
1597 return E_NOINTERFACE
;
1600 /************************************************************************
1601 * OLEClipbrd_IEnumFORMATETC_AddRef (IUnknown)
1603 * Since enumerating formats only makes sense when our data object is around,
1604 * we insure that it stays as long as we stay by calling our parents IUnknown
1605 * for AddRef and Release. But since we are not controlled by the lifetime of
1606 * the outer object, we still keep our own reference count in order to
1609 static ULONG WINAPI
OLEClipbrd_IEnumFORMATETC_AddRef(LPENUMFORMATETC iface
)
1611 ICOM_THIS(IEnumFORMATETCImpl
,iface
);
1612 TRACE("(%p)->(count=%lu)\n",This
, This
->ref
);
1614 if (This
->pUnkDataObj
)
1615 IUnknown_AddRef(This
->pUnkDataObj
);
1617 return ++(This
->ref
);
1620 /************************************************************************
1621 * OLEClipbrd_IEnumFORMATETC_Release (IUnknown)
1623 * See Windows documentation for more details on IUnknown methods.
1625 static ULONG WINAPI
OLEClipbrd_IEnumFORMATETC_Release(LPENUMFORMATETC iface
)
1627 ICOM_THIS(IEnumFORMATETCImpl
,iface
);
1630 TRACE("(%p)->(count=%lu)\n",This
, This
->ref
);
1632 if (This
->pUnkDataObj
)
1633 IUnknown_Release(This
->pUnkDataObj
); /* Release parent data object */
1637 TRACE("() - destroying IEnumFORMATETC(%p)\n",This
);
1638 if (SUCCEEDED(CoGetMalloc(MEMCTX_TASK
, &pIMalloc
)))
1640 IMalloc_Free(pIMalloc
, This
->pFmt
);
1641 IMalloc_Release(pIMalloc
);
1644 HeapFree(GetProcessHeap(),0,This
);
1651 /************************************************************************
1652 * OLEClipbrd_IEnumFORMATETC_Next (IEnumFORMATETC)
1654 * Standard enumerator members for IEnumFORMATETC
1656 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Next
1657 (LPENUMFORMATETC iface
, ULONG celt
, FORMATETC
*rgelt
, ULONG
*pceltFethed
)
1659 ICOM_THIS(IEnumFORMATETCImpl
,iface
);
1661 HRESULT hres
= S_FALSE
;
1663 TRACE("(%p)->(pos=%u)\n", This
, This
->posFmt
);
1665 if (This
->posFmt
< This
->countFmt
)
1667 cfetch
= This
->countFmt
- This
->posFmt
;
1674 memcpy(rgelt
, &This
->pFmt
[This
->posFmt
], cfetch
* sizeof(FORMATETC
));
1675 This
->posFmt
+= cfetch
;
1684 *pceltFethed
= cfetch
;
1690 /************************************************************************
1691 * OLEClipbrd_IEnumFORMATETC_Skip (IEnumFORMATETC)
1693 * Standard enumerator members for IEnumFORMATETC
1695 static HRESULT WINAPI
OLEClipbrd_IEnumFORMATETC_Skip(LPENUMFORMATETC iface
, ULONG celt
)
1697 ICOM_THIS(IEnumFORMATETCImpl
,iface
);
1698 TRACE("(%p)->(num=%lu)\n", This
, celt
);
1700 This
->posFmt
+= celt
;
1701 if (This
->posFmt
> This
->countFmt
)
1703 This
->posFmt
= This
->countFmt
;
1709 /************************************************************************
1710 * OLEClipbrd_IEnumFORMATETC_Reset (IEnumFORMATETC)
1712 * Standard enumerator members for IEnumFORMATETC
1714 static HRESULT WINAPI
OLEClipbrd_IEnumFORMATETC_Reset(LPENUMFORMATETC iface
)
1716 ICOM_THIS(IEnumFORMATETCImpl
,iface
);
1717 TRACE("(%p)->()\n", This
);
1723 /************************************************************************
1724 * OLEClipbrd_IEnumFORMATETC_Clone (IEnumFORMATETC)
1726 * Standard enumerator members for IEnumFORMATETC
1728 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Clone
1729 (LPENUMFORMATETC iface
, LPENUMFORMATETC
* ppenum
)
1731 ICOM_THIS(IEnumFORMATETCImpl
,iface
);
1734 TRACE("(%p)->(ppenum=%p)\n", This
, ppenum
);
1737 return E_INVALIDARG
;
1739 *ppenum
= OLEClipbrd_IEnumFORMATETC_Construct(This
->countFmt
,
1743 if (FAILED( hr
= IEnumFORMATETC_AddRef(*ppenum
)))
1746 return (*ppenum
) ? S_OK
: E_OUTOFMEMORY
;