ntdll: More compatible exception information for protection faults.
[wine/multimedia.git] / dlls / ole32 / clipboard.c
blob61c9441a0b82290296ac7f41e4eb965872322ca5
1 /*
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
21 * NOTES:
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
46 * TODO:
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.
61 #include <assert.h>
62 #include <stdarg.h>
63 #include <string.h>
65 #define COBJMACROS
66 #define NONAMELESSUNION
67 #define NONAMELESSSTRUCT
69 #include "windef.h"
70 #include "winbase.h"
71 #include "wingdi.h"
72 #include "winuser.h"
73 #include "winerror.h"
74 #include "winnls.h"
75 #include "ole2.h"
76 #include "wine/debug.h"
77 #include "olestd.h"
79 #include "storage32.h"
81 #define HANDLE_ERROR(err) { hr = err; TRACE("(HRESULT=%lx)\n", (HRESULT)err); goto CLEANUP; }
83 /* For CoGetMalloc (MEMCTX_TASK is currently ignored) */
84 #ifndef MEMCTX_TASK
85 # define MEMCTX_TASK -1
86 #endif
88 WINE_DEFAULT_DEBUG_CHANNEL(ole);
90 /****************************************************************************
91 * OLEClipbrd
92 * DO NOT add any members before the VTables declaration!
94 struct OLEClipbrd
97 * List all interface VTables here
99 const IDataObjectVtbl* lpvtbl1; /* IDataObject VTable */
102 * The hidden OLE clipboard window. This window is used as the bridge between the
103 * the OLE and windows clipboard API. (Windows creates one such window per process)
105 HWND hWndClipboard;
108 * Pointer to the source data object (via OleSetClipboard)
110 IDataObject* pIDataObjectSrc;
113 * The registered DataObject clipboard format
115 UINT cfDataObj;
118 * The handle to ourself
120 HGLOBAL hSelf;
123 * Reference count of this object
125 LONG ref;
128 typedef struct OLEClipbrd OLEClipbrd;
131 /****************************************************************************
132 * IEnumFORMATETC implementation
133 * DO NOT add any members before the VTables declaration!
135 typedef struct
137 /* IEnumFORMATETC VTable */
138 const IEnumFORMATETCVtbl *lpVtbl;
140 /* IEnumFORMATETC fields */
141 UINT posFmt; /* current enumerator position */
142 UINT countFmt; /* number of EnumFORMATETC's in array */
143 LPFORMATETC pFmt; /* array of EnumFORMATETC's */
146 * Reference count of this object
148 LONG ref;
151 * IUnknown implementation of the parent data object.
153 IUnknown* pUnkDataObj;
155 } IEnumFORMATETCImpl;
157 typedef struct PresentationDataHeader
159 BYTE unknown1[28];
160 DWORD dwObjectExtentX;
161 DWORD dwObjectExtentY;
162 DWORD dwSize;
163 } PresentationDataHeader;
166 * The one and only OLEClipbrd object which is created by OLEClipbrd_Initialize()
168 static HGLOBAL hTheOleClipboard = 0;
169 static OLEClipbrd* theOleClipboard = NULL;
173 * Prototypes for the methods of the OLEClipboard class.
175 void OLEClipbrd_Initialize(void);
176 void OLEClipbrd_UnInitialize(void);
177 static OLEClipbrd* OLEClipbrd_Construct(void);
178 static void OLEClipbrd_Destroy(OLEClipbrd* ptrToDestroy);
179 static HWND OLEClipbrd_CreateWindow(void);
180 static void OLEClipbrd_DestroyWindow(HWND hwnd);
181 LRESULT CALLBACK OLEClipbrd_WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
182 static HRESULT OLEClipbrd_RenderFormat( IDataObject *pIDataObject, LPFORMATETC pFormatetc );
183 static HGLOBAL OLEClipbrd_GlobalDupMem( HGLOBAL hGlobalSrc );
186 * Prototypes for the methods of the OLEClipboard class
187 * that implement IDataObject methods.
189 static HRESULT WINAPI OLEClipbrd_IDataObject_QueryInterface(
190 IDataObject* iface,
191 REFIID riid,
192 void** ppvObject);
193 static ULONG WINAPI OLEClipbrd_IDataObject_AddRef(
194 IDataObject* iface);
195 static ULONG WINAPI OLEClipbrd_IDataObject_Release(
196 IDataObject* iface);
197 static HRESULT WINAPI OLEClipbrd_IDataObject_GetData(
198 IDataObject* iface,
199 LPFORMATETC pformatetcIn,
200 STGMEDIUM* pmedium);
201 static HRESULT WINAPI OLEClipbrd_IDataObject_GetDataHere(
202 IDataObject* iface,
203 LPFORMATETC pformatetc,
204 STGMEDIUM* pmedium);
205 static HRESULT WINAPI OLEClipbrd_IDataObject_QueryGetData(
206 IDataObject* iface,
207 LPFORMATETC pformatetc);
208 static HRESULT WINAPI OLEClipbrd_IDataObject_GetCanonicalFormatEtc(
209 IDataObject* iface,
210 LPFORMATETC pformatectIn,
211 LPFORMATETC pformatetcOut);
212 static HRESULT WINAPI OLEClipbrd_IDataObject_SetData(
213 IDataObject* iface,
214 LPFORMATETC pformatetc,
215 STGMEDIUM* pmedium,
216 BOOL fRelease);
217 static HRESULT WINAPI OLEClipbrd_IDataObject_EnumFormatEtc(
218 IDataObject* iface,
219 DWORD dwDirection,
220 IEnumFORMATETC** ppenumFormatEtc);
221 static HRESULT WINAPI OLEClipbrd_IDataObject_DAdvise(
222 IDataObject* iface,
223 FORMATETC* pformatetc,
224 DWORD advf,
225 IAdviseSink* pAdvSink,
226 DWORD* pdwConnection);
227 static HRESULT WINAPI OLEClipbrd_IDataObject_DUnadvise(
228 IDataObject* iface,
229 DWORD dwConnection);
230 static HRESULT WINAPI OLEClipbrd_IDataObject_EnumDAdvise(
231 IDataObject* iface,
232 IEnumSTATDATA** ppenumAdvise);
235 * Prototypes for the IEnumFORMATETC methods.
237 static LPENUMFORMATETC OLEClipbrd_IEnumFORMATETC_Construct(UINT cfmt, const FORMATETC afmt[],
238 LPUNKNOWN pUnkDataObj);
239 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_QueryInterface(LPENUMFORMATETC iface, REFIID riid,
240 LPVOID* ppvObj);
241 static ULONG WINAPI OLEClipbrd_IEnumFORMATETC_AddRef(LPENUMFORMATETC iface);
242 static ULONG WINAPI OLEClipbrd_IEnumFORMATETC_Release(LPENUMFORMATETC iface);
243 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Next(LPENUMFORMATETC iface, ULONG celt,
244 FORMATETC* rgelt, ULONG* pceltFethed);
245 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Skip(LPENUMFORMATETC iface, ULONG celt);
246 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Reset(LPENUMFORMATETC iface);
247 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Clone(LPENUMFORMATETC iface, LPENUMFORMATETC* ppenum);
251 * Virtual function table for the OLEClipbrd's exposed IDataObject interface
253 static const IDataObjectVtbl OLEClipbrd_IDataObject_VTable =
255 OLEClipbrd_IDataObject_QueryInterface,
256 OLEClipbrd_IDataObject_AddRef,
257 OLEClipbrd_IDataObject_Release,
258 OLEClipbrd_IDataObject_GetData,
259 OLEClipbrd_IDataObject_GetDataHere,
260 OLEClipbrd_IDataObject_QueryGetData,
261 OLEClipbrd_IDataObject_GetCanonicalFormatEtc,
262 OLEClipbrd_IDataObject_SetData,
263 OLEClipbrd_IDataObject_EnumFormatEtc,
264 OLEClipbrd_IDataObject_DAdvise,
265 OLEClipbrd_IDataObject_DUnadvise,
266 OLEClipbrd_IDataObject_EnumDAdvise
270 * Virtual function table for IEnumFORMATETC interface
272 static const IEnumFORMATETCVtbl efvt =
274 OLEClipbrd_IEnumFORMATETC_QueryInterface,
275 OLEClipbrd_IEnumFORMATETC_AddRef,
276 OLEClipbrd_IEnumFORMATETC_Release,
277 OLEClipbrd_IEnumFORMATETC_Next,
278 OLEClipbrd_IEnumFORMATETC_Skip,
279 OLEClipbrd_IEnumFORMATETC_Reset,
280 OLEClipbrd_IEnumFORMATETC_Clone
284 * Name of our registered OLE clipboard window class
286 CHAR OLEClipbrd_WNDCLASS[] = "CLIPBRDWNDCLASS";
289 * If we need to store state info we can store it here.
290 * For now we don't need this functionality.
292 typedef struct tagClipboardWindowInfo
294 } ClipboardWindowInfo;
297 /*---------------------------------------------------------------------*
298 * Win32 OLE clipboard API
299 *---------------------------------------------------------------------*/
301 /***********************************************************************
302 * OleSetClipboard [OLE32.@]
303 * Places a pointer to the specified data object onto the clipboard,
304 * making the data object accessible to the OleGetClipboard function.
306 * RETURNS
308 * S_OK IDataObject pointer placed on the clipboard
309 * CLIPBRD_E_CANT_OPEN OpenClipboard failed
310 * CLIPBRD_E_CANT_EMPTY EmptyClipboard failed
311 * CLIPBRD_E_CANT_CLOSE CloseClipboard failed
312 * CLIPBRD_E_CANT_SET SetClipboard failed
315 HRESULT WINAPI OleSetClipboard(IDataObject* pDataObj)
317 HRESULT hr = S_OK;
318 IEnumFORMATETC* penumFormatetc = NULL;
319 FORMATETC rgelt;
320 BOOL bClipboardOpen = FALSE;
322 HGLOBAL hDataObject = 0;
323 OLEClipbrd **ppDataObject;
326 TRACE("(%p)\n", pDataObj);
329 * Make sure we have a clipboard object
331 OLEClipbrd_Initialize();
334 * If the Ole clipboard window hasn't been created yet, create it now.
336 if ( !theOleClipboard->hWndClipboard )
337 theOleClipboard->hWndClipboard = OLEClipbrd_CreateWindow();
339 if ( !theOleClipboard->hWndClipboard ) /* sanity check */
340 HANDLE_ERROR( E_FAIL );
343 * Open the Windows clipboard, associating it with our hidden window
345 if ( !(bClipboardOpen = OpenClipboard(theOleClipboard->hWndClipboard)) )
346 HANDLE_ERROR( CLIPBRD_E_CANT_OPEN );
349 * Empty the current clipboard and make our window the clipboard owner
350 * NOTE: This will trigger a WM_DESTROYCLIPBOARD message
352 if ( !EmptyClipboard() )
353 HANDLE_ERROR( CLIPBRD_E_CANT_EMPTY );
356 * If we are already holding on to an IDataObject first release that.
358 if ( theOleClipboard->pIDataObjectSrc )
360 IDataObject_Release(theOleClipboard->pIDataObjectSrc);
361 theOleClipboard->pIDataObjectSrc = NULL;
365 * AddRef the data object passed in and save its pointer.
366 * A NULL value indicates that the clipboard should be emptied.
368 theOleClipboard->pIDataObjectSrc = pDataObj;
369 if ( pDataObj )
371 IDataObject_AddRef(theOleClipboard->pIDataObjectSrc);
375 * Enumerate all HGLOBAL formats supported by the source and make
376 * those formats available using delayed rendering using SetClipboardData.
377 * Only global memory based data items may be made available to non-OLE
378 * applications via the standard Windows clipboard API. Data based on other
379 * mediums(non TYMED_HGLOBAL) can only be accessed via the Ole Clipboard API.
381 * TODO: Do we need to additionally handle TYMED_IStorage media by copying
382 * the storage into global memory?
384 if ( pDataObj )
386 if ( FAILED(hr = IDataObject_EnumFormatEtc( pDataObj,
387 DATADIR_GET,
388 &penumFormatetc )))
390 HANDLE_ERROR( hr );
393 while ( S_OK == IEnumFORMATETC_Next(penumFormatetc, 1, &rgelt, NULL) )
395 if ( rgelt.tymed == TYMED_HGLOBAL )
397 CHAR szFmtName[80];
398 TRACE("(cfFormat=%d:%s)\n", rgelt.cfFormat,
399 GetClipboardFormatNameA(rgelt.cfFormat, szFmtName, sizeof(szFmtName)-1)
400 ? szFmtName : "");
402 SetClipboardData( rgelt.cfFormat, NULL);
405 IEnumFORMATETC_Release(penumFormatetc);
409 * Windows additionally creates a new "DataObject" clipboard format
410 * and stores in on the clipboard. We could possibly store a pointer
411 * to our internal IDataObject interface on the clipboard. I'm not
412 * sure what the use of this is though.
413 * Enable the code below for this functionality.
416 theOleClipboard->cfDataObj = RegisterClipboardFormatA("DataObject");
417 hDataObject = GlobalAlloc( GMEM_DDESHARE|GMEM_MOVEABLE|GMEM_ZEROINIT,
418 sizeof(OLEClipbrd *));
419 if (hDataObject==0)
420 HANDLE_ERROR( E_OUTOFMEMORY );
422 ppDataObject = (OLEClipbrd**)GlobalLock(hDataObject);
423 *ppDataObject = theOleClipboard;
424 GlobalUnlock(hDataObject);
426 if ( !SetClipboardData( theOleClipboard->cfDataObj, hDataObject ) )
427 HANDLE_ERROR( CLIPBRD_E_CANT_SET );
430 hr = S_OK;
432 CLEANUP:
435 * Close Windows clipboard (It remains associated with our window)
437 if ( bClipboardOpen && !CloseClipboard() )
438 hr = CLIPBRD_E_CANT_CLOSE;
441 * Release the source IDataObject if something failed
443 if ( FAILED(hr) )
445 if (theOleClipboard->pIDataObjectSrc)
447 IDataObject_Release(theOleClipboard->pIDataObjectSrc);
448 theOleClipboard->pIDataObjectSrc = NULL;
452 return hr;
456 /***********************************************************************
457 * OleGetClipboard [OLE32.@]
458 * Returns a pointer to our internal IDataObject which represents the conceptual
459 * state of the Windows clipboard. If the current clipboard already contains
460 * an IDataObject, our internal IDataObject will delegate to this object.
462 HRESULT WINAPI OleGetClipboard(IDataObject** ppDataObj)
464 HRESULT hr = S_OK;
465 TRACE("()\n");
468 * Make sure we have a clipboard object
470 OLEClipbrd_Initialize();
472 if (!theOleClipboard)
473 return E_OUTOFMEMORY;
475 /* Return a reference counted IDataObject */
476 hr = IDataObject_QueryInterface( (IDataObject*)&(theOleClipboard->lpvtbl1),
477 &IID_IDataObject, (void**)ppDataObj);
478 return hr;
481 /******************************************************************************
482 * OleFlushClipboard [OLE32.@]
483 * Renders the data from the source IDataObject into the windows clipboard
485 * TODO: OleFlushClipboard needs to additionally handle TYMED_IStorage media
486 * by copying the storage into global memory. Subsequently the default
487 * data object exposed through OleGetClipboard must convert this TYMED_HGLOBAL
488 * back to TYMED_IStorage.
490 HRESULT WINAPI OleFlushClipboard()
492 IEnumFORMATETC* penumFormatetc = NULL;
493 FORMATETC rgelt;
494 HRESULT hr = S_OK;
495 BOOL bClipboardOpen = FALSE;
496 IDataObject* pIDataObjectSrc = NULL;
498 TRACE("()\n");
501 * Make sure we have a clipboard object
503 OLEClipbrd_Initialize();
506 * Already flushed or no source DataObject? Nothing to do.
508 if (!theOleClipboard->pIDataObjectSrc)
509 return S_OK;
512 * Addref and save the source data object we are holding on to temporarily,
513 * since it will be released when we empty the clipboard.
515 pIDataObjectSrc = theOleClipboard->pIDataObjectSrc;
516 IDataObject_AddRef(pIDataObjectSrc);
519 * Open the Windows clipboard
521 if ( !(bClipboardOpen = OpenClipboard(theOleClipboard->hWndClipboard)) )
522 HANDLE_ERROR( CLIPBRD_E_CANT_OPEN );
525 * Empty the current clipboard
527 if ( !EmptyClipboard() )
528 HANDLE_ERROR( CLIPBRD_E_CANT_EMPTY );
531 * Render all HGLOBAL formats supported by the source into
532 * the windows clipboard.
534 if ( FAILED( hr = IDataObject_EnumFormatEtc( pIDataObjectSrc,
535 DATADIR_GET,
536 &penumFormatetc) ))
538 HANDLE_ERROR( hr );
541 while ( S_OK == IEnumFORMATETC_Next(penumFormatetc, 1, &rgelt, NULL) )
543 if ( rgelt.tymed == TYMED_HGLOBAL )
545 CHAR szFmtName[80];
546 TRACE("(cfFormat=%d:%s)\n", rgelt.cfFormat,
547 GetClipboardFormatNameA(rgelt.cfFormat, szFmtName, sizeof(szFmtName)-1)
548 ? szFmtName : "");
551 * Render the clipboard data
553 if ( FAILED(OLEClipbrd_RenderFormat( pIDataObjectSrc, &rgelt )) )
554 continue;
558 IEnumFORMATETC_Release(penumFormatetc);
561 * Release the source data object we are holding on to
563 IDataObject_Release(pIDataObjectSrc);
565 CLEANUP:
568 * Close Windows clipboard (It remains associated with our window)
570 if ( bClipboardOpen && !CloseClipboard() )
571 hr = CLIPBRD_E_CANT_CLOSE;
573 return hr;
577 /***********************************************************************
578 * OleIsCurrentClipboard [OLE32.@]
580 HRESULT WINAPI OleIsCurrentClipboard ( IDataObject *pDataObject)
582 TRACE("()\n");
584 * Make sure we have a clipboard object
586 OLEClipbrd_Initialize();
588 if (!theOleClipboard)
589 return E_OUTOFMEMORY;
591 return (pDataObject == theOleClipboard->pIDataObjectSrc) ? S_OK : S_FALSE;
595 /*---------------------------------------------------------------------*
596 * Internal implementation methods for the OLE clipboard
597 *---------------------------------------------------------------------*/
599 /***********************************************************************
600 * OLEClipbrd_Initialize()
601 * Initializes the OLE clipboard.
603 void OLEClipbrd_Initialize(void)
606 * Create the clipboard if necessary
608 if ( !theOleClipboard )
610 TRACE("()\n");
611 theOleClipboard = OLEClipbrd_Construct();
616 /***********************************************************************
617 * OLEClipbrd_UnInitialize()
618 * Un-Initializes the OLE clipboard
620 void OLEClipbrd_UnInitialize(void)
622 TRACE("()\n");
624 * Destroy the clipboard if no one holds a reference to us.
625 * Note that the clipboard was created with a reference count of 1.
627 if ( theOleClipboard && (theOleClipboard->ref <= 1) )
629 OLEClipbrd_Destroy( theOleClipboard );
631 else
633 WARN( "() : OLEClipbrd_UnInitialize called while client holds an IDataObject reference!\n");
638 /*********************************************************
639 * Construct the OLEClipbrd class.
641 static OLEClipbrd* OLEClipbrd_Construct()
643 OLEClipbrd* newObject = NULL;
644 HGLOBAL hNewObject = 0;
647 * Allocate space for the object. We use GlobalAlloc since we need
648 * an HGLOBAL to expose our DataObject as a registered clipboard type.
650 hNewObject = GlobalAlloc( GMEM_DDESHARE|GMEM_MOVEABLE|GMEM_ZEROINIT,
651 sizeof(OLEClipbrd));
652 if (hNewObject==0)
653 return NULL;
656 * Lock the handle for the entire lifetime of the clipboard.
658 newObject = GlobalLock(hNewObject);
661 * Initialize the virtual function table.
663 newObject->lpvtbl1 = &OLEClipbrd_IDataObject_VTable;
666 * Start with one reference count. The caller of this function
667 * must release the interface pointer when it is done.
669 newObject->ref = 1;
671 newObject->hSelf = hNewObject;
674 * The Ole clipboard is a singleton - save the global handle and pointer
676 theOleClipboard = newObject;
677 hTheOleClipboard = hNewObject;
679 return theOleClipboard;
682 static void OLEClipbrd_Destroy(OLEClipbrd* ptrToDestroy)
684 TRACE("()\n");
686 if ( !ptrToDestroy )
687 return;
690 * Destroy the Ole clipboard window
692 if ( ptrToDestroy->hWndClipboard )
693 OLEClipbrd_DestroyWindow(ptrToDestroy->hWndClipboard);
696 * Free the actual OLE Clipboard structure.
698 TRACE("() - Destroying clipboard data object.\n");
699 GlobalUnlock(ptrToDestroy->hSelf);
700 GlobalFree(ptrToDestroy->hSelf);
703 * The Ole clipboard is a singleton (ptrToDestroy == theOleClipboard)
705 theOleClipboard = NULL;
706 hTheOleClipboard = 0;
710 /***********************************************************************
711 * OLEClipbrd_CreateWindow()
712 * Create the clipboard window
714 static HWND OLEClipbrd_CreateWindow()
716 HWND hwnd = 0;
717 WNDCLASSEXA wcex;
720 * Register the clipboard window class if necessary
722 ZeroMemory( &wcex, sizeof(WNDCLASSEXA));
724 wcex.cbSize = sizeof(WNDCLASSEXA);
725 /* Windows creates this class with a style mask of 0
726 * We don't bother doing this since the FindClassByAtom code
727 * would have to be changed to deal with this idiosyncrasy. */
728 wcex.style = CS_GLOBALCLASS;
729 wcex.lpfnWndProc = OLEClipbrd_WndProc;
730 wcex.hInstance = 0;
731 wcex.lpszClassName = OLEClipbrd_WNDCLASS;
733 RegisterClassExA(&wcex);
736 * Create a hidden window to receive OLE clipboard messages
740 * If we need to store state info we can store it here.
741 * For now we don't need this functionality.
742 * ClipboardWindowInfo clipboardInfo;
743 * ZeroMemory( &trackerInfo, sizeof(ClipboardWindowInfo));
746 hwnd = CreateWindowA(OLEClipbrd_WNDCLASS,
747 "ClipboardWindow",
748 WS_POPUP | WS_CLIPSIBLINGS | WS_OVERLAPPED,
749 CW_USEDEFAULT, CW_USEDEFAULT,
750 CW_USEDEFAULT, CW_USEDEFAULT,
754 0 /*(LPVOID)&clipboardInfo */);
756 return hwnd;
759 /***********************************************************************
760 * OLEClipbrd_DestroyWindow(HWND)
761 * Destroy the clipboard window and unregister its class
763 static void OLEClipbrd_DestroyWindow(HWND hwnd)
766 * Destroy clipboard window and unregister its WNDCLASS
768 DestroyWindow(hwnd);
769 UnregisterClassA( OLEClipbrd_WNDCLASS, 0 );
772 /***********************************************************************
773 * OLEClipbrd_WndProc(HWND, unsigned, WORD, LONG)
774 * Processes messages sent to the OLE clipboard window.
775 * Note that we will intercept messages in our WndProc only when data
776 * has been placed in the clipboard via OleSetClipboard().
777 * i.e. Only when OLE owns the windows clipboard.
779 LRESULT CALLBACK OLEClipbrd_WndProc
780 (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
782 switch (message)
785 * WM_RENDERFORMAT
786 * We receive this message to allow us to handle delayed rendering of
787 * a specific clipboard format when an application requests data in
788 * that format by calling GetClipboardData.
789 * (Recall that in OleSetClipboard, we used SetClipboardData to
790 * make all HGLOBAL formats supported by the source IDataObject
791 * available using delayed rendering)
792 * On receiving this message we must actually render the data in the
793 * specified format and place it on the clipboard by calling the
794 * SetClipboardData function.
796 case WM_RENDERFORMAT:
798 FORMATETC rgelt;
800 ZeroMemory( &rgelt, sizeof(FORMATETC));
803 * Initialize FORMATETC to a Windows clipboard friendly format
805 rgelt.cfFormat = (UINT) wParam;
806 rgelt.dwAspect = DVASPECT_CONTENT;
807 rgelt.lindex = -1;
808 rgelt.tymed = TYMED_HGLOBAL;
810 TRACE("(): WM_RENDERFORMAT(cfFormat=%d)\n", rgelt.cfFormat);
813 * Render the clipboard data.
814 * (We must have a source data object or we wouldn't be in this WndProc)
816 OLEClipbrd_RenderFormat( (IDataObject*)&(theOleClipboard->lpvtbl1), &rgelt );
818 break;
822 * WM_RENDERALLFORMATS
823 * Sent before the clipboard owner window is destroyed.
824 * We should receive this message only when OleUninitialize is called
825 * while we have an IDataObject in the clipboard.
826 * For the content of the clipboard to remain available to other
827 * applications, we must render data in all the formats the source IDataObject
828 * is capable of generating, and place the data on the clipboard by calling
829 * SetClipboardData.
831 case WM_RENDERALLFORMATS:
833 IEnumFORMATETC* penumFormatetc = NULL;
834 FORMATETC rgelt;
836 TRACE("(): WM_RENDERALLFORMATS\n");
839 * Render all HGLOBAL formats supported by the source into
840 * the windows clipboard.
842 if ( FAILED( IDataObject_EnumFormatEtc( (IDataObject*)&(theOleClipboard->lpvtbl1),
843 DATADIR_GET, &penumFormatetc) ) )
845 WARN("(): WM_RENDERALLFORMATS failed to retrieve EnumFormatEtc!\n");
846 return 0;
849 while ( S_OK == IEnumFORMATETC_Next(penumFormatetc, 1, &rgelt, NULL) )
851 if ( rgelt.tymed == TYMED_HGLOBAL )
854 * Render the clipboard data.
856 if ( FAILED(OLEClipbrd_RenderFormat( (IDataObject*)&(theOleClipboard->lpvtbl1), &rgelt )) )
857 continue;
859 TRACE("(): WM_RENDERALLFORMATS(cfFormat=%d)\n", rgelt.cfFormat);
863 IEnumFORMATETC_Release(penumFormatetc);
865 break;
869 * WM_DESTROYCLIPBOARD
870 * This is sent by EmptyClipboard before the clipboard is emptied.
871 * We should release any IDataObject we are holding onto when we receive
872 * this message, since it indicates that the OLE clipboard should be empty
873 * from this point on.
875 case WM_DESTROYCLIPBOARD:
877 TRACE("(): WM_DESTROYCLIPBOARD\n");
879 * Release the data object we are holding on to
881 if ( theOleClipboard->pIDataObjectSrc )
883 IDataObject_Release(theOleClipboard->pIDataObjectSrc);
884 theOleClipboard->pIDataObjectSrc = NULL;
886 break;
890 case WM_ASKCBFORMATNAME:
891 case WM_CHANGECBCHAIN:
892 case WM_DRAWCLIPBOARD:
893 case WM_SIZECLIPBOARD:
894 case WM_HSCROLLCLIPBOARD:
895 case WM_VSCROLLCLIPBOARD:
896 case WM_PAINTCLIPBOARD:
898 default:
899 return DefWindowProcA(hWnd, message, wParam, lParam);
902 return 0;
905 #define MAX_CLIPFORMAT_NAME 80
907 /***********************************************************************
908 * OLEClipbrd_RenderFormat(LPFORMATETC)
909 * Render the clipboard data. Note that this call will delegate to the
910 * source data object.
911 * Note: This function assumes it is passed an HGLOBAL format to render.
913 static HRESULT OLEClipbrd_RenderFormat(IDataObject *pIDataObject, LPFORMATETC pFormatetc)
915 STGMEDIUM std;
916 HGLOBAL hDup;
917 HRESULT hr = S_OK;
918 char szFmtName[MAX_CLIPFORMAT_NAME];
919 ILockBytes *ptrILockBytes = 0;
920 HGLOBAL hStorage = 0;
922 GetClipboardFormatNameA(pFormatetc->cfFormat, szFmtName, MAX_CLIPFORMAT_NAME);
924 /* If embed source */
925 if (!strcmp(szFmtName, CF_EMBEDSOURCE))
927 memset(&std, 0, sizeof(STGMEDIUM));
928 std.tymed = pFormatetc->tymed = TYMED_ISTORAGE;
930 hStorage = GlobalAlloc(GMEM_SHARE|GMEM_MOVEABLE, 0);
931 if (hStorage == NULL)
932 HANDLE_ERROR( E_OUTOFMEMORY );
933 hr = CreateILockBytesOnHGlobal(hStorage, FALSE, &ptrILockBytes);
934 hr = StgCreateDocfileOnILockBytes(ptrILockBytes, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &std.u.pstg);
936 if (FAILED(hr = IDataObject_GetDataHere(theOleClipboard->pIDataObjectSrc, pFormatetc, &std)))
938 WARN("() : IDataObject_GetDataHere failed to render clipboard data! (%lx)\n", hr);
939 GlobalFree(hStorage);
940 return hr;
943 if (1) /* check whether the presentation data is already -not- present */
945 FORMATETC fmt2;
946 STGMEDIUM std2;
947 METAFILEPICT *mfp = 0;
949 fmt2.cfFormat = CF_METAFILEPICT;
950 fmt2.ptd = 0;
951 fmt2.dwAspect = DVASPECT_CONTENT;
952 fmt2.lindex = -1;
953 fmt2.tymed = TYMED_MFPICT;
955 memset(&std2, 0, sizeof(STGMEDIUM));
956 std2.tymed = TYMED_MFPICT;
958 /* Get the metafile picture out of it */
960 if (!FAILED(hr = IDataObject_GetData(theOleClipboard->pIDataObjectSrc, &fmt2, &std2)))
962 mfp = (METAFILEPICT *)GlobalLock(std2.u.hGlobal);
965 if (mfp)
967 OLECHAR name[]={ 2, 'O', 'l', 'e', 'P', 'r', 'e', 's', '0', '0', '0', 0};
968 IStream *pStream = 0;
969 void *mfBits;
970 PresentationDataHeader pdh;
971 INT nSize;
972 CLSID clsID;
973 LPOLESTR strProgID;
974 CHAR strOleTypeName[51];
975 BYTE OlePresStreamHeader [] =
977 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00,
978 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
979 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
980 0x00, 0x00, 0x00, 0x00
983 nSize = GetMetaFileBitsEx(mfp->hMF, 0, NULL);
985 memset(&pdh, 0, sizeof(PresentationDataHeader));
986 memcpy(&pdh, OlePresStreamHeader, sizeof(OlePresStreamHeader));
988 pdh.dwObjectExtentX = mfp->xExt;
989 pdh.dwObjectExtentY = mfp->yExt;
990 pdh.dwSize = nSize;
992 hr = IStorage_CreateStream(std.u.pstg, name, STGM_CREATE|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, 0, &pStream);
994 hr = IStream_Write(pStream, &pdh, sizeof(PresentationDataHeader), NULL);
996 mfBits = HeapAlloc(GetProcessHeap(), 0, nSize);
997 nSize = GetMetaFileBitsEx(mfp->hMF, nSize, mfBits);
999 hr = IStream_Write(pStream, mfBits, nSize, NULL);
1001 IStream_Release(pStream);
1003 HeapFree(GetProcessHeap(), 0, mfBits);
1005 GlobalUnlock(std2.u.hGlobal);
1007 ReadClassStg(std.u.pstg, &clsID);
1008 ProgIDFromCLSID(&clsID, &strProgID);
1010 WideCharToMultiByte( CP_ACP, 0, strProgID, -1, strOleTypeName, sizeof(strOleTypeName), NULL, NULL );
1011 OLECONVERT_CreateOleStream(std.u.pstg);
1012 OLECONVERT_CreateCompObjStream(std.u.pstg, strOleTypeName);
1016 else
1018 if (FAILED(hr = IDataObject_GetData(pIDataObject, pFormatetc, &std)))
1020 WARN("() : IDataObject_GetData failed to render clipboard data! (%lx)\n", hr);
1021 GlobalFree(hStorage);
1022 return hr;
1025 /* To put a copy back on the clipboard */
1027 hStorage = std.u.hGlobal;
1031 * Put a copy of the rendered data back on the clipboard
1034 if ( !(hDup = OLEClipbrd_GlobalDupMem(hStorage)) )
1035 HANDLE_ERROR( E_OUTOFMEMORY );
1037 if ( !SetClipboardData( pFormatetc->cfFormat, hDup ) )
1039 GlobalFree(hDup);
1040 WARN("() : Failed to set rendered clipboard data into clipboard!\n");
1043 CLEANUP:
1045 ReleaseStgMedium(&std);
1047 return hr;
1051 /***********************************************************************
1052 * OLEClipbrd_GlobalDupMem( HGLOBAL )
1053 * Helper method to duplicate an HGLOBAL chunk of memory
1055 static HGLOBAL OLEClipbrd_GlobalDupMem( HGLOBAL hGlobalSrc )
1057 HGLOBAL hGlobalDest;
1058 PVOID pGlobalSrc, pGlobalDest;
1059 DWORD cBytes;
1061 if ( !hGlobalSrc )
1062 return 0;
1064 cBytes = GlobalSize(hGlobalSrc);
1065 if ( 0 == cBytes )
1066 return 0;
1068 hGlobalDest = GlobalAlloc( GMEM_DDESHARE|GMEM_MOVEABLE,
1069 cBytes );
1070 if ( !hGlobalDest )
1071 return 0;
1073 pGlobalSrc = GlobalLock(hGlobalSrc);
1074 pGlobalDest = GlobalLock(hGlobalDest);
1075 if ( !pGlobalSrc || !pGlobalDest )
1077 GlobalFree(hGlobalDest);
1078 return 0;
1081 memcpy(pGlobalDest, pGlobalSrc, cBytes);
1083 GlobalUnlock(hGlobalSrc);
1084 GlobalUnlock(hGlobalDest);
1086 return 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(
1102 IDataObject* iface,
1103 REFIID riid,
1104 void** ppvObject)
1107 * Declare "This" pointer
1109 OLEClipbrd *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.
1121 *ppvObject = 0;
1124 * Compare the riid with the interface IDs implemented by this object.
1126 if (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0)
1128 *ppvObject = iface;
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
1142 * successful.
1144 IUnknown_AddRef((IUnknown*)*ppvObject);
1146 return S_OK;
1149 /************************************************************************
1150 * OLEClipbrd_IDataObject_AddRef (IUnknown)
1152 * See Windows documentation for more details on IUnknown methods.
1154 static ULONG WINAPI OLEClipbrd_IDataObject_AddRef(
1155 IDataObject* iface)
1158 * Declare "This" pointer
1160 OLEClipbrd *This = (OLEClipbrd *)iface;
1162 TRACE("(%p)->(count=%lu)\n",This, This->ref);
1164 return InterlockedIncrement(&This->ref);
1168 /************************************************************************
1169 * OLEClipbrd_IDataObject_Release (IUnknown)
1171 * See Windows documentation for more details on IUnknown methods.
1173 static ULONG WINAPI OLEClipbrd_IDataObject_Release(
1174 IDataObject* iface)
1177 * Declare "This" pointer
1179 OLEClipbrd *This = (OLEClipbrd *)iface;
1180 ULONG ref;
1182 TRACE("(%p)->(count=%lu)\n",This, This->ref);
1185 * Decrease the reference count on this object.
1187 ref = InterlockedDecrement(&This->ref);
1190 * If the reference count goes down to 0, perform suicide.
1192 if (ref == 0)
1194 OLEClipbrd_Destroy(This);
1197 return ref;
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(
1210 IDataObject* iface,
1211 LPFORMATETC pformatetcIn,
1212 STGMEDIUM* pmedium)
1214 HANDLE hData = 0;
1215 BOOL bClipboardOpen = FALSE;
1216 HRESULT hr = S_OK;
1217 LPVOID src;
1220 * Declare "This" pointer
1222 OLEClipbrd *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 )
1241 return DV_E_LINDEX;
1242 if ( (pformatetcIn->tymed & TYMED_HGLOBAL) != TYMED_HGLOBAL )
1243 return DV_E_TYMED;
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);
1262 if(src) {
1263 LPVOID dest;
1264 ULONG size;
1265 HANDLE hDest;
1267 size = GlobalSize(hData);
1268 hDest = GlobalAlloc(GHND, size);
1269 dest = GlobalLock(hDest);
1270 memcpy(dest, src, size);
1271 GlobalUnlock(hDest);
1272 GlobalUnlock(hData);
1273 hData = hDest;
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;
1283 hr = S_OK;
1285 CLEANUP:
1287 * Close Windows clipboard
1289 if ( bClipboardOpen && !CloseClipboard() )
1290 hr = CLIPBRD_E_CANT_CLOSE;
1292 if ( FAILED(hr) )
1293 return hr;
1294 return (hData == 0) ? DV_E_FORMATETC : S_OK;
1297 static HRESULT WINAPI OLEClipbrd_IDataObject_GetDataHere(
1298 IDataObject* iface,
1299 LPFORMATETC pformatetc,
1300 STGMEDIUM* pmedium)
1302 FIXME(": Stub\n");
1303 return E_NOTIMPL;
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(
1316 IDataObject* iface,
1317 LPFORMATETC pformatetc)
1320 * Declare "This" pointer
1322 OLEClipbrd *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);
1335 if (!pformatetc)
1336 return E_INVALIDARG;
1338 if ( pformatetc->dwAspect != DVASPECT_CONTENT )
1339 return DV_E_DVASPECT;
1341 if ( pformatetc->lindex != -1 )
1342 return DV_E_LINDEX;
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 )
1349 return DV_E_TYMED;
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(
1363 IDataObject* iface,
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(
1384 IDataObject* iface,
1385 LPFORMATETC pformatetc,
1386 STGMEDIUM* pmedium,
1387 BOOL fRelease)
1389 TRACE("\n");
1390 return E_NOTIMPL;
1393 /************************************************************************
1394 * OLEClipbrd_IDataObject_EnumFormatEtc (IDataObject)
1396 * See Windows documentation for more details on IDataObject methods.
1398 static HRESULT WINAPI OLEClipbrd_IDataObject_EnumFormatEtc(
1399 IDataObject* iface,
1400 DWORD dwDirection,
1401 IEnumFORMATETC** ppenumFormatEtc)
1403 HRESULT hr = S_OK;
1404 FORMATETC *afmt = NULL;
1405 int cfmt, i;
1406 UINT format;
1407 BOOL bClipboardOpen;
1410 * Declare "This" pointer
1412 OLEClipbrd *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 */
1434 return E_NOTIMPL;
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 = 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;
1466 afmt[i].ptd = NULL;
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)))
1481 HANDLE_ERROR( hr );
1483 hr = S_OK;
1485 CLEANUP:
1487 * Free the array of FORMATETC's
1489 HeapFree(GetProcessHeap(), 0, afmt);
1492 * Close Windows clipboard
1494 if ( bClipboardOpen && !CloseClipboard() )
1495 hr = CLIPBRD_E_CANT_CLOSE;
1497 return hr;
1500 /************************************************************************
1501 * OLEClipbrd_IDataObject_DAdvise (IDataObject)
1503 * The OLE Clipboard's does not implement this method
1505 * See Windows documentation for more details on IDataObject methods.
1507 static HRESULT WINAPI OLEClipbrd_IDataObject_DAdvise(
1508 IDataObject* iface,
1509 FORMATETC* pformatetc,
1510 DWORD advf,
1511 IAdviseSink* pAdvSink,
1512 DWORD* pdwConnection)
1514 TRACE("\n");
1515 return E_NOTIMPL;
1518 /************************************************************************
1519 * OLEClipbrd_IDataObject_DUnadvise (IDataObject)
1521 * The OLE Clipboard's does not implement this method
1523 * See Windows documentation for more details on IDataObject methods.
1525 static HRESULT WINAPI OLEClipbrd_IDataObject_DUnadvise(
1526 IDataObject* iface,
1527 DWORD dwConnection)
1529 TRACE("\n");
1530 return E_NOTIMPL;
1533 /************************************************************************
1534 * OLEClipbrd_IDataObject_EnumDAdvise (IDataObject)
1536 * The OLE Clipboard does not implement this method
1538 * See Windows documentation for more details on IDataObject methods.
1540 static HRESULT WINAPI OLEClipbrd_IDataObject_EnumDAdvise(
1541 IDataObject* iface,
1542 IEnumSTATDATA** ppenumAdvise)
1544 TRACE("\n");
1545 return E_NOTIMPL;
1549 /*---------------------------------------------------------------------*
1550 * Implementation of the internal IEnumFORMATETC interface returned by
1551 * the OLE clipboard's IDataObject.
1552 *---------------------------------------------------------------------*/
1554 /************************************************************************
1555 * OLEClipbrd_IEnumFORMATETC_Construct (UINT, const FORMATETC, LPUNKNOWN)
1557 * Creates an IEnumFORMATETC enumerator from an array of FORMATETC
1558 * Structures. pUnkOuter is the outer unknown for reference counting only.
1559 * NOTE: this does not AddRef the interface.
1562 LPENUMFORMATETC OLEClipbrd_IEnumFORMATETC_Construct(UINT cfmt, const FORMATETC afmt[],
1563 LPUNKNOWN pUnkDataObj)
1565 IEnumFORMATETCImpl* ef;
1566 DWORD size=cfmt * sizeof(FORMATETC);
1567 LPMALLOC pIMalloc;
1569 ef = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IEnumFORMATETCImpl));
1570 if (!ef)
1571 return NULL;
1573 ef->ref = 0;
1574 ef->lpVtbl = &efvt;
1575 ef->pUnkDataObj = pUnkDataObj;
1577 ef->posFmt = 0;
1578 ef->countFmt = cfmt;
1579 if (FAILED(CoGetMalloc(MEMCTX_TASK, &pIMalloc))) {
1580 HeapFree(GetProcessHeap(), 0, ef);
1581 return NULL;
1583 ef->pFmt = (LPFORMATETC)IMalloc_Alloc(pIMalloc, size);
1584 IMalloc_Release(pIMalloc);
1586 if (ef->pFmt)
1587 memcpy(ef->pFmt, afmt, size);
1589 TRACE("(%p)->()\n",ef);
1590 return (LPENUMFORMATETC)ef;
1594 /************************************************************************
1595 * OLEClipbrd_IEnumFORMATETC_QueryInterface (IUnknown)
1597 * See Windows documentation for more details on IUnknown methods.
1599 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_QueryInterface
1600 (LPENUMFORMATETC iface, REFIID riid, LPVOID* ppvObj)
1602 IEnumFORMATETCImpl *This = (IEnumFORMATETCImpl *)iface;
1604 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
1607 * Since enumerators are separate objects from the parent data object
1608 * we only need to support the IUnknown and IEnumFORMATETC interfaces
1611 *ppvObj = NULL;
1613 if(IsEqualIID(riid, &IID_IUnknown))
1615 *ppvObj = This;
1617 else if(IsEqualIID(riid, &IID_IEnumFORMATETC))
1619 *ppvObj = (IDataObject*)This;
1622 if(*ppvObj)
1624 IEnumFORMATETC_AddRef((IEnumFORMATETC*)*ppvObj);
1625 TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
1626 return S_OK;
1629 TRACE("-- Interface: E_NOINTERFACE\n");
1630 return E_NOINTERFACE;
1633 /************************************************************************
1634 * OLEClipbrd_IEnumFORMATETC_AddRef (IUnknown)
1636 * Since enumerating formats only makes sense when our data object is around,
1637 * we insure that it stays as long as we stay by calling our parents IUnknown
1638 * for AddRef and Release. But since we are not controlled by the lifetime of
1639 * the outer object, we still keep our own reference count in order to
1640 * free ourselves.
1642 static ULONG WINAPI OLEClipbrd_IEnumFORMATETC_AddRef(LPENUMFORMATETC iface)
1644 IEnumFORMATETCImpl *This = (IEnumFORMATETCImpl *)iface;
1645 TRACE("(%p)->(count=%lu)\n",This, This->ref);
1647 if (This->pUnkDataObj)
1648 IUnknown_AddRef(This->pUnkDataObj);
1650 return InterlockedIncrement(&This->ref);
1653 /************************************************************************
1654 * OLEClipbrd_IEnumFORMATETC_Release (IUnknown)
1656 * See Windows documentation for more details on IUnknown methods.
1658 static ULONG WINAPI OLEClipbrd_IEnumFORMATETC_Release(LPENUMFORMATETC iface)
1660 IEnumFORMATETCImpl *This = (IEnumFORMATETCImpl *)iface;
1661 LPMALLOC pIMalloc;
1662 ULONG ref;
1664 TRACE("(%p)->(count=%lu)\n",This, This->ref);
1666 if (This->pUnkDataObj)
1667 IUnknown_Release(This->pUnkDataObj); /* Release parent data object */
1669 ref = InterlockedDecrement(&This->ref);
1670 if (!ref)
1672 TRACE("() - destroying IEnumFORMATETC(%p)\n",This);
1673 if (SUCCEEDED(CoGetMalloc(MEMCTX_TASK, &pIMalloc)))
1675 IMalloc_Free(pIMalloc, This->pFmt);
1676 IMalloc_Release(pIMalloc);
1679 HeapFree(GetProcessHeap(),0,This);
1681 return ref;
1684 /************************************************************************
1685 * OLEClipbrd_IEnumFORMATETC_Next (IEnumFORMATETC)
1687 * Standard enumerator members for IEnumFORMATETC
1689 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Next
1690 (LPENUMFORMATETC iface, ULONG celt, FORMATETC *rgelt, ULONG *pceltFethed)
1692 IEnumFORMATETCImpl *This = (IEnumFORMATETCImpl *)iface;
1693 UINT cfetch;
1694 HRESULT hres = S_FALSE;
1696 TRACE("(%p)->(pos=%u)\n", This, This->posFmt);
1698 if (This->posFmt < This->countFmt)
1700 cfetch = This->countFmt - This->posFmt;
1701 if (cfetch >= celt)
1703 cfetch = celt;
1704 hres = S_OK;
1707 memcpy(rgelt, &This->pFmt[This->posFmt], cfetch * sizeof(FORMATETC));
1708 This->posFmt += cfetch;
1710 else
1712 cfetch = 0;
1715 if (pceltFethed)
1717 *pceltFethed = cfetch;
1720 return hres;
1723 /************************************************************************
1724 * OLEClipbrd_IEnumFORMATETC_Skip (IEnumFORMATETC)
1726 * Standard enumerator members for IEnumFORMATETC
1728 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Skip(LPENUMFORMATETC iface, ULONG celt)
1730 IEnumFORMATETCImpl *This = (IEnumFORMATETCImpl *)iface;
1731 TRACE("(%p)->(num=%lu)\n", This, celt);
1733 This->posFmt += celt;
1734 if (This->posFmt > This->countFmt)
1736 This->posFmt = This->countFmt;
1737 return S_FALSE;
1739 return S_OK;
1742 /************************************************************************
1743 * OLEClipbrd_IEnumFORMATETC_Reset (IEnumFORMATETC)
1745 * Standard enumerator members for IEnumFORMATETC
1747 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Reset(LPENUMFORMATETC iface)
1749 IEnumFORMATETCImpl *This = (IEnumFORMATETCImpl *)iface;
1750 TRACE("(%p)->()\n", This);
1752 This->posFmt = 0;
1753 return S_OK;
1756 /************************************************************************
1757 * OLEClipbrd_IEnumFORMATETC_Clone (IEnumFORMATETC)
1759 * Standard enumerator members for IEnumFORMATETC
1761 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Clone
1762 (LPENUMFORMATETC iface, LPENUMFORMATETC* ppenum)
1764 IEnumFORMATETCImpl *This = (IEnumFORMATETCImpl *)iface;
1765 HRESULT hr = S_OK;
1767 TRACE("(%p)->(ppenum=%p)\n", This, ppenum);
1769 if ( !ppenum )
1770 return E_INVALIDARG;
1772 *ppenum = OLEClipbrd_IEnumFORMATETC_Construct(This->countFmt,
1773 This->pFmt,
1774 This->pUnkDataObj);
1776 if (FAILED( hr = IEnumFORMATETC_AddRef(*ppenum)))
1777 return ( hr );
1779 return (*ppenum) ? S_OK : E_OUTOFMEMORY;