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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, 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.
66 #define NONAMELESSUNION
67 #define NONAMELESSSTRUCT
76 #include "wine/debug.h"
79 #include "storage32.h"
81 #define HANDLE_ERROR(err) { hr = err; TRACE("(HRESULT=%x)\n", (HRESULT)err); goto CLEANUP; }
83 WINE_DEFAULT_DEBUG_CHANNEL(ole
);
85 /****************************************************************************
87 * DO NOT add any members before the VTables declaration!
92 * List all interface VTables here
94 const IDataObjectVtbl
* 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 const IEnumFORMATETCVtbl
*lpVtbl
;
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 void OLEClipbrd_Initialize(void);
171 void OLEClipbrd_UnInitialize(void);
172 static OLEClipbrd
* OLEClipbrd_Construct(void);
173 static void OLEClipbrd_Destroy(OLEClipbrd
* ptrToDestroy
);
174 static HWND
OLEClipbrd_CreateWindow(void);
175 static void OLEClipbrd_DestroyWindow(HWND hwnd
);
176 static 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 const IDataObjectVtbl OLEClipbrd_IDataObject_VTable
=
250 OLEClipbrd_IDataObject_QueryInterface
,
251 OLEClipbrd_IDataObject_AddRef
,
252 OLEClipbrd_IDataObject_Release
,
253 OLEClipbrd_IDataObject_GetData
,
254 OLEClipbrd_IDataObject_GetDataHere
,
255 OLEClipbrd_IDataObject_QueryGetData
,
256 OLEClipbrd_IDataObject_GetCanonicalFormatEtc
,
257 OLEClipbrd_IDataObject_SetData
,
258 OLEClipbrd_IDataObject_EnumFormatEtc
,
259 OLEClipbrd_IDataObject_DAdvise
,
260 OLEClipbrd_IDataObject_DUnadvise
,
261 OLEClipbrd_IDataObject_EnumDAdvise
265 * Virtual function table for IEnumFORMATETC interface
267 static const IEnumFORMATETCVtbl efvt
=
269 OLEClipbrd_IEnumFORMATETC_QueryInterface
,
270 OLEClipbrd_IEnumFORMATETC_AddRef
,
271 OLEClipbrd_IEnumFORMATETC_Release
,
272 OLEClipbrd_IEnumFORMATETC_Next
,
273 OLEClipbrd_IEnumFORMATETC_Skip
,
274 OLEClipbrd_IEnumFORMATETC_Reset
,
275 OLEClipbrd_IEnumFORMATETC_Clone
279 * Name of our registered OLE clipboard window class
281 static const CHAR OLEClipbrd_WNDCLASS
[] = "CLIPBRDWNDCLASS";
284 * If we need to store state info we can store it here.
285 * For now we don't need this functionality.
287 typedef struct tagClipboardWindowInfo
289 } ClipboardWindowInfo;
292 /*---------------------------------------------------------------------*
293 * Win32 OLE clipboard API
294 *---------------------------------------------------------------------*/
296 /***********************************************************************
297 * OleSetClipboard [OLE32.@]
298 * Places a pointer to the specified data object onto the clipboard,
299 * making the data object accessible to the OleGetClipboard function.
303 * S_OK IDataObject pointer placed on the clipboard
304 * CLIPBRD_E_CANT_OPEN OpenClipboard failed
305 * CLIPBRD_E_CANT_EMPTY EmptyClipboard failed
306 * CLIPBRD_E_CANT_CLOSE CloseClipboard failed
307 * CLIPBRD_E_CANT_SET SetClipboard failed
310 HRESULT WINAPI
OleSetClipboard(IDataObject
* pDataObj
)
313 IEnumFORMATETC
* penumFormatetc
= NULL
;
315 BOOL bClipboardOpen
= FALSE
;
317 HGLOBAL hDataObject = 0;
318 OLEClipbrd **ppDataObject;
321 TRACE("(%p)\n", pDataObj
);
324 * Make sure we have a clipboard object
326 OLEClipbrd_Initialize();
329 * If the Ole clipboard window hasn't been created yet, create it now.
331 if ( !theOleClipboard
->hWndClipboard
)
332 theOleClipboard
->hWndClipboard
= OLEClipbrd_CreateWindow();
334 if ( !theOleClipboard
->hWndClipboard
) /* sanity check */
335 HANDLE_ERROR( E_FAIL
);
338 * Open the Windows clipboard, associating it with our hidden window
340 if ( !(bClipboardOpen
= OpenClipboard(theOleClipboard
->hWndClipboard
)) )
341 HANDLE_ERROR( CLIPBRD_E_CANT_OPEN
);
344 * Empty the current clipboard and make our window the clipboard owner
345 * NOTE: This will trigger a WM_DESTROYCLIPBOARD message
347 if ( !EmptyClipboard() )
348 HANDLE_ERROR( CLIPBRD_E_CANT_EMPTY
);
351 * If we are already holding on to an IDataObject first release that.
353 if ( theOleClipboard
->pIDataObjectSrc
)
355 IDataObject_Release(theOleClipboard
->pIDataObjectSrc
);
356 theOleClipboard
->pIDataObjectSrc
= NULL
;
360 * AddRef the data object passed in and save its pointer.
361 * A NULL value indicates that the clipboard should be emptied.
363 theOleClipboard
->pIDataObjectSrc
= pDataObj
;
366 IDataObject_AddRef(theOleClipboard
->pIDataObjectSrc
);
370 * Enumerate all HGLOBAL formats supported by the source and make
371 * those formats available using delayed rendering using SetClipboardData.
372 * Only global memory based data items may be made available to non-OLE
373 * applications via the standard Windows clipboard API. Data based on other
374 * mediums(non TYMED_HGLOBAL) can only be accessed via the Ole Clipboard API.
376 * TODO: Do we need to additionally handle TYMED_IStorage media by copying
377 * the storage into global memory?
381 if ( FAILED(hr
= IDataObject_EnumFormatEtc( pDataObj
,
388 while ( S_OK
== IEnumFORMATETC_Next(penumFormatetc
, 1, &rgelt
, NULL
) )
390 if ( rgelt
.tymed
== TYMED_HGLOBAL
)
393 TRACE("(cfFormat=%d:%s)\n", rgelt
.cfFormat
,
394 GetClipboardFormatNameA(rgelt
.cfFormat
, szFmtName
, sizeof(szFmtName
)-1)
397 SetClipboardData( rgelt
.cfFormat
, NULL
);
400 IEnumFORMATETC_Release(penumFormatetc
);
404 * Windows additionally creates a new "DataObject" clipboard format
405 * and stores in on the clipboard. We could possibly store a pointer
406 * to our internal IDataObject interface on the clipboard. I'm not
407 * sure what the use of this is though.
408 * Enable the code below for this functionality.
411 theOleClipboard->cfDataObj = RegisterClipboardFormatA("DataObject");
412 hDataObject = GlobalAlloc( GMEM_DDESHARE|GMEM_MOVEABLE|GMEM_ZEROINIT,
413 sizeof(OLEClipbrd *));
415 HANDLE_ERROR( E_OUTOFMEMORY );
417 ppDataObject = (OLEClipbrd**)GlobalLock(hDataObject);
418 *ppDataObject = theOleClipboard;
419 GlobalUnlock(hDataObject);
421 if ( !SetClipboardData( theOleClipboard->cfDataObj, hDataObject ) )
422 HANDLE_ERROR( CLIPBRD_E_CANT_SET );
430 * Close Windows clipboard (It remains associated with our window)
432 if ( bClipboardOpen
&& !CloseClipboard() )
433 hr
= CLIPBRD_E_CANT_CLOSE
;
436 * Release the source IDataObject if something failed
440 if (theOleClipboard
->pIDataObjectSrc
)
442 IDataObject_Release(theOleClipboard
->pIDataObjectSrc
);
443 theOleClipboard
->pIDataObjectSrc
= NULL
;
451 /***********************************************************************
452 * OleGetClipboard [OLE32.@]
453 * Returns a pointer to our internal IDataObject which represents the conceptual
454 * state of the Windows clipboard. If the current clipboard already contains
455 * an IDataObject, our internal IDataObject will delegate to this object.
457 HRESULT WINAPI
OleGetClipboard(IDataObject
** ppDataObj
)
463 * Make sure we have a clipboard object
465 OLEClipbrd_Initialize();
467 if (!theOleClipboard
)
468 return E_OUTOFMEMORY
;
470 /* Return a reference counted IDataObject */
471 hr
= IDataObject_QueryInterface( (IDataObject
*)&(theOleClipboard
->lpvtbl1
),
472 &IID_IDataObject
, (void**)ppDataObj
);
476 /******************************************************************************
477 * OleFlushClipboard [OLE32.@]
478 * Renders the data from the source IDataObject into the windows clipboard
480 * TODO: OleFlushClipboard needs to additionally handle TYMED_IStorage media
481 * by copying the storage into global memory. Subsequently the default
482 * data object exposed through OleGetClipboard must convert this TYMED_HGLOBAL
483 * back to TYMED_IStorage.
485 HRESULT WINAPI
OleFlushClipboard(void)
487 IEnumFORMATETC
* penumFormatetc
= NULL
;
490 BOOL bClipboardOpen
= FALSE
;
491 IDataObject
* pIDataObjectSrc
= NULL
;
496 * Make sure we have a clipboard object
498 OLEClipbrd_Initialize();
501 * Already flushed or no source DataObject? Nothing to do.
503 if (!theOleClipboard
->pIDataObjectSrc
)
507 * Addref and save the source data object we are holding on to temporarily,
508 * since it will be released when we empty the clipboard.
510 pIDataObjectSrc
= theOleClipboard
->pIDataObjectSrc
;
511 IDataObject_AddRef(pIDataObjectSrc
);
514 * Open the Windows clipboard
516 if ( !(bClipboardOpen
= OpenClipboard(theOleClipboard
->hWndClipboard
)) )
517 HANDLE_ERROR( CLIPBRD_E_CANT_OPEN
);
520 * Empty the current clipboard
522 if ( !EmptyClipboard() )
523 HANDLE_ERROR( CLIPBRD_E_CANT_EMPTY
);
526 * Render all HGLOBAL formats supported by the source into
527 * the windows clipboard.
529 if ( FAILED( hr
= IDataObject_EnumFormatEtc( pIDataObjectSrc
,
536 while ( S_OK
== IEnumFORMATETC_Next(penumFormatetc
, 1, &rgelt
, NULL
) )
538 if ( rgelt
.tymed
== TYMED_HGLOBAL
)
541 TRACE("(cfFormat=%d:%s)\n", rgelt
.cfFormat
,
542 GetClipboardFormatNameA(rgelt
.cfFormat
, szFmtName
, sizeof(szFmtName
)-1)
546 * Render the clipboard data
548 if ( FAILED(OLEClipbrd_RenderFormat( pIDataObjectSrc
, &rgelt
)) )
553 IEnumFORMATETC_Release(penumFormatetc
);
556 * Release the source data object we are holding on to
558 IDataObject_Release(pIDataObjectSrc
);
563 * Close Windows clipboard (It remains associated with our window)
565 if ( bClipboardOpen
&& !CloseClipboard() )
566 hr
= CLIPBRD_E_CANT_CLOSE
;
572 /***********************************************************************
573 * OleIsCurrentClipboard [OLE32.@]
575 HRESULT WINAPI
OleIsCurrentClipboard(IDataObject
*pDataObject
)
579 * Make sure we have a clipboard object
581 OLEClipbrd_Initialize();
583 if (!theOleClipboard
)
584 return E_OUTOFMEMORY
;
586 return (pDataObject
== theOleClipboard
->pIDataObjectSrc
) ? S_OK
: S_FALSE
;
590 /*---------------------------------------------------------------------*
591 * Internal implementation methods for the OLE clipboard
592 *---------------------------------------------------------------------*/
594 /***********************************************************************
595 * OLEClipbrd_Initialize()
596 * Initializes the OLE clipboard.
598 void OLEClipbrd_Initialize(void)
601 * Create the clipboard if necessary
603 if ( !theOleClipboard
)
606 theOleClipboard
= OLEClipbrd_Construct();
611 /***********************************************************************
612 * OLEClipbrd_UnInitialize()
613 * Un-Initializes the OLE clipboard
615 void OLEClipbrd_UnInitialize(void)
619 * Destroy the clipboard if no one holds a reference to us.
620 * Note that the clipboard was created with a reference count of 1.
622 if ( theOleClipboard
&& (theOleClipboard
->ref
<= 1) )
624 OLEClipbrd_Destroy( theOleClipboard
);
628 WARN( "() : OLEClipbrd_UnInitialize called while client holds an IDataObject reference!\n");
633 /*********************************************************
634 * Construct the OLEClipbrd class.
636 static OLEClipbrd
* OLEClipbrd_Construct(void)
638 OLEClipbrd
* newObject
= NULL
;
639 HGLOBAL hNewObject
= 0;
642 * Allocate space for the object. We use GlobalAlloc since we need
643 * an HGLOBAL to expose our DataObject as a registered clipboard type.
645 hNewObject
= GlobalAlloc( GMEM_DDESHARE
|GMEM_MOVEABLE
|GMEM_ZEROINIT
,
651 * Lock the handle for the entire lifetime of the clipboard.
653 newObject
= GlobalLock(hNewObject
);
656 * Initialize the virtual function table.
658 newObject
->lpvtbl1
= &OLEClipbrd_IDataObject_VTable
;
661 * Start with one reference count. The caller of this function
662 * must release the interface pointer when it is done.
666 newObject
->hSelf
= hNewObject
;
669 * The Ole clipboard is a singleton - save the global handle and pointer
671 theOleClipboard
= newObject
;
672 hTheOleClipboard
= hNewObject
;
674 return theOleClipboard
;
677 static void OLEClipbrd_Destroy(OLEClipbrd
* ptrToDestroy
)
685 * Destroy the Ole clipboard window
687 if ( ptrToDestroy
->hWndClipboard
)
688 OLEClipbrd_DestroyWindow(ptrToDestroy
->hWndClipboard
);
691 * Free the actual OLE Clipboard structure.
693 TRACE("() - Destroying clipboard data object.\n");
694 GlobalUnlock(ptrToDestroy
->hSelf
);
695 GlobalFree(ptrToDestroy
->hSelf
);
698 * The Ole clipboard is a singleton (ptrToDestroy == theOleClipboard)
700 theOleClipboard
= NULL
;
701 hTheOleClipboard
= 0;
705 /***********************************************************************
706 * OLEClipbrd_CreateWindow()
707 * Create the clipboard window
709 static HWND
OLEClipbrd_CreateWindow(void)
715 * Register the clipboard window class if necessary
717 ZeroMemory( &wcex
, sizeof(WNDCLASSEXA
));
719 wcex
.cbSize
= sizeof(WNDCLASSEXA
);
720 /* Windows creates this class with a style mask of 0
721 * We don't bother doing this since the FindClassByAtom code
722 * would have to be changed to deal with this idiosyncrasy. */
723 wcex
.style
= CS_GLOBALCLASS
;
724 wcex
.lpfnWndProc
= OLEClipbrd_WndProc
;
726 wcex
.lpszClassName
= OLEClipbrd_WNDCLASS
;
728 RegisterClassExA(&wcex
);
731 * Create a hidden window to receive OLE clipboard messages
735 * If we need to store state info we can store it here.
736 * For now we don't need this functionality.
737 * ClipboardWindowInfo clipboardInfo;
738 * ZeroMemory( &trackerInfo, sizeof(ClipboardWindowInfo));
741 hwnd
= CreateWindowA(OLEClipbrd_WNDCLASS
,
743 WS_POPUP
| WS_CLIPSIBLINGS
| WS_OVERLAPPED
,
744 CW_USEDEFAULT
, CW_USEDEFAULT
,
745 CW_USEDEFAULT
, CW_USEDEFAULT
,
749 0 /*(LPVOID)&clipboardInfo */);
754 /***********************************************************************
755 * OLEClipbrd_DestroyWindow(HWND)
756 * Destroy the clipboard window and unregister its class
758 static void OLEClipbrd_DestroyWindow(HWND hwnd
)
761 * Destroy clipboard window and unregister its WNDCLASS
764 UnregisterClassA( OLEClipbrd_WNDCLASS
, 0 );
767 /***********************************************************************
768 * OLEClipbrd_WndProc(HWND, unsigned, WORD, LONG)
769 * Processes messages sent to the OLE clipboard window.
770 * Note that we will intercept messages in our WndProc only when data
771 * has been placed in the clipboard via OleSetClipboard().
772 * i.e. Only when OLE owns the windows clipboard.
774 static LRESULT CALLBACK OLEClipbrd_WndProc
775 (HWND hWnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
781 * We receive this message to allow us to handle delayed rendering of
782 * a specific clipboard format when an application requests data in
783 * that format by calling GetClipboardData.
784 * (Recall that in OleSetClipboard, we used SetClipboardData to
785 * make all HGLOBAL formats supported by the source IDataObject
786 * available using delayed rendering)
787 * On receiving this message we must actually render the data in the
788 * specified format and place it on the clipboard by calling the
789 * SetClipboardData function.
791 case WM_RENDERFORMAT
:
795 ZeroMemory( &rgelt
, sizeof(FORMATETC
));
798 * Initialize FORMATETC to a Windows clipboard friendly format
800 rgelt
.cfFormat
= (UINT
) wParam
;
801 rgelt
.dwAspect
= DVASPECT_CONTENT
;
803 rgelt
.tymed
= TYMED_HGLOBAL
;
805 TRACE("(): WM_RENDERFORMAT(cfFormat=%d)\n", rgelt
.cfFormat
);
808 * Render the clipboard data.
809 * (We must have a source data object or we wouldn't be in this WndProc)
811 OLEClipbrd_RenderFormat( (IDataObject
*)&(theOleClipboard
->lpvtbl1
), &rgelt
);
817 * WM_RENDERALLFORMATS
818 * Sent before the clipboard owner window is destroyed.
819 * We should receive this message only when OleUninitialize is called
820 * while we have an IDataObject in the clipboard.
821 * For the content of the clipboard to remain available to other
822 * applications, we must render data in all the formats the source IDataObject
823 * is capable of generating, and place the data on the clipboard by calling
826 case WM_RENDERALLFORMATS
:
828 IEnumFORMATETC
* penumFormatetc
= NULL
;
831 TRACE("(): WM_RENDERALLFORMATS\n");
834 * Render all HGLOBAL formats supported by the source into
835 * the windows clipboard.
837 if ( FAILED( IDataObject_EnumFormatEtc( (IDataObject
*)&(theOleClipboard
->lpvtbl1
),
838 DATADIR_GET
, &penumFormatetc
) ) )
840 WARN("(): WM_RENDERALLFORMATS failed to retrieve EnumFormatEtc!\n");
844 while ( S_OK
== IEnumFORMATETC_Next(penumFormatetc
, 1, &rgelt
, NULL
) )
846 if ( rgelt
.tymed
== TYMED_HGLOBAL
)
849 * Render the clipboard data.
851 if ( FAILED(OLEClipbrd_RenderFormat( (IDataObject
*)&(theOleClipboard
->lpvtbl1
), &rgelt
)) )
854 TRACE("(): WM_RENDERALLFORMATS(cfFormat=%d)\n", rgelt
.cfFormat
);
858 IEnumFORMATETC_Release(penumFormatetc
);
864 * WM_DESTROYCLIPBOARD
865 * This is sent by EmptyClipboard before the clipboard is emptied.
866 * We should release any IDataObject we are holding onto when we receive
867 * this message, since it indicates that the OLE clipboard should be empty
868 * from this point on.
870 case WM_DESTROYCLIPBOARD
:
872 TRACE("(): WM_DESTROYCLIPBOARD\n");
874 * Release the data object we are holding on to
876 if ( theOleClipboard
->pIDataObjectSrc
)
878 IDataObject_Release(theOleClipboard
->pIDataObjectSrc
);
879 theOleClipboard
->pIDataObjectSrc
= NULL
;
885 case WM_ASKCBFORMATNAME:
886 case WM_CHANGECBCHAIN:
887 case WM_DRAWCLIPBOARD:
888 case WM_SIZECLIPBOARD:
889 case WM_HSCROLLCLIPBOARD:
890 case WM_VSCROLLCLIPBOARD:
891 case WM_PAINTCLIPBOARD:
894 return DefWindowProcA(hWnd
, message
, wParam
, lParam
);
900 #define MAX_CLIPFORMAT_NAME 80
902 /***********************************************************************
903 * OLEClipbrd_RenderFormat(LPFORMATETC)
904 * Render the clipboard data. Note that this call will delegate to the
905 * source data object.
906 * Note: This function assumes it is passed an HGLOBAL format to render.
908 static HRESULT
OLEClipbrd_RenderFormat(IDataObject
*pIDataObject
, LPFORMATETC pFormatetc
)
913 char szFmtName
[MAX_CLIPFORMAT_NAME
];
914 ILockBytes
*ptrILockBytes
= 0;
915 HGLOBAL hStorage
= 0;
917 if (!GetClipboardFormatNameA(pFormatetc
->cfFormat
, szFmtName
, MAX_CLIPFORMAT_NAME
))
920 /* If embed source */
921 if (!strcmp(szFmtName
, CF_EMBEDSOURCE
))
923 memset(&std
, 0, sizeof(STGMEDIUM
));
924 std
.tymed
= pFormatetc
->tymed
= TYMED_ISTORAGE
;
926 hStorage
= GlobalAlloc(GMEM_SHARE
|GMEM_MOVEABLE
, 0);
927 if (hStorage
== NULL
)
928 HANDLE_ERROR( E_OUTOFMEMORY
);
929 hr
= CreateILockBytesOnHGlobal(hStorage
, FALSE
, &ptrILockBytes
);
930 hr
= StgCreateDocfileOnILockBytes(ptrILockBytes
, STGM_SHARE_EXCLUSIVE
|STGM_READWRITE
, 0, &std
.u
.pstg
);
932 if (FAILED(hr
= IDataObject_GetDataHere(theOleClipboard
->pIDataObjectSrc
, pFormatetc
, &std
)))
934 WARN("() : IDataObject_GetDataHere failed to render clipboard data! (%x)\n", hr
);
935 GlobalFree(hStorage
);
939 if (1) /* check whether the presentation data is already -not- present */
943 METAFILEPICT
*mfp
= 0;
945 fmt2
.cfFormat
= CF_METAFILEPICT
;
947 fmt2
.dwAspect
= DVASPECT_CONTENT
;
949 fmt2
.tymed
= TYMED_MFPICT
;
951 memset(&std2
, 0, sizeof(STGMEDIUM
));
952 std2
.tymed
= TYMED_MFPICT
;
954 /* Get the metafile picture out of it */
956 if (!FAILED(hr
= IDataObject_GetData(theOleClipboard
->pIDataObjectSrc
, &fmt2
, &std2
)))
958 mfp
= (METAFILEPICT
*)GlobalLock(std2
.u
.hGlobal
);
963 OLECHAR name
[]={ 2, 'O', 'l', 'e', 'P', 'r', 'e', 's', '0', '0', '0', 0};
964 IStream
*pStream
= 0;
966 PresentationDataHeader pdh
;
970 CHAR strOleTypeName
[51];
971 BYTE OlePresStreamHeader
[] =
973 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00,
974 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
975 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
976 0x00, 0x00, 0x00, 0x00
979 nSize
= GetMetaFileBitsEx(mfp
->hMF
, 0, NULL
);
981 memset(&pdh
, 0, sizeof(PresentationDataHeader
));
982 memcpy(&pdh
, OlePresStreamHeader
, sizeof(OlePresStreamHeader
));
984 pdh
.dwObjectExtentX
= mfp
->xExt
;
985 pdh
.dwObjectExtentY
= mfp
->yExt
;
988 hr
= IStorage_CreateStream(std
.u
.pstg
, name
, STGM_CREATE
|STGM_SHARE_EXCLUSIVE
|STGM_READWRITE
, 0, 0, &pStream
);
990 hr
= IStream_Write(pStream
, &pdh
, sizeof(PresentationDataHeader
), NULL
);
992 mfBits
= HeapAlloc(GetProcessHeap(), 0, nSize
);
993 nSize
= GetMetaFileBitsEx(mfp
->hMF
, nSize
, mfBits
);
995 hr
= IStream_Write(pStream
, mfBits
, nSize
, NULL
);
997 IStream_Release(pStream
);
999 HeapFree(GetProcessHeap(), 0, mfBits
);
1001 GlobalUnlock(std2
.u
.hGlobal
);
1003 ReadClassStg(std
.u
.pstg
, &clsID
);
1004 ProgIDFromCLSID(&clsID
, &strProgID
);
1006 WideCharToMultiByte( CP_ACP
, 0, strProgID
, -1, strOleTypeName
, sizeof(strOleTypeName
), NULL
, NULL
);
1007 OLECONVERT_CreateOleStream(std
.u
.pstg
);
1008 OLECONVERT_CreateCompObjStream(std
.u
.pstg
, strOleTypeName
);
1014 if (FAILED(hr
= IDataObject_GetData(pIDataObject
, pFormatetc
, &std
)))
1016 WARN("() : IDataObject_GetData failed to render clipboard data! (%x)\n", hr
);
1017 GlobalFree(hStorage
);
1021 /* To put a copy back on the clipboard */
1023 hStorage
= std
.u
.hGlobal
;
1027 * Put a copy of the rendered data back on the clipboard
1030 if ( !(hDup
= OLEClipbrd_GlobalDupMem(hStorage
)) )
1031 HANDLE_ERROR( E_OUTOFMEMORY
);
1033 if ( !SetClipboardData( pFormatetc
->cfFormat
, hDup
) )
1036 WARN("() : Failed to set rendered clipboard data into clipboard!\n");
1041 ReleaseStgMedium(&std
);
1047 /***********************************************************************
1048 * OLEClipbrd_GlobalDupMem( HGLOBAL )
1049 * Helper method to duplicate an HGLOBAL chunk of memory
1051 static HGLOBAL
OLEClipbrd_GlobalDupMem( HGLOBAL hGlobalSrc
)
1053 HGLOBAL hGlobalDest
;
1054 PVOID pGlobalSrc
, pGlobalDest
;
1060 cBytes
= GlobalSize(hGlobalSrc
);
1064 hGlobalDest
= GlobalAlloc( GMEM_DDESHARE
|GMEM_MOVEABLE
,
1069 pGlobalSrc
= GlobalLock(hGlobalSrc
);
1070 pGlobalDest
= GlobalLock(hGlobalDest
);
1071 if ( !pGlobalSrc
|| !pGlobalDest
)
1073 GlobalFree(hGlobalDest
);
1077 memcpy(pGlobalDest
, pGlobalSrc
, cBytes
);
1079 GlobalUnlock(hGlobalSrc
);
1080 GlobalUnlock(hGlobalDest
);
1086 /*---------------------------------------------------------------------*
1087 * Implementation of the internal IDataObject interface exposed by
1088 * the OLE clipboard.
1089 *---------------------------------------------------------------------*/
1092 /************************************************************************
1093 * OLEClipbrd_IDataObject_QueryInterface (IUnknown)
1095 * See Windows documentation for more details on IUnknown methods.
1097 static HRESULT WINAPI
OLEClipbrd_IDataObject_QueryInterface(
1103 * Declare "This" pointer
1105 OLEClipbrd
*This
= (OLEClipbrd
*)iface
;
1106 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This
,debugstr_guid(riid
),ppvObject
);
1109 * Perform a sanity check on the parameters.
1111 if ( (This
==0) || (ppvObject
==0) )
1112 return E_INVALIDARG
;
1115 * Initialize the return parameter.
1120 * Compare the riid with the interface IDs implemented by this object.
1122 if (memcmp(&IID_IUnknown
, riid
, sizeof(IID_IUnknown
)) == 0)
1126 else if (memcmp(&IID_IDataObject
, riid
, sizeof(IID_IDataObject
)) == 0)
1128 *ppvObject
= (IDataObject
*)&(This
->lpvtbl1
);
1130 else /* We only support IUnknown and IDataObject */
1132 WARN( "() : asking for unsupported interface %s\n", debugstr_guid(riid
));
1133 return E_NOINTERFACE
;
1137 * Query Interface always increases the reference count by one when it is
1140 IUnknown_AddRef((IUnknown
*)*ppvObject
);
1145 /************************************************************************
1146 * OLEClipbrd_IDataObject_AddRef (IUnknown)
1148 * See Windows documentation for more details on IUnknown methods.
1150 static ULONG WINAPI
OLEClipbrd_IDataObject_AddRef(
1154 * Declare "This" pointer
1156 OLEClipbrd
*This
= (OLEClipbrd
*)iface
;
1158 TRACE("(%p)->(count=%u)\n",This
, This
->ref
);
1160 return InterlockedIncrement(&This
->ref
);
1164 /************************************************************************
1165 * OLEClipbrd_IDataObject_Release (IUnknown)
1167 * See Windows documentation for more details on IUnknown methods.
1169 static ULONG WINAPI
OLEClipbrd_IDataObject_Release(
1173 * Declare "This" pointer
1175 OLEClipbrd
*This
= (OLEClipbrd
*)iface
;
1178 TRACE("(%p)->(count=%u)\n",This
, This
->ref
);
1181 * Decrease the reference count on this object.
1183 ref
= InterlockedDecrement(&This
->ref
);
1186 * If the reference count goes down to 0, perform suicide.
1190 OLEClipbrd_Destroy(This
);
1197 /************************************************************************
1198 * OLEClipbrd_IDataObject_GetData (IDataObject)
1200 * The OLE Clipboard's implementation of this method delegates to
1201 * a data source if there is one or wraps around the windows clipboard
1203 * See Windows documentation for more details on IDataObject methods.
1205 static HRESULT WINAPI
OLEClipbrd_IDataObject_GetData(
1207 LPFORMATETC pformatetcIn
,
1211 BOOL bClipboardOpen
= FALSE
;
1216 * Declare "This" pointer
1218 OLEClipbrd
*This
= (OLEClipbrd
*)iface
;
1220 TRACE("(%p,%p,%p)\n", iface
, pformatetcIn
, pmedium
);
1222 if ( !pformatetcIn
|| !pmedium
)
1223 return E_INVALIDARG
;
1226 * If we have a data source placed on the clipboard (via OleSetClipboard)
1227 * simply delegate to the source object's QueryGetData
1228 * NOTE: This code assumes that the IDataObject is in the same address space!
1229 * We will need to add marshalling support when Wine handles multiple processes.
1231 if ( This
->pIDataObjectSrc
)
1233 return IDataObject_GetData(This
->pIDataObjectSrc
, pformatetcIn
, pmedium
);
1236 if ( pformatetcIn
->lindex
!= -1 )
1238 if ( (pformatetcIn
->tymed
& TYMED_HGLOBAL
) != TYMED_HGLOBAL
)
1241 if ( pformatetcIn->dwAspect != DVASPECT_CONTENT )
1242 return DV_E_DVASPECT;
1246 * Otherwise, get the data from the windows clipboard using GetClipboardData
1248 if ( !(bClipboardOpen
= OpenClipboard(theOleClipboard
->hWndClipboard
)) )
1249 HANDLE_ERROR( CLIPBRD_E_CANT_OPEN
);
1251 hData
= GetClipboardData(pformatetcIn
->cfFormat
);
1253 /* Must make a copy of global handle returned by GetClipboardData; it
1254 * is not valid after we call CloseClipboard
1255 * Application is responsible for freeing the memory (Forte Agent does this)
1257 src
= GlobalLock(hData
);
1263 size
= GlobalSize(hData
);
1264 hDest
= GlobalAlloc(GHND
, size
);
1265 dest
= GlobalLock(hDest
);
1266 memcpy(dest
, src
, size
);
1267 GlobalUnlock(hDest
);
1268 GlobalUnlock(hData
);
1273 * Return the clipboard data in the storage medium structure
1275 pmedium
->tymed
= (hData
== 0) ? TYMED_NULL
: TYMED_HGLOBAL
;
1276 pmedium
->u
.hGlobal
= hData
;
1277 pmedium
->pUnkForRelease
= NULL
;
1283 * Close Windows clipboard
1285 if ( bClipboardOpen
&& !CloseClipboard() )
1286 hr
= CLIPBRD_E_CANT_CLOSE
;
1290 return (hData
== 0) ? DV_E_FORMATETC
: S_OK
;
1293 static HRESULT WINAPI
OLEClipbrd_IDataObject_GetDataHere(
1295 LPFORMATETC pformatetc
,
1302 /************************************************************************
1303 * OLEClipbrd_IDataObject_QueryGetData (IDataObject)
1305 * The OLE Clipboard's implementation of this method delegates to
1306 * a data source if there is one or wraps around the windows clipboard
1307 * function IsClipboardFormatAvailable() otherwise.
1309 * See Windows documentation for more details on IDataObject methods.
1311 static HRESULT WINAPI
OLEClipbrd_IDataObject_QueryGetData(
1313 LPFORMATETC pformatetc
)
1315 TRACE("(%p, %p)\n", iface
, pformatetc
);
1318 return E_INVALIDARG
;
1320 if ( pformatetc
->dwAspect
!= DVASPECT_CONTENT
)
1321 return DV_E_FORMATETC
;
1323 if ( pformatetc
->lindex
!= -1 )
1324 return DV_E_FORMATETC
;
1327 * Delegate to the Windows clipboard function IsClipboardFormatAvailable
1329 return (IsClipboardFormatAvailable(pformatetc
->cfFormat
)) ? S_OK
: DV_E_CLIPFORMAT
;
1332 /************************************************************************
1333 * OLEClipbrd_IDataObject_GetCanonicalFormatEtc (IDataObject)
1335 * See Windows documentation for more details on IDataObject methods.
1337 static HRESULT WINAPI
OLEClipbrd_IDataObject_GetCanonicalFormatEtc(
1339 LPFORMATETC pformatectIn
,
1340 LPFORMATETC pformatetcOut
)
1342 TRACE("(%p, %p, %p)\n", iface
, pformatectIn
, pformatetcOut
);
1344 if ( !pformatectIn
|| !pformatetcOut
)
1345 return E_INVALIDARG
;
1347 *pformatetcOut
= *pformatectIn
;
1348 return DATA_S_SAMEFORMATETC
;
1351 /************************************************************************
1352 * OLEClipbrd_IDataObject_SetData (IDataObject)
1354 * The OLE Clipboard's does not implement this method
1356 * See Windows documentation for more details on IDataObject methods.
1358 static HRESULT WINAPI
OLEClipbrd_IDataObject_SetData(
1360 LPFORMATETC pformatetc
,
1368 /************************************************************************
1369 * OLEClipbrd_IDataObject_EnumFormatEtc (IDataObject)
1371 * See Windows documentation for more details on IDataObject methods.
1373 static HRESULT WINAPI
OLEClipbrd_IDataObject_EnumFormatEtc(
1376 IEnumFORMATETC
** ppenumFormatEtc
)
1379 FORMATETC
*afmt
= NULL
;
1382 BOOL bClipboardOpen
;
1385 * Declare "This" pointer
1387 OLEClipbrd
*This
= (OLEClipbrd
*)iface
;
1389 TRACE("(%p, %x, %p)\n", iface
, dwDirection
, ppenumFormatEtc
);
1392 * If we have a data source placed on the clipboard (via OleSetClipboard)
1393 * simply delegate to the source object's EnumFormatEtc
1395 if ( This
->pIDataObjectSrc
)
1397 return IDataObject_EnumFormatEtc(This
->pIDataObjectSrc
,
1398 dwDirection
, ppenumFormatEtc
);
1402 * Otherwise we must provide our own enumerator which wraps around the
1403 * Windows clipboard function EnumClipboardFormats
1405 if ( !ppenumFormatEtc
)
1406 return E_INVALIDARG
;
1408 if ( dwDirection
!= DATADIR_GET
) /* IDataObject_SetData not implemented */
1412 * Store all current clipboard formats in an array of FORMATETC's,
1413 * and create an IEnumFORMATETC enumerator from this list.
1415 cfmt
= CountClipboardFormats();
1416 afmt
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
1417 sizeof(FORMATETC
) * cfmt
);
1419 * Open the Windows clipboard, associating it with our hidden window
1421 if ( !(bClipboardOpen
= OpenClipboard(This
->hWndClipboard
)) )
1422 HANDLE_ERROR( CLIPBRD_E_CANT_OPEN
);
1425 * Store all current clipboard formats in an array of FORMATETC's
1426 * TODO: Handle TYMED_IStorage media which were put on the clipboard
1427 * by copying the storage into global memory. We must convert this
1428 * TYMED_HGLOBAL back to TYMED_IStorage.
1430 for (i
= 0, format
= 0; i
< cfmt
; i
++)
1432 format
= EnumClipboardFormats(format
);
1433 if (!format
) /* Failed! */
1435 ERR("EnumClipboardFormats failed to return format!\n");
1436 HANDLE_ERROR( E_FAIL
);
1439 /* Init the FORMATETC struct */
1440 afmt
[i
].cfFormat
= format
;
1442 afmt
[i
].dwAspect
= DVASPECT_CONTENT
;
1443 afmt
[i
].lindex
= -1;
1444 afmt
[i
].tymed
= TYMED_HGLOBAL
;
1448 * Create an EnumFORMATETC enumerator and return an
1449 * EnumFORMATETC after bumping up its ref count
1451 *ppenumFormatEtc
= OLEClipbrd_IEnumFORMATETC_Construct( cfmt
, afmt
, (LPUNKNOWN
)iface
);
1452 if (!(*ppenumFormatEtc
))
1453 HANDLE_ERROR( E_OUTOFMEMORY
);
1455 if (FAILED( hr
= IEnumFORMATETC_AddRef(*ppenumFormatEtc
)))
1462 * Free the array of FORMATETC's
1464 HeapFree(GetProcessHeap(), 0, afmt
);
1467 * Close Windows clipboard
1469 if ( bClipboardOpen
&& !CloseClipboard() )
1470 hr
= CLIPBRD_E_CANT_CLOSE
;
1475 /************************************************************************
1476 * OLEClipbrd_IDataObject_DAdvise (IDataObject)
1478 * The OLE Clipboard's does not implement this method
1480 * See Windows documentation for more details on IDataObject methods.
1482 static HRESULT WINAPI
OLEClipbrd_IDataObject_DAdvise(
1484 FORMATETC
* pformatetc
,
1486 IAdviseSink
* pAdvSink
,
1487 DWORD
* pdwConnection
)
1493 /************************************************************************
1494 * OLEClipbrd_IDataObject_DUnadvise (IDataObject)
1496 * The OLE Clipboard's does not implement this method
1498 * See Windows documentation for more details on IDataObject methods.
1500 static HRESULT WINAPI
OLEClipbrd_IDataObject_DUnadvise(
1508 /************************************************************************
1509 * OLEClipbrd_IDataObject_EnumDAdvise (IDataObject)
1511 * The OLE Clipboard does not implement this method
1513 * See Windows documentation for more details on IDataObject methods.
1515 static HRESULT WINAPI
OLEClipbrd_IDataObject_EnumDAdvise(
1517 IEnumSTATDATA
** ppenumAdvise
)
1524 /*---------------------------------------------------------------------*
1525 * Implementation of the internal IEnumFORMATETC interface returned by
1526 * the OLE clipboard's IDataObject.
1527 *---------------------------------------------------------------------*/
1529 /************************************************************************
1530 * OLEClipbrd_IEnumFORMATETC_Construct (UINT, const FORMATETC, LPUNKNOWN)
1532 * Creates an IEnumFORMATETC enumerator from an array of FORMATETC
1533 * Structures. pUnkOuter is the outer unknown for reference counting only.
1534 * NOTE: this does not AddRef the interface.
1537 static LPENUMFORMATETC
OLEClipbrd_IEnumFORMATETC_Construct(UINT cfmt
, const FORMATETC afmt
[],
1538 LPUNKNOWN pUnkDataObj
)
1540 IEnumFORMATETCImpl
* ef
;
1541 DWORD size
=cfmt
* sizeof(FORMATETC
);
1544 ef
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IEnumFORMATETCImpl
));
1550 ef
->pUnkDataObj
= pUnkDataObj
;
1553 ef
->countFmt
= cfmt
;
1554 if (FAILED(CoGetMalloc(MEMCTX_TASK
, &pIMalloc
))) {
1555 HeapFree(GetProcessHeap(), 0, ef
);
1558 ef
->pFmt
= (LPFORMATETC
)IMalloc_Alloc(pIMalloc
, size
);
1559 IMalloc_Release(pIMalloc
);
1562 memcpy(ef
->pFmt
, afmt
, size
);
1564 TRACE("(%p)->()\n",ef
);
1565 return (LPENUMFORMATETC
)ef
;
1569 /************************************************************************
1570 * OLEClipbrd_IEnumFORMATETC_QueryInterface (IUnknown)
1572 * See Windows documentation for more details on IUnknown methods.
1574 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_QueryInterface
1575 (LPENUMFORMATETC iface
, REFIID riid
, LPVOID
* ppvObj
)
1577 IEnumFORMATETCImpl
*This
= (IEnumFORMATETCImpl
*)iface
;
1579 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This
,debugstr_guid(riid
),ppvObj
);
1582 * Since enumerators are separate objects from the parent data object
1583 * we only need to support the IUnknown and IEnumFORMATETC interfaces
1588 if(IsEqualIID(riid
, &IID_IUnknown
))
1592 else if(IsEqualIID(riid
, &IID_IEnumFORMATETC
))
1594 *ppvObj
= (IDataObject
*)This
;
1599 IEnumFORMATETC_AddRef((IEnumFORMATETC
*)*ppvObj
);
1600 TRACE("-- Interface: (%p)->(%p)\n",ppvObj
,*ppvObj
);
1604 TRACE("-- Interface: E_NOINTERFACE\n");
1605 return E_NOINTERFACE
;
1608 /************************************************************************
1609 * OLEClipbrd_IEnumFORMATETC_AddRef (IUnknown)
1611 * Since enumerating formats only makes sense when our data object is around,
1612 * we insure that it stays as long as we stay by calling our parents IUnknown
1613 * for AddRef and Release. But since we are not controlled by the lifetime of
1614 * the outer object, we still keep our own reference count in order to
1617 static ULONG WINAPI
OLEClipbrd_IEnumFORMATETC_AddRef(LPENUMFORMATETC iface
)
1619 IEnumFORMATETCImpl
*This
= (IEnumFORMATETCImpl
*)iface
;
1620 TRACE("(%p)->(count=%u)\n",This
, This
->ref
);
1622 if (This
->pUnkDataObj
)
1623 IUnknown_AddRef(This
->pUnkDataObj
);
1625 return InterlockedIncrement(&This
->ref
);
1628 /************************************************************************
1629 * OLEClipbrd_IEnumFORMATETC_Release (IUnknown)
1631 * See Windows documentation for more details on IUnknown methods.
1633 static ULONG WINAPI
OLEClipbrd_IEnumFORMATETC_Release(LPENUMFORMATETC iface
)
1635 IEnumFORMATETCImpl
*This
= (IEnumFORMATETCImpl
*)iface
;
1639 TRACE("(%p)->(count=%u)\n",This
, This
->ref
);
1641 if (This
->pUnkDataObj
)
1642 IUnknown_Release(This
->pUnkDataObj
); /* Release parent data object */
1644 ref
= InterlockedDecrement(&This
->ref
);
1647 TRACE("() - destroying IEnumFORMATETC(%p)\n",This
);
1648 if (SUCCEEDED(CoGetMalloc(MEMCTX_TASK
, &pIMalloc
)))
1650 IMalloc_Free(pIMalloc
, This
->pFmt
);
1651 IMalloc_Release(pIMalloc
);
1654 HeapFree(GetProcessHeap(),0,This
);
1659 /************************************************************************
1660 * OLEClipbrd_IEnumFORMATETC_Next (IEnumFORMATETC)
1662 * Standard enumerator members for IEnumFORMATETC
1664 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Next
1665 (LPENUMFORMATETC iface
, ULONG celt
, FORMATETC
*rgelt
, ULONG
*pceltFethed
)
1667 IEnumFORMATETCImpl
*This
= (IEnumFORMATETCImpl
*)iface
;
1669 HRESULT hres
= S_FALSE
;
1671 TRACE("(%p)->(pos=%u)\n", This
, This
->posFmt
);
1673 if (This
->posFmt
< This
->countFmt
)
1675 cfetch
= This
->countFmt
- This
->posFmt
;
1682 memcpy(rgelt
, &This
->pFmt
[This
->posFmt
], cfetch
* sizeof(FORMATETC
));
1683 This
->posFmt
+= cfetch
;
1692 *pceltFethed
= cfetch
;
1698 /************************************************************************
1699 * OLEClipbrd_IEnumFORMATETC_Skip (IEnumFORMATETC)
1701 * Standard enumerator members for IEnumFORMATETC
1703 static HRESULT WINAPI
OLEClipbrd_IEnumFORMATETC_Skip(LPENUMFORMATETC iface
, ULONG celt
)
1705 IEnumFORMATETCImpl
*This
= (IEnumFORMATETCImpl
*)iface
;
1706 TRACE("(%p)->(num=%u)\n", This
, celt
);
1708 This
->posFmt
+= celt
;
1709 if (This
->posFmt
> This
->countFmt
)
1711 This
->posFmt
= This
->countFmt
;
1717 /************************************************************************
1718 * OLEClipbrd_IEnumFORMATETC_Reset (IEnumFORMATETC)
1720 * Standard enumerator members for IEnumFORMATETC
1722 static HRESULT WINAPI
OLEClipbrd_IEnumFORMATETC_Reset(LPENUMFORMATETC iface
)
1724 IEnumFORMATETCImpl
*This
= (IEnumFORMATETCImpl
*)iface
;
1725 TRACE("(%p)->()\n", This
);
1731 /************************************************************************
1732 * OLEClipbrd_IEnumFORMATETC_Clone (IEnumFORMATETC)
1734 * Standard enumerator members for IEnumFORMATETC
1736 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Clone
1737 (LPENUMFORMATETC iface
, LPENUMFORMATETC
* ppenum
)
1739 IEnumFORMATETCImpl
*This
= (IEnumFORMATETCImpl
*)iface
;
1742 TRACE("(%p)->(ppenum=%p)\n", This
, ppenum
);
1745 return E_INVALIDARG
;
1747 *ppenum
= OLEClipbrd_IEnumFORMATETC_Construct(This
->countFmt
,
1751 if (FAILED( hr
= IEnumFORMATETC_AddRef(*ppenum
)))
1754 return (*ppenum
) ? S_OK
: E_OUTOFMEMORY
;