user32/tests: Test for failure to change system parameters even if getting them succe...
[wine/multimedia.git] / dlls / ole32 / clipboard.c
blobb33cb5256600757fcf5c748ecedfaef5289d5810
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, 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 #include "compobj_private.h"
83 WINE_DEFAULT_DEBUG_CHANNEL(ole);
85 #define HANDLE_ERROR(err) do { hr = err; TRACE("(HRESULT=%x)\n", (HRESULT)err); goto CLEANUP; } while (0)
88 /****************************************************************************
89 * OLEClipbrd
90 * DO NOT add any members before the VTables declaration!
92 struct OLEClipbrd
95 * List all interface VTables here
97 const 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 LONG 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 const 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 LONG 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 void OLEClipbrd_Initialize(void);
174 void OLEClipbrd_UnInitialize(void);
175 static OLEClipbrd* OLEClipbrd_Construct(void);
176 static void OLEClipbrd_Destroy(OLEClipbrd* ptrToDestroy);
177 static HWND OLEClipbrd_CreateWindow(void);
178 static void OLEClipbrd_DestroyWindow(HWND hwnd);
179 static 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 const 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 const 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 static const 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;
319 struct oletls *info = COM_CurrentInfo();
321 HGLOBAL hDataObject = 0;
322 OLEClipbrd **ppDataObject;
325 TRACE("(%p)\n", pDataObj);
327 if(!info)
328 WARN("Could not allocate tls\n");
329 else
330 if(!info->ole_inits)
331 return CO_E_NOTINITIALIZED;
334 * Make sure we have a clipboard object
336 OLEClipbrd_Initialize();
339 * If the Ole clipboard window hasn't been created yet, create it now.
341 if ( !theOleClipboard->hWndClipboard )
342 theOleClipboard->hWndClipboard = OLEClipbrd_CreateWindow();
344 if ( !theOleClipboard->hWndClipboard ) /* sanity check */
345 HANDLE_ERROR( E_FAIL );
348 * Open the Windows clipboard, associating it with our hidden window
350 if ( !(bClipboardOpen = OpenClipboard(theOleClipboard->hWndClipboard)) )
351 HANDLE_ERROR( CLIPBRD_E_CANT_OPEN );
354 * Empty the current clipboard and make our window the clipboard owner
355 * NOTE: This will trigger a WM_DESTROYCLIPBOARD message
357 if ( !EmptyClipboard() )
358 HANDLE_ERROR( CLIPBRD_E_CANT_EMPTY );
361 * If we are already holding on to an IDataObject first release that.
363 if ( theOleClipboard->pIDataObjectSrc )
365 IDataObject_Release(theOleClipboard->pIDataObjectSrc);
366 theOleClipboard->pIDataObjectSrc = NULL;
370 * AddRef the data object passed in and save its pointer.
371 * A NULL value indicates that the clipboard should be emptied.
373 theOleClipboard->pIDataObjectSrc = pDataObj;
374 if ( pDataObj )
376 IDataObject_AddRef(theOleClipboard->pIDataObjectSrc);
380 * Enumerate all HGLOBAL formats supported by the source and make
381 * those formats available using delayed rendering using SetClipboardData.
382 * Only global memory based data items may be made available to non-OLE
383 * applications via the standard Windows clipboard API. Data based on other
384 * mediums(non TYMED_HGLOBAL) can only be accessed via the Ole Clipboard API.
386 * TODO: Do we need to additionally handle TYMED_IStorage media by copying
387 * the storage into global memory?
389 if ( pDataObj )
391 if ( FAILED(hr = IDataObject_EnumFormatEtc( pDataObj,
392 DATADIR_GET,
393 &penumFormatetc )))
395 HANDLE_ERROR( hr );
398 while ( S_OK == IEnumFORMATETC_Next(penumFormatetc, 1, &rgelt, NULL) )
400 if ( rgelt.tymed == TYMED_HGLOBAL )
402 CHAR szFmtName[80];
403 TRACE("(cfFormat=%d:%s)\n", rgelt.cfFormat,
404 GetClipboardFormatNameA(rgelt.cfFormat, szFmtName, sizeof(szFmtName)-1)
405 ? szFmtName : "");
407 SetClipboardData( rgelt.cfFormat, NULL);
410 IEnumFORMATETC_Release(penumFormatetc);
414 * Windows additionally creates a new "DataObject" clipboard format
415 * and stores in on the clipboard. We could possibly store a pointer
416 * to our internal IDataObject interface on the clipboard. I'm not
417 * sure what the use of this is though.
418 * Enable the code below for this functionality.
421 theOleClipboard->cfDataObj = RegisterClipboardFormatA("DataObject");
422 hDataObject = GlobalAlloc( GMEM_DDESHARE|GMEM_MOVEABLE|GMEM_ZEROINIT,
423 sizeof(OLEClipbrd *));
424 if (hDataObject==0)
425 HANDLE_ERROR( E_OUTOFMEMORY );
427 ppDataObject = GlobalLock(hDataObject);
428 *ppDataObject = theOleClipboard;
429 GlobalUnlock(hDataObject);
431 if ( !SetClipboardData( theOleClipboard->cfDataObj, hDataObject ) )
432 HANDLE_ERROR( CLIPBRD_E_CANT_SET );
435 hr = S_OK;
437 CLEANUP:
440 * Close Windows clipboard (It remains associated with our window)
442 if ( bClipboardOpen && !CloseClipboard() )
443 hr = CLIPBRD_E_CANT_CLOSE;
446 * Release the source IDataObject if something failed
448 if ( FAILED(hr) )
450 if (theOleClipboard->pIDataObjectSrc)
452 IDataObject_Release(theOleClipboard->pIDataObjectSrc);
453 theOleClipboard->pIDataObjectSrc = NULL;
457 return hr;
461 /***********************************************************************
462 * OleGetClipboard [OLE32.@]
463 * Returns a pointer to our internal IDataObject which represents the conceptual
464 * state of the Windows clipboard. If the current clipboard already contains
465 * an IDataObject, our internal IDataObject will delegate to this object.
467 HRESULT WINAPI OleGetClipboard(IDataObject** ppDataObj)
469 HRESULT hr = S_OK;
470 TRACE("()\n");
473 * Make sure we have a clipboard object
475 OLEClipbrd_Initialize();
477 if (!theOleClipboard)
478 return E_OUTOFMEMORY;
480 /* Return a reference counted IDataObject */
481 hr = IDataObject_QueryInterface( (IDataObject*)&(theOleClipboard->lpvtbl1),
482 &IID_IDataObject, (void**)ppDataObj);
483 return hr;
486 /******************************************************************************
487 * OleFlushClipboard [OLE32.@]
488 * Renders the data from the source IDataObject into the windows clipboard
490 * TODO: OleFlushClipboard needs to additionally handle TYMED_IStorage media
491 * by copying the storage into global memory. Subsequently the default
492 * data object exposed through OleGetClipboard must convert this TYMED_HGLOBAL
493 * back to TYMED_IStorage.
495 HRESULT WINAPI OleFlushClipboard(void)
497 IEnumFORMATETC* penumFormatetc = NULL;
498 FORMATETC rgelt;
499 HRESULT hr = S_OK;
500 BOOL bClipboardOpen = FALSE;
501 IDataObject* pIDataObjectSrc = NULL;
503 TRACE("()\n");
506 * Make sure we have a clipboard object
508 OLEClipbrd_Initialize();
511 * Already flushed or no source DataObject? Nothing to do.
513 if (!theOleClipboard->pIDataObjectSrc)
514 return S_OK;
517 * Addref and save the source data object we are holding on to temporarily,
518 * since it will be released when we empty the clipboard.
520 pIDataObjectSrc = theOleClipboard->pIDataObjectSrc;
521 IDataObject_AddRef(pIDataObjectSrc);
524 * Open the Windows clipboard
526 if ( !(bClipboardOpen = OpenClipboard(theOleClipboard->hWndClipboard)) )
527 HANDLE_ERROR( CLIPBRD_E_CANT_OPEN );
530 * Empty the current clipboard
532 if ( !EmptyClipboard() )
533 HANDLE_ERROR( CLIPBRD_E_CANT_EMPTY );
536 * Render all HGLOBAL formats supported by the source into
537 * the windows clipboard.
539 if ( FAILED( hr = IDataObject_EnumFormatEtc( pIDataObjectSrc,
540 DATADIR_GET,
541 &penumFormatetc) ))
543 HANDLE_ERROR( hr );
546 while ( S_OK == IEnumFORMATETC_Next(penumFormatetc, 1, &rgelt, NULL) )
548 if ( rgelt.tymed == TYMED_HGLOBAL )
550 CHAR szFmtName[80];
551 TRACE("(cfFormat=%d:%s)\n", rgelt.cfFormat,
552 GetClipboardFormatNameA(rgelt.cfFormat, szFmtName, sizeof(szFmtName)-1)
553 ? szFmtName : "");
556 * Render the clipboard data
558 if ( FAILED(OLEClipbrd_RenderFormat( pIDataObjectSrc, &rgelt )) )
559 continue;
563 IEnumFORMATETC_Release(penumFormatetc);
566 * Release the source data object we are holding on to
568 IDataObject_Release(pIDataObjectSrc);
570 CLEANUP:
573 * Close Windows clipboard (It remains associated with our window)
575 if ( bClipboardOpen && !CloseClipboard() )
576 hr = CLIPBRD_E_CANT_CLOSE;
578 return hr;
582 /***********************************************************************
583 * OleIsCurrentClipboard [OLE32.@]
585 HRESULT WINAPI OleIsCurrentClipboard(IDataObject *pDataObject)
587 TRACE("()\n");
589 * Make sure we have a clipboard object
591 OLEClipbrd_Initialize();
593 if (!theOleClipboard)
594 return E_OUTOFMEMORY;
596 if (pDataObject == NULL)
597 return S_FALSE;
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(void)
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(void)
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(void)
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(void)
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 = 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 static 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 message 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 if (!GetClipboardFormatNameA(pFormatetc->cfFormat, szFmtName, MAX_CLIPFORMAT_NAME))
931 szFmtName[0] = '\0';
933 /* If embed source */
934 if (!strcmp(szFmtName, CF_EMBEDSOURCE))
936 memset(&std, 0, sizeof(STGMEDIUM));
937 std.tymed = pFormatetc->tymed = TYMED_ISTORAGE;
939 hStorage = GlobalAlloc(GMEM_SHARE|GMEM_MOVEABLE, 0);
940 if (hStorage == NULL)
941 HANDLE_ERROR( E_OUTOFMEMORY );
942 hr = CreateILockBytesOnHGlobal(hStorage, FALSE, &ptrILockBytes);
943 hr = StgCreateDocfileOnILockBytes(ptrILockBytes, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &std.u.pstg);
945 if (FAILED(hr = IDataObject_GetDataHere(theOleClipboard->pIDataObjectSrc, pFormatetc, &std)))
947 WARN("() : IDataObject_GetDataHere failed to render clipboard data! (%x)\n", hr);
948 GlobalFree(hStorage);
949 return hr;
952 if (1) /* check whether the presentation data is already -not- present */
954 FORMATETC fmt2;
955 STGMEDIUM std2;
956 METAFILEPICT *mfp = 0;
958 fmt2.cfFormat = CF_METAFILEPICT;
959 fmt2.ptd = 0;
960 fmt2.dwAspect = DVASPECT_CONTENT;
961 fmt2.lindex = -1;
962 fmt2.tymed = TYMED_MFPICT;
964 memset(&std2, 0, sizeof(STGMEDIUM));
965 std2.tymed = TYMED_MFPICT;
967 /* Get the metafile picture out of it */
969 if (SUCCEEDED(hr = IDataObject_GetData(theOleClipboard->pIDataObjectSrc, &fmt2, &std2)))
971 mfp = GlobalLock(std2.u.hGlobal);
974 if (mfp)
976 OLECHAR name[]={ 2, 'O', 'l', 'e', 'P', 'r', 'e', 's', '0', '0', '0', 0};
977 IStream *pStream = 0;
978 void *mfBits;
979 PresentationDataHeader pdh;
980 INT nSize;
981 CLSID clsID;
982 LPOLESTR strProgID;
983 CHAR strOleTypeName[51];
984 BYTE OlePresStreamHeader [] =
986 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00,
987 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
988 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
989 0x00, 0x00, 0x00, 0x00
992 nSize = GetMetaFileBitsEx(mfp->hMF, 0, NULL);
994 memset(&pdh, 0, sizeof(PresentationDataHeader));
995 memcpy(&pdh, OlePresStreamHeader, sizeof(OlePresStreamHeader));
997 pdh.dwObjectExtentX = mfp->xExt;
998 pdh.dwObjectExtentY = mfp->yExt;
999 pdh.dwSize = nSize;
1001 hr = IStorage_CreateStream(std.u.pstg, name, STGM_CREATE|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, 0, &pStream);
1003 hr = IStream_Write(pStream, &pdh, sizeof(PresentationDataHeader), NULL);
1005 mfBits = HeapAlloc(GetProcessHeap(), 0, nSize);
1006 nSize = GetMetaFileBitsEx(mfp->hMF, nSize, mfBits);
1008 hr = IStream_Write(pStream, mfBits, nSize, NULL);
1010 IStream_Release(pStream);
1012 HeapFree(GetProcessHeap(), 0, mfBits);
1014 GlobalUnlock(std2.u.hGlobal);
1016 ReadClassStg(std.u.pstg, &clsID);
1017 ProgIDFromCLSID(&clsID, &strProgID);
1019 WideCharToMultiByte( CP_ACP, 0, strProgID, -1, strOleTypeName, sizeof(strOleTypeName), NULL, NULL );
1020 OLECONVERT_CreateOleStream(std.u.pstg);
1021 OLECONVERT_CreateCompObjStream(std.u.pstg, strOleTypeName);
1025 else
1027 if (FAILED(hr = IDataObject_GetData(pIDataObject, pFormatetc, &std)))
1029 WARN("() : IDataObject_GetData failed to render clipboard data! (%x)\n", hr);
1030 GlobalFree(hStorage);
1031 return hr;
1034 /* To put a copy back on the clipboard */
1036 hStorage = std.u.hGlobal;
1040 * Put a copy of the rendered data back on the clipboard
1043 if ( !(hDup = OLEClipbrd_GlobalDupMem(hStorage)) )
1044 HANDLE_ERROR( E_OUTOFMEMORY );
1046 if ( !SetClipboardData( pFormatetc->cfFormat, hDup ) )
1048 GlobalFree(hDup);
1049 WARN("() : Failed to set rendered clipboard data into clipboard!\n");
1052 CLEANUP:
1054 ReleaseStgMedium(&std);
1056 return hr;
1060 /***********************************************************************
1061 * OLEClipbrd_GlobalDupMem( HGLOBAL )
1062 * Helper method to duplicate an HGLOBAL chunk of memory
1064 static HGLOBAL OLEClipbrd_GlobalDupMem( HGLOBAL hGlobalSrc )
1066 HGLOBAL hGlobalDest;
1067 PVOID pGlobalSrc, pGlobalDest;
1068 DWORD cBytes;
1070 if ( !hGlobalSrc )
1071 return 0;
1073 cBytes = GlobalSize(hGlobalSrc);
1074 if ( 0 == cBytes )
1075 return 0;
1077 hGlobalDest = GlobalAlloc( GMEM_DDESHARE|GMEM_MOVEABLE,
1078 cBytes );
1079 if ( !hGlobalDest )
1080 return 0;
1082 pGlobalSrc = GlobalLock(hGlobalSrc);
1083 pGlobalDest = GlobalLock(hGlobalDest);
1084 if ( !pGlobalSrc || !pGlobalDest )
1086 GlobalFree(hGlobalDest);
1087 return 0;
1090 memcpy(pGlobalDest, pGlobalSrc, cBytes);
1092 GlobalUnlock(hGlobalSrc);
1093 GlobalUnlock(hGlobalDest);
1095 return hGlobalDest;
1099 /*---------------------------------------------------------------------*
1100 * Implementation of the internal IDataObject interface exposed by
1101 * the OLE clipboard.
1102 *---------------------------------------------------------------------*/
1105 /************************************************************************
1106 * OLEClipbrd_IDataObject_QueryInterface (IUnknown)
1108 * See Windows documentation for more details on IUnknown methods.
1110 static HRESULT WINAPI OLEClipbrd_IDataObject_QueryInterface(
1111 IDataObject* iface,
1112 REFIID riid,
1113 void** ppvObject)
1116 * Declare "This" pointer
1118 OLEClipbrd *This = (OLEClipbrd *)iface;
1119 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObject);
1122 * Perform a sanity check on the parameters.
1124 if ( (This==0) || (ppvObject==0) )
1125 return E_INVALIDARG;
1128 * Initialize the return parameter.
1130 *ppvObject = 0;
1133 * Compare the riid with the interface IDs implemented by this object.
1135 if (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0)
1137 *ppvObject = iface;
1139 else if (memcmp(&IID_IDataObject, riid, sizeof(IID_IDataObject)) == 0)
1141 *ppvObject = &This->lpvtbl1;
1143 else /* We only support IUnknown and IDataObject */
1145 WARN( "() : asking for unsupported interface %s\n", debugstr_guid(riid));
1146 return E_NOINTERFACE;
1150 * Query Interface always increases the reference count by one when it is
1151 * successful.
1153 IUnknown_AddRef((IUnknown*)*ppvObject);
1155 return S_OK;
1158 /************************************************************************
1159 * OLEClipbrd_IDataObject_AddRef (IUnknown)
1161 * See Windows documentation for more details on IUnknown methods.
1163 static ULONG WINAPI OLEClipbrd_IDataObject_AddRef(
1164 IDataObject* iface)
1167 * Declare "This" pointer
1169 OLEClipbrd *This = (OLEClipbrd *)iface;
1171 TRACE("(%p)->(count=%u)\n",This, This->ref);
1173 return InterlockedIncrement(&This->ref);
1177 /************************************************************************
1178 * OLEClipbrd_IDataObject_Release (IUnknown)
1180 * See Windows documentation for more details on IUnknown methods.
1182 static ULONG WINAPI OLEClipbrd_IDataObject_Release(
1183 IDataObject* iface)
1186 * Declare "This" pointer
1188 OLEClipbrd *This = (OLEClipbrd *)iface;
1189 ULONG ref;
1191 TRACE("(%p)->(count=%u)\n",This, This->ref);
1194 * Decrease the reference count on this object.
1196 ref = InterlockedDecrement(&This->ref);
1199 * If the reference count goes down to 0, perform suicide.
1201 if (ref == 0)
1203 OLEClipbrd_Destroy(This);
1206 return ref;
1210 /************************************************************************
1211 * OLEClipbrd_IDataObject_GetData (IDataObject)
1213 * The OLE Clipboard's implementation of this method delegates to
1214 * a data source if there is one or wraps around the windows clipboard
1216 * See Windows documentation for more details on IDataObject methods.
1218 static HRESULT WINAPI OLEClipbrd_IDataObject_GetData(
1219 IDataObject* iface,
1220 LPFORMATETC pformatetcIn,
1221 STGMEDIUM* pmedium)
1223 HANDLE hData = 0;
1224 BOOL bClipboardOpen = FALSE;
1225 HRESULT hr = S_OK;
1226 LPVOID src;
1229 * Declare "This" pointer
1231 OLEClipbrd *This = (OLEClipbrd *)iface;
1233 TRACE("(%p,%p,%p)\n", iface, pformatetcIn, pmedium);
1235 if ( !pformatetcIn || !pmedium )
1236 return E_INVALIDARG;
1239 * If we have a data source placed on the clipboard (via OleSetClipboard)
1240 * simply delegate to the source object's QueryGetData
1241 * NOTE: This code assumes that the IDataObject is in the same address space!
1242 * We will need to add marshalling support when Wine handles multiple processes.
1244 if ( This->pIDataObjectSrc )
1246 return IDataObject_GetData(This->pIDataObjectSrc, pformatetcIn, pmedium);
1249 if ( pformatetcIn->lindex != -1 )
1250 return DV_E_FORMATETC;
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 = 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)
1329 TRACE("(%p, %p)\n", iface, pformatetc);
1331 if (!pformatetc)
1332 return E_INVALIDARG;
1334 if ( pformatetc->dwAspect != DVASPECT_CONTENT )
1335 return DV_E_FORMATETC;
1337 if ( pformatetc->lindex != -1 )
1338 return DV_E_FORMATETC;
1341 * Delegate to the Windows clipboard function IsClipboardFormatAvailable
1343 return (IsClipboardFormatAvailable(pformatetc->cfFormat)) ? S_OK : DV_E_CLIPFORMAT;
1346 /************************************************************************
1347 * OLEClipbrd_IDataObject_GetCanonicalFormatEtc (IDataObject)
1349 * See Windows documentation for more details on IDataObject methods.
1351 static HRESULT WINAPI OLEClipbrd_IDataObject_GetCanonicalFormatEtc(
1352 IDataObject* iface,
1353 LPFORMATETC pformatectIn,
1354 LPFORMATETC pformatetcOut)
1356 TRACE("(%p, %p, %p)\n", iface, pformatectIn, pformatetcOut);
1358 if ( !pformatectIn || !pformatetcOut )
1359 return E_INVALIDARG;
1361 *pformatetcOut = *pformatectIn;
1362 return DATA_S_SAMEFORMATETC;
1365 /************************************************************************
1366 * OLEClipbrd_IDataObject_SetData (IDataObject)
1368 * The OLE Clipboard's does not implement this method
1370 * See Windows documentation for more details on IDataObject methods.
1372 static HRESULT WINAPI OLEClipbrd_IDataObject_SetData(
1373 IDataObject* iface,
1374 LPFORMATETC pformatetc,
1375 STGMEDIUM* pmedium,
1376 BOOL fRelease)
1378 TRACE("\n");
1379 return E_NOTIMPL;
1382 /************************************************************************
1383 * OLEClipbrd_IDataObject_EnumFormatEtc (IDataObject)
1385 * See Windows documentation for more details on IDataObject methods.
1387 static HRESULT WINAPI OLEClipbrd_IDataObject_EnumFormatEtc(
1388 IDataObject* iface,
1389 DWORD dwDirection,
1390 IEnumFORMATETC** ppenumFormatEtc)
1392 HRESULT hr = S_OK;
1393 FORMATETC *afmt = NULL;
1394 int cfmt, i;
1395 UINT format;
1396 BOOL bClipboardOpen;
1399 * Declare "This" pointer
1401 OLEClipbrd *This = (OLEClipbrd *)iface;
1403 TRACE("(%p, %x, %p)\n", iface, dwDirection, ppenumFormatEtc);
1406 * If we have a data source placed on the clipboard (via OleSetClipboard)
1407 * simply delegate to the source object's EnumFormatEtc
1409 if ( This->pIDataObjectSrc )
1411 return IDataObject_EnumFormatEtc(This->pIDataObjectSrc,
1412 dwDirection, ppenumFormatEtc);
1416 * Otherwise we must provide our own enumerator which wraps around the
1417 * Windows clipboard function EnumClipboardFormats
1419 if ( !ppenumFormatEtc )
1420 return E_INVALIDARG;
1422 if ( dwDirection != DATADIR_GET ) /* IDataObject_SetData not implemented */
1423 return E_NOTIMPL;
1426 * Store all current clipboard formats in an array of FORMATETC's,
1427 * and create an IEnumFORMATETC enumerator from this list.
1429 cfmt = CountClipboardFormats();
1430 afmt = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1431 sizeof(FORMATETC) * cfmt);
1433 * Open the Windows clipboard, associating it with our hidden window
1435 if ( !(bClipboardOpen = OpenClipboard(This->hWndClipboard)) )
1436 HANDLE_ERROR( CLIPBRD_E_CANT_OPEN );
1439 * Store all current clipboard formats in an array of FORMATETC's
1440 * TODO: Handle TYMED_IStorage media which were put on the clipboard
1441 * by copying the storage into global memory. We must convert this
1442 * TYMED_HGLOBAL back to TYMED_IStorage.
1444 for (i = 0, format = 0; i < cfmt; i++)
1446 format = EnumClipboardFormats(format);
1447 if (!format) /* Failed! */
1449 ERR("EnumClipboardFormats failed to return format!\n");
1450 HANDLE_ERROR( E_FAIL );
1453 /* Init the FORMATETC struct */
1454 afmt[i].cfFormat = format;
1455 afmt[i].ptd = NULL;
1456 afmt[i].dwAspect = DVASPECT_CONTENT;
1457 afmt[i].lindex = -1;
1458 afmt[i].tymed = TYMED_HGLOBAL;
1462 * Create an EnumFORMATETC enumerator and return an
1463 * EnumFORMATETC after bumping up its ref count
1465 *ppenumFormatEtc = OLEClipbrd_IEnumFORMATETC_Construct( cfmt, afmt, (LPUNKNOWN)iface);
1466 if (!(*ppenumFormatEtc))
1467 HANDLE_ERROR( E_OUTOFMEMORY );
1469 if (FAILED( hr = IEnumFORMATETC_AddRef(*ppenumFormatEtc)))
1470 HANDLE_ERROR( hr );
1472 hr = S_OK;
1474 CLEANUP:
1476 * Free the array of FORMATETC's
1478 HeapFree(GetProcessHeap(), 0, afmt);
1481 * Close Windows clipboard
1483 if ( bClipboardOpen && !CloseClipboard() )
1484 hr = CLIPBRD_E_CANT_CLOSE;
1486 return hr;
1489 /************************************************************************
1490 * OLEClipbrd_IDataObject_DAdvise (IDataObject)
1492 * The OLE Clipboard's does not implement this method
1494 * See Windows documentation for more details on IDataObject methods.
1496 static HRESULT WINAPI OLEClipbrd_IDataObject_DAdvise(
1497 IDataObject* iface,
1498 FORMATETC* pformatetc,
1499 DWORD advf,
1500 IAdviseSink* pAdvSink,
1501 DWORD* pdwConnection)
1503 TRACE("\n");
1504 return E_NOTIMPL;
1507 /************************************************************************
1508 * OLEClipbrd_IDataObject_DUnadvise (IDataObject)
1510 * The OLE Clipboard's does not implement this method
1512 * See Windows documentation for more details on IDataObject methods.
1514 static HRESULT WINAPI OLEClipbrd_IDataObject_DUnadvise(
1515 IDataObject* iface,
1516 DWORD dwConnection)
1518 TRACE("\n");
1519 return E_NOTIMPL;
1522 /************************************************************************
1523 * OLEClipbrd_IDataObject_EnumDAdvise (IDataObject)
1525 * The OLE Clipboard does not implement this method
1527 * See Windows documentation for more details on IDataObject methods.
1529 static HRESULT WINAPI OLEClipbrd_IDataObject_EnumDAdvise(
1530 IDataObject* iface,
1531 IEnumSTATDATA** ppenumAdvise)
1533 TRACE("\n");
1534 return E_NOTIMPL;
1538 /*---------------------------------------------------------------------*
1539 * Implementation of the internal IEnumFORMATETC interface returned by
1540 * the OLE clipboard's IDataObject.
1541 *---------------------------------------------------------------------*/
1543 /************************************************************************
1544 * OLEClipbrd_IEnumFORMATETC_Construct (UINT, const FORMATETC, LPUNKNOWN)
1546 * Creates an IEnumFORMATETC enumerator from an array of FORMATETC
1547 * Structures. pUnkOuter is the outer unknown for reference counting only.
1548 * NOTE: this does not AddRef the interface.
1551 static LPENUMFORMATETC OLEClipbrd_IEnumFORMATETC_Construct(UINT cfmt, const FORMATETC afmt[],
1552 LPUNKNOWN pUnkDataObj)
1554 IEnumFORMATETCImpl* ef;
1555 DWORD size=cfmt * sizeof(FORMATETC);
1556 LPMALLOC pIMalloc;
1558 ef = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IEnumFORMATETCImpl));
1559 if (!ef)
1560 return NULL;
1562 ef->ref = 0;
1563 ef->lpVtbl = &efvt;
1564 ef->pUnkDataObj = pUnkDataObj;
1566 ef->posFmt = 0;
1567 ef->countFmt = cfmt;
1568 if (FAILED(CoGetMalloc(MEMCTX_TASK, &pIMalloc))) {
1569 HeapFree(GetProcessHeap(), 0, ef);
1570 return NULL;
1572 ef->pFmt = IMalloc_Alloc(pIMalloc, size);
1573 IMalloc_Release(pIMalloc);
1575 if (ef->pFmt)
1576 memcpy(ef->pFmt, afmt, size);
1578 TRACE("(%p)->()\n",ef);
1579 return (LPENUMFORMATETC)ef;
1583 /************************************************************************
1584 * OLEClipbrd_IEnumFORMATETC_QueryInterface (IUnknown)
1586 * See Windows documentation for more details on IUnknown methods.
1588 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_QueryInterface
1589 (LPENUMFORMATETC iface, REFIID riid, LPVOID* ppvObj)
1591 IEnumFORMATETCImpl *This = (IEnumFORMATETCImpl *)iface;
1593 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
1596 * Since enumerators are separate objects from the parent data object
1597 * we only need to support the IUnknown and IEnumFORMATETC interfaces
1600 *ppvObj = NULL;
1602 if(IsEqualIID(riid, &IID_IUnknown))
1604 *ppvObj = This;
1606 else if(IsEqualIID(riid, &IID_IEnumFORMATETC))
1608 *ppvObj = This;
1611 if(*ppvObj)
1613 IEnumFORMATETC_AddRef((IEnumFORMATETC*)*ppvObj);
1614 TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
1615 return S_OK;
1618 TRACE("-- Interface: E_NOINTERFACE\n");
1619 return E_NOINTERFACE;
1622 /************************************************************************
1623 * OLEClipbrd_IEnumFORMATETC_AddRef (IUnknown)
1625 * Since enumerating formats only makes sense when our data object is around,
1626 * we insure that it stays as long as we stay by calling our parents IUnknown
1627 * for AddRef and Release. But since we are not controlled by the lifetime of
1628 * the outer object, we still keep our own reference count in order to
1629 * free ourselves.
1631 static ULONG WINAPI OLEClipbrd_IEnumFORMATETC_AddRef(LPENUMFORMATETC iface)
1633 IEnumFORMATETCImpl *This = (IEnumFORMATETCImpl *)iface;
1634 TRACE("(%p)->(count=%u)\n",This, This->ref);
1636 if (This->pUnkDataObj)
1637 IUnknown_AddRef(This->pUnkDataObj);
1639 return InterlockedIncrement(&This->ref);
1642 /************************************************************************
1643 * OLEClipbrd_IEnumFORMATETC_Release (IUnknown)
1645 * See Windows documentation for more details on IUnknown methods.
1647 static ULONG WINAPI OLEClipbrd_IEnumFORMATETC_Release(LPENUMFORMATETC iface)
1649 IEnumFORMATETCImpl *This = (IEnumFORMATETCImpl *)iface;
1650 LPMALLOC pIMalloc;
1651 ULONG ref;
1653 TRACE("(%p)->(count=%u)\n",This, This->ref);
1655 if (This->pUnkDataObj)
1656 IUnknown_Release(This->pUnkDataObj); /* Release parent data object */
1658 ref = InterlockedDecrement(&This->ref);
1659 if (!ref)
1661 TRACE("() - destroying IEnumFORMATETC(%p)\n",This);
1662 if (SUCCEEDED(CoGetMalloc(MEMCTX_TASK, &pIMalloc)))
1664 IMalloc_Free(pIMalloc, This->pFmt);
1665 IMalloc_Release(pIMalloc);
1668 HeapFree(GetProcessHeap(),0,This);
1670 return ref;
1673 /************************************************************************
1674 * OLEClipbrd_IEnumFORMATETC_Next (IEnumFORMATETC)
1676 * Standard enumerator members for IEnumFORMATETC
1678 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Next
1679 (LPENUMFORMATETC iface, ULONG celt, FORMATETC *rgelt, ULONG *pceltFethed)
1681 IEnumFORMATETCImpl *This = (IEnumFORMATETCImpl *)iface;
1682 UINT cfetch;
1683 HRESULT hres = S_FALSE;
1685 TRACE("(%p)->(pos=%u)\n", This, This->posFmt);
1687 if (This->posFmt < This->countFmt)
1689 cfetch = This->countFmt - This->posFmt;
1690 if (cfetch >= celt)
1692 cfetch = celt;
1693 hres = S_OK;
1696 memcpy(rgelt, &This->pFmt[This->posFmt], cfetch * sizeof(FORMATETC));
1697 This->posFmt += cfetch;
1699 else
1701 cfetch = 0;
1704 if (pceltFethed)
1706 *pceltFethed = cfetch;
1709 return hres;
1712 /************************************************************************
1713 * OLEClipbrd_IEnumFORMATETC_Skip (IEnumFORMATETC)
1715 * Standard enumerator members for IEnumFORMATETC
1717 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Skip(LPENUMFORMATETC iface, ULONG celt)
1719 IEnumFORMATETCImpl *This = (IEnumFORMATETCImpl *)iface;
1720 TRACE("(%p)->(num=%u)\n", This, celt);
1722 This->posFmt += celt;
1723 if (This->posFmt > This->countFmt)
1725 This->posFmt = This->countFmt;
1726 return S_FALSE;
1728 return S_OK;
1731 /************************************************************************
1732 * OLEClipbrd_IEnumFORMATETC_Reset (IEnumFORMATETC)
1734 * Standard enumerator members for IEnumFORMATETC
1736 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Reset(LPENUMFORMATETC iface)
1738 IEnumFORMATETCImpl *This = (IEnumFORMATETCImpl *)iface;
1739 TRACE("(%p)->()\n", This);
1741 This->posFmt = 0;
1742 return S_OK;
1745 /************************************************************************
1746 * OLEClipbrd_IEnumFORMATETC_Clone (IEnumFORMATETC)
1748 * Standard enumerator members for IEnumFORMATETC
1750 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Clone
1751 (LPENUMFORMATETC iface, LPENUMFORMATETC* ppenum)
1753 IEnumFORMATETCImpl *This = (IEnumFORMATETCImpl *)iface;
1754 HRESULT hr = S_OK;
1756 TRACE("(%p)->(ppenum=%p)\n", This, ppenum);
1758 if ( !ppenum )
1759 return E_INVALIDARG;
1761 *ppenum = OLEClipbrd_IEnumFORMATETC_Construct(This->countFmt,
1762 This->pFmt,
1763 This->pUnkDataObj);
1765 if (FAILED( hr = IEnumFORMATETC_AddRef(*ppenum)))
1766 return ( hr );
1768 return (*ppenum) ? S_OK : E_OUTOFMEMORY;