Added descriptions for a few more machine types.
[wine/multimedia.git] / dlls / ole32 / clipboard.c
blob75b706dc1429e80348ec347ad9fa516a1090795b
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 [OLE2.76]
485 HRESULT WINAPI OleFlushClipboard16(void)
487 return OleFlushClipboard();
491 /******************************************************************************
492 * OleFlushClipboard [OLE32.@]
493 * Renders the data from the source IDataObject into the windows clipboard
495 * TODO: OleFlushClipboard needs to additionally handle TYMED_IStorage media
496 * by copying the storage into global memory. Subsequently the default
497 * data object exposed through OleGetClipboard must convert this TYMED_HGLOBAL
498 * back to TYMED_IStorage.
500 HRESULT WINAPI OleFlushClipboard()
502 IEnumFORMATETC* penumFormatetc = NULL;
503 FORMATETC rgelt;
504 HRESULT hr = S_OK;
505 BOOL bClipboardOpen = FALSE;
506 IDataObject* pIDataObjectSrc = NULL;
508 TRACE("()\n");
511 * Make sure we have a clipboard object
513 OLEClipbrd_Initialize();
516 * Already flushed or no source DataObject? Nothing to do.
518 if (!theOleClipboard->pIDataObjectSrc)
519 return S_OK;
522 * Addref and save the source data object we are holding on to temporarily,
523 * since it will be released when we empty the clipboard.
525 pIDataObjectSrc = theOleClipboard->pIDataObjectSrc;
526 IDataObject_AddRef(pIDataObjectSrc);
529 * Open the Windows clipboard
531 if ( !(bClipboardOpen = OpenClipboard(theOleClipboard->hWndClipboard)) )
532 HANDLE_ERROR( CLIPBRD_E_CANT_OPEN );
535 * Empty the current clipboard
537 if ( !EmptyClipboard() )
538 HANDLE_ERROR( CLIPBRD_E_CANT_EMPTY );
541 * Render all HGLOBAL formats supported by the source into
542 * the windows clipboard.
544 if ( FAILED( hr = IDataObject_EnumFormatEtc( pIDataObjectSrc,
545 DATADIR_GET,
546 &penumFormatetc) ))
548 HANDLE_ERROR( hr );
551 while ( S_OK == IEnumFORMATETC_Next(penumFormatetc, 1, &rgelt, NULL) )
553 if ( rgelt.tymed == TYMED_HGLOBAL )
555 CHAR szFmtName[80];
556 TRACE("(cfFormat=%d:%s)\n", rgelt.cfFormat,
557 GetClipboardFormatNameA(rgelt.cfFormat, szFmtName, sizeof(szFmtName)-1)
558 ? szFmtName : "");
561 * Render the clipboard data
563 if ( FAILED(OLEClipbrd_RenderFormat( pIDataObjectSrc, &rgelt )) )
564 continue;
568 IEnumFORMATETC_Release(penumFormatetc);
571 * Release the source data object we are holding on to
573 IDataObject_Release(pIDataObjectSrc);
575 CLEANUP:
578 * Close Windows clipboard (It remains associated with our window)
580 if ( bClipboardOpen && !CloseClipboard() )
581 hr = CLIPBRD_E_CANT_CLOSE;
583 return hr;
587 /***********************************************************************
588 * OleIsCurrentClipboard [OLE32.@]
590 HRESULT WINAPI OleIsCurrentClipboard ( IDataObject *pDataObject)
592 TRACE("()\n");
594 * Make sure we have a clipboard object
596 OLEClipbrd_Initialize();
598 if (!theOleClipboard)
599 return E_OUTOFMEMORY;
601 return (pDataObject == theOleClipboard->pIDataObjectSrc) ? S_OK : S_FALSE;
605 /*---------------------------------------------------------------------*
606 * Internal implementation methods for the OLE clipboard
607 *---------------------------------------------------------------------*/
609 /***********************************************************************
610 * OLEClipbrd_Initialize()
611 * Initializes the OLE clipboard.
613 void OLEClipbrd_Initialize(void)
616 * Create the clipboard if necessary
618 if ( !theOleClipboard )
620 TRACE("()\n");
621 theOleClipboard = OLEClipbrd_Construct();
626 /***********************************************************************
627 * OLEClipbrd_UnInitialize()
628 * Un-Initializes the OLE clipboard
630 void OLEClipbrd_UnInitialize(void)
632 TRACE("()\n");
634 * Destroy the clipboard if no one holds a reference to us.
635 * Note that the clipboard was created with a reference count of 1.
637 if ( theOleClipboard && (theOleClipboard->ref <= 1) )
639 OLEClipbrd_Destroy( theOleClipboard );
641 else
643 WARN( "() : OLEClipbrd_UnInitialize called while client holds an IDataObject reference!\n");
648 /*********************************************************
649 * Construct the OLEClipbrd class.
651 static OLEClipbrd* OLEClipbrd_Construct()
653 OLEClipbrd* newObject = NULL;
654 HGLOBAL hNewObject = 0;
657 * Allocate space for the object. We use GlobalAlloc since we need
658 * an HGLOBAL to expose our DataObject as a registered clipboard type.
660 hNewObject = GlobalAlloc( GMEM_DDESHARE|GMEM_MOVEABLE|GMEM_ZEROINIT,
661 sizeof(OLEClipbrd));
662 if (hNewObject==0)
663 return NULL;
666 * Lock the handle for the entire lifetime of the clipboard.
668 newObject = GlobalLock(hNewObject);
671 * Initialize the virtual function table.
673 newObject->lpvtbl1 = &OLEClipbrd_IDataObject_VTable;
676 * Start with one reference count. The caller of this function
677 * must release the interface pointer when it is done.
679 newObject->ref = 1;
681 newObject->hSelf = hNewObject;
684 * The Ole clipboard is a singleton - save the global handle and pointer
686 theOleClipboard = newObject;
687 hTheOleClipboard = hNewObject;
689 return theOleClipboard;
692 static void OLEClipbrd_Destroy(OLEClipbrd* ptrToDestroy)
694 TRACE("()\n");
696 if ( !ptrToDestroy )
697 return;
700 * Destroy the Ole clipboard window
702 if ( ptrToDestroy->hWndClipboard )
703 OLEClipbrd_DestroyWindow(ptrToDestroy->hWndClipboard);
706 * Free the actual OLE Clipboard structure.
708 TRACE("() - Destroying clipboard data object.\n");
709 GlobalUnlock(ptrToDestroy->hSelf);
710 GlobalFree(ptrToDestroy->hSelf);
713 * The Ole clipboard is a singleton (ptrToDestroy == theOleClipboard)
715 theOleClipboard = NULL;
716 hTheOleClipboard = 0;
720 /***********************************************************************
721 * OLEClipbrd_CreateWindow()
722 * Create the clipboard window
724 static HWND OLEClipbrd_CreateWindow()
726 HWND hwnd = 0;
727 WNDCLASSEXA wcex;
730 * Register the clipboard window class if necessary
732 ZeroMemory( &wcex, sizeof(WNDCLASSEXA));
734 wcex.cbSize = sizeof(WNDCLASSEXA);
735 /* Windows creates this class with a style mask of 0
736 * We don't bother doing this since the FindClassByAtom code
737 * would have to be changed to deal with this idiosyncrasy. */
738 wcex.style = CS_GLOBALCLASS;
739 wcex.lpfnWndProc = OLEClipbrd_WndProc;
740 wcex.hInstance = 0;
741 wcex.lpszClassName = OLEClipbrd_WNDCLASS;
743 RegisterClassExA(&wcex);
746 * Create a hidden window to receive OLE clipboard messages
750 * If we need to store state info we can store it here.
751 * For now we don't need this functionality.
752 * ClipboardWindowInfo clipboardInfo;
753 * ZeroMemory( &trackerInfo, sizeof(ClipboardWindowInfo));
756 hwnd = CreateWindowA(OLEClipbrd_WNDCLASS,
757 "ClipboardWindow",
758 WS_POPUP | WS_CLIPSIBLINGS | WS_OVERLAPPED,
759 CW_USEDEFAULT, CW_USEDEFAULT,
760 CW_USEDEFAULT, CW_USEDEFAULT,
764 0 /*(LPVOID)&clipboardInfo */);
766 return hwnd;
769 /***********************************************************************
770 * OLEClipbrd_DestroyWindow(HWND)
771 * Destroy the clipboard window and unregister its class
773 static void OLEClipbrd_DestroyWindow(HWND hwnd)
776 * Destroy clipboard window and unregister its WNDCLASS
778 DestroyWindow(hwnd);
779 UnregisterClassA( OLEClipbrd_WNDCLASS, 0 );
782 /***********************************************************************
783 * OLEClipbrd_WndProc(HWND, unsigned, WORD, LONG)
784 * Processes messages sent to the OLE clipboard window.
785 * Note that we will intercept messages in our WndProc only when data
786 * has been placed in the clipboard via OleSetClipboard().
787 * i.e. Only when OLE owns the windows clipboard.
789 LRESULT CALLBACK OLEClipbrd_WndProc
790 (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
792 switch (message)
795 * WM_RENDERFORMAT
796 * We receive this message to allow us to handle delayed rendering of
797 * a specific clipboard format when an application requests data in
798 * that format by calling GetClipboardData.
799 * (Recall that in OleSetClipboard, we used SetClipboardData to
800 * make all HGLOBAL formats supported by the source IDataObject
801 * available using delayed rendering)
802 * On receiving this message we must actually render the data in the
803 * specified format and place it on the clipboard by calling the
804 * SetClipboardData function.
806 case WM_RENDERFORMAT:
808 FORMATETC rgelt;
810 ZeroMemory( &rgelt, sizeof(FORMATETC));
813 * Initialize FORMATETC to a Windows clipboard friendly format
815 rgelt.cfFormat = (UINT) wParam;
816 rgelt.dwAspect = DVASPECT_CONTENT;
817 rgelt.lindex = -1;
818 rgelt.tymed = TYMED_HGLOBAL;
820 TRACE("(): WM_RENDERFORMAT(cfFormat=%d)\n", rgelt.cfFormat);
823 * Render the clipboard data.
824 * (We must have a source data object or we wouldn't be in this WndProc)
826 OLEClipbrd_RenderFormat( (IDataObject*)&(theOleClipboard->lpvtbl1), &rgelt );
828 break;
832 * WM_RENDERALLFORMATS
833 * Sent before the clipboard owner window is destroyed.
834 * We should receive this message only when OleUninitialize is called
835 * while we have an IDataObject in the clipboard.
836 * For the content of the clipboard to remain available to other
837 * applications, we must render data in all the formats the source IDataObject
838 * is capable of generating, and place the data on the clipboard by calling
839 * SetClipboardData.
841 case WM_RENDERALLFORMATS:
843 IEnumFORMATETC* penumFormatetc = NULL;
844 FORMATETC rgelt;
846 TRACE("(): WM_RENDERALLFORMATS\n");
849 * Render all HGLOBAL formats supported by the source into
850 * the windows clipboard.
852 if ( FAILED( IDataObject_EnumFormatEtc( (IDataObject*)&(theOleClipboard->lpvtbl1),
853 DATADIR_GET, &penumFormatetc) ) )
855 WARN("(): WM_RENDERALLFORMATS failed to retrieve EnumFormatEtc!\n");
856 return 0;
859 while ( S_OK == IEnumFORMATETC_Next(penumFormatetc, 1, &rgelt, NULL) )
861 if ( rgelt.tymed == TYMED_HGLOBAL )
864 * Render the clipboard data.
866 if ( FAILED(OLEClipbrd_RenderFormat( (IDataObject*)&(theOleClipboard->lpvtbl1), &rgelt )) )
867 continue;
869 TRACE("(): WM_RENDERALLFORMATS(cfFormat=%d)\n", rgelt.cfFormat);
873 IEnumFORMATETC_Release(penumFormatetc);
875 break;
879 * WM_DESTROYCLIPBOARD
880 * This is sent by EmptyClipboard before the clipboard is emptied.
881 * We should release any IDataObject we are holding onto when we receive
882 * this message, since it indicates that the OLE clipboard should be empty
883 * from this point on.
885 case WM_DESTROYCLIPBOARD:
887 TRACE("(): WM_DESTROYCLIPBOARD\n");
889 * Release the data object we are holding on to
891 if ( theOleClipboard->pIDataObjectSrc )
893 IDataObject_Release(theOleClipboard->pIDataObjectSrc);
894 theOleClipboard->pIDataObjectSrc = NULL;
896 break;
900 case WM_ASKCBFORMATNAME:
901 case WM_CHANGECBCHAIN:
902 case WM_DRAWCLIPBOARD:
903 case WM_SIZECLIPBOARD:
904 case WM_HSCROLLCLIPBOARD:
905 case WM_VSCROLLCLIPBOARD:
906 case WM_PAINTCLIPBOARD:
908 default:
909 return DefWindowProcA(hWnd, message, wParam, lParam);
912 return 0;
915 #define MAX_CLIPFORMAT_NAME 80
917 /***********************************************************************
918 * OLEClipbrd_RenderFormat(LPFORMATETC)
919 * Render the clipboard data. Note that this call will delegate to the
920 * source data object.
921 * Note: This function assumes it is passed an HGLOBAL format to render.
923 static HRESULT OLEClipbrd_RenderFormat(IDataObject *pIDataObject, LPFORMATETC pFormatetc)
925 STGMEDIUM std;
926 HGLOBAL hDup;
927 HRESULT hr = S_OK;
928 char szFmtName[MAX_CLIPFORMAT_NAME];
929 ILockBytes *ptrILockBytes = 0;
930 HGLOBAL hStorage = 0;
932 GetClipboardFormatNameA(pFormatetc->cfFormat, szFmtName, MAX_CLIPFORMAT_NAME);
934 /* If embed source */
935 if (!strcmp(szFmtName, CF_EMBEDSOURCE))
937 memset(&std, 0, sizeof(STGMEDIUM));
938 std.tymed = pFormatetc->tymed = TYMED_ISTORAGE;
940 hStorage = GlobalAlloc(GMEM_SHARE|GMEM_MOVEABLE, 0);
941 if (hStorage == NULL)
942 HANDLE_ERROR( E_OUTOFMEMORY );
943 hr = CreateILockBytesOnHGlobal(hStorage, FALSE, &ptrILockBytes);
944 hr = StgCreateDocfileOnILockBytes(ptrILockBytes, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &std.u.pstg);
946 if (FAILED(hr = IDataObject_GetDataHere(theOleClipboard->pIDataObjectSrc, pFormatetc, &std)))
948 WARN("() : IDataObject_GetDataHere failed to render clipboard data! (%lx)\n", hr);
949 GlobalFree(hStorage);
950 return hr;
953 if (1) /* check whether the presentation data is already -not- present */
955 FORMATETC fmt2;
956 STGMEDIUM std2;
957 METAFILEPICT *mfp = 0;
959 fmt2.cfFormat = CF_METAFILEPICT;
960 fmt2.ptd = 0;
961 fmt2.dwAspect = DVASPECT_CONTENT;
962 fmt2.lindex = -1;
963 fmt2.tymed = TYMED_MFPICT;
965 memset(&std2, 0, sizeof(STGMEDIUM));
966 std2.tymed = TYMED_MFPICT;
968 /* Get the metafile picture out of it */
970 if (!FAILED(hr = IDataObject_GetData(theOleClipboard->pIDataObjectSrc, &fmt2, &std2)))
972 mfp = (METAFILEPICT *)GlobalLock(std2.u.hGlobal);
975 if (mfp)
977 OLECHAR name[]={ 2, 'O', 'l', 'e', 'P', 'r', 'e', 's', '0', '0', '0', 0};
978 IStream *pStream = 0;
979 void *mfBits;
980 PresentationDataHeader pdh;
981 INT nSize;
982 CLSID clsID;
983 LPOLESTR strProgID;
984 CHAR strOleTypeName[51];
985 BYTE OlePresStreamHeader [] =
987 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00,
988 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
989 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
990 0x00, 0x00, 0x00, 0x00
993 nSize = GetMetaFileBitsEx(mfp->hMF, 0, NULL);
995 memset(&pdh, 0, sizeof(PresentationDataHeader));
996 memcpy(&pdh, OlePresStreamHeader, sizeof(OlePresStreamHeader));
998 pdh.dwObjectExtentX = mfp->xExt;
999 pdh.dwObjectExtentY = mfp->yExt;
1000 pdh.dwSize = nSize;
1002 hr = IStorage_CreateStream(std.u.pstg, name, STGM_CREATE|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, 0, &pStream);
1004 hr = IStream_Write(pStream, &pdh, sizeof(PresentationDataHeader), NULL);
1006 mfBits = HeapAlloc(GetProcessHeap(), 0, nSize);
1007 nSize = GetMetaFileBitsEx(mfp->hMF, nSize, mfBits);
1009 hr = IStream_Write(pStream, mfBits, nSize, NULL);
1011 IStream_Release(pStream);
1013 HeapFree(GetProcessHeap(), 0, mfBits);
1015 GlobalUnlock(std2.u.hGlobal);
1017 ReadClassStg(std.u.pstg, &clsID);
1018 ProgIDFromCLSID(&clsID, &strProgID);
1020 WideCharToMultiByte( CP_ACP, 0, strProgID, -1, strOleTypeName, sizeof(strOleTypeName), NULL, NULL );
1021 OLECONVERT_CreateOleStream(std.u.pstg);
1022 OLECONVERT_CreateCompObjStream(std.u.pstg, strOleTypeName);
1026 else
1028 if (FAILED(hr = IDataObject_GetData(pIDataObject, pFormatetc, &std)))
1030 WARN("() : IDataObject_GetData failed to render clipboard data! (%lx)\n", hr);
1031 GlobalFree(hStorage);
1032 return hr;
1035 /* To put a copy back on the clipboard */
1037 hStorage = std.u.hGlobal;
1041 * Put a copy of the rendered data back on the clipboard
1044 if ( !(hDup = OLEClipbrd_GlobalDupMem(hStorage)) )
1045 HANDLE_ERROR( E_OUTOFMEMORY );
1047 if ( !SetClipboardData( pFormatetc->cfFormat, hDup ) )
1049 GlobalFree(hDup);
1050 WARN("() : Failed to set rendered clipboard data into clipboard!\n");
1053 CLEANUP:
1055 ReleaseStgMedium(&std);
1057 return hr;
1061 /***********************************************************************
1062 * OLEClipbrd_GlobalDupMem( HGLOBAL )
1063 * Helper method to duplicate an HGLOBAL chunk of memory
1065 static HGLOBAL OLEClipbrd_GlobalDupMem( HGLOBAL hGlobalSrc )
1067 HGLOBAL hGlobalDest;
1068 PVOID pGlobalSrc, pGlobalDest;
1069 DWORD cBytes;
1071 if ( !hGlobalSrc )
1072 return 0;
1074 cBytes = GlobalSize(hGlobalSrc);
1075 if ( 0 == cBytes )
1076 return 0;
1078 hGlobalDest = GlobalAlloc( GMEM_DDESHARE|GMEM_MOVEABLE,
1079 cBytes );
1080 if ( !hGlobalDest )
1081 return 0;
1083 pGlobalSrc = GlobalLock(hGlobalSrc);
1084 pGlobalDest = GlobalLock(hGlobalDest);
1085 if ( !pGlobalSrc || !pGlobalDest )
1087 GlobalFree(hGlobalDest);
1088 return 0;
1091 memcpy(pGlobalDest, pGlobalSrc, cBytes);
1093 GlobalUnlock(hGlobalSrc);
1094 GlobalUnlock(hGlobalDest);
1096 return hGlobalDest;
1100 /*---------------------------------------------------------------------*
1101 * Implementation of the internal IDataObject interface exposed by
1102 * the OLE clipboard.
1103 *---------------------------------------------------------------------*/
1106 /************************************************************************
1107 * OLEClipbrd_IDataObject_QueryInterface (IUnknown)
1109 * See Windows documentation for more details on IUnknown methods.
1111 static HRESULT WINAPI OLEClipbrd_IDataObject_QueryInterface(
1112 IDataObject* iface,
1113 REFIID riid,
1114 void** ppvObject)
1117 * Declare "This" pointer
1119 OLEClipbrd *This = (OLEClipbrd *)iface;
1120 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObject);
1123 * Perform a sanity check on the parameters.
1125 if ( (This==0) || (ppvObject==0) )
1126 return E_INVALIDARG;
1129 * Initialize the return parameter.
1131 *ppvObject = 0;
1134 * Compare the riid with the interface IDs implemented by this object.
1136 if (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0)
1138 *ppvObject = iface;
1140 else if (memcmp(&IID_IDataObject, riid, sizeof(IID_IDataObject)) == 0)
1142 *ppvObject = (IDataObject*)&(This->lpvtbl1);
1144 else /* We only support IUnknown and IDataObject */
1146 WARN( "() : asking for unsupported interface %s\n", debugstr_guid(riid));
1147 return E_NOINTERFACE;
1151 * Query Interface always increases the reference count by one when it is
1152 * successful.
1154 IUnknown_AddRef((IUnknown*)*ppvObject);
1156 return S_OK;
1159 /************************************************************************
1160 * OLEClipbrd_IDataObject_AddRef (IUnknown)
1162 * See Windows documentation for more details on IUnknown methods.
1164 static ULONG WINAPI OLEClipbrd_IDataObject_AddRef(
1165 IDataObject* iface)
1168 * Declare "This" pointer
1170 OLEClipbrd *This = (OLEClipbrd *)iface;
1172 TRACE("(%p)->(count=%lu)\n",This, This->ref);
1174 return InterlockedIncrement(&This->ref);
1178 /************************************************************************
1179 * OLEClipbrd_IDataObject_Release (IUnknown)
1181 * See Windows documentation for more details on IUnknown methods.
1183 static ULONG WINAPI OLEClipbrd_IDataObject_Release(
1184 IDataObject* iface)
1187 * Declare "This" pointer
1189 OLEClipbrd *This = (OLEClipbrd *)iface;
1190 ULONG ref;
1192 TRACE("(%p)->(count=%lu)\n",This, This->ref);
1195 * Decrease the reference count on this object.
1197 ref = InterlockedDecrement(&This->ref);
1200 * If the reference count goes down to 0, perform suicide.
1202 if (ref == 0)
1204 OLEClipbrd_Destroy(This);
1207 return ref;
1211 /************************************************************************
1212 * OLEClipbrd_IDataObject_GetData (IDataObject)
1214 * The OLE Clipboard's implementation of this method delegates to
1215 * a data source if there is one or wraps around the windows clipboard
1217 * See Windows documentation for more details on IDataObject methods.
1219 static HRESULT WINAPI OLEClipbrd_IDataObject_GetData(
1220 IDataObject* iface,
1221 LPFORMATETC pformatetcIn,
1222 STGMEDIUM* pmedium)
1224 HANDLE hData = 0;
1225 BOOL bClipboardOpen = FALSE;
1226 HRESULT hr = S_OK;
1227 LPVOID src;
1230 * Declare "This" pointer
1232 OLEClipbrd *This = (OLEClipbrd *)iface;
1234 TRACE("(%p,%p,%p)\n", iface, pformatetcIn, pmedium);
1236 if ( !pformatetcIn || !pmedium )
1237 return E_INVALIDARG;
1240 * If we have a data source placed on the clipboard (via OleSetClipboard)
1241 * simply delegate to the source object's QueryGetData
1242 * NOTE: This code assumes that the IDataObject is in the same address space!
1243 * We will need to add marshalling support when Wine handles multiple processes.
1245 if ( This->pIDataObjectSrc )
1247 return IDataObject_GetData(This->pIDataObjectSrc, pformatetcIn, pmedium);
1250 if ( pformatetcIn->lindex != -1 )
1251 return DV_E_LINDEX;
1252 if ( (pformatetcIn->tymed & TYMED_HGLOBAL) != TYMED_HGLOBAL )
1253 return DV_E_TYMED;
1255 if ( pformatetcIn->dwAspect != DVASPECT_CONTENT )
1256 return DV_E_DVASPECT;
1260 * Otherwise, get the data from the windows clipboard using GetClipboardData
1262 if ( !(bClipboardOpen = OpenClipboard(theOleClipboard->hWndClipboard)) )
1263 HANDLE_ERROR( CLIPBRD_E_CANT_OPEN );
1265 hData = GetClipboardData(pformatetcIn->cfFormat);
1267 /* Must make a copy of global handle returned by GetClipboardData; it
1268 * is not valid after we call CloseClipboard
1269 * Application is responsible for freeing the memory (Forte Agent does this)
1271 src = GlobalLock(hData);
1272 if(src) {
1273 LPVOID dest;
1274 ULONG size;
1275 HANDLE hDest;
1277 size = GlobalSize(hData);
1278 hDest = GlobalAlloc(GHND, size);
1279 dest = GlobalLock(hDest);
1280 memcpy(dest, src, size);
1281 GlobalUnlock(hDest);
1282 GlobalUnlock(hData);
1283 hData = hDest;
1287 * Return the clipboard data in the storage medium structure
1289 pmedium->tymed = (hData == 0) ? TYMED_NULL : TYMED_HGLOBAL;
1290 pmedium->u.hGlobal = (HGLOBAL)hData;
1291 pmedium->pUnkForRelease = NULL;
1293 hr = S_OK;
1295 CLEANUP:
1297 * Close Windows clipboard
1299 if ( bClipboardOpen && !CloseClipboard() )
1300 hr = CLIPBRD_E_CANT_CLOSE;
1302 if ( FAILED(hr) )
1303 return hr;
1304 return (hData == 0) ? DV_E_FORMATETC : S_OK;
1307 static HRESULT WINAPI OLEClipbrd_IDataObject_GetDataHere(
1308 IDataObject* iface,
1309 LPFORMATETC pformatetc,
1310 STGMEDIUM* pmedium)
1312 FIXME(": Stub\n");
1313 return E_NOTIMPL;
1316 /************************************************************************
1317 * OLEClipbrd_IDataObject_QueryGetData (IDataObject)
1319 * The OLE Clipboard's implementation of this method delegates to
1320 * a data source if there is one or wraps around the windows clipboard
1321 * function IsClipboardFormatAvailable() otherwise.
1323 * See Windows documentation for more details on IDataObject methods.
1325 static HRESULT WINAPI OLEClipbrd_IDataObject_QueryGetData(
1326 IDataObject* iface,
1327 LPFORMATETC pformatetc)
1330 * Declare "This" pointer
1332 OLEClipbrd *This = (OLEClipbrd *)iface;
1334 TRACE("(%p, %p)\n", iface, pformatetc);
1337 * If we have a data source placed on the clipboard (via OleSetClipboard)
1338 * simply delegate to the source object's QueryGetData
1340 if ( This->pIDataObjectSrc )
1342 return IDataObject_QueryGetData(This->pIDataObjectSrc, pformatetc);
1345 if (!pformatetc)
1346 return E_INVALIDARG;
1348 if ( pformatetc->dwAspect != DVASPECT_CONTENT )
1349 return DV_E_DVASPECT;
1351 if ( pformatetc->lindex != -1 )
1352 return DV_E_LINDEX;
1354 /* TODO: Handle TYMED_IStorage media which were put on the clipboard
1355 * by copying the storage into global memory. We must convert this
1356 * TYMED_HGLOBAL back to TYMED_IStorage.
1358 if ( pformatetc->tymed != TYMED_HGLOBAL )
1359 return DV_E_TYMED;
1362 * Delegate to the Windows clipboard function IsClipboardFormatAvailable
1364 return (IsClipboardFormatAvailable(pformatetc->cfFormat)) ? S_OK : DV_E_FORMATETC;
1367 /************************************************************************
1368 * OLEClipbrd_IDataObject_GetCanonicalFormatEtc (IDataObject)
1370 * See Windows documentation for more details on IDataObject methods.
1372 static HRESULT WINAPI OLEClipbrd_IDataObject_GetCanonicalFormatEtc(
1373 IDataObject* iface,
1374 LPFORMATETC pformatectIn,
1375 LPFORMATETC pformatetcOut)
1377 TRACE("(%p, %p, %p)\n", iface, pformatectIn, pformatetcOut);
1379 if ( !pformatectIn || !pformatetcOut )
1380 return E_INVALIDARG;
1382 memcpy(pformatetcOut, pformatectIn, sizeof(FORMATETC));
1383 return DATA_S_SAMEFORMATETC;
1386 /************************************************************************
1387 * OLEClipbrd_IDataObject_SetData (IDataObject)
1389 * The OLE Clipboard's does not implement this method
1391 * See Windows documentation for more details on IDataObject methods.
1393 static HRESULT WINAPI OLEClipbrd_IDataObject_SetData(
1394 IDataObject* iface,
1395 LPFORMATETC pformatetc,
1396 STGMEDIUM* pmedium,
1397 BOOL fRelease)
1399 TRACE("\n");
1400 return E_NOTIMPL;
1403 /************************************************************************
1404 * OLEClipbrd_IDataObject_EnumFormatEtc (IDataObject)
1406 * See Windows documentation for more details on IDataObject methods.
1408 static HRESULT WINAPI OLEClipbrd_IDataObject_EnumFormatEtc(
1409 IDataObject* iface,
1410 DWORD dwDirection,
1411 IEnumFORMATETC** ppenumFormatEtc)
1413 HRESULT hr = S_OK;
1414 FORMATETC *afmt = NULL;
1415 int cfmt, i;
1416 UINT format;
1417 BOOL bClipboardOpen;
1420 * Declare "This" pointer
1422 OLEClipbrd *This = (OLEClipbrd *)iface;
1424 TRACE("(%p, %lx, %p)\n", iface, dwDirection, ppenumFormatEtc);
1427 * If we have a data source placed on the clipboard (via OleSetClipboard)
1428 * simply delegate to the source object's EnumFormatEtc
1430 if ( This->pIDataObjectSrc )
1432 return IDataObject_EnumFormatEtc(This->pIDataObjectSrc,
1433 dwDirection, ppenumFormatEtc);
1437 * Otherwise we must provide our own enumerator which wraps around the
1438 * Windows clipboard function EnumClipboardFormats
1440 if ( !ppenumFormatEtc )
1441 return E_INVALIDARG;
1443 if ( dwDirection != DATADIR_GET ) /* IDataObject_SetData not implemented */
1444 return E_NOTIMPL;
1447 * Store all current clipboard formats in an array of FORMATETC's,
1448 * and create an IEnumFORMATETC enumerator from this list.
1450 cfmt = CountClipboardFormats();
1451 afmt = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1452 sizeof(FORMATETC) * cfmt);
1454 * Open the Windows clipboard, associating it with our hidden window
1456 if ( !(bClipboardOpen = OpenClipboard(This->hWndClipboard)) )
1457 HANDLE_ERROR( CLIPBRD_E_CANT_OPEN );
1460 * Store all current clipboard formats in an array of FORMATETC's
1461 * TODO: Handle TYMED_IStorage media which were put on the clipboard
1462 * by copying the storage into global memory. We must convert this
1463 * TYMED_HGLOBAL back to TYMED_IStorage.
1465 for (i = 0, format = 0; i < cfmt; i++)
1467 format = EnumClipboardFormats(format);
1468 if (!format) /* Failed! */
1470 ERR("EnumClipboardFormats failed to return format!\n");
1471 HANDLE_ERROR( E_FAIL );
1474 /* Init the FORMATETC struct */
1475 afmt[i].cfFormat = format;
1476 afmt[i].ptd = NULL;
1477 afmt[i].dwAspect = DVASPECT_CONTENT;
1478 afmt[i].lindex = -1;
1479 afmt[i].tymed = TYMED_HGLOBAL;
1483 * Create an EnumFORMATETC enumerator and return an
1484 * EnumFORMATETC after bumping up its ref count
1486 *ppenumFormatEtc = OLEClipbrd_IEnumFORMATETC_Construct( cfmt, afmt, (LPUNKNOWN)iface);
1487 if (!(*ppenumFormatEtc))
1488 HANDLE_ERROR( E_OUTOFMEMORY );
1490 if (FAILED( hr = IEnumFORMATETC_AddRef(*ppenumFormatEtc)))
1491 HANDLE_ERROR( hr );
1493 hr = S_OK;
1495 CLEANUP:
1497 * Free the array of FORMATETC's
1499 HeapFree(GetProcessHeap(), 0, afmt);
1502 * Close Windows clipboard
1504 if ( bClipboardOpen && !CloseClipboard() )
1505 hr = CLIPBRD_E_CANT_CLOSE;
1507 return hr;
1510 /************************************************************************
1511 * OLEClipbrd_IDataObject_DAdvise (IDataObject)
1513 * The OLE Clipboard's does not implement this method
1515 * See Windows documentation for more details on IDataObject methods.
1517 static HRESULT WINAPI OLEClipbrd_IDataObject_DAdvise(
1518 IDataObject* iface,
1519 FORMATETC* pformatetc,
1520 DWORD advf,
1521 IAdviseSink* pAdvSink,
1522 DWORD* pdwConnection)
1524 TRACE("\n");
1525 return E_NOTIMPL;
1528 /************************************************************************
1529 * OLEClipbrd_IDataObject_DUnadvise (IDataObject)
1531 * The OLE Clipboard's does not implement this method
1533 * See Windows documentation for more details on IDataObject methods.
1535 static HRESULT WINAPI OLEClipbrd_IDataObject_DUnadvise(
1536 IDataObject* iface,
1537 DWORD dwConnection)
1539 TRACE("\n");
1540 return E_NOTIMPL;
1543 /************************************************************************
1544 * OLEClipbrd_IDataObject_EnumDAdvise (IDataObject)
1546 * The OLE Clipboard does not implement this method
1548 * See Windows documentation for more details on IDataObject methods.
1550 static HRESULT WINAPI OLEClipbrd_IDataObject_EnumDAdvise(
1551 IDataObject* iface,
1552 IEnumSTATDATA** ppenumAdvise)
1554 TRACE("\n");
1555 return E_NOTIMPL;
1559 /*---------------------------------------------------------------------*
1560 * Implementation of the internal IEnumFORMATETC interface returned by
1561 * the OLE clipboard's IDataObject.
1562 *---------------------------------------------------------------------*/
1564 /************************************************************************
1565 * OLEClipbrd_IEnumFORMATETC_Construct (UINT, const FORMATETC, LPUNKNOWN)
1567 * Creates an IEnumFORMATETC enumerator from an array of FORMATETC
1568 * Structures. pUnkOuter is the outer unknown for reference counting only.
1569 * NOTE: this does not AddRef the interface.
1572 LPENUMFORMATETC OLEClipbrd_IEnumFORMATETC_Construct(UINT cfmt, const FORMATETC afmt[],
1573 LPUNKNOWN pUnkDataObj)
1575 IEnumFORMATETCImpl* ef;
1576 DWORD size=cfmt * sizeof(FORMATETC);
1577 LPMALLOC pIMalloc;
1579 ef = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IEnumFORMATETCImpl));
1580 if (!ef)
1581 return NULL;
1583 ef->ref = 0;
1584 ef->lpVtbl = &efvt;
1585 ef->pUnkDataObj = pUnkDataObj;
1587 ef->posFmt = 0;
1588 ef->countFmt = cfmt;
1589 if (FAILED(CoGetMalloc(MEMCTX_TASK, &pIMalloc))) {
1590 HeapFree(GetProcessHeap(), 0, ef);
1591 return NULL;
1593 ef->pFmt = (LPFORMATETC)IMalloc_Alloc(pIMalloc, size);
1594 IMalloc_Release(pIMalloc);
1596 if (ef->pFmt)
1597 memcpy(ef->pFmt, afmt, size);
1599 TRACE("(%p)->()\n",ef);
1600 return (LPENUMFORMATETC)ef;
1604 /************************************************************************
1605 * OLEClipbrd_IEnumFORMATETC_QueryInterface (IUnknown)
1607 * See Windows documentation for more details on IUnknown methods.
1609 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_QueryInterface
1610 (LPENUMFORMATETC iface, REFIID riid, LPVOID* ppvObj)
1612 IEnumFORMATETCImpl *This = (IEnumFORMATETCImpl *)iface;
1614 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
1617 * Since enumerators are separate objects from the parent data object
1618 * we only need to support the IUnknown and IEnumFORMATETC interfaces
1621 *ppvObj = NULL;
1623 if(IsEqualIID(riid, &IID_IUnknown))
1625 *ppvObj = This;
1627 else if(IsEqualIID(riid, &IID_IEnumFORMATETC))
1629 *ppvObj = (IDataObject*)This;
1632 if(*ppvObj)
1634 IEnumFORMATETC_AddRef((IEnumFORMATETC*)*ppvObj);
1635 TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
1636 return S_OK;
1639 TRACE("-- Interface: E_NOINTERFACE\n");
1640 return E_NOINTERFACE;
1643 /************************************************************************
1644 * OLEClipbrd_IEnumFORMATETC_AddRef (IUnknown)
1646 * Since enumerating formats only makes sense when our data object is around,
1647 * we insure that it stays as long as we stay by calling our parents IUnknown
1648 * for AddRef and Release. But since we are not controlled by the lifetime of
1649 * the outer object, we still keep our own reference count in order to
1650 * free ourselves.
1652 static ULONG WINAPI OLEClipbrd_IEnumFORMATETC_AddRef(LPENUMFORMATETC iface)
1654 IEnumFORMATETCImpl *This = (IEnumFORMATETCImpl *)iface;
1655 TRACE("(%p)->(count=%lu)\n",This, This->ref);
1657 if (This->pUnkDataObj)
1658 IUnknown_AddRef(This->pUnkDataObj);
1660 return InterlockedIncrement(&This->ref);
1663 /************************************************************************
1664 * OLEClipbrd_IEnumFORMATETC_Release (IUnknown)
1666 * See Windows documentation for more details on IUnknown methods.
1668 static ULONG WINAPI OLEClipbrd_IEnumFORMATETC_Release(LPENUMFORMATETC iface)
1670 IEnumFORMATETCImpl *This = (IEnumFORMATETCImpl *)iface;
1671 LPMALLOC pIMalloc;
1672 ULONG ref;
1674 TRACE("(%p)->(count=%lu)\n",This, This->ref);
1676 if (This->pUnkDataObj)
1677 IUnknown_Release(This->pUnkDataObj); /* Release parent data object */
1679 ref = InterlockedDecrement(&This->ref);
1680 if (!ref)
1682 TRACE("() - destroying IEnumFORMATETC(%p)\n",This);
1683 if (SUCCEEDED(CoGetMalloc(MEMCTX_TASK, &pIMalloc)))
1685 IMalloc_Free(pIMalloc, This->pFmt);
1686 IMalloc_Release(pIMalloc);
1689 HeapFree(GetProcessHeap(),0,This);
1691 return ref;
1694 /************************************************************************
1695 * OLEClipbrd_IEnumFORMATETC_Next (IEnumFORMATETC)
1697 * Standard enumerator members for IEnumFORMATETC
1699 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Next
1700 (LPENUMFORMATETC iface, ULONG celt, FORMATETC *rgelt, ULONG *pceltFethed)
1702 IEnumFORMATETCImpl *This = (IEnumFORMATETCImpl *)iface;
1703 UINT cfetch;
1704 HRESULT hres = S_FALSE;
1706 TRACE("(%p)->(pos=%u)\n", This, This->posFmt);
1708 if (This->posFmt < This->countFmt)
1710 cfetch = This->countFmt - This->posFmt;
1711 if (cfetch >= celt)
1713 cfetch = celt;
1714 hres = S_OK;
1717 memcpy(rgelt, &This->pFmt[This->posFmt], cfetch * sizeof(FORMATETC));
1718 This->posFmt += cfetch;
1720 else
1722 cfetch = 0;
1725 if (pceltFethed)
1727 *pceltFethed = cfetch;
1730 return hres;
1733 /************************************************************************
1734 * OLEClipbrd_IEnumFORMATETC_Skip (IEnumFORMATETC)
1736 * Standard enumerator members for IEnumFORMATETC
1738 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Skip(LPENUMFORMATETC iface, ULONG celt)
1740 IEnumFORMATETCImpl *This = (IEnumFORMATETCImpl *)iface;
1741 TRACE("(%p)->(num=%lu)\n", This, celt);
1743 This->posFmt += celt;
1744 if (This->posFmt > This->countFmt)
1746 This->posFmt = This->countFmt;
1747 return S_FALSE;
1749 return S_OK;
1752 /************************************************************************
1753 * OLEClipbrd_IEnumFORMATETC_Reset (IEnumFORMATETC)
1755 * Standard enumerator members for IEnumFORMATETC
1757 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Reset(LPENUMFORMATETC iface)
1759 IEnumFORMATETCImpl *This = (IEnumFORMATETCImpl *)iface;
1760 TRACE("(%p)->()\n", This);
1762 This->posFmt = 0;
1763 return S_OK;
1766 /************************************************************************
1767 * OLEClipbrd_IEnumFORMATETC_Clone (IEnumFORMATETC)
1769 * Standard enumerator members for IEnumFORMATETC
1771 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Clone
1772 (LPENUMFORMATETC iface, LPENUMFORMATETC* ppenum)
1774 IEnumFORMATETCImpl *This = (IEnumFORMATETCImpl *)iface;
1775 HRESULT hr = S_OK;
1777 TRACE("(%p)->(ppenum=%p)\n", This, ppenum);
1779 if ( !ppenum )
1780 return E_INVALIDARG;
1782 *ppenum = OLEClipbrd_IEnumFORMATETC_Construct(This->countFmt,
1783 This->pFmt,
1784 This->pUnkDataObj);
1786 if (FAILED( hr = IEnumFORMATETC_AddRef(*ppenum)))
1787 return ( hr );
1789 return (*ppenum) ? S_OK : E_OUTOFMEMORY;