Implement a class factory for the Global Interface Table.
[wine/hacks.git] / dlls / ole32 / clipboard.c
blob7d43d3bcb26bd58c1b1aaa75937f003f3c51b9d1
1 /*
2 * OLE 2 clipboard support
4 * Copyright 1999 Noel Borthwick <noel@macadamian.com>
5 * Copyright 2000 Abey George <abey@macadamian.com>
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 * NOTES:
22 * This file contains the implementation for the OLE Clipboard and its
23 * internal interfaces. The OLE clipboard interacts with an IDataObject
24 * interface via the OleSetClipboard, OleGetClipboard and
25 * OleIsCurrentClipboard API's. An internal IDataObject delegates
26 * to a client supplied IDataObject or the WIN32 clipboard API depending
27 * on whether OleSetClipboard has been invoked.
28 * Here are some operating scenarios:
30 * 1. OleSetClipboard called: In this case the internal IDataObject
31 * delegates to the client supplied IDataObject. Additionally OLE takes
32 * ownership of the Windows clipboard and any HGLOCBAL IDataObject
33 * items are placed on the Windows clipboard. This allows non OLE aware
34 * applications to access these. A local WinProc fields WM_RENDERFORMAT
35 * and WM_RENDERALLFORMATS messages in this case.
37 * 2. OleGetClipboard called without previous OleSetClipboard. Here the internal
38 * IDataObject functionality wraps around the WIN32 clipboard API.
40 * 3. OleGetClipboard called after previous OleSetClipboard. Here the internal
41 * IDataObject delegates to the source IDataObjects functionality directly,
42 * thereby bypassing the Windows clipboard.
44 * Implementation references : Inside OLE 2'nd edition by Kraig Brockschmidt
46 * TODO:
47 * - Support for pasting between different processes. OLE clipboard support
48 * currently works only for in process copy and paste. Since we internally
49 * store a pointer to the source's IDataObject and delegate to that, this
50 * will fail if the IDataObject client belongs to a different process.
51 * - IDataObject::GetDataHere is not implemented
52 * - OleFlushClipboard needs to additionally handle TYMED_IStorage media
53 * by copying the storage into global memory. Subsequently the default
54 * data object exposed through OleGetClipboard must convert this TYMED_HGLOBAL
55 * back to TYMED_IStorage.
56 * - OLE1 compatibility formats to be synthesized from OLE2 formats and put on
57 * clipboard in OleSetClipboard.
61 #include <assert.h>
62 #include <string.h>
64 #define NONAMELESSUNION
65 #define NONAMELESSSTRUCT
66 #include "windef.h"
67 #include "winbase.h"
68 #include "wingdi.h"
69 #include "winuser.h"
70 #include "winerror.h"
71 #include "winnls.h"
72 #include "ole2.h"
73 #include "wine/debug.h"
74 #include "olestd.h"
76 #include "storage32.h"
78 #define HANDLE_ERROR(err) { hr = err; TRACE("(HRESULT=%lx)\n", (HRESULT)err); goto CLEANUP; }
80 /* For CoGetMalloc (MEMCTX_TASK is currently ignored) */
81 #ifndef MEMCTX_TASK
82 #define MEMCTX_TASK -1
83 #endif
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 ICOM_VTABLE(IDataObject)* 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 ULONG 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 ICOM_VFIELD(IEnumFORMATETC);
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 DWORD 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 extern void OLEClipbrd_Initialize();
173 extern void OLEClipbrd_UnInitialize();
174 static OLEClipbrd* OLEClipbrd_Construct();
175 static void OLEClipbrd_Destroy(OLEClipbrd* ptrToDestroy);
176 static HWND OLEClipbrd_CreateWindow();
177 static void OLEClipbrd_DestroyWindow(HWND hwnd);
178 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 ICOM_VTABLE(IDataObject) OLEClipbrd_IDataObject_VTable =
252 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
253 OLEClipbrd_IDataObject_QueryInterface,
254 OLEClipbrd_IDataObject_AddRef,
255 OLEClipbrd_IDataObject_Release,
256 OLEClipbrd_IDataObject_GetData,
257 OLEClipbrd_IDataObject_GetDataHere,
258 OLEClipbrd_IDataObject_QueryGetData,
259 OLEClipbrd_IDataObject_GetCanonicalFormatEtc,
260 OLEClipbrd_IDataObject_SetData,
261 OLEClipbrd_IDataObject_EnumFormatEtc,
262 OLEClipbrd_IDataObject_DAdvise,
263 OLEClipbrd_IDataObject_DUnadvise,
264 OLEClipbrd_IDataObject_EnumDAdvise
268 * Virtual function table for IEnumFORMATETC interface
270 static struct ICOM_VTABLE(IEnumFORMATETC) efvt =
272 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
273 OLEClipbrd_IEnumFORMATETC_QueryInterface,
274 OLEClipbrd_IEnumFORMATETC_AddRef,
275 OLEClipbrd_IEnumFORMATETC_Release,
276 OLEClipbrd_IEnumFORMATETC_Next,
277 OLEClipbrd_IEnumFORMATETC_Skip,
278 OLEClipbrd_IEnumFORMATETC_Reset,
279 OLEClipbrd_IEnumFORMATETC_Clone
283 * Name of our registered OLE clipboard window class
285 CHAR OLEClipbrd_WNDCLASS[] = "CLIPBRDWNDCLASS";
288 * If we need to store state info we can store it here.
289 * For now we dont need this functionality.
291 typedef struct tagClipboardWindowInfo
293 } ClipboardWindowInfo;
296 /*---------------------------------------------------------------------*
297 * Win32 OLE clipboard API
298 *---------------------------------------------------------------------*/
300 /***********************************************************************
301 * OleSetClipboard [OLE32.127]
302 * Places a pointer to the specified data object onto the clipboard,
303 * making the data object accessible to the OleGetClipboard function.
305 * RETURNS:
307 * S_OK IDataObject pointer placed on the clipboard
308 * CLIPBRD_E_CANT_OPEN OpenClipboard failed
309 * CLIPBRD_E_CANT_EMPTY EmptyClipboard failed
310 * CLIPBRD_E_CANT_CLOSE CloseClipboard failed
311 * CLIPBRD_E_CANT_SET SetClipboard failed
314 HRESULT WINAPI OleSetClipboard(IDataObject* pDataObj)
316 HRESULT hr = S_OK;
317 IEnumFORMATETC* penumFormatetc = NULL;
318 FORMATETC rgelt;
319 BOOL bClipboardOpen = FALSE;
321 HGLOBAL hDataObject = 0;
322 OLEClipbrd **ppDataObject;
325 TRACE("(%p)\n", pDataObj);
328 * Make sure we have a clipboard object
330 OLEClipbrd_Initialize();
333 * If the Ole clipboard window hasn't been created yet, create it now.
335 if ( !theOleClipboard->hWndClipboard )
336 theOleClipboard->hWndClipboard = OLEClipbrd_CreateWindow();
338 if ( !theOleClipboard->hWndClipboard ) /* sanity check */
339 HANDLE_ERROR( E_FAIL );
342 * Open the Windows clipboard, associating it with our hidden window
344 if ( !(bClipboardOpen = OpenClipboard(theOleClipboard->hWndClipboard)) )
345 HANDLE_ERROR( CLIPBRD_E_CANT_OPEN );
348 * Empty the current clipboard and make our window the clipboard owner
349 * NOTE: This will trigger a WM_DESTROYCLIPBOARD message
351 if ( !EmptyClipboard() )
352 HANDLE_ERROR( CLIPBRD_E_CANT_EMPTY );
355 * If we are already holding on to an IDataObject first release that.
357 if ( theOleClipboard->pIDataObjectSrc )
359 IDataObject_Release(theOleClipboard->pIDataObjectSrc);
360 theOleClipboard->pIDataObjectSrc = NULL;
364 * AddRef the data object passed in and save its pointer.
365 * A NULL value indicates that the clipboard should be emptied.
367 theOleClipboard->pIDataObjectSrc = pDataObj;
368 if ( pDataObj )
370 IDataObject_AddRef(theOleClipboard->pIDataObjectSrc);
374 * Enumerate all HGLOBAL formats supported by the source and make
375 * those formats available using delayed rendering using SetClipboardData.
376 * Only global memory based data items may be made available to non-OLE
377 * applications via the standard Windows clipboard API. Data based on other
378 * mediums(non TYMED_HGLOBAL) can only be accessed via the Ole Clipboard API.
380 * TODO: Do we need to additionally handle TYMED_IStorage media by copying
381 * the storage into global memory?
383 if ( pDataObj )
385 if ( FAILED(hr = IDataObject_EnumFormatEtc( pDataObj,
386 DATADIR_GET,
387 &penumFormatetc )))
389 HANDLE_ERROR( hr );
392 while ( S_OK == IEnumFORMATETC_Next(penumFormatetc, 1, &rgelt, NULL) )
394 if ( rgelt.tymed == TYMED_HGLOBAL )
396 CHAR szFmtName[80];
397 TRACE("(cfFormat=%d:%s)\n", rgelt.cfFormat,
398 GetClipboardFormatNameA(rgelt.cfFormat, szFmtName, sizeof(szFmtName)-1)
399 ? szFmtName : "");
401 SetClipboardData( rgelt.cfFormat, NULL);
404 IEnumFORMATETC_Release(penumFormatetc);
408 * Windows additionally creates a new "DataObject" clipboard format
409 * and stores in on the clipboard. We could possibly store a pointer
410 * to our internal IDataObject interface on the clipboard. I'm not
411 * sure what the use of this is though.
412 * Enable the code below for this functionality.
415 theOleClipboard->cfDataObj = RegisterClipboardFormatA("DataObject");
416 hDataObject = GlobalAlloc( GMEM_DDESHARE|GMEM_MOVEABLE|GMEM_ZEROINIT,
417 sizeof(OLEClipbrd *));
418 if (hDataObject==0)
419 HANDLE_ERROR( E_OUTOFMEMORY );
421 ppDataObject = (OLEClipbrd**)GlobalLock(hDataObject);
422 *ppDataObject = theOleClipboard;
423 GlobalUnlock(hDataObject);
425 if ( !SetClipboardData( theOleClipboard->cfDataObj, hDataObject ) )
426 HANDLE_ERROR( CLIPBRD_E_CANT_SET );
429 hr = S_OK;
431 CLEANUP:
434 * Close Windows clipboard (It remains associated with our window)
436 if ( bClipboardOpen && !CloseClipboard() )
437 hr = CLIPBRD_E_CANT_CLOSE;
440 * Release the source IDataObject if something failed
442 if ( FAILED(hr) )
444 if (theOleClipboard->pIDataObjectSrc)
446 IDataObject_Release(theOleClipboard->pIDataObjectSrc);
447 theOleClipboard->pIDataObjectSrc = NULL;
451 return hr;
455 /***********************************************************************
456 * OleGetClipboard [OLE32.105]
457 * Returns a pointer to our internal IDataObject which represents the conceptual
458 * state of the Windows clipboard. If the current clipboard already contains
459 * an IDataObject, our internal IDataObject will delegate to this object.
461 HRESULT WINAPI OleGetClipboard(IDataObject** ppDataObj)
463 HRESULT hr = S_OK;
464 TRACE("()\n");
467 * Make sure we have a clipboard object
469 OLEClipbrd_Initialize();
471 if (!theOleClipboard)
472 return E_OUTOFMEMORY;
474 /* Return a reference counted IDataObject */
475 hr = IDataObject_QueryInterface( (IDataObject*)&(theOleClipboard->lpvtbl1),
476 &IID_IDataObject, (void**)ppDataObj);
477 return hr;
480 /***********************************************************************
481 * OleFlushClipboard [OLE2.76]
484 HRESULT WINAPI OleFlushClipboard16(void)
486 return OleFlushClipboard();
490 /******************************************************************************
491 * OleFlushClipboard [OLE32.103]
492 * Renders the data from the source IDataObject into the windows clipboard
494 * TODO: OleFlushClipboard needs to additionally handle TYMED_IStorage media
495 * by copying the storage into global memory. Subsequently the default
496 * data object exposed through OleGetClipboard must convert this TYMED_HGLOBAL
497 * back to TYMED_IStorage.
499 HRESULT WINAPI OleFlushClipboard()
501 IEnumFORMATETC* penumFormatetc = NULL;
502 FORMATETC rgelt;
503 HRESULT hr = S_OK;
504 BOOL bClipboardOpen = FALSE;
505 IDataObject* pIDataObjectSrc = NULL;
507 TRACE("()\n");
510 * Make sure we have a clipboard object
512 OLEClipbrd_Initialize();
515 * Already flushed or no source DataObject? Nothing to do.
517 if (!theOleClipboard->pIDataObjectSrc)
518 return S_OK;
521 * Addref and save the source data object we are holding on to temporarily,
522 * since it will be released when we empty the clipboard.
524 pIDataObjectSrc = theOleClipboard->pIDataObjectSrc;
525 IDataObject_AddRef(pIDataObjectSrc);
528 * Open the Windows clipboard
530 if ( !(bClipboardOpen = OpenClipboard(theOleClipboard->hWndClipboard)) )
531 HANDLE_ERROR( CLIPBRD_E_CANT_OPEN );
534 * Empty the current clipboard
536 if ( !EmptyClipboard() )
537 HANDLE_ERROR( CLIPBRD_E_CANT_EMPTY );
540 * Render all HGLOBAL formats supported by the source into
541 * the windows clipboard.
543 if ( FAILED( hr = IDataObject_EnumFormatEtc( pIDataObjectSrc,
544 DATADIR_GET,
545 &penumFormatetc) ))
547 HANDLE_ERROR( hr );
550 while ( S_OK == IEnumFORMATETC_Next(penumFormatetc, 1, &rgelt, NULL) )
552 if ( rgelt.tymed == TYMED_HGLOBAL )
554 CHAR szFmtName[80];
555 TRACE("(cfFormat=%d:%s)\n", rgelt.cfFormat,
556 GetClipboardFormatNameA(rgelt.cfFormat, szFmtName, sizeof(szFmtName)-1)
557 ? szFmtName : "");
560 * Render the clipboard data
562 if ( FAILED(OLEClipbrd_RenderFormat( pIDataObjectSrc, &rgelt )) )
563 continue;
567 IEnumFORMATETC_Release(penumFormatetc);
570 * Release the source data object we are holding on to
572 IDataObject_Release(pIDataObjectSrc);
574 CLEANUP:
577 * Close Windows clipboard (It remains associated with our window)
579 if ( bClipboardOpen && !CloseClipboard() )
580 hr = CLIPBRD_E_CANT_CLOSE;
582 return hr;
586 /***********************************************************************
587 * OleIsCurrentClipboard [OLE32.110]
589 HRESULT WINAPI OleIsCurrentClipboard ( IDataObject *pDataObject)
591 TRACE("()\n");
593 * Make sure we have a clipboard object
595 OLEClipbrd_Initialize();
597 if (!theOleClipboard)
598 return E_OUTOFMEMORY;
600 return (pDataObject == theOleClipboard->pIDataObjectSrc) ? S_OK : S_FALSE;
604 /*---------------------------------------------------------------------*
605 * Internal implementation methods for the OLE clipboard
606 *---------------------------------------------------------------------*/
608 /***********************************************************************
609 * OLEClipbrd_Initialize()
610 * Initializes the OLE clipboard.
612 void OLEClipbrd_Initialize()
615 * Create the clipboard if necessary
617 if ( !theOleClipboard )
619 TRACE("()\n");
620 theOleClipboard = OLEClipbrd_Construct();
625 /***********************************************************************
626 * OLEClipbrd_UnInitialize()
627 * Un-Initializes the OLE clipboard
629 void OLEClipbrd_UnInitialize()
631 TRACE("()\n");
633 * Destroy the clipboard if no one holds a reference to us.
634 * Note that the clipboard was created with a reference count of 1.
636 if ( theOleClipboard && (theOleClipboard->ref <= 1) )
638 OLEClipbrd_Destroy( theOleClipboard );
640 else
642 WARN( "() : OLEClipbrd_UnInitialize called while client holds an IDataObject reference!\n");
647 /*********************************************************
648 * Construct the OLEClipbrd class.
650 static OLEClipbrd* OLEClipbrd_Construct()
652 OLEClipbrd* newObject = NULL;
653 HGLOBAL hNewObject = 0;
656 * Allocate space for the object. We use GlobalAlloc since we need
657 * an HGLOBAL to expose our DataObject as a registered clipboard type.
659 hNewObject = GlobalAlloc( GMEM_DDESHARE|GMEM_MOVEABLE|GMEM_ZEROINIT,
660 sizeof(OLEClipbrd));
661 if (hNewObject==0)
662 return NULL;
665 * Lock the handle for the entire lifetime of the clipboard.
667 newObject = GlobalLock(hNewObject);
670 * Initialize the virtual function table.
672 newObject->lpvtbl1 = &OLEClipbrd_IDataObject_VTable;
675 * Start with one reference count. The caller of this function
676 * must release the interface pointer when it is done.
678 newObject->ref = 1;
680 newObject->hSelf = hNewObject;
683 * The Ole clipboard is a singleton - save the global handle and pointer
685 theOleClipboard = newObject;
686 hTheOleClipboard = hNewObject;
688 return theOleClipboard;
691 static void OLEClipbrd_Destroy(OLEClipbrd* ptrToDestroy)
693 TRACE("()\n");
695 if ( !ptrToDestroy )
696 return;
699 * Destroy the Ole clipboard window
701 if ( ptrToDestroy->hWndClipboard )
702 OLEClipbrd_DestroyWindow(ptrToDestroy->hWndClipboard);
705 * Free the actual OLE Clipboard structure.
707 TRACE("() - Destroying clipboard data object.\n");
708 GlobalUnlock(ptrToDestroy->hSelf);
709 GlobalFree(ptrToDestroy->hSelf);
712 * The Ole clipboard is a singleton (ptrToDestroy == theOleClipboard)
714 theOleClipboard = NULL;
715 hTheOleClipboard = 0;
719 /***********************************************************************
720 * OLEClipbrd_CreateWindow()
721 * Create the clipboard window
723 static HWND OLEClipbrd_CreateWindow()
725 HWND hwnd = 0;
726 WNDCLASSEXA wcex;
729 * Register the clipboard window class if necessary
731 ZeroMemory( &wcex, sizeof(WNDCLASSEXA));
733 wcex.cbSize = sizeof(WNDCLASSEXA);
734 /* Windows creates this class with a style mask of 0
735 * We dont bother doing this since the FindClassByAtom code
736 * would have to be changed to deal with this idiosyncracy. */
737 wcex.style = CS_GLOBALCLASS;
738 wcex.lpfnWndProc = (WNDPROC)OLEClipbrd_WndProc;
739 wcex.hInstance = 0;
740 wcex.lpszClassName = OLEClipbrd_WNDCLASS;
742 RegisterClassExA(&wcex);
745 * Create a hidden window to receive OLE clipboard messages
749 * If we need to store state info we can store it here.
750 * For now we dont need this functionality.
751 * ClipboardWindowInfo clipboardInfo;
752 * ZeroMemory( &trackerInfo, sizeof(ClipboardWindowInfo));
755 hwnd = CreateWindowA(OLEClipbrd_WNDCLASS,
756 "ClipboardWindow",
757 WS_POPUP | WS_CLIPSIBLINGS | WS_OVERLAPPED,
758 CW_USEDEFAULT, CW_USEDEFAULT,
759 CW_USEDEFAULT, CW_USEDEFAULT,
763 0 /*(LPVOID)&clipboardInfo */);
765 return hwnd;
768 /***********************************************************************
769 * OLEClipbrd_DestroyWindow(HWND)
770 * Destroy the clipboard window and unregister its class
772 static void OLEClipbrd_DestroyWindow(HWND hwnd)
775 * Destroy clipboard window and unregister its WNDCLASS
777 DestroyWindow(hwnd);
778 UnregisterClassA( OLEClipbrd_WNDCLASS, 0 );
781 /***********************************************************************
782 * OLEClipbrd_WndProc(HWND, unsigned, WORD, LONG)
783 * Processes messages sent to the OLE clipboard window.
784 * Note that we will intercept messages in our WndProc only when data
785 * has been placed in the clipboard via OleSetClipboard().
786 * i.e. Only when OLE owns the windows clipboard.
788 LRESULT CALLBACK OLEClipbrd_WndProc
789 (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
791 switch (message)
794 * WM_RENDERFORMAT
795 * We receive this message to allow us to handle delayed rendering of
796 * a specific clipboard format when an application requests data in
797 * that format by calling GetClipboardData.
798 * (Recall that in OleSetClipboard, we used SetClipboardData to
799 * make all HGLOBAL formats supported by the source IDataObject
800 * available using delayed rendering)
801 * On receiving this mesage we must actually render the data in the
802 * specified format and place it on the clipboard by calling the
803 * SetClipboardData function.
805 case WM_RENDERFORMAT:
807 FORMATETC rgelt;
809 ZeroMemory( &rgelt, sizeof(FORMATETC));
812 * Initialize FORMATETC to a Windows clipboard friendly format
814 rgelt.cfFormat = (UINT) wParam;
815 rgelt.dwAspect = DVASPECT_CONTENT;
816 rgelt.lindex = -1;
817 rgelt.tymed = TYMED_HGLOBAL;
819 TRACE("(): WM_RENDERFORMAT(cfFormat=%d)\n", rgelt.cfFormat);
822 * Render the clipboard data.
823 * (We must have a source data object or we wouldn't be in this WndProc)
825 OLEClipbrd_RenderFormat( (IDataObject*)&(theOleClipboard->lpvtbl1), &rgelt );
827 break;
831 * WM_RENDERALLFORMATS
832 * Sent before the clipboard owner window is destroyed.
833 * We should receive this message only when OleUninitialize is called
834 * while we have an IDataObject in the clipboard.
835 * For the content of the clipboard to remain available to other
836 * applications, we must render data in all the formats the source IDataObject
837 * is capable of generating, and place the data on the clipboard by calling
838 * SetClipboardData.
840 case WM_RENDERALLFORMATS:
842 IEnumFORMATETC* penumFormatetc = NULL;
843 FORMATETC rgelt;
845 TRACE("(): WM_RENDERALLFORMATS\n");
848 * Render all HGLOBAL formats supported by the source into
849 * the windows clipboard.
851 if ( FAILED( IDataObject_EnumFormatEtc( (IDataObject*)&(theOleClipboard->lpvtbl1),
852 DATADIR_GET, &penumFormatetc) ) )
854 WARN("(): WM_RENDERALLFORMATS failed to retrieve EnumFormatEtc!\n");
855 return 0;
858 while ( S_OK == IEnumFORMATETC_Next(penumFormatetc, 1, &rgelt, NULL) )
860 if ( rgelt.tymed == TYMED_HGLOBAL )
863 * Render the clipboard data.
865 if ( FAILED(OLEClipbrd_RenderFormat( (IDataObject*)&(theOleClipboard->lpvtbl1), &rgelt )) )
866 continue;
868 TRACE("(): WM_RENDERALLFORMATS(cfFormat=%d)\n", rgelt.cfFormat);
872 IEnumFORMATETC_Release(penumFormatetc);
874 break;
878 * WM_DESTROYCLIPBOARD
879 * This is sent by EmptyClipboard before the clipboard is emptied.
880 * We should release any IDataObject we are holding onto when we receive
881 * this message, since it indicates that the OLE clipboard should be empty
882 * from this point on.
884 case WM_DESTROYCLIPBOARD:
886 TRACE("(): WM_DESTROYCLIPBOARD\n");
888 * Release the data object we are holding on to
890 if ( theOleClipboard->pIDataObjectSrc )
892 IDataObject_Release(theOleClipboard->pIDataObjectSrc);
893 theOleClipboard->pIDataObjectSrc = NULL;
895 break;
899 case WM_ASKCBFORMATNAME:
900 case WM_CHANGECBCHAIN:
901 case WM_DRAWCLIPBOARD:
902 case WM_SIZECLIPBOARD:
903 case WM_HSCROLLCLIPBOARD:
904 case WM_VSCROLLCLIPBOARD:
905 case WM_PAINTCLIPBOARD:
907 default:
908 return DefWindowProcA(hWnd, message, wParam, lParam);
911 return 0;
914 #define MAX_CLIPFORMAT_NAME 80
916 /***********************************************************************
917 * OLEClipbrd_RenderFormat(LPFORMATETC)
918 * Render the clipboard data. Note that this call will delegate to the
919 * source data object.
920 * Note: This function assumes it is passed an HGLOBAL format to render.
922 static HRESULT OLEClipbrd_RenderFormat(IDataObject *pIDataObject, LPFORMATETC pFormatetc)
924 STGMEDIUM std;
925 HGLOBAL hDup;
926 HRESULT hr = S_OK;
927 char szFmtName[MAX_CLIPFORMAT_NAME];
928 ILockBytes *ptrILockBytes = 0;
929 HGLOBAL hStorage = 0;
931 GetClipboardFormatNameA(pFormatetc->cfFormat, szFmtName, MAX_CLIPFORMAT_NAME);
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 hr = CreateILockBytesOnHGlobal(hStorage, FALSE, &ptrILockBytes);
941 hr = StgCreateDocfileOnILockBytes(ptrILockBytes, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &std.u.pstg);
943 if (FAILED(hr = IDataObject_GetDataHere(theOleClipboard->pIDataObjectSrc, pFormatetc, &std)))
945 WARN("() : IDataObject_GetDataHere failed to render clipboard data! (%lx)\n", hr);
946 return hr;
949 if (1) /* check whether the presentation data is already -not- present */
951 FORMATETC fmt2;
952 STGMEDIUM std2;
953 METAFILEPICT *mfp = 0;
955 fmt2.cfFormat = CF_METAFILEPICT;
956 fmt2.ptd = 0;
957 fmt2.dwAspect = DVASPECT_CONTENT;
958 fmt2.lindex = -1;
959 fmt2.tymed = TYMED_MFPICT;
961 memset(&std2, 0, sizeof(STGMEDIUM));
962 std2.tymed = TYMED_MFPICT;
964 /* Get the metafile picture out of it */
966 if (!FAILED(hr = IDataObject_GetData(theOleClipboard->pIDataObjectSrc, &fmt2, &std2)))
968 mfp = (METAFILEPICT *)GlobalLock(std2.u.hGlobal);
971 if (mfp)
973 OLECHAR name[]={ 2, 'O', 'l', 'e', 'P', 'r', 'e', 's', '0', '0', '0', 0};
974 IStream *pStream = 0;
975 void *mfBits;
976 PresentationDataHeader pdh;
977 INT nSize;
978 CLSID clsID;
979 LPOLESTR strProgID;
980 CHAR strOleTypeName[51];
981 BYTE OlePresStreamHeader [] =
983 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00,
984 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
985 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
986 0x00, 0x00, 0x00, 0x00
989 nSize = GetMetaFileBitsEx(mfp->hMF, 0, NULL);
991 memset(&pdh, 0, sizeof(PresentationDataHeader));
992 memcpy(&pdh, OlePresStreamHeader, sizeof(OlePresStreamHeader));
994 pdh.dwObjectExtentX = mfp->xExt;
995 pdh.dwObjectExtentY = mfp->yExt;
996 pdh.dwSize = nSize;
998 hr = IStorage_CreateStream(std.u.pstg, name, STGM_CREATE|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, 0, &pStream);
1000 hr = IStream_Write(pStream, &pdh, sizeof(PresentationDataHeader), NULL);
1002 mfBits = HeapAlloc(GetProcessHeap(), 0, nSize);
1003 nSize = GetMetaFileBitsEx(mfp->hMF, nSize, mfBits);
1005 hr = IStream_Write(pStream, mfBits, nSize, NULL);
1007 IStream_Release(pStream);
1009 HeapFree(GetProcessHeap(), 0, mfBits);
1011 GlobalUnlock(std2.u.hGlobal);
1013 ReadClassStg(std.u.pstg, &clsID);
1014 ProgIDFromCLSID(&clsID, &strProgID);
1016 WideCharToMultiByte( CP_ACP, 0, strProgID, -1, strOleTypeName, sizeof(strOleTypeName), NULL, NULL );
1017 OLECONVERT_CreateOleStream(std.u.pstg);
1018 OLECONVERT_CreateCompObjStream(std.u.pstg, strOleTypeName);
1022 else
1024 if (FAILED(hr = IDataObject_GetData(pIDataObject, pFormatetc, &std)))
1026 WARN("() : IDataObject_GetData failed to render clipboard data! (%lx)\n", hr);
1027 return hr;
1030 /* To put a copy back on the clipboard */
1032 hStorage = std.u.hGlobal;
1036 * Put a copy of the rendered data back on the clipboard
1039 if ( !(hDup = OLEClipbrd_GlobalDupMem(hStorage)) )
1040 HANDLE_ERROR( E_OUTOFMEMORY );
1042 if ( !SetClipboardData( pFormatetc->cfFormat, hDup ) )
1044 GlobalFree(hDup);
1045 WARN("() : Failed to set rendered clipboard data into clipboard!\n");
1048 CLEANUP:
1050 ReleaseStgMedium(&std);
1052 return hr;
1056 /***********************************************************************
1057 * OLEClipbrd_GlobalDupMem( HGLOBAL )
1058 * Helper method to duplicate an HGLOBAL chunk of memory
1060 static HGLOBAL OLEClipbrd_GlobalDupMem( HGLOBAL hGlobalSrc )
1062 HGLOBAL hGlobalDest;
1063 PVOID pGlobalSrc, pGlobalDest;
1064 DWORD cBytes;
1066 if ( !hGlobalSrc )
1067 return 0;
1069 cBytes = GlobalSize(hGlobalSrc);
1070 if ( 0 == cBytes )
1071 return 0;
1073 hGlobalDest = GlobalAlloc( GMEM_DDESHARE|GMEM_MOVEABLE,
1074 cBytes );
1075 if ( !hGlobalDest )
1076 return 0;
1078 pGlobalSrc = GlobalLock(hGlobalSrc);
1079 pGlobalDest = GlobalLock(hGlobalDest);
1080 if ( !pGlobalSrc || !pGlobalDest )
1081 return 0;
1083 memcpy(pGlobalDest, pGlobalSrc, cBytes);
1085 GlobalUnlock(hGlobalSrc);
1086 GlobalUnlock(hGlobalDest);
1088 return hGlobalDest;
1092 /*---------------------------------------------------------------------*
1093 * Implementation of the internal IDataObject interface exposed by
1094 * the OLE clipboard.
1095 *---------------------------------------------------------------------*/
1098 /************************************************************************
1099 * OLEClipbrd_IDataObject_QueryInterface (IUnknown)
1101 * See Windows documentation for more details on IUnknown methods.
1103 static HRESULT WINAPI OLEClipbrd_IDataObject_QueryInterface(
1104 IDataObject* iface,
1105 REFIID riid,
1106 void** ppvObject)
1109 * Declare "This" pointer
1111 ICOM_THIS(OLEClipbrd, iface);
1112 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObject);
1115 * Perform a sanity check on the parameters.
1117 if ( (This==0) || (ppvObject==0) )
1118 return E_INVALIDARG;
1121 * Initialize the return parameter.
1123 *ppvObject = 0;
1126 * Compare the riid with the interface IDs implemented by this object.
1128 if (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0)
1130 *ppvObject = iface;
1132 else if (memcmp(&IID_IDataObject, riid, sizeof(IID_IDataObject)) == 0)
1134 *ppvObject = (IDataObject*)&(This->lpvtbl1);
1136 else /* We only support IUnknown and IDataObject */
1138 WARN( "() : asking for unsupported interface %s\n", debugstr_guid(riid));
1139 return E_NOINTERFACE;
1143 * Query Interface always increases the reference count by one when it is
1144 * successful.
1146 IUnknown_AddRef((IUnknown*)*ppvObject);
1148 return S_OK;
1151 /************************************************************************
1152 * OLEClipbrd_IDataObject_AddRef (IUnknown)
1154 * See Windows documentation for more details on IUnknown methods.
1156 static ULONG WINAPI OLEClipbrd_IDataObject_AddRef(
1157 IDataObject* iface)
1160 * Declare "This" pointer
1162 ICOM_THIS(OLEClipbrd, iface);
1164 TRACE("(%p)->(count=%lu)\n",This, This->ref);
1166 This->ref++;
1168 return This->ref;
1171 /************************************************************************
1172 * OLEClipbrd_IDataObject_Release (IUnknown)
1174 * See Windows documentation for more details on IUnknown methods.
1176 static ULONG WINAPI OLEClipbrd_IDataObject_Release(
1177 IDataObject* iface)
1180 * Declare "This" pointer
1182 ICOM_THIS(OLEClipbrd, iface);
1184 TRACE("(%p)->(count=%lu)\n",This, This->ref);
1187 * Decrease the reference count on this object.
1189 This->ref--;
1192 * If the reference count goes down to 0, perform suicide.
1194 if (This->ref==0)
1196 OLEClipbrd_Destroy(This);
1199 return This->ref;
1203 /************************************************************************
1204 * OLEClipbrd_IDataObject_GetData (IDataObject)
1206 * The OLE Clipboard's implementation of this method delegates to
1207 * a data source if there is one or wraps around the windows clipboard
1209 * See Windows documentation for more details on IDataObject methods.
1211 static HRESULT WINAPI OLEClipbrd_IDataObject_GetData(
1212 IDataObject* iface,
1213 LPFORMATETC pformatetcIn,
1214 STGMEDIUM* pmedium)
1216 HANDLE hData = 0;
1217 BOOL bClipboardOpen = FALSE;
1218 HRESULT hr = S_OK;
1219 LPVOID src;
1222 * Declare "This" pointer
1224 ICOM_THIS(OLEClipbrd, iface);
1226 TRACE("(%p,%p,%p)\n", iface, pformatetcIn, pmedium);
1228 if ( !pformatetcIn || !pmedium )
1229 return E_INVALIDARG;
1232 * If we have a data source placed on the clipboard (via OleSetClipboard)
1233 * simply delegate to the source object's QueryGetData
1234 * NOTE: This code assumes that the IDataObject is in the same address space!
1235 * We will need to add marshalling support when Wine handles multiple processes.
1237 if ( This->pIDataObjectSrc )
1239 return IDataObject_GetData(This->pIDataObjectSrc, pformatetcIn, pmedium);
1242 if ( pformatetcIn->lindex != -1 )
1243 return DV_E_LINDEX;
1244 if ( (pformatetcIn->tymed & TYMED_HGLOBAL) != TYMED_HGLOBAL )
1245 return DV_E_TYMED;
1247 if ( pformatetcIn->dwAspect != DVASPECT_CONTENT )
1248 return DV_E_DVASPECT;
1252 * Otherwise, get the data from the windows clipboard using GetClipboardData
1254 if ( !(bClipboardOpen = OpenClipboard(theOleClipboard->hWndClipboard)) )
1255 HANDLE_ERROR( CLIPBRD_E_CANT_OPEN );
1257 hData = GetClipboardData(pformatetcIn->cfFormat);
1259 /* Must make a copy of global handle returned by GetClipboardData; it
1260 * is not valid after we call CloseClipboard
1261 * Application is responsible for freeing the memory (Forte Agent does this)
1263 src = GlobalLock(hData);
1264 if(src) {
1265 LPVOID dest;
1266 ULONG size;
1267 HANDLE hDest;
1269 size = GlobalSize(hData);
1270 hDest = GlobalAlloc(GHND, size);
1271 dest = GlobalLock(hDest);
1272 memcpy(dest, src, size);
1273 GlobalUnlock(hDest);
1274 GlobalUnlock(hData);
1275 hData = hDest;
1279 * Return the clipboard data in the storage medium structure
1281 pmedium->tymed = (hData == 0) ? TYMED_NULL : TYMED_HGLOBAL;
1282 pmedium->u.hGlobal = (HGLOBAL)hData;
1283 pmedium->pUnkForRelease = NULL;
1285 hr = S_OK;
1287 CLEANUP:
1289 * Close Windows clipboard
1291 if ( bClipboardOpen && !CloseClipboard() )
1292 hr = CLIPBRD_E_CANT_CLOSE;
1294 if ( FAILED(hr) )
1295 return hr;
1296 return (hData == 0) ? DV_E_FORMATETC : S_OK;
1299 static HRESULT WINAPI OLEClipbrd_IDataObject_GetDataHere(
1300 IDataObject* iface,
1301 LPFORMATETC pformatetc,
1302 STGMEDIUM* pmedium)
1304 FIXME(": Stub\n");
1305 return E_NOTIMPL;
1308 /************************************************************************
1309 * OLEClipbrd_IDataObject_QueryGetData (IDataObject)
1311 * The OLE Clipboard's implementation of this method delegates to
1312 * a data source if there is one or wraps around the windows clipboard
1313 * function IsClipboardFormatAvailable() otherwise.
1315 * See Windows documentation for more details on IDataObject methods.
1317 static HRESULT WINAPI OLEClipbrd_IDataObject_QueryGetData(
1318 IDataObject* iface,
1319 LPFORMATETC pformatetc)
1322 * Declare "This" pointer
1324 ICOM_THIS(OLEClipbrd, iface);
1326 TRACE("(%p, %p)\n", iface, pformatetc);
1329 * If we have a data source placed on the clipboard (via OleSetClipboard)
1330 * simply delegate to the source object's QueryGetData
1332 if ( This->pIDataObjectSrc )
1334 return IDataObject_QueryGetData(This->pIDataObjectSrc, pformatetc);
1337 if (!pformatetc)
1338 return E_INVALIDARG;
1340 if ( pformatetc->dwAspect != DVASPECT_CONTENT )
1341 return DV_E_DVASPECT;
1343 if ( pformatetc->lindex != -1 )
1344 return DV_E_LINDEX;
1346 /* TODO: Handle TYMED_IStorage media which were put on the clipboard
1347 * by copying the storage into global memory. We must convert this
1348 * TYMED_HGLOBAL back to TYMED_IStorage.
1350 if ( pformatetc->tymed != TYMED_HGLOBAL )
1351 return DV_E_TYMED;
1354 * Delegate to the Windows clipboard function IsClipboardFormatAvailable
1356 return (IsClipboardFormatAvailable(pformatetc->cfFormat)) ? S_OK : DV_E_FORMATETC;
1359 /************************************************************************
1360 * OLEClipbrd_IDataObject_GetCanonicalFormatEtc (IDataObject)
1362 * See Windows documentation for more details on IDataObject methods.
1364 static HRESULT WINAPI OLEClipbrd_IDataObject_GetCanonicalFormatEtc(
1365 IDataObject* iface,
1366 LPFORMATETC pformatectIn,
1367 LPFORMATETC pformatetcOut)
1369 TRACE("(%p, %p, %p)\n", iface, pformatectIn, pformatetcOut);
1371 if ( !pformatectIn || !pformatetcOut )
1372 return E_INVALIDARG;
1374 memcpy(pformatetcOut, pformatectIn, sizeof(FORMATETC));
1375 return DATA_S_SAMEFORMATETC;
1378 /************************************************************************
1379 * OLEClipbrd_IDataObject_SetData (IDataObject)
1381 * The OLE Clipboard's does not implement this method
1383 * See Windows documentation for more details on IDataObject methods.
1385 static HRESULT WINAPI OLEClipbrd_IDataObject_SetData(
1386 IDataObject* iface,
1387 LPFORMATETC pformatetc,
1388 STGMEDIUM* pmedium,
1389 BOOL fRelease)
1391 TRACE("\n");
1392 return E_NOTIMPL;
1395 /************************************************************************
1396 * OLEClipbrd_IDataObject_EnumFormatEtc (IDataObject)
1398 * See Windows documentation for more details on IDataObject methods.
1400 static HRESULT WINAPI OLEClipbrd_IDataObject_EnumFormatEtc(
1401 IDataObject* iface,
1402 DWORD dwDirection,
1403 IEnumFORMATETC** ppenumFormatEtc)
1405 HRESULT hr = S_OK;
1406 FORMATETC *afmt = NULL;
1407 int cfmt, i;
1408 UINT format;
1409 BOOL bClipboardOpen;
1412 * Declare "This" pointer
1414 ICOM_THIS(OLEClipbrd, iface);
1416 TRACE("(%p, %lx, %p)\n", iface, dwDirection, ppenumFormatEtc);
1419 * If we have a data source placed on the clipboard (via OleSetClipboard)
1420 * simply delegate to the source object's EnumFormatEtc
1422 if ( This->pIDataObjectSrc )
1424 return IDataObject_EnumFormatEtc(This->pIDataObjectSrc,
1425 dwDirection, ppenumFormatEtc);
1429 * Otherwise we must provide our own enumerator which wraps around the
1430 * Windows clipboard function EnumClipboardFormats
1432 if ( !ppenumFormatEtc )
1433 return E_INVALIDARG;
1435 if ( dwDirection != DATADIR_GET ) /* IDataObject_SetData not implemented */
1436 return E_NOTIMPL;
1439 * Store all current clipboard formats in an array of FORMATETC's,
1440 * and create an IEnumFORMATETC enumerator from this list.
1442 cfmt = CountClipboardFormats();
1443 afmt = (FORMATETC *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1444 sizeof(FORMATETC) * cfmt);
1446 * Open the Windows clipboard, associating it with our hidden window
1448 if ( !(bClipboardOpen = OpenClipboard(This->hWndClipboard)) )
1449 HANDLE_ERROR( CLIPBRD_E_CANT_OPEN );
1452 * Store all current clipboard formats in an array of FORMATETC's
1453 * TODO: Handle TYMED_IStorage media which were put on the clipboard
1454 * by copying the storage into global memory. We must convert this
1455 * TYMED_HGLOBAL back to TYMED_IStorage.
1457 for (i = 0, format = 0; i < cfmt; i++)
1459 format = EnumClipboardFormats(format);
1460 if (!format) /* Failed! */
1462 ERR("EnumClipboardFormats failed to return format!\n");
1463 HANDLE_ERROR( E_FAIL );
1466 /* Init the FORMATETC struct */
1467 afmt[i].cfFormat = format;
1468 afmt[i].ptd = NULL;
1469 afmt[i].dwAspect = DVASPECT_CONTENT;
1470 afmt[i].lindex = -1;
1471 afmt[i].tymed = TYMED_HGLOBAL;
1475 * Create an EnumFORMATETC enumerator and return an
1476 * EnumFORMATETC after bumping up its ref count
1478 *ppenumFormatEtc = OLEClipbrd_IEnumFORMATETC_Construct( cfmt, afmt, (LPUNKNOWN)iface);
1479 if (!(*ppenumFormatEtc))
1480 HANDLE_ERROR( E_OUTOFMEMORY );
1482 if (FAILED( hr = IEnumFORMATETC_AddRef(*ppenumFormatEtc)))
1483 HANDLE_ERROR( hr );
1485 hr = S_OK;
1487 CLEANUP:
1489 * Free the array of FORMATETC's
1491 if (afmt)
1492 HeapFree(GetProcessHeap(), 0, afmt);
1495 * Close Windows clipboard
1497 if ( bClipboardOpen && !CloseClipboard() )
1498 hr = CLIPBRD_E_CANT_CLOSE;
1500 return hr;
1503 /************************************************************************
1504 * OLEClipbrd_IDataObject_DAdvise (IDataObject)
1506 * The OLE Clipboard's does not implement this method
1508 * See Windows documentation for more details on IDataObject methods.
1510 static HRESULT WINAPI OLEClipbrd_IDataObject_DAdvise(
1511 IDataObject* iface,
1512 FORMATETC* pformatetc,
1513 DWORD advf,
1514 IAdviseSink* pAdvSink,
1515 DWORD* pdwConnection)
1517 TRACE("\n");
1518 return E_NOTIMPL;
1521 /************************************************************************
1522 * OLEClipbrd_IDataObject_DUnadvise (IDataObject)
1524 * The OLE Clipboard's does not implement this method
1526 * See Windows documentation for more details on IDataObject methods.
1528 static HRESULT WINAPI OLEClipbrd_IDataObject_DUnadvise(
1529 IDataObject* iface,
1530 DWORD dwConnection)
1532 TRACE("\n");
1533 return E_NOTIMPL;
1536 /************************************************************************
1537 * OLEClipbrd_IDataObject_EnumDAdvise (IDataObject)
1539 * The OLE Clipboard does not implement this method
1541 * See Windows documentation for more details on IDataObject methods.
1543 static HRESULT WINAPI OLEClipbrd_IDataObject_EnumDAdvise(
1544 IDataObject* iface,
1545 IEnumSTATDATA** ppenumAdvise)
1547 TRACE("\n");
1548 return E_NOTIMPL;
1552 /*---------------------------------------------------------------------*
1553 * Implementation of the internal IEnumFORMATETC interface returned by
1554 * the OLE clipboard's IDataObject.
1555 *---------------------------------------------------------------------*/
1557 /************************************************************************
1558 * OLEClipbrd_IEnumFORMATETC_Construct (UINT, const FORMATETC, LPUNKNOWN)
1560 * Creates an IEnumFORMATETC enumerator from an array of FORMATETC
1561 * Structures. pUnkOuter is the outer unknown for reference counting only.
1562 * NOTE: this does not AddRef the interface.
1565 LPENUMFORMATETC OLEClipbrd_IEnumFORMATETC_Construct(UINT cfmt, const FORMATETC afmt[],
1566 LPUNKNOWN pUnkDataObj)
1568 IEnumFORMATETCImpl* ef;
1569 DWORD size=cfmt * sizeof(FORMATETC);
1570 LPMALLOC pIMalloc;
1572 ef = (IEnumFORMATETCImpl*)HeapAlloc(GetProcessHeap(),
1573 HEAP_ZERO_MEMORY,
1574 sizeof(IEnumFORMATETCImpl));
1575 if (!ef)
1576 return NULL;
1578 ef->ref = 0;
1579 ef->lpVtbl = &efvt;
1580 ef->pUnkDataObj = pUnkDataObj;
1582 ef->posFmt = 0;
1583 ef->countFmt = cfmt;
1584 if (FAILED(CoGetMalloc(MEMCTX_TASK, &pIMalloc)))
1585 return NULL;
1586 ef->pFmt = (LPFORMATETC)IMalloc_Alloc(pIMalloc, size);
1587 IMalloc_Release(pIMalloc);
1589 if (ef->pFmt)
1590 memcpy(ef->pFmt, afmt, size);
1592 TRACE("(%p)->()\n",ef);
1593 return (LPENUMFORMATETC)ef;
1597 /************************************************************************
1598 * OLEClipbrd_IEnumFORMATETC_QueryInterface (IUnknown)
1600 * See Windows documentation for more details on IUnknown methods.
1602 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_QueryInterface
1603 (LPENUMFORMATETC iface, REFIID riid, LPVOID* ppvObj)
1605 ICOM_THIS(IEnumFORMATETCImpl,iface);
1607 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
1610 * Since enumerators are separate objects from the parent data object
1611 * we only need to support the IUnknown and IEnumFORMATETC interfaces
1614 *ppvObj = NULL;
1616 if(IsEqualIID(riid, &IID_IUnknown))
1618 *ppvObj = This;
1620 else if(IsEqualIID(riid, &IID_IEnumFORMATETC))
1622 *ppvObj = (IDataObject*)This;
1625 if(*ppvObj)
1627 IEnumFORMATETC_AddRef((IEnumFORMATETC*)*ppvObj);
1628 TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
1629 return S_OK;
1632 TRACE("-- Interface: E_NOINTERFACE\n");
1633 return E_NOINTERFACE;
1636 /************************************************************************
1637 * OLEClipbrd_IEnumFORMATETC_AddRef (IUnknown)
1639 * Since enumerating formats only makes sense when our data object is around,
1640 * we insure that it stays as long as we stay by calling our parents IUnknown
1641 * for AddRef and Release. But since we are not controlled by the lifetime of
1642 * the outer object, we still keep our own reference count in order to
1643 * free ourselves.
1645 static ULONG WINAPI OLEClipbrd_IEnumFORMATETC_AddRef(LPENUMFORMATETC iface)
1647 ICOM_THIS(IEnumFORMATETCImpl,iface);
1648 TRACE("(%p)->(count=%lu)\n",This, This->ref);
1650 if (This->pUnkDataObj)
1651 IUnknown_AddRef(This->pUnkDataObj);
1653 return ++(This->ref);
1656 /************************************************************************
1657 * OLEClipbrd_IEnumFORMATETC_Release (IUnknown)
1659 * See Windows documentation for more details on IUnknown methods.
1661 static ULONG WINAPI OLEClipbrd_IEnumFORMATETC_Release(LPENUMFORMATETC iface)
1663 ICOM_THIS(IEnumFORMATETCImpl,iface);
1664 LPMALLOC pIMalloc;
1666 TRACE("(%p)->(count=%lu)\n",This, This->ref);
1668 if (This->pUnkDataObj)
1669 IUnknown_Release(This->pUnkDataObj); /* Release parent data object */
1671 if (!--(This->ref))
1673 TRACE("() - destroying IEnumFORMATETC(%p)\n",This);
1674 if (SUCCEEDED(CoGetMalloc(MEMCTX_TASK, &pIMalloc)))
1676 IMalloc_Free(pIMalloc, This->pFmt);
1677 IMalloc_Release(pIMalloc);
1680 HeapFree(GetProcessHeap(),0,This);
1681 return 0;
1684 return This->ref;
1687 /************************************************************************
1688 * OLEClipbrd_IEnumFORMATETC_Next (IEnumFORMATETC)
1690 * Standard enumerator members for IEnumFORMATETC
1692 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Next
1693 (LPENUMFORMATETC iface, ULONG celt, FORMATETC *rgelt, ULONG *pceltFethed)
1695 ICOM_THIS(IEnumFORMATETCImpl,iface);
1696 UINT cfetch;
1697 HRESULT hres = S_FALSE;
1699 TRACE("(%p)->(pos=%u)\n", This, This->posFmt);
1701 if (This->posFmt < This->countFmt)
1703 cfetch = This->countFmt - This->posFmt;
1704 if (cfetch >= celt)
1706 cfetch = celt;
1707 hres = S_OK;
1710 memcpy(rgelt, &This->pFmt[This->posFmt], cfetch * sizeof(FORMATETC));
1711 This->posFmt += cfetch;
1713 else
1715 cfetch = 0;
1718 if (pceltFethed)
1720 *pceltFethed = cfetch;
1723 return hres;
1726 /************************************************************************
1727 * OLEClipbrd_IEnumFORMATETC_Skip (IEnumFORMATETC)
1729 * Standard enumerator members for IEnumFORMATETC
1731 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Skip(LPENUMFORMATETC iface, ULONG celt)
1733 ICOM_THIS(IEnumFORMATETCImpl,iface);
1734 TRACE("(%p)->(num=%lu)\n", This, celt);
1736 This->posFmt += celt;
1737 if (This->posFmt > This->countFmt)
1739 This->posFmt = This->countFmt;
1740 return S_FALSE;
1742 return S_OK;
1745 /************************************************************************
1746 * OLEClipbrd_IEnumFORMATETC_Reset (IEnumFORMATETC)
1748 * Standard enumerator members for IEnumFORMATETC
1750 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Reset(LPENUMFORMATETC iface)
1752 ICOM_THIS(IEnumFORMATETCImpl,iface);
1753 TRACE("(%p)->()\n", This);
1755 This->posFmt = 0;
1756 return S_OK;
1759 /************************************************************************
1760 * OLEClipbrd_IEnumFORMATETC_Clone (IEnumFORMATETC)
1762 * Standard enumerator members for IEnumFORMATETC
1764 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Clone
1765 (LPENUMFORMATETC iface, LPENUMFORMATETC* ppenum)
1767 ICOM_THIS(IEnumFORMATETCImpl,iface);
1768 HRESULT hr = S_OK;
1770 TRACE("(%p)->(ppenum=%p)\n", This, ppenum);
1772 if ( !ppenum )
1773 return E_INVALIDARG;
1775 *ppenum = OLEClipbrd_IEnumFORMATETC_Construct(This->countFmt,
1776 This->pFmt,
1777 This->pUnkDataObj);
1779 if (FAILED( hr = IEnumFORMATETC_AddRef(*ppenum)))
1780 return ( hr );
1782 return (*ppenum) ? S_OK : E_OUTOFMEMORY;