Get rid of the no longer used ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
[wine/multimedia.git] / dlls / ole32 / clipboard.c
blob2a7b756a8c18f4309cfe7ef1dcb095dc23e3d3de
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 NONAMELESSUNION
66 #define NONAMELESSSTRUCT
67 #include "windef.h"
68 #include "winbase.h"
69 #include "wingdi.h"
70 #include "winuser.h"
71 #include "winerror.h"
72 #include "winnls.h"
73 #include "ole2.h"
74 #include "wine/debug.h"
75 #include "olestd.h"
77 #include "storage32.h"
79 #define HANDLE_ERROR(err) { hr = err; TRACE("(HRESULT=%lx)\n", (HRESULT)err); goto CLEANUP; }
81 /* For CoGetMalloc (MEMCTX_TASK is currently ignored) */
82 #ifndef MEMCTX_TASK
83 #define MEMCTX_TASK -1
84 #endif
86 WINE_DEFAULT_DEBUG_CHANNEL(ole);
88 /****************************************************************************
89 * OLEClipbrd
90 * DO NOT add any members before the VTables declaration!
92 struct OLEClipbrd
95 * List all interface VTables here
97 IDataObjectVtbl* lpvtbl1; /* IDataObject VTable */
100 * The hidden OLE clipboard window. This window is used as the bridge between the
101 * the OLE and windows clipboard API. (Windows creates one such window per process)
103 HWND hWndClipboard;
106 * Pointer to the source data object (via OleSetClipboard)
108 IDataObject* pIDataObjectSrc;
111 * The registered DataObject clipboard format
113 UINT cfDataObj;
116 * The handle to ourself
118 HGLOBAL hSelf;
121 * Reference count of this object
123 ULONG ref;
126 typedef struct OLEClipbrd OLEClipbrd;
129 /****************************************************************************
130 * IEnumFORMATETC implementation
131 * DO NOT add any members before the VTables declaration!
133 typedef struct
135 /* IEnumFORMATETC VTable */
136 IEnumFORMATETCVtbl *lpVtbl;
138 /* IEnumFORMATETC fields */
139 UINT posFmt; /* current enumerator position */
140 UINT countFmt; /* number of EnumFORMATETC's in array */
141 LPFORMATETC pFmt; /* array of EnumFORMATETC's */
144 * Reference count of this object
146 DWORD ref;
149 * IUnknown implementation of the parent data object.
151 IUnknown* pUnkDataObj;
153 } IEnumFORMATETCImpl;
155 typedef struct PresentationDataHeader
157 BYTE unknown1[28];
158 DWORD dwObjectExtentX;
159 DWORD dwObjectExtentY;
160 DWORD dwSize;
161 } PresentationDataHeader;
164 * The one and only OLEClipbrd object which is created by OLEClipbrd_Initialize()
166 static HGLOBAL hTheOleClipboard = 0;
167 static OLEClipbrd* theOleClipboard = NULL;
171 * Prototypes for the methods of the OLEClipboard class.
173 extern void OLEClipbrd_Initialize();
174 extern void OLEClipbrd_UnInitialize();
175 static OLEClipbrd* OLEClipbrd_Construct();
176 static void OLEClipbrd_Destroy(OLEClipbrd* ptrToDestroy);
177 static HWND OLEClipbrd_CreateWindow();
178 static void OLEClipbrd_DestroyWindow(HWND hwnd);
179 LRESULT CALLBACK OLEClipbrd_WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
180 static HRESULT OLEClipbrd_RenderFormat( IDataObject *pIDataObject, LPFORMATETC pFormatetc );
181 static HGLOBAL OLEClipbrd_GlobalDupMem( HGLOBAL hGlobalSrc );
184 * Prototypes for the methods of the OLEClipboard class
185 * that implement IDataObject methods.
187 static HRESULT WINAPI OLEClipbrd_IDataObject_QueryInterface(
188 IDataObject* iface,
189 REFIID riid,
190 void** ppvObject);
191 static ULONG WINAPI OLEClipbrd_IDataObject_AddRef(
192 IDataObject* iface);
193 static ULONG WINAPI OLEClipbrd_IDataObject_Release(
194 IDataObject* iface);
195 static HRESULT WINAPI OLEClipbrd_IDataObject_GetData(
196 IDataObject* iface,
197 LPFORMATETC pformatetcIn,
198 STGMEDIUM* pmedium);
199 static HRESULT WINAPI OLEClipbrd_IDataObject_GetDataHere(
200 IDataObject* iface,
201 LPFORMATETC pformatetc,
202 STGMEDIUM* pmedium);
203 static HRESULT WINAPI OLEClipbrd_IDataObject_QueryGetData(
204 IDataObject* iface,
205 LPFORMATETC pformatetc);
206 static HRESULT WINAPI OLEClipbrd_IDataObject_GetCanonicalFormatEtc(
207 IDataObject* iface,
208 LPFORMATETC pformatectIn,
209 LPFORMATETC pformatetcOut);
210 static HRESULT WINAPI OLEClipbrd_IDataObject_SetData(
211 IDataObject* iface,
212 LPFORMATETC pformatetc,
213 STGMEDIUM* pmedium,
214 BOOL fRelease);
215 static HRESULT WINAPI OLEClipbrd_IDataObject_EnumFormatEtc(
216 IDataObject* iface,
217 DWORD dwDirection,
218 IEnumFORMATETC** ppenumFormatEtc);
219 static HRESULT WINAPI OLEClipbrd_IDataObject_DAdvise(
220 IDataObject* iface,
221 FORMATETC* pformatetc,
222 DWORD advf,
223 IAdviseSink* pAdvSink,
224 DWORD* pdwConnection);
225 static HRESULT WINAPI OLEClipbrd_IDataObject_DUnadvise(
226 IDataObject* iface,
227 DWORD dwConnection);
228 static HRESULT WINAPI OLEClipbrd_IDataObject_EnumDAdvise(
229 IDataObject* iface,
230 IEnumSTATDATA** ppenumAdvise);
233 * Prototypes for the IEnumFORMATETC methods.
235 static LPENUMFORMATETC OLEClipbrd_IEnumFORMATETC_Construct(UINT cfmt, const FORMATETC afmt[],
236 LPUNKNOWN pUnkDataObj);
237 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_QueryInterface(LPENUMFORMATETC iface, REFIID riid,
238 LPVOID* ppvObj);
239 static ULONG WINAPI OLEClipbrd_IEnumFORMATETC_AddRef(LPENUMFORMATETC iface);
240 static ULONG WINAPI OLEClipbrd_IEnumFORMATETC_Release(LPENUMFORMATETC iface);
241 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Next(LPENUMFORMATETC iface, ULONG celt,
242 FORMATETC* rgelt, ULONG* pceltFethed);
243 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Skip(LPENUMFORMATETC iface, ULONG celt);
244 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Reset(LPENUMFORMATETC iface);
245 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Clone(LPENUMFORMATETC iface, LPENUMFORMATETC* ppenum);
249 * Virtual function table for the OLEClipbrd's exposed IDataObject interface
251 static IDataObjectVtbl OLEClipbrd_IDataObject_VTable =
253 OLEClipbrd_IDataObject_QueryInterface,
254 OLEClipbrd_IDataObject_AddRef,
255 OLEClipbrd_IDataObject_Release,
256 OLEClipbrd_IDataObject_GetData,
257 OLEClipbrd_IDataObject_GetDataHere,
258 OLEClipbrd_IDataObject_QueryGetData,
259 OLEClipbrd_IDataObject_GetCanonicalFormatEtc,
260 OLEClipbrd_IDataObject_SetData,
261 OLEClipbrd_IDataObject_EnumFormatEtc,
262 OLEClipbrd_IDataObject_DAdvise,
263 OLEClipbrd_IDataObject_DUnadvise,
264 OLEClipbrd_IDataObject_EnumDAdvise
268 * Virtual function table for IEnumFORMATETC interface
270 static struct IEnumFORMATETCVtbl efvt =
272 OLEClipbrd_IEnumFORMATETC_QueryInterface,
273 OLEClipbrd_IEnumFORMATETC_AddRef,
274 OLEClipbrd_IEnumFORMATETC_Release,
275 OLEClipbrd_IEnumFORMATETC_Next,
276 OLEClipbrd_IEnumFORMATETC_Skip,
277 OLEClipbrd_IEnumFORMATETC_Reset,
278 OLEClipbrd_IEnumFORMATETC_Clone
282 * Name of our registered OLE clipboard window class
284 CHAR OLEClipbrd_WNDCLASS[] = "CLIPBRDWNDCLASS";
287 * If we need to store state info we can store it here.
288 * For now we don't need this functionality.
290 typedef struct tagClipboardWindowInfo
292 } ClipboardWindowInfo;
295 /*---------------------------------------------------------------------*
296 * Win32 OLE clipboard API
297 *---------------------------------------------------------------------*/
299 /***********************************************************************
300 * OleSetClipboard [OLE32.@]
301 * Places a pointer to the specified data object onto the clipboard,
302 * making the data object accessible to the OleGetClipboard function.
304 * RETURNS:
306 * S_OK IDataObject pointer placed on the clipboard
307 * CLIPBRD_E_CANT_OPEN OpenClipboard failed
308 * CLIPBRD_E_CANT_EMPTY EmptyClipboard failed
309 * CLIPBRD_E_CANT_CLOSE CloseClipboard failed
310 * CLIPBRD_E_CANT_SET SetClipboard failed
313 HRESULT WINAPI OleSetClipboard(IDataObject* pDataObj)
315 HRESULT hr = S_OK;
316 IEnumFORMATETC* penumFormatetc = NULL;
317 FORMATETC rgelt;
318 BOOL bClipboardOpen = FALSE;
320 HGLOBAL hDataObject = 0;
321 OLEClipbrd **ppDataObject;
324 TRACE("(%p)\n", pDataObj);
327 * Make sure we have a clipboard object
329 OLEClipbrd_Initialize();
332 * If the Ole clipboard window hasn't been created yet, create it now.
334 if ( !theOleClipboard->hWndClipboard )
335 theOleClipboard->hWndClipboard = OLEClipbrd_CreateWindow();
337 if ( !theOleClipboard->hWndClipboard ) /* sanity check */
338 HANDLE_ERROR( E_FAIL );
341 * Open the Windows clipboard, associating it with our hidden window
343 if ( !(bClipboardOpen = OpenClipboard(theOleClipboard->hWndClipboard)) )
344 HANDLE_ERROR( CLIPBRD_E_CANT_OPEN );
347 * Empty the current clipboard and make our window the clipboard owner
348 * NOTE: This will trigger a WM_DESTROYCLIPBOARD message
350 if ( !EmptyClipboard() )
351 HANDLE_ERROR( CLIPBRD_E_CANT_EMPTY );
354 * If we are already holding on to an IDataObject first release that.
356 if ( theOleClipboard->pIDataObjectSrc )
358 IDataObject_Release(theOleClipboard->pIDataObjectSrc);
359 theOleClipboard->pIDataObjectSrc = NULL;
363 * AddRef the data object passed in and save its pointer.
364 * A NULL value indicates that the clipboard should be emptied.
366 theOleClipboard->pIDataObjectSrc = pDataObj;
367 if ( pDataObj )
369 IDataObject_AddRef(theOleClipboard->pIDataObjectSrc);
373 * Enumerate all HGLOBAL formats supported by the source and make
374 * those formats available using delayed rendering using SetClipboardData.
375 * Only global memory based data items may be made available to non-OLE
376 * applications via the standard Windows clipboard API. Data based on other
377 * mediums(non TYMED_HGLOBAL) can only be accessed via the Ole Clipboard API.
379 * TODO: Do we need to additionally handle TYMED_IStorage media by copying
380 * the storage into global memory?
382 if ( pDataObj )
384 if ( FAILED(hr = IDataObject_EnumFormatEtc( pDataObj,
385 DATADIR_GET,
386 &penumFormatetc )))
388 HANDLE_ERROR( hr );
391 while ( S_OK == IEnumFORMATETC_Next(penumFormatetc, 1, &rgelt, NULL) )
393 if ( rgelt.tymed == TYMED_HGLOBAL )
395 CHAR szFmtName[80];
396 TRACE("(cfFormat=%d:%s)\n", rgelt.cfFormat,
397 GetClipboardFormatNameA(rgelt.cfFormat, szFmtName, sizeof(szFmtName)-1)
398 ? szFmtName : "");
400 SetClipboardData( rgelt.cfFormat, NULL);
403 IEnumFORMATETC_Release(penumFormatetc);
407 * Windows additionally creates a new "DataObject" clipboard format
408 * and stores in on the clipboard. We could possibly store a pointer
409 * to our internal IDataObject interface on the clipboard. I'm not
410 * sure what the use of this is though.
411 * Enable the code below for this functionality.
414 theOleClipboard->cfDataObj = RegisterClipboardFormatA("DataObject");
415 hDataObject = GlobalAlloc( GMEM_DDESHARE|GMEM_MOVEABLE|GMEM_ZEROINIT,
416 sizeof(OLEClipbrd *));
417 if (hDataObject==0)
418 HANDLE_ERROR( E_OUTOFMEMORY );
420 ppDataObject = (OLEClipbrd**)GlobalLock(hDataObject);
421 *ppDataObject = theOleClipboard;
422 GlobalUnlock(hDataObject);
424 if ( !SetClipboardData( theOleClipboard->cfDataObj, hDataObject ) )
425 HANDLE_ERROR( CLIPBRD_E_CANT_SET );
428 hr = S_OK;
430 CLEANUP:
433 * Close Windows clipboard (It remains associated with our window)
435 if ( bClipboardOpen && !CloseClipboard() )
436 hr = CLIPBRD_E_CANT_CLOSE;
439 * Release the source IDataObject if something failed
441 if ( FAILED(hr) )
443 if (theOleClipboard->pIDataObjectSrc)
445 IDataObject_Release(theOleClipboard->pIDataObjectSrc);
446 theOleClipboard->pIDataObjectSrc = NULL;
450 return hr;
454 /***********************************************************************
455 * OleGetClipboard [OLE32.@]
456 * Returns a pointer to our internal IDataObject which represents the conceptual
457 * state of the Windows clipboard. If the current clipboard already contains
458 * an IDataObject, our internal IDataObject will delegate to this object.
460 HRESULT WINAPI OleGetClipboard(IDataObject** ppDataObj)
462 HRESULT hr = S_OK;
463 TRACE("()\n");
466 * Make sure we have a clipboard object
468 OLEClipbrd_Initialize();
470 if (!theOleClipboard)
471 return E_OUTOFMEMORY;
473 /* Return a reference counted IDataObject */
474 hr = IDataObject_QueryInterface( (IDataObject*)&(theOleClipboard->lpvtbl1),
475 &IID_IDataObject, (void**)ppDataObj);
476 return hr;
479 /***********************************************************************
480 * OleFlushClipboard [OLE2.76]
483 HRESULT WINAPI OleFlushClipboard16(void)
485 return OleFlushClipboard();
489 /******************************************************************************
490 * OleFlushClipboard [OLE32.@]
491 * Renders the data from the source IDataObject into the windows clipboard
493 * TODO: OleFlushClipboard needs to additionally handle TYMED_IStorage media
494 * by copying the storage into global memory. Subsequently the default
495 * data object exposed through OleGetClipboard must convert this TYMED_HGLOBAL
496 * back to TYMED_IStorage.
498 HRESULT WINAPI OleFlushClipboard()
500 IEnumFORMATETC* penumFormatetc = NULL;
501 FORMATETC rgelt;
502 HRESULT hr = S_OK;
503 BOOL bClipboardOpen = FALSE;
504 IDataObject* pIDataObjectSrc = NULL;
506 TRACE("()\n");
509 * Make sure we have a clipboard object
511 OLEClipbrd_Initialize();
514 * Already flushed or no source DataObject? Nothing to do.
516 if (!theOleClipboard->pIDataObjectSrc)
517 return S_OK;
520 * Addref and save the source data object we are holding on to temporarily,
521 * since it will be released when we empty the clipboard.
523 pIDataObjectSrc = theOleClipboard->pIDataObjectSrc;
524 IDataObject_AddRef(pIDataObjectSrc);
527 * Open the Windows clipboard
529 if ( !(bClipboardOpen = OpenClipboard(theOleClipboard->hWndClipboard)) )
530 HANDLE_ERROR( CLIPBRD_E_CANT_OPEN );
533 * Empty the current clipboard
535 if ( !EmptyClipboard() )
536 HANDLE_ERROR( CLIPBRD_E_CANT_EMPTY );
539 * Render all HGLOBAL formats supported by the source into
540 * the windows clipboard.
542 if ( FAILED( hr = IDataObject_EnumFormatEtc( pIDataObjectSrc,
543 DATADIR_GET,
544 &penumFormatetc) ))
546 HANDLE_ERROR( hr );
549 while ( S_OK == IEnumFORMATETC_Next(penumFormatetc, 1, &rgelt, NULL) )
551 if ( rgelt.tymed == TYMED_HGLOBAL )
553 CHAR szFmtName[80];
554 TRACE("(cfFormat=%d:%s)\n", rgelt.cfFormat,
555 GetClipboardFormatNameA(rgelt.cfFormat, szFmtName, sizeof(szFmtName)-1)
556 ? szFmtName : "");
559 * Render the clipboard data
561 if ( FAILED(OLEClipbrd_RenderFormat( pIDataObjectSrc, &rgelt )) )
562 continue;
566 IEnumFORMATETC_Release(penumFormatetc);
569 * Release the source data object we are holding on to
571 IDataObject_Release(pIDataObjectSrc);
573 CLEANUP:
576 * Close Windows clipboard (It remains associated with our window)
578 if ( bClipboardOpen && !CloseClipboard() )
579 hr = CLIPBRD_E_CANT_CLOSE;
581 return hr;
585 /***********************************************************************
586 * OleIsCurrentClipboard [OLE32.@]
588 HRESULT WINAPI OleIsCurrentClipboard ( IDataObject *pDataObject)
590 TRACE("()\n");
592 * Make sure we have a clipboard object
594 OLEClipbrd_Initialize();
596 if (!theOleClipboard)
597 return E_OUTOFMEMORY;
599 return (pDataObject == theOleClipboard->pIDataObjectSrc) ? S_OK : S_FALSE;
603 /*---------------------------------------------------------------------*
604 * Internal implementation methods for the OLE clipboard
605 *---------------------------------------------------------------------*/
607 /***********************************************************************
608 * OLEClipbrd_Initialize()
609 * Initializes the OLE clipboard.
611 void OLEClipbrd_Initialize()
614 * Create the clipboard if necessary
616 if ( !theOleClipboard )
618 TRACE("()\n");
619 theOleClipboard = OLEClipbrd_Construct();
624 /***********************************************************************
625 * OLEClipbrd_UnInitialize()
626 * Un-Initializes the OLE clipboard
628 void OLEClipbrd_UnInitialize()
630 TRACE("()\n");
632 * Destroy the clipboard if no one holds a reference to us.
633 * Note that the clipboard was created with a reference count of 1.
635 if ( theOleClipboard && (theOleClipboard->ref <= 1) )
637 OLEClipbrd_Destroy( theOleClipboard );
639 else
641 WARN( "() : OLEClipbrd_UnInitialize called while client holds an IDataObject reference!\n");
646 /*********************************************************
647 * Construct the OLEClipbrd class.
649 static OLEClipbrd* OLEClipbrd_Construct()
651 OLEClipbrd* newObject = NULL;
652 HGLOBAL hNewObject = 0;
655 * Allocate space for the object. We use GlobalAlloc since we need
656 * an HGLOBAL to expose our DataObject as a registered clipboard type.
658 hNewObject = GlobalAlloc( GMEM_DDESHARE|GMEM_MOVEABLE|GMEM_ZEROINIT,
659 sizeof(OLEClipbrd));
660 if (hNewObject==0)
661 return NULL;
664 * Lock the handle for the entire lifetime of the clipboard.
666 newObject = GlobalLock(hNewObject);
669 * Initialize the virtual function table.
671 newObject->lpvtbl1 = &OLEClipbrd_IDataObject_VTable;
674 * Start with one reference count. The caller of this function
675 * must release the interface pointer when it is done.
677 newObject->ref = 1;
679 newObject->hSelf = hNewObject;
682 * The Ole clipboard is a singleton - save the global handle and pointer
684 theOleClipboard = newObject;
685 hTheOleClipboard = hNewObject;
687 return theOleClipboard;
690 static void OLEClipbrd_Destroy(OLEClipbrd* ptrToDestroy)
692 TRACE("()\n");
694 if ( !ptrToDestroy )
695 return;
698 * Destroy the Ole clipboard window
700 if ( ptrToDestroy->hWndClipboard )
701 OLEClipbrd_DestroyWindow(ptrToDestroy->hWndClipboard);
704 * Free the actual OLE Clipboard structure.
706 TRACE("() - Destroying clipboard data object.\n");
707 GlobalUnlock(ptrToDestroy->hSelf);
708 GlobalFree(ptrToDestroy->hSelf);
711 * The Ole clipboard is a singleton (ptrToDestroy == theOleClipboard)
713 theOleClipboard = NULL;
714 hTheOleClipboard = 0;
718 /***********************************************************************
719 * OLEClipbrd_CreateWindow()
720 * Create the clipboard window
722 static HWND OLEClipbrd_CreateWindow()
724 HWND hwnd = 0;
725 WNDCLASSEXA wcex;
728 * Register the clipboard window class if necessary
730 ZeroMemory( &wcex, sizeof(WNDCLASSEXA));
732 wcex.cbSize = sizeof(WNDCLASSEXA);
733 /* Windows creates this class with a style mask of 0
734 * We don't bother doing this since the FindClassByAtom code
735 * would have to be changed to deal with this idiosyncrasy. */
736 wcex.style = CS_GLOBALCLASS;
737 wcex.lpfnWndProc = (WNDPROC)OLEClipbrd_WndProc;
738 wcex.hInstance = 0;
739 wcex.lpszClassName = OLEClipbrd_WNDCLASS;
741 RegisterClassExA(&wcex);
744 * Create a hidden window to receive OLE clipboard messages
748 * If we need to store state info we can store it here.
749 * For now we don't need this functionality.
750 * ClipboardWindowInfo clipboardInfo;
751 * ZeroMemory( &trackerInfo, sizeof(ClipboardWindowInfo));
754 hwnd = CreateWindowA(OLEClipbrd_WNDCLASS,
755 "ClipboardWindow",
756 WS_POPUP | WS_CLIPSIBLINGS | WS_OVERLAPPED,
757 CW_USEDEFAULT, CW_USEDEFAULT,
758 CW_USEDEFAULT, CW_USEDEFAULT,
762 0 /*(LPVOID)&clipboardInfo */);
764 return hwnd;
767 /***********************************************************************
768 * OLEClipbrd_DestroyWindow(HWND)
769 * Destroy the clipboard window and unregister its class
771 static void OLEClipbrd_DestroyWindow(HWND hwnd)
774 * Destroy clipboard window and unregister its WNDCLASS
776 DestroyWindow(hwnd);
777 UnregisterClassA( OLEClipbrd_WNDCLASS, 0 );
780 /***********************************************************************
781 * OLEClipbrd_WndProc(HWND, unsigned, WORD, LONG)
782 * Processes messages sent to the OLE clipboard window.
783 * Note that we will intercept messages in our WndProc only when data
784 * has been placed in the clipboard via OleSetClipboard().
785 * i.e. Only when OLE owns the windows clipboard.
787 LRESULT CALLBACK OLEClipbrd_WndProc
788 (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
790 switch (message)
793 * WM_RENDERFORMAT
794 * We receive this message to allow us to handle delayed rendering of
795 * a specific clipboard format when an application requests data in
796 * that format by calling GetClipboardData.
797 * (Recall that in OleSetClipboard, we used SetClipboardData to
798 * make all HGLOBAL formats supported by the source IDataObject
799 * available using delayed rendering)
800 * On receiving this mesage we must actually render the data in the
801 * specified format and place it on the clipboard by calling the
802 * SetClipboardData function.
804 case WM_RENDERFORMAT:
806 FORMATETC rgelt;
808 ZeroMemory( &rgelt, sizeof(FORMATETC));
811 * Initialize FORMATETC to a Windows clipboard friendly format
813 rgelt.cfFormat = (UINT) wParam;
814 rgelt.dwAspect = DVASPECT_CONTENT;
815 rgelt.lindex = -1;
816 rgelt.tymed = TYMED_HGLOBAL;
818 TRACE("(): WM_RENDERFORMAT(cfFormat=%d)\n", rgelt.cfFormat);
821 * Render the clipboard data.
822 * (We must have a source data object or we wouldn't be in this WndProc)
824 OLEClipbrd_RenderFormat( (IDataObject*)&(theOleClipboard->lpvtbl1), &rgelt );
826 break;
830 * WM_RENDERALLFORMATS
831 * Sent before the clipboard owner window is destroyed.
832 * We should receive this message only when OleUninitialize is called
833 * while we have an IDataObject in the clipboard.
834 * For the content of the clipboard to remain available to other
835 * applications, we must render data in all the formats the source IDataObject
836 * is capable of generating, and place the data on the clipboard by calling
837 * SetClipboardData.
839 case WM_RENDERALLFORMATS:
841 IEnumFORMATETC* penumFormatetc = NULL;
842 FORMATETC rgelt;
844 TRACE("(): WM_RENDERALLFORMATS\n");
847 * Render all HGLOBAL formats supported by the source into
848 * the windows clipboard.
850 if ( FAILED( IDataObject_EnumFormatEtc( (IDataObject*)&(theOleClipboard->lpvtbl1),
851 DATADIR_GET, &penumFormatetc) ) )
853 WARN("(): WM_RENDERALLFORMATS failed to retrieve EnumFormatEtc!\n");
854 return 0;
857 while ( S_OK == IEnumFORMATETC_Next(penumFormatetc, 1, &rgelt, NULL) )
859 if ( rgelt.tymed == TYMED_HGLOBAL )
862 * Render the clipboard data.
864 if ( FAILED(OLEClipbrd_RenderFormat( (IDataObject*)&(theOleClipboard->lpvtbl1), &rgelt )) )
865 continue;
867 TRACE("(): WM_RENDERALLFORMATS(cfFormat=%d)\n", rgelt.cfFormat);
871 IEnumFORMATETC_Release(penumFormatetc);
873 break;
877 * WM_DESTROYCLIPBOARD
878 * This is sent by EmptyClipboard before the clipboard is emptied.
879 * We should release any IDataObject we are holding onto when we receive
880 * this message, since it indicates that the OLE clipboard should be empty
881 * from this point on.
883 case WM_DESTROYCLIPBOARD:
885 TRACE("(): WM_DESTROYCLIPBOARD\n");
887 * Release the data object we are holding on to
889 if ( theOleClipboard->pIDataObjectSrc )
891 IDataObject_Release(theOleClipboard->pIDataObjectSrc);
892 theOleClipboard->pIDataObjectSrc = NULL;
894 break;
898 case WM_ASKCBFORMATNAME:
899 case WM_CHANGECBCHAIN:
900 case WM_DRAWCLIPBOARD:
901 case WM_SIZECLIPBOARD:
902 case WM_HSCROLLCLIPBOARD:
903 case WM_VSCROLLCLIPBOARD:
904 case WM_PAINTCLIPBOARD:
906 default:
907 return DefWindowProcA(hWnd, message, wParam, lParam);
910 return 0;
913 #define MAX_CLIPFORMAT_NAME 80
915 /***********************************************************************
916 * OLEClipbrd_RenderFormat(LPFORMATETC)
917 * Render the clipboard data. Note that this call will delegate to the
918 * source data object.
919 * Note: This function assumes it is passed an HGLOBAL format to render.
921 static HRESULT OLEClipbrd_RenderFormat(IDataObject *pIDataObject, LPFORMATETC pFormatetc)
923 STGMEDIUM std;
924 HGLOBAL hDup;
925 HRESULT hr = S_OK;
926 char szFmtName[MAX_CLIPFORMAT_NAME];
927 ILockBytes *ptrILockBytes = 0;
928 HGLOBAL hStorage = 0;
930 GetClipboardFormatNameA(pFormatetc->cfFormat, szFmtName, MAX_CLIPFORMAT_NAME);
932 /* If embed source */
933 if (!strcmp(szFmtName, CF_EMBEDSOURCE))
935 memset(&std, 0, sizeof(STGMEDIUM));
936 std.tymed = pFormatetc->tymed = TYMED_ISTORAGE;
938 hStorage = GlobalAlloc(GMEM_SHARE|GMEM_MOVEABLE, 0);
939 hr = CreateILockBytesOnHGlobal(hStorage, FALSE, &ptrILockBytes);
940 hr = StgCreateDocfileOnILockBytes(ptrILockBytes, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &std.u.pstg);
942 if (FAILED(hr = IDataObject_GetDataHere(theOleClipboard->pIDataObjectSrc, pFormatetc, &std)))
944 WARN("() : IDataObject_GetDataHere failed to render clipboard data! (%lx)\n", hr);
945 return hr;
948 if (1) /* check whether the presentation data is already -not- present */
950 FORMATETC fmt2;
951 STGMEDIUM std2;
952 METAFILEPICT *mfp = 0;
954 fmt2.cfFormat = CF_METAFILEPICT;
955 fmt2.ptd = 0;
956 fmt2.dwAspect = DVASPECT_CONTENT;
957 fmt2.lindex = -1;
958 fmt2.tymed = TYMED_MFPICT;
960 memset(&std2, 0, sizeof(STGMEDIUM));
961 std2.tymed = TYMED_MFPICT;
963 /* Get the metafile picture out of it */
965 if (!FAILED(hr = IDataObject_GetData(theOleClipboard->pIDataObjectSrc, &fmt2, &std2)))
967 mfp = (METAFILEPICT *)GlobalLock(std2.u.hGlobal);
970 if (mfp)
972 OLECHAR name[]={ 2, 'O', 'l', 'e', 'P', 'r', 'e', 's', '0', '0', '0', 0};
973 IStream *pStream = 0;
974 void *mfBits;
975 PresentationDataHeader pdh;
976 INT nSize;
977 CLSID clsID;
978 LPOLESTR strProgID;
979 CHAR strOleTypeName[51];
980 BYTE OlePresStreamHeader [] =
982 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00,
983 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
984 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
985 0x00, 0x00, 0x00, 0x00
988 nSize = GetMetaFileBitsEx(mfp->hMF, 0, NULL);
990 memset(&pdh, 0, sizeof(PresentationDataHeader));
991 memcpy(&pdh, OlePresStreamHeader, sizeof(OlePresStreamHeader));
993 pdh.dwObjectExtentX = mfp->xExt;
994 pdh.dwObjectExtentY = mfp->yExt;
995 pdh.dwSize = nSize;
997 hr = IStorage_CreateStream(std.u.pstg, name, STGM_CREATE|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, 0, &pStream);
999 hr = IStream_Write(pStream, &pdh, sizeof(PresentationDataHeader), NULL);
1001 mfBits = HeapAlloc(GetProcessHeap(), 0, nSize);
1002 nSize = GetMetaFileBitsEx(mfp->hMF, nSize, mfBits);
1004 hr = IStream_Write(pStream, mfBits, nSize, NULL);
1006 IStream_Release(pStream);
1008 HeapFree(GetProcessHeap(), 0, mfBits);
1010 GlobalUnlock(std2.u.hGlobal);
1012 ReadClassStg(std.u.pstg, &clsID);
1013 ProgIDFromCLSID(&clsID, &strProgID);
1015 WideCharToMultiByte( CP_ACP, 0, strProgID, -1, strOleTypeName, sizeof(strOleTypeName), NULL, NULL );
1016 OLECONVERT_CreateOleStream(std.u.pstg);
1017 OLECONVERT_CreateCompObjStream(std.u.pstg, strOleTypeName);
1021 else
1023 if (FAILED(hr = IDataObject_GetData(pIDataObject, pFormatetc, &std)))
1025 WARN("() : IDataObject_GetData failed to render clipboard data! (%lx)\n", hr);
1026 return hr;
1029 /* To put a copy back on the clipboard */
1031 hStorage = std.u.hGlobal;
1035 * Put a copy of the rendered data back on the clipboard
1038 if ( !(hDup = OLEClipbrd_GlobalDupMem(hStorage)) )
1039 HANDLE_ERROR( E_OUTOFMEMORY );
1041 if ( !SetClipboardData( pFormatetc->cfFormat, hDup ) )
1043 GlobalFree(hDup);
1044 WARN("() : Failed to set rendered clipboard data into clipboard!\n");
1047 CLEANUP:
1049 ReleaseStgMedium(&std);
1051 return hr;
1055 /***********************************************************************
1056 * OLEClipbrd_GlobalDupMem( HGLOBAL )
1057 * Helper method to duplicate an HGLOBAL chunk of memory
1059 static HGLOBAL OLEClipbrd_GlobalDupMem( HGLOBAL hGlobalSrc )
1061 HGLOBAL hGlobalDest;
1062 PVOID pGlobalSrc, pGlobalDest;
1063 DWORD cBytes;
1065 if ( !hGlobalSrc )
1066 return 0;
1068 cBytes = GlobalSize(hGlobalSrc);
1069 if ( 0 == cBytes )
1070 return 0;
1072 hGlobalDest = GlobalAlloc( GMEM_DDESHARE|GMEM_MOVEABLE,
1073 cBytes );
1074 if ( !hGlobalDest )
1075 return 0;
1077 pGlobalSrc = GlobalLock(hGlobalSrc);
1078 pGlobalDest = GlobalLock(hGlobalDest);
1079 if ( !pGlobalSrc || !pGlobalDest )
1080 return 0;
1082 memcpy(pGlobalDest, pGlobalSrc, cBytes);
1084 GlobalUnlock(hGlobalSrc);
1085 GlobalUnlock(hGlobalDest);
1087 return hGlobalDest;
1091 /*---------------------------------------------------------------------*
1092 * Implementation of the internal IDataObject interface exposed by
1093 * the OLE clipboard.
1094 *---------------------------------------------------------------------*/
1097 /************************************************************************
1098 * OLEClipbrd_IDataObject_QueryInterface (IUnknown)
1100 * See Windows documentation for more details on IUnknown methods.
1102 static HRESULT WINAPI OLEClipbrd_IDataObject_QueryInterface(
1103 IDataObject* iface,
1104 REFIID riid,
1105 void** ppvObject)
1108 * Declare "This" pointer
1110 ICOM_THIS(OLEClipbrd, iface);
1111 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObject);
1114 * Perform a sanity check on the parameters.
1116 if ( (This==0) || (ppvObject==0) )
1117 return E_INVALIDARG;
1120 * Initialize the return parameter.
1122 *ppvObject = 0;
1125 * Compare the riid with the interface IDs implemented by this object.
1127 if (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0)
1129 *ppvObject = iface;
1131 else if (memcmp(&IID_IDataObject, riid, sizeof(IID_IDataObject)) == 0)
1133 *ppvObject = (IDataObject*)&(This->lpvtbl1);
1135 else /* We only support IUnknown and IDataObject */
1137 WARN( "() : asking for unsupported interface %s\n", debugstr_guid(riid));
1138 return E_NOINTERFACE;
1142 * Query Interface always increases the reference count by one when it is
1143 * successful.
1145 IUnknown_AddRef((IUnknown*)*ppvObject);
1147 return S_OK;
1150 /************************************************************************
1151 * OLEClipbrd_IDataObject_AddRef (IUnknown)
1153 * See Windows documentation for more details on IUnknown methods.
1155 static ULONG WINAPI OLEClipbrd_IDataObject_AddRef(
1156 IDataObject* iface)
1159 * Declare "This" pointer
1161 ICOM_THIS(OLEClipbrd, iface);
1163 TRACE("(%p)->(count=%lu)\n",This, This->ref);
1165 This->ref++;
1167 return This->ref;
1170 /************************************************************************
1171 * OLEClipbrd_IDataObject_Release (IUnknown)
1173 * See Windows documentation for more details on IUnknown methods.
1175 static ULONG WINAPI OLEClipbrd_IDataObject_Release(
1176 IDataObject* iface)
1179 * Declare "This" pointer
1181 ICOM_THIS(OLEClipbrd, iface);
1183 TRACE("(%p)->(count=%lu)\n",This, This->ref);
1186 * Decrease the reference count on this object.
1188 This->ref--;
1191 * If the reference count goes down to 0, perform suicide.
1193 if (This->ref==0)
1195 OLEClipbrd_Destroy(This);
1198 return This->ref;
1202 /************************************************************************
1203 * OLEClipbrd_IDataObject_GetData (IDataObject)
1205 * The OLE Clipboard's implementation of this method delegates to
1206 * a data source if there is one or wraps around the windows clipboard
1208 * See Windows documentation for more details on IDataObject methods.
1210 static HRESULT WINAPI OLEClipbrd_IDataObject_GetData(
1211 IDataObject* iface,
1212 LPFORMATETC pformatetcIn,
1213 STGMEDIUM* pmedium)
1215 HANDLE hData = 0;
1216 BOOL bClipboardOpen = FALSE;
1217 HRESULT hr = S_OK;
1218 LPVOID src;
1221 * Declare "This" pointer
1223 ICOM_THIS(OLEClipbrd, iface);
1225 TRACE("(%p,%p,%p)\n", iface, pformatetcIn, pmedium);
1227 if ( !pformatetcIn || !pmedium )
1228 return E_INVALIDARG;
1231 * If we have a data source placed on the clipboard (via OleSetClipboard)
1232 * simply delegate to the source object's QueryGetData
1233 * NOTE: This code assumes that the IDataObject is in the same address space!
1234 * We will need to add marshalling support when Wine handles multiple processes.
1236 if ( This->pIDataObjectSrc )
1238 return IDataObject_GetData(This->pIDataObjectSrc, pformatetcIn, pmedium);
1241 if ( pformatetcIn->lindex != -1 )
1242 return DV_E_LINDEX;
1243 if ( (pformatetcIn->tymed & TYMED_HGLOBAL) != TYMED_HGLOBAL )
1244 return DV_E_TYMED;
1246 if ( pformatetcIn->dwAspect != DVASPECT_CONTENT )
1247 return DV_E_DVASPECT;
1251 * Otherwise, get the data from the windows clipboard using GetClipboardData
1253 if ( !(bClipboardOpen = OpenClipboard(theOleClipboard->hWndClipboard)) )
1254 HANDLE_ERROR( CLIPBRD_E_CANT_OPEN );
1256 hData = GetClipboardData(pformatetcIn->cfFormat);
1258 /* Must make a copy of global handle returned by GetClipboardData; it
1259 * is not valid after we call CloseClipboard
1260 * Application is responsible for freeing the memory (Forte Agent does this)
1262 src = GlobalLock(hData);
1263 if(src) {
1264 LPVOID dest;
1265 ULONG size;
1266 HANDLE hDest;
1268 size = GlobalSize(hData);
1269 hDest = GlobalAlloc(GHND, size);
1270 dest = GlobalLock(hDest);
1271 memcpy(dest, src, size);
1272 GlobalUnlock(hDest);
1273 GlobalUnlock(hData);
1274 hData = hDest;
1278 * Return the clipboard data in the storage medium structure
1280 pmedium->tymed = (hData == 0) ? TYMED_NULL : TYMED_HGLOBAL;
1281 pmedium->u.hGlobal = (HGLOBAL)hData;
1282 pmedium->pUnkForRelease = NULL;
1284 hr = S_OK;
1286 CLEANUP:
1288 * Close Windows clipboard
1290 if ( bClipboardOpen && !CloseClipboard() )
1291 hr = CLIPBRD_E_CANT_CLOSE;
1293 if ( FAILED(hr) )
1294 return hr;
1295 return (hData == 0) ? DV_E_FORMATETC : S_OK;
1298 static HRESULT WINAPI OLEClipbrd_IDataObject_GetDataHere(
1299 IDataObject* iface,
1300 LPFORMATETC pformatetc,
1301 STGMEDIUM* pmedium)
1303 FIXME(": Stub\n");
1304 return E_NOTIMPL;
1307 /************************************************************************
1308 * OLEClipbrd_IDataObject_QueryGetData (IDataObject)
1310 * The OLE Clipboard's implementation of this method delegates to
1311 * a data source if there is one or wraps around the windows clipboard
1312 * function IsClipboardFormatAvailable() otherwise.
1314 * See Windows documentation for more details on IDataObject methods.
1316 static HRESULT WINAPI OLEClipbrd_IDataObject_QueryGetData(
1317 IDataObject* iface,
1318 LPFORMATETC pformatetc)
1321 * Declare "This" pointer
1323 ICOM_THIS(OLEClipbrd, iface);
1325 TRACE("(%p, %p)\n", iface, pformatetc);
1328 * If we have a data source placed on the clipboard (via OleSetClipboard)
1329 * simply delegate to the source object's QueryGetData
1331 if ( This->pIDataObjectSrc )
1333 return IDataObject_QueryGetData(This->pIDataObjectSrc, pformatetc);
1336 if (!pformatetc)
1337 return E_INVALIDARG;
1339 if ( pformatetc->dwAspect != DVASPECT_CONTENT )
1340 return DV_E_DVASPECT;
1342 if ( pformatetc->lindex != -1 )
1343 return DV_E_LINDEX;
1345 /* TODO: Handle TYMED_IStorage media which were put on the clipboard
1346 * by copying the storage into global memory. We must convert this
1347 * TYMED_HGLOBAL back to TYMED_IStorage.
1349 if ( pformatetc->tymed != TYMED_HGLOBAL )
1350 return DV_E_TYMED;
1353 * Delegate to the Windows clipboard function IsClipboardFormatAvailable
1355 return (IsClipboardFormatAvailable(pformatetc->cfFormat)) ? S_OK : DV_E_FORMATETC;
1358 /************************************************************************
1359 * OLEClipbrd_IDataObject_GetCanonicalFormatEtc (IDataObject)
1361 * See Windows documentation for more details on IDataObject methods.
1363 static HRESULT WINAPI OLEClipbrd_IDataObject_GetCanonicalFormatEtc(
1364 IDataObject* iface,
1365 LPFORMATETC pformatectIn,
1366 LPFORMATETC pformatetcOut)
1368 TRACE("(%p, %p, %p)\n", iface, pformatectIn, pformatetcOut);
1370 if ( !pformatectIn || !pformatetcOut )
1371 return E_INVALIDARG;
1373 memcpy(pformatetcOut, pformatectIn, sizeof(FORMATETC));
1374 return DATA_S_SAMEFORMATETC;
1377 /************************************************************************
1378 * OLEClipbrd_IDataObject_SetData (IDataObject)
1380 * The OLE Clipboard's does not implement this method
1382 * See Windows documentation for more details on IDataObject methods.
1384 static HRESULT WINAPI OLEClipbrd_IDataObject_SetData(
1385 IDataObject* iface,
1386 LPFORMATETC pformatetc,
1387 STGMEDIUM* pmedium,
1388 BOOL fRelease)
1390 TRACE("\n");
1391 return E_NOTIMPL;
1394 /************************************************************************
1395 * OLEClipbrd_IDataObject_EnumFormatEtc (IDataObject)
1397 * See Windows documentation for more details on IDataObject methods.
1399 static HRESULT WINAPI OLEClipbrd_IDataObject_EnumFormatEtc(
1400 IDataObject* iface,
1401 DWORD dwDirection,
1402 IEnumFORMATETC** ppenumFormatEtc)
1404 HRESULT hr = S_OK;
1405 FORMATETC *afmt = NULL;
1406 int cfmt, i;
1407 UINT format;
1408 BOOL bClipboardOpen;
1411 * Declare "This" pointer
1413 ICOM_THIS(OLEClipbrd, iface);
1415 TRACE("(%p, %lx, %p)\n", iface, dwDirection, ppenumFormatEtc);
1418 * If we have a data source placed on the clipboard (via OleSetClipboard)
1419 * simply delegate to the source object's EnumFormatEtc
1421 if ( This->pIDataObjectSrc )
1423 return IDataObject_EnumFormatEtc(This->pIDataObjectSrc,
1424 dwDirection, ppenumFormatEtc);
1428 * Otherwise we must provide our own enumerator which wraps around the
1429 * Windows clipboard function EnumClipboardFormats
1431 if ( !ppenumFormatEtc )
1432 return E_INVALIDARG;
1434 if ( dwDirection != DATADIR_GET ) /* IDataObject_SetData not implemented */
1435 return E_NOTIMPL;
1438 * Store all current clipboard formats in an array of FORMATETC's,
1439 * and create an IEnumFORMATETC enumerator from this list.
1441 cfmt = CountClipboardFormats();
1442 afmt = (FORMATETC *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1443 sizeof(FORMATETC) * cfmt);
1445 * Open the Windows clipboard, associating it with our hidden window
1447 if ( !(bClipboardOpen = OpenClipboard(This->hWndClipboard)) )
1448 HANDLE_ERROR( CLIPBRD_E_CANT_OPEN );
1451 * Store all current clipboard formats in an array of FORMATETC's
1452 * TODO: Handle TYMED_IStorage media which were put on the clipboard
1453 * by copying the storage into global memory. We must convert this
1454 * TYMED_HGLOBAL back to TYMED_IStorage.
1456 for (i = 0, format = 0; i < cfmt; i++)
1458 format = EnumClipboardFormats(format);
1459 if (!format) /* Failed! */
1461 ERR("EnumClipboardFormats failed to return format!\n");
1462 HANDLE_ERROR( E_FAIL );
1465 /* Init the FORMATETC struct */
1466 afmt[i].cfFormat = format;
1467 afmt[i].ptd = NULL;
1468 afmt[i].dwAspect = DVASPECT_CONTENT;
1469 afmt[i].lindex = -1;
1470 afmt[i].tymed = TYMED_HGLOBAL;
1474 * Create an EnumFORMATETC enumerator and return an
1475 * EnumFORMATETC after bumping up its ref count
1477 *ppenumFormatEtc = OLEClipbrd_IEnumFORMATETC_Construct( cfmt, afmt, (LPUNKNOWN)iface);
1478 if (!(*ppenumFormatEtc))
1479 HANDLE_ERROR( E_OUTOFMEMORY );
1481 if (FAILED( hr = IEnumFORMATETC_AddRef(*ppenumFormatEtc)))
1482 HANDLE_ERROR( hr );
1484 hr = S_OK;
1486 CLEANUP:
1488 * Free the array of FORMATETC's
1490 if (afmt)
1491 HeapFree(GetProcessHeap(), 0, afmt);
1494 * Close Windows clipboard
1496 if ( bClipboardOpen && !CloseClipboard() )
1497 hr = CLIPBRD_E_CANT_CLOSE;
1499 return hr;
1502 /************************************************************************
1503 * OLEClipbrd_IDataObject_DAdvise (IDataObject)
1505 * The OLE Clipboard's does not implement this method
1507 * See Windows documentation for more details on IDataObject methods.
1509 static HRESULT WINAPI OLEClipbrd_IDataObject_DAdvise(
1510 IDataObject* iface,
1511 FORMATETC* pformatetc,
1512 DWORD advf,
1513 IAdviseSink* pAdvSink,
1514 DWORD* pdwConnection)
1516 TRACE("\n");
1517 return E_NOTIMPL;
1520 /************************************************************************
1521 * OLEClipbrd_IDataObject_DUnadvise (IDataObject)
1523 * The OLE Clipboard's does not implement this method
1525 * See Windows documentation for more details on IDataObject methods.
1527 static HRESULT WINAPI OLEClipbrd_IDataObject_DUnadvise(
1528 IDataObject* iface,
1529 DWORD dwConnection)
1531 TRACE("\n");
1532 return E_NOTIMPL;
1535 /************************************************************************
1536 * OLEClipbrd_IDataObject_EnumDAdvise (IDataObject)
1538 * The OLE Clipboard does not implement this method
1540 * See Windows documentation for more details on IDataObject methods.
1542 static HRESULT WINAPI OLEClipbrd_IDataObject_EnumDAdvise(
1543 IDataObject* iface,
1544 IEnumSTATDATA** ppenumAdvise)
1546 TRACE("\n");
1547 return E_NOTIMPL;
1551 /*---------------------------------------------------------------------*
1552 * Implementation of the internal IEnumFORMATETC interface returned by
1553 * the OLE clipboard's IDataObject.
1554 *---------------------------------------------------------------------*/
1556 /************************************************************************
1557 * OLEClipbrd_IEnumFORMATETC_Construct (UINT, const FORMATETC, LPUNKNOWN)
1559 * Creates an IEnumFORMATETC enumerator from an array of FORMATETC
1560 * Structures. pUnkOuter is the outer unknown for reference counting only.
1561 * NOTE: this does not AddRef the interface.
1564 LPENUMFORMATETC OLEClipbrd_IEnumFORMATETC_Construct(UINT cfmt, const FORMATETC afmt[],
1565 LPUNKNOWN pUnkDataObj)
1567 IEnumFORMATETCImpl* ef;
1568 DWORD size=cfmt * sizeof(FORMATETC);
1569 LPMALLOC pIMalloc;
1571 ef = (IEnumFORMATETCImpl*)HeapAlloc(GetProcessHeap(),
1572 HEAP_ZERO_MEMORY,
1573 sizeof(IEnumFORMATETCImpl));
1574 if (!ef)
1575 return NULL;
1577 ef->ref = 0;
1578 ef->lpVtbl = &efvt;
1579 ef->pUnkDataObj = pUnkDataObj;
1581 ef->posFmt = 0;
1582 ef->countFmt = cfmt;
1583 if (FAILED(CoGetMalloc(MEMCTX_TASK, &pIMalloc))) {
1584 HeapFree(GetProcessHeap(), 0, ef);
1585 return NULL;
1587 ef->pFmt = (LPFORMATETC)IMalloc_Alloc(pIMalloc, size);
1588 IMalloc_Release(pIMalloc);
1590 if (ef->pFmt)
1591 memcpy(ef->pFmt, afmt, size);
1593 TRACE("(%p)->()\n",ef);
1594 return (LPENUMFORMATETC)ef;
1598 /************************************************************************
1599 * OLEClipbrd_IEnumFORMATETC_QueryInterface (IUnknown)
1601 * See Windows documentation for more details on IUnknown methods.
1603 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_QueryInterface
1604 (LPENUMFORMATETC iface, REFIID riid, LPVOID* ppvObj)
1606 ICOM_THIS(IEnumFORMATETCImpl,iface);
1608 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
1611 * Since enumerators are separate objects from the parent data object
1612 * we only need to support the IUnknown and IEnumFORMATETC interfaces
1615 *ppvObj = NULL;
1617 if(IsEqualIID(riid, &IID_IUnknown))
1619 *ppvObj = This;
1621 else if(IsEqualIID(riid, &IID_IEnumFORMATETC))
1623 *ppvObj = (IDataObject*)This;
1626 if(*ppvObj)
1628 IEnumFORMATETC_AddRef((IEnumFORMATETC*)*ppvObj);
1629 TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
1630 return S_OK;
1633 TRACE("-- Interface: E_NOINTERFACE\n");
1634 return E_NOINTERFACE;
1637 /************************************************************************
1638 * OLEClipbrd_IEnumFORMATETC_AddRef (IUnknown)
1640 * Since enumerating formats only makes sense when our data object is around,
1641 * we insure that it stays as long as we stay by calling our parents IUnknown
1642 * for AddRef and Release. But since we are not controlled by the lifetime of
1643 * the outer object, we still keep our own reference count in order to
1644 * free ourselves.
1646 static ULONG WINAPI OLEClipbrd_IEnumFORMATETC_AddRef(LPENUMFORMATETC iface)
1648 ICOM_THIS(IEnumFORMATETCImpl,iface);
1649 TRACE("(%p)->(count=%lu)\n",This, This->ref);
1651 if (This->pUnkDataObj)
1652 IUnknown_AddRef(This->pUnkDataObj);
1654 return ++(This->ref);
1657 /************************************************************************
1658 * OLEClipbrd_IEnumFORMATETC_Release (IUnknown)
1660 * See Windows documentation for more details on IUnknown methods.
1662 static ULONG WINAPI OLEClipbrd_IEnumFORMATETC_Release(LPENUMFORMATETC iface)
1664 ICOM_THIS(IEnumFORMATETCImpl,iface);
1665 LPMALLOC pIMalloc;
1667 TRACE("(%p)->(count=%lu)\n",This, This->ref);
1669 if (This->pUnkDataObj)
1670 IUnknown_Release(This->pUnkDataObj); /* Release parent data object */
1672 if (!--(This->ref))
1674 TRACE("() - destroying IEnumFORMATETC(%p)\n",This);
1675 if (SUCCEEDED(CoGetMalloc(MEMCTX_TASK, &pIMalloc)))
1677 IMalloc_Free(pIMalloc, This->pFmt);
1678 IMalloc_Release(pIMalloc);
1681 HeapFree(GetProcessHeap(),0,This);
1682 return 0;
1685 return This->ref;
1688 /************************************************************************
1689 * OLEClipbrd_IEnumFORMATETC_Next (IEnumFORMATETC)
1691 * Standard enumerator members for IEnumFORMATETC
1693 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Next
1694 (LPENUMFORMATETC iface, ULONG celt, FORMATETC *rgelt, ULONG *pceltFethed)
1696 ICOM_THIS(IEnumFORMATETCImpl,iface);
1697 UINT cfetch;
1698 HRESULT hres = S_FALSE;
1700 TRACE("(%p)->(pos=%u)\n", This, This->posFmt);
1702 if (This->posFmt < This->countFmt)
1704 cfetch = This->countFmt - This->posFmt;
1705 if (cfetch >= celt)
1707 cfetch = celt;
1708 hres = S_OK;
1711 memcpy(rgelt, &This->pFmt[This->posFmt], cfetch * sizeof(FORMATETC));
1712 This->posFmt += cfetch;
1714 else
1716 cfetch = 0;
1719 if (pceltFethed)
1721 *pceltFethed = cfetch;
1724 return hres;
1727 /************************************************************************
1728 * OLEClipbrd_IEnumFORMATETC_Skip (IEnumFORMATETC)
1730 * Standard enumerator members for IEnumFORMATETC
1732 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Skip(LPENUMFORMATETC iface, ULONG celt)
1734 ICOM_THIS(IEnumFORMATETCImpl,iface);
1735 TRACE("(%p)->(num=%lu)\n", This, celt);
1737 This->posFmt += celt;
1738 if (This->posFmt > This->countFmt)
1740 This->posFmt = This->countFmt;
1741 return S_FALSE;
1743 return S_OK;
1746 /************************************************************************
1747 * OLEClipbrd_IEnumFORMATETC_Reset (IEnumFORMATETC)
1749 * Standard enumerator members for IEnumFORMATETC
1751 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Reset(LPENUMFORMATETC iface)
1753 ICOM_THIS(IEnumFORMATETCImpl,iface);
1754 TRACE("(%p)->()\n", This);
1756 This->posFmt = 0;
1757 return S_OK;
1760 /************************************************************************
1761 * OLEClipbrd_IEnumFORMATETC_Clone (IEnumFORMATETC)
1763 * Standard enumerator members for IEnumFORMATETC
1765 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Clone
1766 (LPENUMFORMATETC iface, LPENUMFORMATETC* ppenum)
1768 ICOM_THIS(IEnumFORMATETCImpl,iface);
1769 HRESULT hr = S_OK;
1771 TRACE("(%p)->(ppenum=%p)\n", This, ppenum);
1773 if ( !ppenum )
1774 return E_INVALIDARG;
1776 *ppenum = OLEClipbrd_IEnumFORMATETC_Construct(This->countFmt,
1777 This->pFmt,
1778 This->pUnkDataObj);
1780 if (FAILED( hr = IEnumFORMATETC_AddRef(*ppenum)))
1781 return ( hr );
1783 return (*ppenum) ? S_OK : E_OUTOFMEMORY;