ole32: Superfluous semicolons fix.
[wine/wine64.git] / dlls / ole32 / clipboard.c
bloba3586542d093193a8e9455ae4f0398a6df5584d6
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 #define HANDLE_ERROR(err) do { hr = err; TRACE("(HRESULT=%x)\n", (HRESULT)err); goto CLEANUP; } while (0)
85 WINE_DEFAULT_DEBUG_CHANNEL(ole);
87 /****************************************************************************
88 * OLEClipbrd
89 * DO NOT add any members before the VTables declaration!
91 struct OLEClipbrd
94 * List all interface VTables here
96 const IDataObjectVtbl* lpvtbl1; /* IDataObject VTable */
99 * The hidden OLE clipboard window. This window is used as the bridge between the
100 * the OLE and windows clipboard API. (Windows creates one such window per process)
102 HWND hWndClipboard;
105 * Pointer to the source data object (via OleSetClipboard)
107 IDataObject* pIDataObjectSrc;
110 * The registered DataObject clipboard format
112 UINT cfDataObj;
115 * The handle to ourself
117 HGLOBAL hSelf;
120 * Reference count of this object
122 LONG ref;
125 typedef struct OLEClipbrd OLEClipbrd;
128 /****************************************************************************
129 * IEnumFORMATETC implementation
130 * DO NOT add any members before the VTables declaration!
132 typedef struct
134 /* IEnumFORMATETC VTable */
135 const IEnumFORMATETCVtbl *lpVtbl;
137 /* IEnumFORMATETC fields */
138 UINT posFmt; /* current enumerator position */
139 UINT countFmt; /* number of EnumFORMATETC's in array */
140 LPFORMATETC pFmt; /* array of EnumFORMATETC's */
143 * Reference count of this object
145 LONG ref;
148 * IUnknown implementation of the parent data object.
150 IUnknown* pUnkDataObj;
152 } IEnumFORMATETCImpl;
154 typedef struct PresentationDataHeader
156 BYTE unknown1[28];
157 DWORD dwObjectExtentX;
158 DWORD dwObjectExtentY;
159 DWORD dwSize;
160 } PresentationDataHeader;
163 * The one and only OLEClipbrd object which is created by OLEClipbrd_Initialize()
165 static HGLOBAL hTheOleClipboard = 0;
166 static OLEClipbrd* theOleClipboard = NULL;
170 * Prototypes for the methods of the OLEClipboard class.
172 void OLEClipbrd_Initialize(void);
173 void OLEClipbrd_UnInitialize(void);
174 static OLEClipbrd* OLEClipbrd_Construct(void);
175 static void OLEClipbrd_Destroy(OLEClipbrd* ptrToDestroy);
176 static HWND OLEClipbrd_CreateWindow(void);
177 static void OLEClipbrd_DestroyWindow(HWND hwnd);
178 static LRESULT CALLBACK OLEClipbrd_WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
179 static HRESULT OLEClipbrd_RenderFormat( IDataObject *pIDataObject, LPFORMATETC pFormatetc );
180 static HGLOBAL OLEClipbrd_GlobalDupMem( HGLOBAL hGlobalSrc );
183 * Prototypes for the methods of the OLEClipboard class
184 * that implement IDataObject methods.
186 static HRESULT WINAPI OLEClipbrd_IDataObject_QueryInterface(
187 IDataObject* iface,
188 REFIID riid,
189 void** ppvObject);
190 static ULONG WINAPI OLEClipbrd_IDataObject_AddRef(
191 IDataObject* iface);
192 static ULONG WINAPI OLEClipbrd_IDataObject_Release(
193 IDataObject* iface);
194 static HRESULT WINAPI OLEClipbrd_IDataObject_GetData(
195 IDataObject* iface,
196 LPFORMATETC pformatetcIn,
197 STGMEDIUM* pmedium);
198 static HRESULT WINAPI OLEClipbrd_IDataObject_GetDataHere(
199 IDataObject* iface,
200 LPFORMATETC pformatetc,
201 STGMEDIUM* pmedium);
202 static HRESULT WINAPI OLEClipbrd_IDataObject_QueryGetData(
203 IDataObject* iface,
204 LPFORMATETC pformatetc);
205 static HRESULT WINAPI OLEClipbrd_IDataObject_GetCanonicalFormatEtc(
206 IDataObject* iface,
207 LPFORMATETC pformatectIn,
208 LPFORMATETC pformatetcOut);
209 static HRESULT WINAPI OLEClipbrd_IDataObject_SetData(
210 IDataObject* iface,
211 LPFORMATETC pformatetc,
212 STGMEDIUM* pmedium,
213 BOOL fRelease);
214 static HRESULT WINAPI OLEClipbrd_IDataObject_EnumFormatEtc(
215 IDataObject* iface,
216 DWORD dwDirection,
217 IEnumFORMATETC** ppenumFormatEtc);
218 static HRESULT WINAPI OLEClipbrd_IDataObject_DAdvise(
219 IDataObject* iface,
220 FORMATETC* pformatetc,
221 DWORD advf,
222 IAdviseSink* pAdvSink,
223 DWORD* pdwConnection);
224 static HRESULT WINAPI OLEClipbrd_IDataObject_DUnadvise(
225 IDataObject* iface,
226 DWORD dwConnection);
227 static HRESULT WINAPI OLEClipbrd_IDataObject_EnumDAdvise(
228 IDataObject* iface,
229 IEnumSTATDATA** ppenumAdvise);
232 * Prototypes for the IEnumFORMATETC methods.
234 static LPENUMFORMATETC OLEClipbrd_IEnumFORMATETC_Construct(UINT cfmt, const FORMATETC afmt[],
235 LPUNKNOWN pUnkDataObj);
236 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_QueryInterface(LPENUMFORMATETC iface, REFIID riid,
237 LPVOID* ppvObj);
238 static ULONG WINAPI OLEClipbrd_IEnumFORMATETC_AddRef(LPENUMFORMATETC iface);
239 static ULONG WINAPI OLEClipbrd_IEnumFORMATETC_Release(LPENUMFORMATETC iface);
240 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Next(LPENUMFORMATETC iface, ULONG celt,
241 FORMATETC* rgelt, ULONG* pceltFethed);
242 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Skip(LPENUMFORMATETC iface, ULONG celt);
243 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Reset(LPENUMFORMATETC iface);
244 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Clone(LPENUMFORMATETC iface, LPENUMFORMATETC* ppenum);
248 * Virtual function table for the OLEClipbrd's exposed IDataObject interface
250 static const IDataObjectVtbl OLEClipbrd_IDataObject_VTable =
252 OLEClipbrd_IDataObject_QueryInterface,
253 OLEClipbrd_IDataObject_AddRef,
254 OLEClipbrd_IDataObject_Release,
255 OLEClipbrd_IDataObject_GetData,
256 OLEClipbrd_IDataObject_GetDataHere,
257 OLEClipbrd_IDataObject_QueryGetData,
258 OLEClipbrd_IDataObject_GetCanonicalFormatEtc,
259 OLEClipbrd_IDataObject_SetData,
260 OLEClipbrd_IDataObject_EnumFormatEtc,
261 OLEClipbrd_IDataObject_DAdvise,
262 OLEClipbrd_IDataObject_DUnadvise,
263 OLEClipbrd_IDataObject_EnumDAdvise
267 * Virtual function table for IEnumFORMATETC interface
269 static const IEnumFORMATETCVtbl efvt =
271 OLEClipbrd_IEnumFORMATETC_QueryInterface,
272 OLEClipbrd_IEnumFORMATETC_AddRef,
273 OLEClipbrd_IEnumFORMATETC_Release,
274 OLEClipbrd_IEnumFORMATETC_Next,
275 OLEClipbrd_IEnumFORMATETC_Skip,
276 OLEClipbrd_IEnumFORMATETC_Reset,
277 OLEClipbrd_IEnumFORMATETC_Clone
281 * Name of our registered OLE clipboard window class
283 static const CHAR OLEClipbrd_WNDCLASS[] = "CLIPBRDWNDCLASS";
286 * If we need to store state info we can store it here.
287 * For now we don't need this functionality.
289 typedef struct tagClipboardWindowInfo
291 } ClipboardWindowInfo;
294 /*---------------------------------------------------------------------*
295 * Win32 OLE clipboard API
296 *---------------------------------------------------------------------*/
298 /***********************************************************************
299 * OleSetClipboard [OLE32.@]
300 * Places a pointer to the specified data object onto the clipboard,
301 * making the data object accessible to the OleGetClipboard function.
303 * RETURNS
305 * S_OK IDataObject pointer placed on the clipboard
306 * CLIPBRD_E_CANT_OPEN OpenClipboard failed
307 * CLIPBRD_E_CANT_EMPTY EmptyClipboard failed
308 * CLIPBRD_E_CANT_CLOSE CloseClipboard failed
309 * CLIPBRD_E_CANT_SET SetClipboard failed
312 HRESULT WINAPI OleSetClipboard(IDataObject* pDataObj)
314 HRESULT hr = S_OK;
315 IEnumFORMATETC* penumFormatetc = NULL;
316 FORMATETC rgelt;
317 BOOL bClipboardOpen = FALSE;
318 struct oletls *info = COM_CurrentInfo();
320 HGLOBAL hDataObject = 0;
321 OLEClipbrd **ppDataObject;
324 TRACE("(%p)\n", pDataObj);
326 if(!info)
327 WARN("Could not allocate tls\n");
328 else
329 if(!info->ole_inits)
330 return CO_E_NOTINITIALIZED;
333 * Make sure we have a clipboard object
335 OLEClipbrd_Initialize();
338 * If the Ole clipboard window hasn't been created yet, create it now.
340 if ( !theOleClipboard->hWndClipboard )
341 theOleClipboard->hWndClipboard = OLEClipbrd_CreateWindow();
343 if ( !theOleClipboard->hWndClipboard ) /* sanity check */
344 HANDLE_ERROR( E_FAIL );
347 * Open the Windows clipboard, associating it with our hidden window
349 if ( !(bClipboardOpen = OpenClipboard(theOleClipboard->hWndClipboard)) )
350 HANDLE_ERROR( CLIPBRD_E_CANT_OPEN );
353 * Empty the current clipboard and make our window the clipboard owner
354 * NOTE: This will trigger a WM_DESTROYCLIPBOARD message
356 if ( !EmptyClipboard() )
357 HANDLE_ERROR( CLIPBRD_E_CANT_EMPTY );
360 * If we are already holding on to an IDataObject first release that.
362 if ( theOleClipboard->pIDataObjectSrc )
364 IDataObject_Release(theOleClipboard->pIDataObjectSrc);
365 theOleClipboard->pIDataObjectSrc = NULL;
369 * AddRef the data object passed in and save its pointer.
370 * A NULL value indicates that the clipboard should be emptied.
372 theOleClipboard->pIDataObjectSrc = pDataObj;
373 if ( pDataObj )
375 IDataObject_AddRef(theOleClipboard->pIDataObjectSrc);
379 * Enumerate all HGLOBAL formats supported by the source and make
380 * those formats available using delayed rendering using SetClipboardData.
381 * Only global memory based data items may be made available to non-OLE
382 * applications via the standard Windows clipboard API. Data based on other
383 * mediums(non TYMED_HGLOBAL) can only be accessed via the Ole Clipboard API.
385 * TODO: Do we need to additionally handle TYMED_IStorage media by copying
386 * the storage into global memory?
388 if ( pDataObj )
390 if ( FAILED(hr = IDataObject_EnumFormatEtc( pDataObj,
391 DATADIR_GET,
392 &penumFormatetc )))
394 HANDLE_ERROR( hr );
397 while ( S_OK == IEnumFORMATETC_Next(penumFormatetc, 1, &rgelt, NULL) )
399 if ( rgelt.tymed == TYMED_HGLOBAL )
401 CHAR szFmtName[80];
402 TRACE("(cfFormat=%d:%s)\n", rgelt.cfFormat,
403 GetClipboardFormatNameA(rgelt.cfFormat, szFmtName, sizeof(szFmtName)-1)
404 ? szFmtName : "");
406 SetClipboardData( rgelt.cfFormat, NULL);
409 IEnumFORMATETC_Release(penumFormatetc);
413 * Windows additionally creates a new "DataObject" clipboard format
414 * and stores in on the clipboard. We could possibly store a pointer
415 * to our internal IDataObject interface on the clipboard. I'm not
416 * sure what the use of this is though.
417 * Enable the code below for this functionality.
420 theOleClipboard->cfDataObj = RegisterClipboardFormatA("DataObject");
421 hDataObject = GlobalAlloc( GMEM_DDESHARE|GMEM_MOVEABLE|GMEM_ZEROINIT,
422 sizeof(OLEClipbrd *));
423 if (hDataObject==0)
424 HANDLE_ERROR( E_OUTOFMEMORY );
426 ppDataObject = GlobalLock(hDataObject);
427 *ppDataObject = theOleClipboard;
428 GlobalUnlock(hDataObject);
430 if ( !SetClipboardData( theOleClipboard->cfDataObj, hDataObject ) )
431 HANDLE_ERROR( CLIPBRD_E_CANT_SET );
434 hr = S_OK;
436 CLEANUP:
439 * Close Windows clipboard (It remains associated with our window)
441 if ( bClipboardOpen && !CloseClipboard() )
442 hr = CLIPBRD_E_CANT_CLOSE;
445 * Release the source IDataObject if something failed
447 if ( FAILED(hr) )
449 if (theOleClipboard->pIDataObjectSrc)
451 IDataObject_Release(theOleClipboard->pIDataObjectSrc);
452 theOleClipboard->pIDataObjectSrc = NULL;
456 return hr;
460 /***********************************************************************
461 * OleGetClipboard [OLE32.@]
462 * Returns a pointer to our internal IDataObject which represents the conceptual
463 * state of the Windows clipboard. If the current clipboard already contains
464 * an IDataObject, our internal IDataObject will delegate to this object.
466 HRESULT WINAPI OleGetClipboard(IDataObject** ppDataObj)
468 HRESULT hr = S_OK;
469 TRACE("()\n");
472 * Make sure we have a clipboard object
474 OLEClipbrd_Initialize();
476 if (!theOleClipboard)
477 return E_OUTOFMEMORY;
479 /* Return a reference counted IDataObject */
480 hr = IDataObject_QueryInterface( (IDataObject*)&(theOleClipboard->lpvtbl1),
481 &IID_IDataObject, (void**)ppDataObj);
482 return hr;
485 /******************************************************************************
486 * OleFlushClipboard [OLE32.@]
487 * Renders the data from the source IDataObject into the windows clipboard
489 * TODO: OleFlushClipboard needs to additionally handle TYMED_IStorage media
490 * by copying the storage into global memory. Subsequently the default
491 * data object exposed through OleGetClipboard must convert this TYMED_HGLOBAL
492 * back to TYMED_IStorage.
494 HRESULT WINAPI OleFlushClipboard(void)
496 IEnumFORMATETC* penumFormatetc = NULL;
497 FORMATETC rgelt;
498 HRESULT hr = S_OK;
499 BOOL bClipboardOpen = FALSE;
500 IDataObject* pIDataObjectSrc = NULL;
502 TRACE("()\n");
505 * Make sure we have a clipboard object
507 OLEClipbrd_Initialize();
510 * Already flushed or no source DataObject? Nothing to do.
512 if (!theOleClipboard->pIDataObjectSrc)
513 return S_OK;
516 * Addref and save the source data object we are holding on to temporarily,
517 * since it will be released when we empty the clipboard.
519 pIDataObjectSrc = theOleClipboard->pIDataObjectSrc;
520 IDataObject_AddRef(pIDataObjectSrc);
523 * Open the Windows clipboard
525 if ( !(bClipboardOpen = OpenClipboard(theOleClipboard->hWndClipboard)) )
526 HANDLE_ERROR( CLIPBRD_E_CANT_OPEN );
529 * Empty the current clipboard
531 if ( !EmptyClipboard() )
532 HANDLE_ERROR( CLIPBRD_E_CANT_EMPTY );
535 * Render all HGLOBAL formats supported by the source into
536 * the windows clipboard.
538 if ( FAILED( hr = IDataObject_EnumFormatEtc( pIDataObjectSrc,
539 DATADIR_GET,
540 &penumFormatetc) ))
542 HANDLE_ERROR( hr );
545 while ( S_OK == IEnumFORMATETC_Next(penumFormatetc, 1, &rgelt, NULL) )
547 if ( rgelt.tymed == TYMED_HGLOBAL )
549 CHAR szFmtName[80];
550 TRACE("(cfFormat=%d:%s)\n", rgelt.cfFormat,
551 GetClipboardFormatNameA(rgelt.cfFormat, szFmtName, sizeof(szFmtName)-1)
552 ? szFmtName : "");
555 * Render the clipboard data
557 if ( FAILED(OLEClipbrd_RenderFormat( pIDataObjectSrc, &rgelt )) )
558 continue;
562 IEnumFORMATETC_Release(penumFormatetc);
565 * Release the source data object we are holding on to
567 IDataObject_Release(pIDataObjectSrc);
569 CLEANUP:
572 * Close Windows clipboard (It remains associated with our window)
574 if ( bClipboardOpen && !CloseClipboard() )
575 hr = CLIPBRD_E_CANT_CLOSE;
577 return hr;
581 /***********************************************************************
582 * OleIsCurrentClipboard [OLE32.@]
584 HRESULT WINAPI OleIsCurrentClipboard(IDataObject *pDataObject)
586 TRACE("()\n");
588 * Make sure we have a clipboard object
590 OLEClipbrd_Initialize();
592 if (!theOleClipboard)
593 return E_OUTOFMEMORY;
595 if (pDataObject == NULL)
596 return S_FALSE;
598 return (pDataObject == theOleClipboard->pIDataObjectSrc) ? S_OK : S_FALSE;
602 /*---------------------------------------------------------------------*
603 * Internal implementation methods for the OLE clipboard
604 *---------------------------------------------------------------------*/
606 /***********************************************************************
607 * OLEClipbrd_Initialize()
608 * Initializes the OLE clipboard.
610 void OLEClipbrd_Initialize(void)
613 * Create the clipboard if necessary
615 if ( !theOleClipboard )
617 TRACE("()\n");
618 theOleClipboard = OLEClipbrd_Construct();
623 /***********************************************************************
624 * OLEClipbrd_UnInitialize()
625 * Un-Initializes the OLE clipboard
627 void OLEClipbrd_UnInitialize(void)
629 TRACE("()\n");
631 * Destroy the clipboard if no one holds a reference to us.
632 * Note that the clipboard was created with a reference count of 1.
634 if ( theOleClipboard && (theOleClipboard->ref <= 1) )
636 OLEClipbrd_Destroy( theOleClipboard );
638 else
640 WARN( "() : OLEClipbrd_UnInitialize called while client holds an IDataObject reference!\n");
645 /*********************************************************
646 * Construct the OLEClipbrd class.
648 static OLEClipbrd* OLEClipbrd_Construct(void)
650 OLEClipbrd* newObject = NULL;
651 HGLOBAL hNewObject = 0;
654 * Allocate space for the object. We use GlobalAlloc since we need
655 * an HGLOBAL to expose our DataObject as a registered clipboard type.
657 hNewObject = GlobalAlloc( GMEM_DDESHARE|GMEM_MOVEABLE|GMEM_ZEROINIT,
658 sizeof(OLEClipbrd));
659 if (hNewObject==0)
660 return NULL;
663 * Lock the handle for the entire lifetime of the clipboard.
665 newObject = GlobalLock(hNewObject);
668 * Initialize the virtual function table.
670 newObject->lpvtbl1 = &OLEClipbrd_IDataObject_VTable;
673 * Start with one reference count. The caller of this function
674 * must release the interface pointer when it is done.
676 newObject->ref = 1;
678 newObject->hSelf = hNewObject;
681 * The Ole clipboard is a singleton - save the global handle and pointer
683 theOleClipboard = newObject;
684 hTheOleClipboard = hNewObject;
686 return theOleClipboard;
689 static void OLEClipbrd_Destroy(OLEClipbrd* ptrToDestroy)
691 TRACE("()\n");
693 if ( !ptrToDestroy )
694 return;
697 * Destroy the Ole clipboard window
699 if ( ptrToDestroy->hWndClipboard )
700 OLEClipbrd_DestroyWindow(ptrToDestroy->hWndClipboard);
703 * Free the actual OLE Clipboard structure.
705 TRACE("() - Destroying clipboard data object.\n");
706 GlobalUnlock(ptrToDestroy->hSelf);
707 GlobalFree(ptrToDestroy->hSelf);
710 * The Ole clipboard is a singleton (ptrToDestroy == theOleClipboard)
712 theOleClipboard = NULL;
713 hTheOleClipboard = 0;
717 /***********************************************************************
718 * OLEClipbrd_CreateWindow()
719 * Create the clipboard window
721 static HWND OLEClipbrd_CreateWindow(void)
723 HWND hwnd = 0;
724 WNDCLASSEXA wcex;
727 * Register the clipboard window class if necessary
729 ZeroMemory( &wcex, sizeof(WNDCLASSEXA));
731 wcex.cbSize = sizeof(WNDCLASSEXA);
732 /* Windows creates this class with a style mask of 0
733 * We don't bother doing this since the FindClassByAtom code
734 * would have to be changed to deal with this idiosyncrasy. */
735 wcex.style = CS_GLOBALCLASS;
736 wcex.lpfnWndProc = OLEClipbrd_WndProc;
737 wcex.hInstance = 0;
738 wcex.lpszClassName = OLEClipbrd_WNDCLASS;
740 RegisterClassExA(&wcex);
743 * Create a hidden window to receive OLE clipboard messages
747 * If we need to store state info we can store it here.
748 * For now we don't need this functionality.
749 * ClipboardWindowInfo clipboardInfo;
750 * ZeroMemory( &trackerInfo, sizeof(ClipboardWindowInfo));
753 hwnd = CreateWindowA(OLEClipbrd_WNDCLASS,
754 "ClipboardWindow",
755 WS_POPUP | WS_CLIPSIBLINGS | WS_OVERLAPPED,
756 CW_USEDEFAULT, CW_USEDEFAULT,
757 CW_USEDEFAULT, CW_USEDEFAULT,
761 0 /*(LPVOID)&clipboardInfo */);
763 return hwnd;
766 /***********************************************************************
767 * OLEClipbrd_DestroyWindow(HWND)
768 * Destroy the clipboard window and unregister its class
770 static void OLEClipbrd_DestroyWindow(HWND hwnd)
773 * Destroy clipboard window and unregister its WNDCLASS
775 DestroyWindow(hwnd);
776 UnregisterClassA( OLEClipbrd_WNDCLASS, 0 );
779 /***********************************************************************
780 * OLEClipbrd_WndProc(HWND, unsigned, WORD, LONG)
781 * Processes messages sent to the OLE clipboard window.
782 * Note that we will intercept messages in our WndProc only when data
783 * has been placed in the clipboard via OleSetClipboard().
784 * i.e. Only when OLE owns the windows clipboard.
786 static LRESULT CALLBACK OLEClipbrd_WndProc
787 (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
789 switch (message)
792 * WM_RENDERFORMAT
793 * We receive this message to allow us to handle delayed rendering of
794 * a specific clipboard format when an application requests data in
795 * that format by calling GetClipboardData.
796 * (Recall that in OleSetClipboard, we used SetClipboardData to
797 * make all HGLOBAL formats supported by the source IDataObject
798 * available using delayed rendering)
799 * On receiving this message we must actually render the data in the
800 * specified format and place it on the clipboard by calling the
801 * SetClipboardData function.
803 case WM_RENDERFORMAT:
805 FORMATETC rgelt;
807 ZeroMemory( &rgelt, sizeof(FORMATETC));
810 * Initialize FORMATETC to a Windows clipboard friendly format
812 rgelt.cfFormat = (UINT) wParam;
813 rgelt.dwAspect = DVASPECT_CONTENT;
814 rgelt.lindex = -1;
815 rgelt.tymed = TYMED_HGLOBAL;
817 TRACE("(): WM_RENDERFORMAT(cfFormat=%d)\n", rgelt.cfFormat);
820 * Render the clipboard data.
821 * (We must have a source data object or we wouldn't be in this WndProc)
823 OLEClipbrd_RenderFormat( (IDataObject*)&(theOleClipboard->lpvtbl1), &rgelt );
825 break;
829 * WM_RENDERALLFORMATS
830 * Sent before the clipboard owner window is destroyed.
831 * We should receive this message only when OleUninitialize is called
832 * while we have an IDataObject in the clipboard.
833 * For the content of the clipboard to remain available to other
834 * applications, we must render data in all the formats the source IDataObject
835 * is capable of generating, and place the data on the clipboard by calling
836 * SetClipboardData.
838 case WM_RENDERALLFORMATS:
840 IEnumFORMATETC* penumFormatetc = NULL;
841 FORMATETC rgelt;
843 TRACE("(): WM_RENDERALLFORMATS\n");
846 * Render all HGLOBAL formats supported by the source into
847 * the windows clipboard.
849 if ( FAILED( IDataObject_EnumFormatEtc( (IDataObject*)&(theOleClipboard->lpvtbl1),
850 DATADIR_GET, &penumFormatetc) ) )
852 WARN("(): WM_RENDERALLFORMATS failed to retrieve EnumFormatEtc!\n");
853 return 0;
856 while ( S_OK == IEnumFORMATETC_Next(penumFormatetc, 1, &rgelt, NULL) )
858 if ( rgelt.tymed == TYMED_HGLOBAL )
861 * Render the clipboard data.
863 if ( FAILED(OLEClipbrd_RenderFormat( (IDataObject*)&(theOleClipboard->lpvtbl1), &rgelt )) )
864 continue;
866 TRACE("(): WM_RENDERALLFORMATS(cfFormat=%d)\n", rgelt.cfFormat);
870 IEnumFORMATETC_Release(penumFormatetc);
872 break;
876 * WM_DESTROYCLIPBOARD
877 * This is sent by EmptyClipboard before the clipboard is emptied.
878 * We should release any IDataObject we are holding onto when we receive
879 * this message, since it indicates that the OLE clipboard should be empty
880 * from this point on.
882 case WM_DESTROYCLIPBOARD:
884 TRACE("(): WM_DESTROYCLIPBOARD\n");
886 * Release the data object we are holding on to
888 if ( theOleClipboard->pIDataObjectSrc )
890 IDataObject_Release(theOleClipboard->pIDataObjectSrc);
891 theOleClipboard->pIDataObjectSrc = NULL;
893 break;
897 case WM_ASKCBFORMATNAME:
898 case WM_CHANGECBCHAIN:
899 case WM_DRAWCLIPBOARD:
900 case WM_SIZECLIPBOARD:
901 case WM_HSCROLLCLIPBOARD:
902 case WM_VSCROLLCLIPBOARD:
903 case WM_PAINTCLIPBOARD:
905 default:
906 return DefWindowProcA(hWnd, message, wParam, lParam);
909 return 0;
912 #define MAX_CLIPFORMAT_NAME 80
914 /***********************************************************************
915 * OLEClipbrd_RenderFormat(LPFORMATETC)
916 * Render the clipboard data. Note that this call will delegate to the
917 * source data object.
918 * Note: This function assumes it is passed an HGLOBAL format to render.
920 static HRESULT OLEClipbrd_RenderFormat(IDataObject *pIDataObject, LPFORMATETC pFormatetc)
922 STGMEDIUM std;
923 HGLOBAL hDup;
924 HRESULT hr = S_OK;
925 char szFmtName[MAX_CLIPFORMAT_NAME];
926 ILockBytes *ptrILockBytes = 0;
927 HGLOBAL hStorage = 0;
929 if (!GetClipboardFormatNameA(pFormatetc->cfFormat, szFmtName, MAX_CLIPFORMAT_NAME))
930 szFmtName[0] = '\0';
932 /* If embed source */
933 if (!strcmp(szFmtName, CF_EMBEDSOURCE))
935 memset(&std, 0, sizeof(STGMEDIUM));
936 std.tymed = pFormatetc->tymed = TYMED_ISTORAGE;
938 hStorage = GlobalAlloc(GMEM_SHARE|GMEM_MOVEABLE, 0);
939 if (hStorage == NULL)
940 HANDLE_ERROR( E_OUTOFMEMORY );
941 hr = CreateILockBytesOnHGlobal(hStorage, FALSE, &ptrILockBytes);
942 hr = StgCreateDocfileOnILockBytes(ptrILockBytes, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &std.u.pstg);
944 if (FAILED(hr = IDataObject_GetDataHere(theOleClipboard->pIDataObjectSrc, pFormatetc, &std)))
946 WARN("() : IDataObject_GetDataHere failed to render clipboard data! (%x)\n", hr);
947 GlobalFree(hStorage);
948 return hr;
951 if (1) /* check whether the presentation data is already -not- present */
953 FORMATETC fmt2;
954 STGMEDIUM std2;
955 METAFILEPICT *mfp = 0;
957 fmt2.cfFormat = CF_METAFILEPICT;
958 fmt2.ptd = 0;
959 fmt2.dwAspect = DVASPECT_CONTENT;
960 fmt2.lindex = -1;
961 fmt2.tymed = TYMED_MFPICT;
963 memset(&std2, 0, sizeof(STGMEDIUM));
964 std2.tymed = TYMED_MFPICT;
966 /* Get the metafile picture out of it */
968 if (SUCCEEDED(hr = IDataObject_GetData(theOleClipboard->pIDataObjectSrc, &fmt2, &std2)))
970 mfp = GlobalLock(std2.u.hGlobal);
973 if (mfp)
975 OLECHAR name[]={ 2, 'O', 'l', 'e', 'P', 'r', 'e', 's', '0', '0', '0', 0};
976 IStream *pStream = 0;
977 void *mfBits;
978 PresentationDataHeader pdh;
979 INT nSize;
980 CLSID clsID;
981 LPOLESTR strProgID;
982 CHAR strOleTypeName[51];
983 BYTE OlePresStreamHeader [] =
985 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00,
986 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
987 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
988 0x00, 0x00, 0x00, 0x00
991 nSize = GetMetaFileBitsEx(mfp->hMF, 0, NULL);
993 memset(&pdh, 0, sizeof(PresentationDataHeader));
994 memcpy(&pdh, OlePresStreamHeader, sizeof(OlePresStreamHeader));
996 pdh.dwObjectExtentX = mfp->xExt;
997 pdh.dwObjectExtentY = mfp->yExt;
998 pdh.dwSize = nSize;
1000 hr = IStorage_CreateStream(std.u.pstg, name, STGM_CREATE|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, 0, &pStream);
1002 hr = IStream_Write(pStream, &pdh, sizeof(PresentationDataHeader), NULL);
1004 mfBits = HeapAlloc(GetProcessHeap(), 0, nSize);
1005 nSize = GetMetaFileBitsEx(mfp->hMF, nSize, mfBits);
1007 hr = IStream_Write(pStream, mfBits, nSize, NULL);
1009 IStream_Release(pStream);
1011 HeapFree(GetProcessHeap(), 0, mfBits);
1013 GlobalUnlock(std2.u.hGlobal);
1015 ReadClassStg(std.u.pstg, &clsID);
1016 ProgIDFromCLSID(&clsID, &strProgID);
1018 WideCharToMultiByte( CP_ACP, 0, strProgID, -1, strOleTypeName, sizeof(strOleTypeName), NULL, NULL );
1019 OLECONVERT_CreateOleStream(std.u.pstg);
1020 OLECONVERT_CreateCompObjStream(std.u.pstg, strOleTypeName);
1024 else
1026 if (FAILED(hr = IDataObject_GetData(pIDataObject, pFormatetc, &std)))
1028 WARN("() : IDataObject_GetData failed to render clipboard data! (%x)\n", hr);
1029 GlobalFree(hStorage);
1030 return hr;
1033 /* To put a copy back on the clipboard */
1035 hStorage = std.u.hGlobal;
1039 * Put a copy of the rendered data back on the clipboard
1042 if ( !(hDup = OLEClipbrd_GlobalDupMem(hStorage)) )
1043 HANDLE_ERROR( E_OUTOFMEMORY );
1045 if ( !SetClipboardData( pFormatetc->cfFormat, hDup ) )
1047 GlobalFree(hDup);
1048 WARN("() : Failed to set rendered clipboard data into clipboard!\n");
1051 CLEANUP:
1053 ReleaseStgMedium(&std);
1055 return hr;
1059 /***********************************************************************
1060 * OLEClipbrd_GlobalDupMem( HGLOBAL )
1061 * Helper method to duplicate an HGLOBAL chunk of memory
1063 static HGLOBAL OLEClipbrd_GlobalDupMem( HGLOBAL hGlobalSrc )
1065 HGLOBAL hGlobalDest;
1066 PVOID pGlobalSrc, pGlobalDest;
1067 DWORD cBytes;
1069 if ( !hGlobalSrc )
1070 return 0;
1072 cBytes = GlobalSize(hGlobalSrc);
1073 if ( 0 == cBytes )
1074 return 0;
1076 hGlobalDest = GlobalAlloc( GMEM_DDESHARE|GMEM_MOVEABLE,
1077 cBytes );
1078 if ( !hGlobalDest )
1079 return 0;
1081 pGlobalSrc = GlobalLock(hGlobalSrc);
1082 pGlobalDest = GlobalLock(hGlobalDest);
1083 if ( !pGlobalSrc || !pGlobalDest )
1085 GlobalFree(hGlobalDest);
1086 return 0;
1089 memcpy(pGlobalDest, pGlobalSrc, cBytes);
1091 GlobalUnlock(hGlobalSrc);
1092 GlobalUnlock(hGlobalDest);
1094 return hGlobalDest;
1098 /*---------------------------------------------------------------------*
1099 * Implementation of the internal IDataObject interface exposed by
1100 * the OLE clipboard.
1101 *---------------------------------------------------------------------*/
1104 /************************************************************************
1105 * OLEClipbrd_IDataObject_QueryInterface (IUnknown)
1107 * See Windows documentation for more details on IUnknown methods.
1109 static HRESULT WINAPI OLEClipbrd_IDataObject_QueryInterface(
1110 IDataObject* iface,
1111 REFIID riid,
1112 void** ppvObject)
1115 * Declare "This" pointer
1117 OLEClipbrd *This = (OLEClipbrd *)iface;
1118 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObject);
1121 * Perform a sanity check on the parameters.
1123 if ( (This==0) || (ppvObject==0) )
1124 return E_INVALIDARG;
1127 * Initialize the return parameter.
1129 *ppvObject = 0;
1132 * Compare the riid with the interface IDs implemented by this object.
1134 if (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0)
1136 *ppvObject = iface;
1138 else if (memcmp(&IID_IDataObject, riid, sizeof(IID_IDataObject)) == 0)
1140 *ppvObject = (IDataObject*)&(This->lpvtbl1);
1142 else /* We only support IUnknown and IDataObject */
1144 WARN( "() : asking for unsupported interface %s\n", debugstr_guid(riid));
1145 return E_NOINTERFACE;
1149 * Query Interface always increases the reference count by one when it is
1150 * successful.
1152 IUnknown_AddRef((IUnknown*)*ppvObject);
1154 return S_OK;
1157 /************************************************************************
1158 * OLEClipbrd_IDataObject_AddRef (IUnknown)
1160 * See Windows documentation for more details on IUnknown methods.
1162 static ULONG WINAPI OLEClipbrd_IDataObject_AddRef(
1163 IDataObject* iface)
1166 * Declare "This" pointer
1168 OLEClipbrd *This = (OLEClipbrd *)iface;
1170 TRACE("(%p)->(count=%u)\n",This, This->ref);
1172 return InterlockedIncrement(&This->ref);
1176 /************************************************************************
1177 * OLEClipbrd_IDataObject_Release (IUnknown)
1179 * See Windows documentation for more details on IUnknown methods.
1181 static ULONG WINAPI OLEClipbrd_IDataObject_Release(
1182 IDataObject* iface)
1185 * Declare "This" pointer
1187 OLEClipbrd *This = (OLEClipbrd *)iface;
1188 ULONG ref;
1190 TRACE("(%p)->(count=%u)\n",This, This->ref);
1193 * Decrease the reference count on this object.
1195 ref = InterlockedDecrement(&This->ref);
1198 * If the reference count goes down to 0, perform suicide.
1200 if (ref == 0)
1202 OLEClipbrd_Destroy(This);
1205 return ref;
1209 /************************************************************************
1210 * OLEClipbrd_IDataObject_GetData (IDataObject)
1212 * The OLE Clipboard's implementation of this method delegates to
1213 * a data source if there is one or wraps around the windows clipboard
1215 * See Windows documentation for more details on IDataObject methods.
1217 static HRESULT WINAPI OLEClipbrd_IDataObject_GetData(
1218 IDataObject* iface,
1219 LPFORMATETC pformatetcIn,
1220 STGMEDIUM* pmedium)
1222 HANDLE hData = 0;
1223 BOOL bClipboardOpen = FALSE;
1224 HRESULT hr = S_OK;
1225 LPVOID src;
1228 * Declare "This" pointer
1230 OLEClipbrd *This = (OLEClipbrd *)iface;
1232 TRACE("(%p,%p,%p)\n", iface, pformatetcIn, pmedium);
1234 if ( !pformatetcIn || !pmedium )
1235 return E_INVALIDARG;
1238 * If we have a data source placed on the clipboard (via OleSetClipboard)
1239 * simply delegate to the source object's QueryGetData
1240 * NOTE: This code assumes that the IDataObject is in the same address space!
1241 * We will need to add marshalling support when Wine handles multiple processes.
1243 if ( This->pIDataObjectSrc )
1245 return IDataObject_GetData(This->pIDataObjectSrc, pformatetcIn, pmedium);
1248 if ( pformatetcIn->lindex != -1 )
1249 return DV_E_FORMATETC;
1251 if ( (pformatetcIn->tymed & TYMED_HGLOBAL) != TYMED_HGLOBAL )
1252 return DV_E_TYMED;
1254 if ( pformatetcIn->dwAspect != DVASPECT_CONTENT )
1255 return DV_E_DVASPECT;
1259 * Otherwise, get the data from the windows clipboard using GetClipboardData
1261 if ( !(bClipboardOpen = OpenClipboard(theOleClipboard->hWndClipboard)) )
1262 HANDLE_ERROR( CLIPBRD_E_CANT_OPEN );
1264 hData = GetClipboardData(pformatetcIn->cfFormat);
1266 /* Must make a copy of global handle returned by GetClipboardData; it
1267 * is not valid after we call CloseClipboard
1268 * Application is responsible for freeing the memory (Forte Agent does this)
1270 src = GlobalLock(hData);
1271 if(src) {
1272 LPVOID dest;
1273 ULONG size;
1274 HANDLE hDest;
1276 size = GlobalSize(hData);
1277 hDest = GlobalAlloc(GHND, size);
1278 dest = GlobalLock(hDest);
1279 memcpy(dest, src, size);
1280 GlobalUnlock(hDest);
1281 GlobalUnlock(hData);
1282 hData = hDest;
1286 * Return the clipboard data in the storage medium structure
1288 pmedium->tymed = (hData == 0) ? TYMED_NULL : TYMED_HGLOBAL;
1289 pmedium->u.hGlobal = hData;
1290 pmedium->pUnkForRelease = NULL;
1292 hr = S_OK;
1294 CLEANUP:
1296 * Close Windows clipboard
1298 if ( bClipboardOpen && !CloseClipboard() )
1299 hr = CLIPBRD_E_CANT_CLOSE;
1301 if ( FAILED(hr) )
1302 return hr;
1303 return (hData == 0) ? DV_E_FORMATETC : S_OK;
1306 static HRESULT WINAPI OLEClipbrd_IDataObject_GetDataHere(
1307 IDataObject* iface,
1308 LPFORMATETC pformatetc,
1309 STGMEDIUM* pmedium)
1311 FIXME(": Stub\n");
1312 return E_NOTIMPL;
1315 /************************************************************************
1316 * OLEClipbrd_IDataObject_QueryGetData (IDataObject)
1318 * The OLE Clipboard's implementation of this method delegates to
1319 * a data source if there is one or wraps around the windows clipboard
1320 * function IsClipboardFormatAvailable() otherwise.
1322 * See Windows documentation for more details on IDataObject methods.
1324 static HRESULT WINAPI OLEClipbrd_IDataObject_QueryGetData(
1325 IDataObject* iface,
1326 LPFORMATETC pformatetc)
1328 TRACE("(%p, %p)\n", iface, pformatetc);
1330 if (!pformatetc)
1331 return E_INVALIDARG;
1333 if ( pformatetc->dwAspect != DVASPECT_CONTENT )
1334 return DV_E_FORMATETC;
1336 if ( pformatetc->lindex != -1 )
1337 return DV_E_FORMATETC;
1340 * Delegate to the Windows clipboard function IsClipboardFormatAvailable
1342 return (IsClipboardFormatAvailable(pformatetc->cfFormat)) ? S_OK : DV_E_CLIPFORMAT;
1345 /************************************************************************
1346 * OLEClipbrd_IDataObject_GetCanonicalFormatEtc (IDataObject)
1348 * See Windows documentation for more details on IDataObject methods.
1350 static HRESULT WINAPI OLEClipbrd_IDataObject_GetCanonicalFormatEtc(
1351 IDataObject* iface,
1352 LPFORMATETC pformatectIn,
1353 LPFORMATETC pformatetcOut)
1355 TRACE("(%p, %p, %p)\n", iface, pformatectIn, pformatetcOut);
1357 if ( !pformatectIn || !pformatetcOut )
1358 return E_INVALIDARG;
1360 *pformatetcOut = *pformatectIn;
1361 return DATA_S_SAMEFORMATETC;
1364 /************************************************************************
1365 * OLEClipbrd_IDataObject_SetData (IDataObject)
1367 * The OLE Clipboard's does not implement this method
1369 * See Windows documentation for more details on IDataObject methods.
1371 static HRESULT WINAPI OLEClipbrd_IDataObject_SetData(
1372 IDataObject* iface,
1373 LPFORMATETC pformatetc,
1374 STGMEDIUM* pmedium,
1375 BOOL fRelease)
1377 TRACE("\n");
1378 return E_NOTIMPL;
1381 /************************************************************************
1382 * OLEClipbrd_IDataObject_EnumFormatEtc (IDataObject)
1384 * See Windows documentation for more details on IDataObject methods.
1386 static HRESULT WINAPI OLEClipbrd_IDataObject_EnumFormatEtc(
1387 IDataObject* iface,
1388 DWORD dwDirection,
1389 IEnumFORMATETC** ppenumFormatEtc)
1391 HRESULT hr = S_OK;
1392 FORMATETC *afmt = NULL;
1393 int cfmt, i;
1394 UINT format;
1395 BOOL bClipboardOpen;
1398 * Declare "This" pointer
1400 OLEClipbrd *This = (OLEClipbrd *)iface;
1402 TRACE("(%p, %x, %p)\n", iface, dwDirection, ppenumFormatEtc);
1405 * If we have a data source placed on the clipboard (via OleSetClipboard)
1406 * simply delegate to the source object's EnumFormatEtc
1408 if ( This->pIDataObjectSrc )
1410 return IDataObject_EnumFormatEtc(This->pIDataObjectSrc,
1411 dwDirection, ppenumFormatEtc);
1415 * Otherwise we must provide our own enumerator which wraps around the
1416 * Windows clipboard function EnumClipboardFormats
1418 if ( !ppenumFormatEtc )
1419 return E_INVALIDARG;
1421 if ( dwDirection != DATADIR_GET ) /* IDataObject_SetData not implemented */
1422 return E_NOTIMPL;
1425 * Store all current clipboard formats in an array of FORMATETC's,
1426 * and create an IEnumFORMATETC enumerator from this list.
1428 cfmt = CountClipboardFormats();
1429 afmt = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1430 sizeof(FORMATETC) * cfmt);
1432 * Open the Windows clipboard, associating it with our hidden window
1434 if ( !(bClipboardOpen = OpenClipboard(This->hWndClipboard)) )
1435 HANDLE_ERROR( CLIPBRD_E_CANT_OPEN );
1438 * Store all current clipboard formats in an array of FORMATETC's
1439 * TODO: Handle TYMED_IStorage media which were put on the clipboard
1440 * by copying the storage into global memory. We must convert this
1441 * TYMED_HGLOBAL back to TYMED_IStorage.
1443 for (i = 0, format = 0; i < cfmt; i++)
1445 format = EnumClipboardFormats(format);
1446 if (!format) /* Failed! */
1448 ERR("EnumClipboardFormats failed to return format!\n");
1449 HANDLE_ERROR( E_FAIL );
1452 /* Init the FORMATETC struct */
1453 afmt[i].cfFormat = format;
1454 afmt[i].ptd = NULL;
1455 afmt[i].dwAspect = DVASPECT_CONTENT;
1456 afmt[i].lindex = -1;
1457 afmt[i].tymed = TYMED_HGLOBAL;
1461 * Create an EnumFORMATETC enumerator and return an
1462 * EnumFORMATETC after bumping up its ref count
1464 *ppenumFormatEtc = OLEClipbrd_IEnumFORMATETC_Construct( cfmt, afmt, (LPUNKNOWN)iface);
1465 if (!(*ppenumFormatEtc))
1466 HANDLE_ERROR( E_OUTOFMEMORY );
1468 if (FAILED( hr = IEnumFORMATETC_AddRef(*ppenumFormatEtc)))
1469 HANDLE_ERROR( hr );
1471 hr = S_OK;
1473 CLEANUP:
1475 * Free the array of FORMATETC's
1477 HeapFree(GetProcessHeap(), 0, afmt);
1480 * Close Windows clipboard
1482 if ( bClipboardOpen && !CloseClipboard() )
1483 hr = CLIPBRD_E_CANT_CLOSE;
1485 return hr;
1488 /************************************************************************
1489 * OLEClipbrd_IDataObject_DAdvise (IDataObject)
1491 * The OLE Clipboard's does not implement this method
1493 * See Windows documentation for more details on IDataObject methods.
1495 static HRESULT WINAPI OLEClipbrd_IDataObject_DAdvise(
1496 IDataObject* iface,
1497 FORMATETC* pformatetc,
1498 DWORD advf,
1499 IAdviseSink* pAdvSink,
1500 DWORD* pdwConnection)
1502 TRACE("\n");
1503 return E_NOTIMPL;
1506 /************************************************************************
1507 * OLEClipbrd_IDataObject_DUnadvise (IDataObject)
1509 * The OLE Clipboard's does not implement this method
1511 * See Windows documentation for more details on IDataObject methods.
1513 static HRESULT WINAPI OLEClipbrd_IDataObject_DUnadvise(
1514 IDataObject* iface,
1515 DWORD dwConnection)
1517 TRACE("\n");
1518 return E_NOTIMPL;
1521 /************************************************************************
1522 * OLEClipbrd_IDataObject_EnumDAdvise (IDataObject)
1524 * The OLE Clipboard does not implement this method
1526 * See Windows documentation for more details on IDataObject methods.
1528 static HRESULT WINAPI OLEClipbrd_IDataObject_EnumDAdvise(
1529 IDataObject* iface,
1530 IEnumSTATDATA** ppenumAdvise)
1532 TRACE("\n");
1533 return E_NOTIMPL;
1537 /*---------------------------------------------------------------------*
1538 * Implementation of the internal IEnumFORMATETC interface returned by
1539 * the OLE clipboard's IDataObject.
1540 *---------------------------------------------------------------------*/
1542 /************************************************************************
1543 * OLEClipbrd_IEnumFORMATETC_Construct (UINT, const FORMATETC, LPUNKNOWN)
1545 * Creates an IEnumFORMATETC enumerator from an array of FORMATETC
1546 * Structures. pUnkOuter is the outer unknown for reference counting only.
1547 * NOTE: this does not AddRef the interface.
1550 static LPENUMFORMATETC OLEClipbrd_IEnumFORMATETC_Construct(UINT cfmt, const FORMATETC afmt[],
1551 LPUNKNOWN pUnkDataObj)
1553 IEnumFORMATETCImpl* ef;
1554 DWORD size=cfmt * sizeof(FORMATETC);
1555 LPMALLOC pIMalloc;
1557 ef = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IEnumFORMATETCImpl));
1558 if (!ef)
1559 return NULL;
1561 ef->ref = 0;
1562 ef->lpVtbl = &efvt;
1563 ef->pUnkDataObj = pUnkDataObj;
1565 ef->posFmt = 0;
1566 ef->countFmt = cfmt;
1567 if (FAILED(CoGetMalloc(MEMCTX_TASK, &pIMalloc))) {
1568 HeapFree(GetProcessHeap(), 0, ef);
1569 return NULL;
1571 ef->pFmt = (LPFORMATETC)IMalloc_Alloc(pIMalloc, size);
1572 IMalloc_Release(pIMalloc);
1574 if (ef->pFmt)
1575 memcpy(ef->pFmt, afmt, size);
1577 TRACE("(%p)->()\n",ef);
1578 return (LPENUMFORMATETC)ef;
1582 /************************************************************************
1583 * OLEClipbrd_IEnumFORMATETC_QueryInterface (IUnknown)
1585 * See Windows documentation for more details on IUnknown methods.
1587 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_QueryInterface
1588 (LPENUMFORMATETC iface, REFIID riid, LPVOID* ppvObj)
1590 IEnumFORMATETCImpl *This = (IEnumFORMATETCImpl *)iface;
1592 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
1595 * Since enumerators are separate objects from the parent data object
1596 * we only need to support the IUnknown and IEnumFORMATETC interfaces
1599 *ppvObj = NULL;
1601 if(IsEqualIID(riid, &IID_IUnknown))
1603 *ppvObj = This;
1605 else if(IsEqualIID(riid, &IID_IEnumFORMATETC))
1607 *ppvObj = (IDataObject*)This;
1610 if(*ppvObj)
1612 IEnumFORMATETC_AddRef((IEnumFORMATETC*)*ppvObj);
1613 TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
1614 return S_OK;
1617 TRACE("-- Interface: E_NOINTERFACE\n");
1618 return E_NOINTERFACE;
1621 /************************************************************************
1622 * OLEClipbrd_IEnumFORMATETC_AddRef (IUnknown)
1624 * Since enumerating formats only makes sense when our data object is around,
1625 * we insure that it stays as long as we stay by calling our parents IUnknown
1626 * for AddRef and Release. But since we are not controlled by the lifetime of
1627 * the outer object, we still keep our own reference count in order to
1628 * free ourselves.
1630 static ULONG WINAPI OLEClipbrd_IEnumFORMATETC_AddRef(LPENUMFORMATETC iface)
1632 IEnumFORMATETCImpl *This = (IEnumFORMATETCImpl *)iface;
1633 TRACE("(%p)->(count=%u)\n",This, This->ref);
1635 if (This->pUnkDataObj)
1636 IUnknown_AddRef(This->pUnkDataObj);
1638 return InterlockedIncrement(&This->ref);
1641 /************************************************************************
1642 * OLEClipbrd_IEnumFORMATETC_Release (IUnknown)
1644 * See Windows documentation for more details on IUnknown methods.
1646 static ULONG WINAPI OLEClipbrd_IEnumFORMATETC_Release(LPENUMFORMATETC iface)
1648 IEnumFORMATETCImpl *This = (IEnumFORMATETCImpl *)iface;
1649 LPMALLOC pIMalloc;
1650 ULONG ref;
1652 TRACE("(%p)->(count=%u)\n",This, This->ref);
1654 if (This->pUnkDataObj)
1655 IUnknown_Release(This->pUnkDataObj); /* Release parent data object */
1657 ref = InterlockedDecrement(&This->ref);
1658 if (!ref)
1660 TRACE("() - destroying IEnumFORMATETC(%p)\n",This);
1661 if (SUCCEEDED(CoGetMalloc(MEMCTX_TASK, &pIMalloc)))
1663 IMalloc_Free(pIMalloc, This->pFmt);
1664 IMalloc_Release(pIMalloc);
1667 HeapFree(GetProcessHeap(),0,This);
1669 return ref;
1672 /************************************************************************
1673 * OLEClipbrd_IEnumFORMATETC_Next (IEnumFORMATETC)
1675 * Standard enumerator members for IEnumFORMATETC
1677 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Next
1678 (LPENUMFORMATETC iface, ULONG celt, FORMATETC *rgelt, ULONG *pceltFethed)
1680 IEnumFORMATETCImpl *This = (IEnumFORMATETCImpl *)iface;
1681 UINT cfetch;
1682 HRESULT hres = S_FALSE;
1684 TRACE("(%p)->(pos=%u)\n", This, This->posFmt);
1686 if (This->posFmt < This->countFmt)
1688 cfetch = This->countFmt - This->posFmt;
1689 if (cfetch >= celt)
1691 cfetch = celt;
1692 hres = S_OK;
1695 memcpy(rgelt, &This->pFmt[This->posFmt], cfetch * sizeof(FORMATETC));
1696 This->posFmt += cfetch;
1698 else
1700 cfetch = 0;
1703 if (pceltFethed)
1705 *pceltFethed = cfetch;
1708 return hres;
1711 /************************************************************************
1712 * OLEClipbrd_IEnumFORMATETC_Skip (IEnumFORMATETC)
1714 * Standard enumerator members for IEnumFORMATETC
1716 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Skip(LPENUMFORMATETC iface, ULONG celt)
1718 IEnumFORMATETCImpl *This = (IEnumFORMATETCImpl *)iface;
1719 TRACE("(%p)->(num=%u)\n", This, celt);
1721 This->posFmt += celt;
1722 if (This->posFmt > This->countFmt)
1724 This->posFmt = This->countFmt;
1725 return S_FALSE;
1727 return S_OK;
1730 /************************************************************************
1731 * OLEClipbrd_IEnumFORMATETC_Reset (IEnumFORMATETC)
1733 * Standard enumerator members for IEnumFORMATETC
1735 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Reset(LPENUMFORMATETC iface)
1737 IEnumFORMATETCImpl *This = (IEnumFORMATETCImpl *)iface;
1738 TRACE("(%p)->()\n", This);
1740 This->posFmt = 0;
1741 return S_OK;
1744 /************************************************************************
1745 * OLEClipbrd_IEnumFORMATETC_Clone (IEnumFORMATETC)
1747 * Standard enumerator members for IEnumFORMATETC
1749 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Clone
1750 (LPENUMFORMATETC iface, LPENUMFORMATETC* ppenum)
1752 IEnumFORMATETCImpl *This = (IEnumFORMATETCImpl *)iface;
1753 HRESULT hr = S_OK;
1755 TRACE("(%p)->(ppenum=%p)\n", This, ppenum);
1757 if ( !ppenum )
1758 return E_INVALIDARG;
1760 *ppenum = OLEClipbrd_IEnumFORMATETC_Construct(This->countFmt,
1761 This->pFmt,
1762 This->pUnkDataObj);
1764 if (FAILED( hr = IEnumFORMATETC_AddRef(*ppenum)))
1765 return ( hr );
1767 return (*ppenum) ? S_OK : E_OUTOFMEMORY;