push decde5eed3d79f9d889b4d757f73e86ce6ff9241
[wine/hacks.git] / dlls / ole32 / clipboard.c
blob909b21547d286b7a3a80c3316f8517742df1885c
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 #define HANDLE_ERROR(err) { hr = err; TRACE("(HRESULT=%x)\n", (HRESULT)err); goto CLEANUP; }
83 WINE_DEFAULT_DEBUG_CHANNEL(ole);
85 /****************************************************************************
86 * OLEClipbrd
87 * DO NOT add any members before the VTables declaration!
89 struct OLEClipbrd
92 * List all interface VTables here
94 const IDataObjectVtbl* lpvtbl1; /* IDataObject VTable */
97 * The hidden OLE clipboard window. This window is used as the bridge between the
98 * the OLE and windows clipboard API. (Windows creates one such window per process)
100 HWND hWndClipboard;
103 * Pointer to the source data object (via OleSetClipboard)
105 IDataObject* pIDataObjectSrc;
108 * The registered DataObject clipboard format
110 UINT cfDataObj;
113 * The handle to ourself
115 HGLOBAL hSelf;
118 * Reference count of this object
120 LONG ref;
123 typedef struct OLEClipbrd OLEClipbrd;
126 /****************************************************************************
127 * IEnumFORMATETC implementation
128 * DO NOT add any members before the VTables declaration!
130 typedef struct
132 /* IEnumFORMATETC VTable */
133 const IEnumFORMATETCVtbl *lpVtbl;
135 /* IEnumFORMATETC fields */
136 UINT posFmt; /* current enumerator position */
137 UINT countFmt; /* number of EnumFORMATETC's in array */
138 LPFORMATETC pFmt; /* array of EnumFORMATETC's */
141 * Reference count of this object
143 LONG ref;
146 * IUnknown implementation of the parent data object.
148 IUnknown* pUnkDataObj;
150 } IEnumFORMATETCImpl;
152 typedef struct PresentationDataHeader
154 BYTE unknown1[28];
155 DWORD dwObjectExtentX;
156 DWORD dwObjectExtentY;
157 DWORD dwSize;
158 } PresentationDataHeader;
161 * The one and only OLEClipbrd object which is created by OLEClipbrd_Initialize()
163 static HGLOBAL hTheOleClipboard = 0;
164 static OLEClipbrd* theOleClipboard = NULL;
168 * Prototypes for the methods of the OLEClipboard class.
170 void OLEClipbrd_Initialize(void);
171 void OLEClipbrd_UnInitialize(void);
172 static OLEClipbrd* OLEClipbrd_Construct(void);
173 static void OLEClipbrd_Destroy(OLEClipbrd* ptrToDestroy);
174 static HWND OLEClipbrd_CreateWindow(void);
175 static void OLEClipbrd_DestroyWindow(HWND hwnd);
176 static LRESULT CALLBACK OLEClipbrd_WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
177 static HRESULT OLEClipbrd_RenderFormat( IDataObject *pIDataObject, LPFORMATETC pFormatetc );
178 static HGLOBAL OLEClipbrd_GlobalDupMem( HGLOBAL hGlobalSrc );
181 * Prototypes for the methods of the OLEClipboard class
182 * that implement IDataObject methods.
184 static HRESULT WINAPI OLEClipbrd_IDataObject_QueryInterface(
185 IDataObject* iface,
186 REFIID riid,
187 void** ppvObject);
188 static ULONG WINAPI OLEClipbrd_IDataObject_AddRef(
189 IDataObject* iface);
190 static ULONG WINAPI OLEClipbrd_IDataObject_Release(
191 IDataObject* iface);
192 static HRESULT WINAPI OLEClipbrd_IDataObject_GetData(
193 IDataObject* iface,
194 LPFORMATETC pformatetcIn,
195 STGMEDIUM* pmedium);
196 static HRESULT WINAPI OLEClipbrd_IDataObject_GetDataHere(
197 IDataObject* iface,
198 LPFORMATETC pformatetc,
199 STGMEDIUM* pmedium);
200 static HRESULT WINAPI OLEClipbrd_IDataObject_QueryGetData(
201 IDataObject* iface,
202 LPFORMATETC pformatetc);
203 static HRESULT WINAPI OLEClipbrd_IDataObject_GetCanonicalFormatEtc(
204 IDataObject* iface,
205 LPFORMATETC pformatectIn,
206 LPFORMATETC pformatetcOut);
207 static HRESULT WINAPI OLEClipbrd_IDataObject_SetData(
208 IDataObject* iface,
209 LPFORMATETC pformatetc,
210 STGMEDIUM* pmedium,
211 BOOL fRelease);
212 static HRESULT WINAPI OLEClipbrd_IDataObject_EnumFormatEtc(
213 IDataObject* iface,
214 DWORD dwDirection,
215 IEnumFORMATETC** ppenumFormatEtc);
216 static HRESULT WINAPI OLEClipbrd_IDataObject_DAdvise(
217 IDataObject* iface,
218 FORMATETC* pformatetc,
219 DWORD advf,
220 IAdviseSink* pAdvSink,
221 DWORD* pdwConnection);
222 static HRESULT WINAPI OLEClipbrd_IDataObject_DUnadvise(
223 IDataObject* iface,
224 DWORD dwConnection);
225 static HRESULT WINAPI OLEClipbrd_IDataObject_EnumDAdvise(
226 IDataObject* iface,
227 IEnumSTATDATA** ppenumAdvise);
230 * Prototypes for the IEnumFORMATETC methods.
232 static LPENUMFORMATETC OLEClipbrd_IEnumFORMATETC_Construct(UINT cfmt, const FORMATETC afmt[],
233 LPUNKNOWN pUnkDataObj);
234 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_QueryInterface(LPENUMFORMATETC iface, REFIID riid,
235 LPVOID* ppvObj);
236 static ULONG WINAPI OLEClipbrd_IEnumFORMATETC_AddRef(LPENUMFORMATETC iface);
237 static ULONG WINAPI OLEClipbrd_IEnumFORMATETC_Release(LPENUMFORMATETC iface);
238 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Next(LPENUMFORMATETC iface, ULONG celt,
239 FORMATETC* rgelt, ULONG* pceltFethed);
240 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Skip(LPENUMFORMATETC iface, ULONG celt);
241 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Reset(LPENUMFORMATETC iface);
242 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Clone(LPENUMFORMATETC iface, LPENUMFORMATETC* ppenum);
246 * Virtual function table for the OLEClipbrd's exposed IDataObject interface
248 static const IDataObjectVtbl OLEClipbrd_IDataObject_VTable =
250 OLEClipbrd_IDataObject_QueryInterface,
251 OLEClipbrd_IDataObject_AddRef,
252 OLEClipbrd_IDataObject_Release,
253 OLEClipbrd_IDataObject_GetData,
254 OLEClipbrd_IDataObject_GetDataHere,
255 OLEClipbrd_IDataObject_QueryGetData,
256 OLEClipbrd_IDataObject_GetCanonicalFormatEtc,
257 OLEClipbrd_IDataObject_SetData,
258 OLEClipbrd_IDataObject_EnumFormatEtc,
259 OLEClipbrd_IDataObject_DAdvise,
260 OLEClipbrd_IDataObject_DUnadvise,
261 OLEClipbrd_IDataObject_EnumDAdvise
265 * Virtual function table for IEnumFORMATETC interface
267 static const IEnumFORMATETCVtbl efvt =
269 OLEClipbrd_IEnumFORMATETC_QueryInterface,
270 OLEClipbrd_IEnumFORMATETC_AddRef,
271 OLEClipbrd_IEnumFORMATETC_Release,
272 OLEClipbrd_IEnumFORMATETC_Next,
273 OLEClipbrd_IEnumFORMATETC_Skip,
274 OLEClipbrd_IEnumFORMATETC_Reset,
275 OLEClipbrd_IEnumFORMATETC_Clone
279 * Name of our registered OLE clipboard window class
281 static const CHAR OLEClipbrd_WNDCLASS[] = "CLIPBRDWNDCLASS";
284 * If we need to store state info we can store it here.
285 * For now we don't need this functionality.
287 typedef struct tagClipboardWindowInfo
289 } ClipboardWindowInfo;
292 /*---------------------------------------------------------------------*
293 * Win32 OLE clipboard API
294 *---------------------------------------------------------------------*/
296 /***********************************************************************
297 * OleSetClipboard [OLE32.@]
298 * Places a pointer to the specified data object onto the clipboard,
299 * making the data object accessible to the OleGetClipboard function.
301 * RETURNS
303 * S_OK IDataObject pointer placed on the clipboard
304 * CLIPBRD_E_CANT_OPEN OpenClipboard failed
305 * CLIPBRD_E_CANT_EMPTY EmptyClipboard failed
306 * CLIPBRD_E_CANT_CLOSE CloseClipboard failed
307 * CLIPBRD_E_CANT_SET SetClipboard failed
310 HRESULT WINAPI OleSetClipboard(IDataObject* pDataObj)
312 HRESULT hr = S_OK;
313 IEnumFORMATETC* penumFormatetc = NULL;
314 FORMATETC rgelt;
315 BOOL bClipboardOpen = FALSE;
317 HGLOBAL hDataObject = 0;
318 OLEClipbrd **ppDataObject;
321 TRACE("(%p)\n", pDataObj);
324 * Make sure we have a clipboard object
326 OLEClipbrd_Initialize();
329 * If the Ole clipboard window hasn't been created yet, create it now.
331 if ( !theOleClipboard->hWndClipboard )
332 theOleClipboard->hWndClipboard = OLEClipbrd_CreateWindow();
334 if ( !theOleClipboard->hWndClipboard ) /* sanity check */
335 HANDLE_ERROR( E_FAIL );
338 * Open the Windows clipboard, associating it with our hidden window
340 if ( !(bClipboardOpen = OpenClipboard(theOleClipboard->hWndClipboard)) )
341 HANDLE_ERROR( CLIPBRD_E_CANT_OPEN );
344 * Empty the current clipboard and make our window the clipboard owner
345 * NOTE: This will trigger a WM_DESTROYCLIPBOARD message
347 if ( !EmptyClipboard() )
348 HANDLE_ERROR( CLIPBRD_E_CANT_EMPTY );
351 * If we are already holding on to an IDataObject first release that.
353 if ( theOleClipboard->pIDataObjectSrc )
355 IDataObject_Release(theOleClipboard->pIDataObjectSrc);
356 theOleClipboard->pIDataObjectSrc = NULL;
360 * AddRef the data object passed in and save its pointer.
361 * A NULL value indicates that the clipboard should be emptied.
363 theOleClipboard->pIDataObjectSrc = pDataObj;
364 if ( pDataObj )
366 IDataObject_AddRef(theOleClipboard->pIDataObjectSrc);
370 * Enumerate all HGLOBAL formats supported by the source and make
371 * those formats available using delayed rendering using SetClipboardData.
372 * Only global memory based data items may be made available to non-OLE
373 * applications via the standard Windows clipboard API. Data based on other
374 * mediums(non TYMED_HGLOBAL) can only be accessed via the Ole Clipboard API.
376 * TODO: Do we need to additionally handle TYMED_IStorage media by copying
377 * the storage into global memory?
379 if ( pDataObj )
381 if ( FAILED(hr = IDataObject_EnumFormatEtc( pDataObj,
382 DATADIR_GET,
383 &penumFormatetc )))
385 HANDLE_ERROR( hr );
388 while ( S_OK == IEnumFORMATETC_Next(penumFormatetc, 1, &rgelt, NULL) )
390 if ( rgelt.tymed == TYMED_HGLOBAL )
392 CHAR szFmtName[80];
393 TRACE("(cfFormat=%d:%s)\n", rgelt.cfFormat,
394 GetClipboardFormatNameA(rgelt.cfFormat, szFmtName, sizeof(szFmtName)-1)
395 ? szFmtName : "");
397 SetClipboardData( rgelt.cfFormat, NULL);
400 IEnumFORMATETC_Release(penumFormatetc);
404 * Windows additionally creates a new "DataObject" clipboard format
405 * and stores in on the clipboard. We could possibly store a pointer
406 * to our internal IDataObject interface on the clipboard. I'm not
407 * sure what the use of this is though.
408 * Enable the code below for this functionality.
411 theOleClipboard->cfDataObj = RegisterClipboardFormatA("DataObject");
412 hDataObject = GlobalAlloc( GMEM_DDESHARE|GMEM_MOVEABLE|GMEM_ZEROINIT,
413 sizeof(OLEClipbrd *));
414 if (hDataObject==0)
415 HANDLE_ERROR( E_OUTOFMEMORY );
417 ppDataObject = (OLEClipbrd**)GlobalLock(hDataObject);
418 *ppDataObject = theOleClipboard;
419 GlobalUnlock(hDataObject);
421 if ( !SetClipboardData( theOleClipboard->cfDataObj, hDataObject ) )
422 HANDLE_ERROR( CLIPBRD_E_CANT_SET );
425 hr = S_OK;
427 CLEANUP:
430 * Close Windows clipboard (It remains associated with our window)
432 if ( bClipboardOpen && !CloseClipboard() )
433 hr = CLIPBRD_E_CANT_CLOSE;
436 * Release the source IDataObject if something failed
438 if ( FAILED(hr) )
440 if (theOleClipboard->pIDataObjectSrc)
442 IDataObject_Release(theOleClipboard->pIDataObjectSrc);
443 theOleClipboard->pIDataObjectSrc = NULL;
447 return hr;
451 /***********************************************************************
452 * OleGetClipboard [OLE32.@]
453 * Returns a pointer to our internal IDataObject which represents the conceptual
454 * state of the Windows clipboard. If the current clipboard already contains
455 * an IDataObject, our internal IDataObject will delegate to this object.
457 HRESULT WINAPI OleGetClipboard(IDataObject** ppDataObj)
459 HRESULT hr = S_OK;
460 TRACE("()\n");
463 * Make sure we have a clipboard object
465 OLEClipbrd_Initialize();
467 if (!theOleClipboard)
468 return E_OUTOFMEMORY;
470 /* Return a reference counted IDataObject */
471 hr = IDataObject_QueryInterface( (IDataObject*)&(theOleClipboard->lpvtbl1),
472 &IID_IDataObject, (void**)ppDataObj);
473 return hr;
476 /******************************************************************************
477 * OleFlushClipboard [OLE32.@]
478 * Renders the data from the source IDataObject into the windows clipboard
480 * TODO: OleFlushClipboard needs to additionally handle TYMED_IStorage media
481 * by copying the storage into global memory. Subsequently the default
482 * data object exposed through OleGetClipboard must convert this TYMED_HGLOBAL
483 * back to TYMED_IStorage.
485 HRESULT WINAPI OleFlushClipboard(void)
487 IEnumFORMATETC* penumFormatetc = NULL;
488 FORMATETC rgelt;
489 HRESULT hr = S_OK;
490 BOOL bClipboardOpen = FALSE;
491 IDataObject* pIDataObjectSrc = NULL;
493 TRACE("()\n");
496 * Make sure we have a clipboard object
498 OLEClipbrd_Initialize();
501 * Already flushed or no source DataObject? Nothing to do.
503 if (!theOleClipboard->pIDataObjectSrc)
504 return S_OK;
507 * Addref and save the source data object we are holding on to temporarily,
508 * since it will be released when we empty the clipboard.
510 pIDataObjectSrc = theOleClipboard->pIDataObjectSrc;
511 IDataObject_AddRef(pIDataObjectSrc);
514 * Open the Windows clipboard
516 if ( !(bClipboardOpen = OpenClipboard(theOleClipboard->hWndClipboard)) )
517 HANDLE_ERROR( CLIPBRD_E_CANT_OPEN );
520 * Empty the current clipboard
522 if ( !EmptyClipboard() )
523 HANDLE_ERROR( CLIPBRD_E_CANT_EMPTY );
526 * Render all HGLOBAL formats supported by the source into
527 * the windows clipboard.
529 if ( FAILED( hr = IDataObject_EnumFormatEtc( pIDataObjectSrc,
530 DATADIR_GET,
531 &penumFormatetc) ))
533 HANDLE_ERROR( hr );
536 while ( S_OK == IEnumFORMATETC_Next(penumFormatetc, 1, &rgelt, NULL) )
538 if ( rgelt.tymed == TYMED_HGLOBAL )
540 CHAR szFmtName[80];
541 TRACE("(cfFormat=%d:%s)\n", rgelt.cfFormat,
542 GetClipboardFormatNameA(rgelt.cfFormat, szFmtName, sizeof(szFmtName)-1)
543 ? szFmtName : "");
546 * Render the clipboard data
548 if ( FAILED(OLEClipbrd_RenderFormat( pIDataObjectSrc, &rgelt )) )
549 continue;
553 IEnumFORMATETC_Release(penumFormatetc);
556 * Release the source data object we are holding on to
558 IDataObject_Release(pIDataObjectSrc);
560 CLEANUP:
563 * Close Windows clipboard (It remains associated with our window)
565 if ( bClipboardOpen && !CloseClipboard() )
566 hr = CLIPBRD_E_CANT_CLOSE;
568 return hr;
572 /***********************************************************************
573 * OleIsCurrentClipboard [OLE32.@]
575 HRESULT WINAPI OleIsCurrentClipboard(IDataObject *pDataObject)
577 TRACE("()\n");
579 * Make sure we have a clipboard object
581 OLEClipbrd_Initialize();
583 if (!theOleClipboard)
584 return E_OUTOFMEMORY;
586 if (pDataObject == NULL)
587 return S_FALSE;
589 return (pDataObject == theOleClipboard->pIDataObjectSrc) ? S_OK : S_FALSE;
593 /*---------------------------------------------------------------------*
594 * Internal implementation methods for the OLE clipboard
595 *---------------------------------------------------------------------*/
597 /***********************************************************************
598 * OLEClipbrd_Initialize()
599 * Initializes the OLE clipboard.
601 void OLEClipbrd_Initialize(void)
604 * Create the clipboard if necessary
606 if ( !theOleClipboard )
608 TRACE("()\n");
609 theOleClipboard = OLEClipbrd_Construct();
614 /***********************************************************************
615 * OLEClipbrd_UnInitialize()
616 * Un-Initializes the OLE clipboard
618 void OLEClipbrd_UnInitialize(void)
620 TRACE("()\n");
622 * Destroy the clipboard if no one holds a reference to us.
623 * Note that the clipboard was created with a reference count of 1.
625 if ( theOleClipboard && (theOleClipboard->ref <= 1) )
627 OLEClipbrd_Destroy( theOleClipboard );
629 else
631 WARN( "() : OLEClipbrd_UnInitialize called while client holds an IDataObject reference!\n");
636 /*********************************************************
637 * Construct the OLEClipbrd class.
639 static OLEClipbrd* OLEClipbrd_Construct(void)
641 OLEClipbrd* newObject = NULL;
642 HGLOBAL hNewObject = 0;
645 * Allocate space for the object. We use GlobalAlloc since we need
646 * an HGLOBAL to expose our DataObject as a registered clipboard type.
648 hNewObject = GlobalAlloc( GMEM_DDESHARE|GMEM_MOVEABLE|GMEM_ZEROINIT,
649 sizeof(OLEClipbrd));
650 if (hNewObject==0)
651 return NULL;
654 * Lock the handle for the entire lifetime of the clipboard.
656 newObject = GlobalLock(hNewObject);
659 * Initialize the virtual function table.
661 newObject->lpvtbl1 = &OLEClipbrd_IDataObject_VTable;
664 * Start with one reference count. The caller of this function
665 * must release the interface pointer when it is done.
667 newObject->ref = 1;
669 newObject->hSelf = hNewObject;
672 * The Ole clipboard is a singleton - save the global handle and pointer
674 theOleClipboard = newObject;
675 hTheOleClipboard = hNewObject;
677 return theOleClipboard;
680 static void OLEClipbrd_Destroy(OLEClipbrd* ptrToDestroy)
682 TRACE("()\n");
684 if ( !ptrToDestroy )
685 return;
688 * Destroy the Ole clipboard window
690 if ( ptrToDestroy->hWndClipboard )
691 OLEClipbrd_DestroyWindow(ptrToDestroy->hWndClipboard);
694 * Free the actual OLE Clipboard structure.
696 TRACE("() - Destroying clipboard data object.\n");
697 GlobalUnlock(ptrToDestroy->hSelf);
698 GlobalFree(ptrToDestroy->hSelf);
701 * The Ole clipboard is a singleton (ptrToDestroy == theOleClipboard)
703 theOleClipboard = NULL;
704 hTheOleClipboard = 0;
708 /***********************************************************************
709 * OLEClipbrd_CreateWindow()
710 * Create the clipboard window
712 static HWND OLEClipbrd_CreateWindow(void)
714 HWND hwnd = 0;
715 WNDCLASSEXA wcex;
718 * Register the clipboard window class if necessary
720 ZeroMemory( &wcex, sizeof(WNDCLASSEXA));
722 wcex.cbSize = sizeof(WNDCLASSEXA);
723 /* Windows creates this class with a style mask of 0
724 * We don't bother doing this since the FindClassByAtom code
725 * would have to be changed to deal with this idiosyncrasy. */
726 wcex.style = CS_GLOBALCLASS;
727 wcex.lpfnWndProc = OLEClipbrd_WndProc;
728 wcex.hInstance = 0;
729 wcex.lpszClassName = OLEClipbrd_WNDCLASS;
731 RegisterClassExA(&wcex);
734 * Create a hidden window to receive OLE clipboard messages
738 * If we need to store state info we can store it here.
739 * For now we don't need this functionality.
740 * ClipboardWindowInfo clipboardInfo;
741 * ZeroMemory( &trackerInfo, sizeof(ClipboardWindowInfo));
744 hwnd = CreateWindowA(OLEClipbrd_WNDCLASS,
745 "ClipboardWindow",
746 WS_POPUP | WS_CLIPSIBLINGS | WS_OVERLAPPED,
747 CW_USEDEFAULT, CW_USEDEFAULT,
748 CW_USEDEFAULT, CW_USEDEFAULT,
752 0 /*(LPVOID)&clipboardInfo */);
754 return hwnd;
757 /***********************************************************************
758 * OLEClipbrd_DestroyWindow(HWND)
759 * Destroy the clipboard window and unregister its class
761 static void OLEClipbrd_DestroyWindow(HWND hwnd)
764 * Destroy clipboard window and unregister its WNDCLASS
766 DestroyWindow(hwnd);
767 UnregisterClassA( OLEClipbrd_WNDCLASS, 0 );
770 /***********************************************************************
771 * OLEClipbrd_WndProc(HWND, unsigned, WORD, LONG)
772 * Processes messages sent to the OLE clipboard window.
773 * Note that we will intercept messages in our WndProc only when data
774 * has been placed in the clipboard via OleSetClipboard().
775 * i.e. Only when OLE owns the windows clipboard.
777 static LRESULT CALLBACK OLEClipbrd_WndProc
778 (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
780 switch (message)
783 * WM_RENDERFORMAT
784 * We receive this message to allow us to handle delayed rendering of
785 * a specific clipboard format when an application requests data in
786 * that format by calling GetClipboardData.
787 * (Recall that in OleSetClipboard, we used SetClipboardData to
788 * make all HGLOBAL formats supported by the source IDataObject
789 * available using delayed rendering)
790 * On receiving this message we must actually render the data in the
791 * specified format and place it on the clipboard by calling the
792 * SetClipboardData function.
794 case WM_RENDERFORMAT:
796 FORMATETC rgelt;
798 ZeroMemory( &rgelt, sizeof(FORMATETC));
801 * Initialize FORMATETC to a Windows clipboard friendly format
803 rgelt.cfFormat = (UINT) wParam;
804 rgelt.dwAspect = DVASPECT_CONTENT;
805 rgelt.lindex = -1;
806 rgelt.tymed = TYMED_HGLOBAL;
808 TRACE("(): WM_RENDERFORMAT(cfFormat=%d)\n", rgelt.cfFormat);
811 * Render the clipboard data.
812 * (We must have a source data object or we wouldn't be in this WndProc)
814 OLEClipbrd_RenderFormat( (IDataObject*)&(theOleClipboard->lpvtbl1), &rgelt );
816 break;
820 * WM_RENDERALLFORMATS
821 * Sent before the clipboard owner window is destroyed.
822 * We should receive this message only when OleUninitialize is called
823 * while we have an IDataObject in the clipboard.
824 * For the content of the clipboard to remain available to other
825 * applications, we must render data in all the formats the source IDataObject
826 * is capable of generating, and place the data on the clipboard by calling
827 * SetClipboardData.
829 case WM_RENDERALLFORMATS:
831 IEnumFORMATETC* penumFormatetc = NULL;
832 FORMATETC rgelt;
834 TRACE("(): WM_RENDERALLFORMATS\n");
837 * Render all HGLOBAL formats supported by the source into
838 * the windows clipboard.
840 if ( FAILED( IDataObject_EnumFormatEtc( (IDataObject*)&(theOleClipboard->lpvtbl1),
841 DATADIR_GET, &penumFormatetc) ) )
843 WARN("(): WM_RENDERALLFORMATS failed to retrieve EnumFormatEtc!\n");
844 return 0;
847 while ( S_OK == IEnumFORMATETC_Next(penumFormatetc, 1, &rgelt, NULL) )
849 if ( rgelt.tymed == TYMED_HGLOBAL )
852 * Render the clipboard data.
854 if ( FAILED(OLEClipbrd_RenderFormat( (IDataObject*)&(theOleClipboard->lpvtbl1), &rgelt )) )
855 continue;
857 TRACE("(): WM_RENDERALLFORMATS(cfFormat=%d)\n", rgelt.cfFormat);
861 IEnumFORMATETC_Release(penumFormatetc);
863 break;
867 * WM_DESTROYCLIPBOARD
868 * This is sent by EmptyClipboard before the clipboard is emptied.
869 * We should release any IDataObject we are holding onto when we receive
870 * this message, since it indicates that the OLE clipboard should be empty
871 * from this point on.
873 case WM_DESTROYCLIPBOARD:
875 TRACE("(): WM_DESTROYCLIPBOARD\n");
877 * Release the data object we are holding on to
879 if ( theOleClipboard->pIDataObjectSrc )
881 IDataObject_Release(theOleClipboard->pIDataObjectSrc);
882 theOleClipboard->pIDataObjectSrc = NULL;
884 break;
888 case WM_ASKCBFORMATNAME:
889 case WM_CHANGECBCHAIN:
890 case WM_DRAWCLIPBOARD:
891 case WM_SIZECLIPBOARD:
892 case WM_HSCROLLCLIPBOARD:
893 case WM_VSCROLLCLIPBOARD:
894 case WM_PAINTCLIPBOARD:
896 default:
897 return DefWindowProcA(hWnd, message, wParam, lParam);
900 return 0;
903 #define MAX_CLIPFORMAT_NAME 80
905 /***********************************************************************
906 * OLEClipbrd_RenderFormat(LPFORMATETC)
907 * Render the clipboard data. Note that this call will delegate to the
908 * source data object.
909 * Note: This function assumes it is passed an HGLOBAL format to render.
911 static HRESULT OLEClipbrd_RenderFormat(IDataObject *pIDataObject, LPFORMATETC pFormatetc)
913 STGMEDIUM std;
914 HGLOBAL hDup;
915 HRESULT hr = S_OK;
916 char szFmtName[MAX_CLIPFORMAT_NAME];
917 ILockBytes *ptrILockBytes = 0;
918 HGLOBAL hStorage = 0;
920 if (!GetClipboardFormatNameA(pFormatetc->cfFormat, szFmtName, MAX_CLIPFORMAT_NAME))
921 szFmtName[0] = '\0';
923 /* If embed source */
924 if (!strcmp(szFmtName, CF_EMBEDSOURCE))
926 memset(&std, 0, sizeof(STGMEDIUM));
927 std.tymed = pFormatetc->tymed = TYMED_ISTORAGE;
929 hStorage = GlobalAlloc(GMEM_SHARE|GMEM_MOVEABLE, 0);
930 if (hStorage == NULL)
931 HANDLE_ERROR( E_OUTOFMEMORY );
932 hr = CreateILockBytesOnHGlobal(hStorage, FALSE, &ptrILockBytes);
933 hr = StgCreateDocfileOnILockBytes(ptrILockBytes, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &std.u.pstg);
935 if (FAILED(hr = IDataObject_GetDataHere(theOleClipboard->pIDataObjectSrc, pFormatetc, &std)))
937 WARN("() : IDataObject_GetDataHere failed to render clipboard data! (%x)\n", hr);
938 GlobalFree(hStorage);
939 return hr;
942 if (1) /* check whether the presentation data is already -not- present */
944 FORMATETC fmt2;
945 STGMEDIUM std2;
946 METAFILEPICT *mfp = 0;
948 fmt2.cfFormat = CF_METAFILEPICT;
949 fmt2.ptd = 0;
950 fmt2.dwAspect = DVASPECT_CONTENT;
951 fmt2.lindex = -1;
952 fmt2.tymed = TYMED_MFPICT;
954 memset(&std2, 0, sizeof(STGMEDIUM));
955 std2.tymed = TYMED_MFPICT;
957 /* Get the metafile picture out of it */
959 if (!FAILED(hr = IDataObject_GetData(theOleClipboard->pIDataObjectSrc, &fmt2, &std2)))
961 mfp = (METAFILEPICT *)GlobalLock(std2.u.hGlobal);
964 if (mfp)
966 OLECHAR name[]={ 2, 'O', 'l', 'e', 'P', 'r', 'e', 's', '0', '0', '0', 0};
967 IStream *pStream = 0;
968 void *mfBits;
969 PresentationDataHeader pdh;
970 INT nSize;
971 CLSID clsID;
972 LPOLESTR strProgID;
973 CHAR strOleTypeName[51];
974 BYTE OlePresStreamHeader [] =
976 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00,
977 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
978 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
979 0x00, 0x00, 0x00, 0x00
982 nSize = GetMetaFileBitsEx(mfp->hMF, 0, NULL);
984 memset(&pdh, 0, sizeof(PresentationDataHeader));
985 memcpy(&pdh, OlePresStreamHeader, sizeof(OlePresStreamHeader));
987 pdh.dwObjectExtentX = mfp->xExt;
988 pdh.dwObjectExtentY = mfp->yExt;
989 pdh.dwSize = nSize;
991 hr = IStorage_CreateStream(std.u.pstg, name, STGM_CREATE|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, 0, &pStream);
993 hr = IStream_Write(pStream, &pdh, sizeof(PresentationDataHeader), NULL);
995 mfBits = HeapAlloc(GetProcessHeap(), 0, nSize);
996 nSize = GetMetaFileBitsEx(mfp->hMF, nSize, mfBits);
998 hr = IStream_Write(pStream, mfBits, nSize, NULL);
1000 IStream_Release(pStream);
1002 HeapFree(GetProcessHeap(), 0, mfBits);
1004 GlobalUnlock(std2.u.hGlobal);
1006 ReadClassStg(std.u.pstg, &clsID);
1007 ProgIDFromCLSID(&clsID, &strProgID);
1009 WideCharToMultiByte( CP_ACP, 0, strProgID, -1, strOleTypeName, sizeof(strOleTypeName), NULL, NULL );
1010 OLECONVERT_CreateOleStream(std.u.pstg);
1011 OLECONVERT_CreateCompObjStream(std.u.pstg, strOleTypeName);
1015 else
1017 if (FAILED(hr = IDataObject_GetData(pIDataObject, pFormatetc, &std)))
1019 WARN("() : IDataObject_GetData failed to render clipboard data! (%x)\n", hr);
1020 GlobalFree(hStorage);
1021 return hr;
1024 /* To put a copy back on the clipboard */
1026 hStorage = std.u.hGlobal;
1030 * Put a copy of the rendered data back on the clipboard
1033 if ( !(hDup = OLEClipbrd_GlobalDupMem(hStorage)) )
1034 HANDLE_ERROR( E_OUTOFMEMORY );
1036 if ( !SetClipboardData( pFormatetc->cfFormat, hDup ) )
1038 GlobalFree(hDup);
1039 WARN("() : Failed to set rendered clipboard data into clipboard!\n");
1042 CLEANUP:
1044 ReleaseStgMedium(&std);
1046 return hr;
1050 /***********************************************************************
1051 * OLEClipbrd_GlobalDupMem( HGLOBAL )
1052 * Helper method to duplicate an HGLOBAL chunk of memory
1054 static HGLOBAL OLEClipbrd_GlobalDupMem( HGLOBAL hGlobalSrc )
1056 HGLOBAL hGlobalDest;
1057 PVOID pGlobalSrc, pGlobalDest;
1058 DWORD cBytes;
1060 if ( !hGlobalSrc )
1061 return 0;
1063 cBytes = GlobalSize(hGlobalSrc);
1064 if ( 0 == cBytes )
1065 return 0;
1067 hGlobalDest = GlobalAlloc( GMEM_DDESHARE|GMEM_MOVEABLE,
1068 cBytes );
1069 if ( !hGlobalDest )
1070 return 0;
1072 pGlobalSrc = GlobalLock(hGlobalSrc);
1073 pGlobalDest = GlobalLock(hGlobalDest);
1074 if ( !pGlobalSrc || !pGlobalDest )
1076 GlobalFree(hGlobalDest);
1077 return 0;
1080 memcpy(pGlobalDest, pGlobalSrc, cBytes);
1082 GlobalUnlock(hGlobalSrc);
1083 GlobalUnlock(hGlobalDest);
1085 return hGlobalDest;
1089 /*---------------------------------------------------------------------*
1090 * Implementation of the internal IDataObject interface exposed by
1091 * the OLE clipboard.
1092 *---------------------------------------------------------------------*/
1095 /************************************************************************
1096 * OLEClipbrd_IDataObject_QueryInterface (IUnknown)
1098 * See Windows documentation for more details on IUnknown methods.
1100 static HRESULT WINAPI OLEClipbrd_IDataObject_QueryInterface(
1101 IDataObject* iface,
1102 REFIID riid,
1103 void** ppvObject)
1106 * Declare "This" pointer
1108 OLEClipbrd *This = (OLEClipbrd *)iface;
1109 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObject);
1112 * Perform a sanity check on the parameters.
1114 if ( (This==0) || (ppvObject==0) )
1115 return E_INVALIDARG;
1118 * Initialize the return parameter.
1120 *ppvObject = 0;
1123 * Compare the riid with the interface IDs implemented by this object.
1125 if (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0)
1127 *ppvObject = iface;
1129 else if (memcmp(&IID_IDataObject, riid, sizeof(IID_IDataObject)) == 0)
1131 *ppvObject = (IDataObject*)&(This->lpvtbl1);
1133 else /* We only support IUnknown and IDataObject */
1135 WARN( "() : asking for unsupported interface %s\n", debugstr_guid(riid));
1136 return E_NOINTERFACE;
1140 * Query Interface always increases the reference count by one when it is
1141 * successful.
1143 IUnknown_AddRef((IUnknown*)*ppvObject);
1145 return S_OK;
1148 /************************************************************************
1149 * OLEClipbrd_IDataObject_AddRef (IUnknown)
1151 * See Windows documentation for more details on IUnknown methods.
1153 static ULONG WINAPI OLEClipbrd_IDataObject_AddRef(
1154 IDataObject* iface)
1157 * Declare "This" pointer
1159 OLEClipbrd *This = (OLEClipbrd *)iface;
1161 TRACE("(%p)->(count=%u)\n",This, This->ref);
1163 return InterlockedIncrement(&This->ref);
1167 /************************************************************************
1168 * OLEClipbrd_IDataObject_Release (IUnknown)
1170 * See Windows documentation for more details on IUnknown methods.
1172 static ULONG WINAPI OLEClipbrd_IDataObject_Release(
1173 IDataObject* iface)
1176 * Declare "This" pointer
1178 OLEClipbrd *This = (OLEClipbrd *)iface;
1179 ULONG ref;
1181 TRACE("(%p)->(count=%u)\n",This, This->ref);
1184 * Decrease the reference count on this object.
1186 ref = InterlockedDecrement(&This->ref);
1189 * If the reference count goes down to 0, perform suicide.
1191 if (ref == 0)
1193 OLEClipbrd_Destroy(This);
1196 return ref;
1200 /************************************************************************
1201 * OLEClipbrd_IDataObject_GetData (IDataObject)
1203 * The OLE Clipboard's implementation of this method delegates to
1204 * a data source if there is one or wraps around the windows clipboard
1206 * See Windows documentation for more details on IDataObject methods.
1208 static HRESULT WINAPI OLEClipbrd_IDataObject_GetData(
1209 IDataObject* iface,
1210 LPFORMATETC pformatetcIn,
1211 STGMEDIUM* pmedium)
1213 HANDLE hData = 0;
1214 BOOL bClipboardOpen = FALSE;
1215 HRESULT hr = S_OK;
1216 LPVOID src;
1219 * Declare "This" pointer
1221 OLEClipbrd *This = (OLEClipbrd *)iface;
1223 TRACE("(%p,%p,%p)\n", iface, pformatetcIn, pmedium);
1225 if ( !pformatetcIn || !pmedium )
1226 return E_INVALIDARG;
1229 * If we have a data source placed on the clipboard (via OleSetClipboard)
1230 * simply delegate to the source object's QueryGetData
1231 * NOTE: This code assumes that the IDataObject is in the same address space!
1232 * We will need to add marshalling support when Wine handles multiple processes.
1234 if ( This->pIDataObjectSrc )
1236 return IDataObject_GetData(This->pIDataObjectSrc, pformatetcIn, pmedium);
1239 if ( pformatetcIn->lindex != -1 )
1240 return DV_E_LINDEX;
1241 if ( (pformatetcIn->tymed & TYMED_HGLOBAL) != TYMED_HGLOBAL )
1242 return DV_E_TYMED;
1244 if ( pformatetcIn->dwAspect != DVASPECT_CONTENT )
1245 return DV_E_DVASPECT;
1249 * Otherwise, get the data from the windows clipboard using GetClipboardData
1251 if ( !(bClipboardOpen = OpenClipboard(theOleClipboard->hWndClipboard)) )
1252 HANDLE_ERROR( CLIPBRD_E_CANT_OPEN );
1254 hData = GetClipboardData(pformatetcIn->cfFormat);
1256 /* Must make a copy of global handle returned by GetClipboardData; it
1257 * is not valid after we call CloseClipboard
1258 * Application is responsible for freeing the memory (Forte Agent does this)
1260 src = GlobalLock(hData);
1261 if(src) {
1262 LPVOID dest;
1263 ULONG size;
1264 HANDLE hDest;
1266 size = GlobalSize(hData);
1267 hDest = GlobalAlloc(GHND, size);
1268 dest = GlobalLock(hDest);
1269 memcpy(dest, src, size);
1270 GlobalUnlock(hDest);
1271 GlobalUnlock(hData);
1272 hData = hDest;
1276 * Return the clipboard data in the storage medium structure
1278 pmedium->tymed = (hData == 0) ? TYMED_NULL : TYMED_HGLOBAL;
1279 pmedium->u.hGlobal = hData;
1280 pmedium->pUnkForRelease = NULL;
1282 hr = S_OK;
1284 CLEANUP:
1286 * Close Windows clipboard
1288 if ( bClipboardOpen && !CloseClipboard() )
1289 hr = CLIPBRD_E_CANT_CLOSE;
1291 if ( FAILED(hr) )
1292 return hr;
1293 return (hData == 0) ? DV_E_FORMATETC : S_OK;
1296 static HRESULT WINAPI OLEClipbrd_IDataObject_GetDataHere(
1297 IDataObject* iface,
1298 LPFORMATETC pformatetc,
1299 STGMEDIUM* pmedium)
1301 FIXME(": Stub\n");
1302 return E_NOTIMPL;
1305 /************************************************************************
1306 * OLEClipbrd_IDataObject_QueryGetData (IDataObject)
1308 * The OLE Clipboard's implementation of this method delegates to
1309 * a data source if there is one or wraps around the windows clipboard
1310 * function IsClipboardFormatAvailable() otherwise.
1312 * See Windows documentation for more details on IDataObject methods.
1314 static HRESULT WINAPI OLEClipbrd_IDataObject_QueryGetData(
1315 IDataObject* iface,
1316 LPFORMATETC pformatetc)
1318 TRACE("(%p, %p)\n", iface, pformatetc);
1320 if (!pformatetc)
1321 return E_INVALIDARG;
1323 if ( pformatetc->dwAspect != DVASPECT_CONTENT )
1324 return DV_E_FORMATETC;
1326 if ( pformatetc->lindex != -1 )
1327 return DV_E_FORMATETC;
1330 * Delegate to the Windows clipboard function IsClipboardFormatAvailable
1332 return (IsClipboardFormatAvailable(pformatetc->cfFormat)) ? S_OK : DV_E_CLIPFORMAT;
1335 /************************************************************************
1336 * OLEClipbrd_IDataObject_GetCanonicalFormatEtc (IDataObject)
1338 * See Windows documentation for more details on IDataObject methods.
1340 static HRESULT WINAPI OLEClipbrd_IDataObject_GetCanonicalFormatEtc(
1341 IDataObject* iface,
1342 LPFORMATETC pformatectIn,
1343 LPFORMATETC pformatetcOut)
1345 TRACE("(%p, %p, %p)\n", iface, pformatectIn, pformatetcOut);
1347 if ( !pformatectIn || !pformatetcOut )
1348 return E_INVALIDARG;
1350 *pformatetcOut = *pformatectIn;
1351 return DATA_S_SAMEFORMATETC;
1354 /************************************************************************
1355 * OLEClipbrd_IDataObject_SetData (IDataObject)
1357 * The OLE Clipboard's does not implement this method
1359 * See Windows documentation for more details on IDataObject methods.
1361 static HRESULT WINAPI OLEClipbrd_IDataObject_SetData(
1362 IDataObject* iface,
1363 LPFORMATETC pformatetc,
1364 STGMEDIUM* pmedium,
1365 BOOL fRelease)
1367 TRACE("\n");
1368 return E_NOTIMPL;
1371 /************************************************************************
1372 * OLEClipbrd_IDataObject_EnumFormatEtc (IDataObject)
1374 * See Windows documentation for more details on IDataObject methods.
1376 static HRESULT WINAPI OLEClipbrd_IDataObject_EnumFormatEtc(
1377 IDataObject* iface,
1378 DWORD dwDirection,
1379 IEnumFORMATETC** ppenumFormatEtc)
1381 HRESULT hr = S_OK;
1382 FORMATETC *afmt = NULL;
1383 int cfmt, i;
1384 UINT format;
1385 BOOL bClipboardOpen;
1388 * Declare "This" pointer
1390 OLEClipbrd *This = (OLEClipbrd *)iface;
1392 TRACE("(%p, %x, %p)\n", iface, dwDirection, ppenumFormatEtc);
1395 * If we have a data source placed on the clipboard (via OleSetClipboard)
1396 * simply delegate to the source object's EnumFormatEtc
1398 if ( This->pIDataObjectSrc )
1400 return IDataObject_EnumFormatEtc(This->pIDataObjectSrc,
1401 dwDirection, ppenumFormatEtc);
1405 * Otherwise we must provide our own enumerator which wraps around the
1406 * Windows clipboard function EnumClipboardFormats
1408 if ( !ppenumFormatEtc )
1409 return E_INVALIDARG;
1411 if ( dwDirection != DATADIR_GET ) /* IDataObject_SetData not implemented */
1412 return E_NOTIMPL;
1415 * Store all current clipboard formats in an array of FORMATETC's,
1416 * and create an IEnumFORMATETC enumerator from this list.
1418 cfmt = CountClipboardFormats();
1419 afmt = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1420 sizeof(FORMATETC) * cfmt);
1422 * Open the Windows clipboard, associating it with our hidden window
1424 if ( !(bClipboardOpen = OpenClipboard(This->hWndClipboard)) )
1425 HANDLE_ERROR( CLIPBRD_E_CANT_OPEN );
1428 * Store all current clipboard formats in an array of FORMATETC's
1429 * TODO: Handle TYMED_IStorage media which were put on the clipboard
1430 * by copying the storage into global memory. We must convert this
1431 * TYMED_HGLOBAL back to TYMED_IStorage.
1433 for (i = 0, format = 0; i < cfmt; i++)
1435 format = EnumClipboardFormats(format);
1436 if (!format) /* Failed! */
1438 ERR("EnumClipboardFormats failed to return format!\n");
1439 HANDLE_ERROR( E_FAIL );
1442 /* Init the FORMATETC struct */
1443 afmt[i].cfFormat = format;
1444 afmt[i].ptd = NULL;
1445 afmt[i].dwAspect = DVASPECT_CONTENT;
1446 afmt[i].lindex = -1;
1447 afmt[i].tymed = TYMED_HGLOBAL;
1451 * Create an EnumFORMATETC enumerator and return an
1452 * EnumFORMATETC after bumping up its ref count
1454 *ppenumFormatEtc = OLEClipbrd_IEnumFORMATETC_Construct( cfmt, afmt, (LPUNKNOWN)iface);
1455 if (!(*ppenumFormatEtc))
1456 HANDLE_ERROR( E_OUTOFMEMORY );
1458 if (FAILED( hr = IEnumFORMATETC_AddRef(*ppenumFormatEtc)))
1459 HANDLE_ERROR( hr );
1461 hr = S_OK;
1463 CLEANUP:
1465 * Free the array of FORMATETC's
1467 HeapFree(GetProcessHeap(), 0, afmt);
1470 * Close Windows clipboard
1472 if ( bClipboardOpen && !CloseClipboard() )
1473 hr = CLIPBRD_E_CANT_CLOSE;
1475 return hr;
1478 /************************************************************************
1479 * OLEClipbrd_IDataObject_DAdvise (IDataObject)
1481 * The OLE Clipboard's does not implement this method
1483 * See Windows documentation for more details on IDataObject methods.
1485 static HRESULT WINAPI OLEClipbrd_IDataObject_DAdvise(
1486 IDataObject* iface,
1487 FORMATETC* pformatetc,
1488 DWORD advf,
1489 IAdviseSink* pAdvSink,
1490 DWORD* pdwConnection)
1492 TRACE("\n");
1493 return E_NOTIMPL;
1496 /************************************************************************
1497 * OLEClipbrd_IDataObject_DUnadvise (IDataObject)
1499 * The OLE Clipboard's does not implement this method
1501 * See Windows documentation for more details on IDataObject methods.
1503 static HRESULT WINAPI OLEClipbrd_IDataObject_DUnadvise(
1504 IDataObject* iface,
1505 DWORD dwConnection)
1507 TRACE("\n");
1508 return E_NOTIMPL;
1511 /************************************************************************
1512 * OLEClipbrd_IDataObject_EnumDAdvise (IDataObject)
1514 * The OLE Clipboard does not implement this method
1516 * See Windows documentation for more details on IDataObject methods.
1518 static HRESULT WINAPI OLEClipbrd_IDataObject_EnumDAdvise(
1519 IDataObject* iface,
1520 IEnumSTATDATA** ppenumAdvise)
1522 TRACE("\n");
1523 return E_NOTIMPL;
1527 /*---------------------------------------------------------------------*
1528 * Implementation of the internal IEnumFORMATETC interface returned by
1529 * the OLE clipboard's IDataObject.
1530 *---------------------------------------------------------------------*/
1532 /************************************************************************
1533 * OLEClipbrd_IEnumFORMATETC_Construct (UINT, const FORMATETC, LPUNKNOWN)
1535 * Creates an IEnumFORMATETC enumerator from an array of FORMATETC
1536 * Structures. pUnkOuter is the outer unknown for reference counting only.
1537 * NOTE: this does not AddRef the interface.
1540 static LPENUMFORMATETC OLEClipbrd_IEnumFORMATETC_Construct(UINT cfmt, const FORMATETC afmt[],
1541 LPUNKNOWN pUnkDataObj)
1543 IEnumFORMATETCImpl* ef;
1544 DWORD size=cfmt * sizeof(FORMATETC);
1545 LPMALLOC pIMalloc;
1547 ef = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IEnumFORMATETCImpl));
1548 if (!ef)
1549 return NULL;
1551 ef->ref = 0;
1552 ef->lpVtbl = &efvt;
1553 ef->pUnkDataObj = pUnkDataObj;
1555 ef->posFmt = 0;
1556 ef->countFmt = cfmt;
1557 if (FAILED(CoGetMalloc(MEMCTX_TASK, &pIMalloc))) {
1558 HeapFree(GetProcessHeap(), 0, ef);
1559 return NULL;
1561 ef->pFmt = (LPFORMATETC)IMalloc_Alloc(pIMalloc, size);
1562 IMalloc_Release(pIMalloc);
1564 if (ef->pFmt)
1565 memcpy(ef->pFmt, afmt, size);
1567 TRACE("(%p)->()\n",ef);
1568 return (LPENUMFORMATETC)ef;
1572 /************************************************************************
1573 * OLEClipbrd_IEnumFORMATETC_QueryInterface (IUnknown)
1575 * See Windows documentation for more details on IUnknown methods.
1577 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_QueryInterface
1578 (LPENUMFORMATETC iface, REFIID riid, LPVOID* ppvObj)
1580 IEnumFORMATETCImpl *This = (IEnumFORMATETCImpl *)iface;
1582 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
1585 * Since enumerators are separate objects from the parent data object
1586 * we only need to support the IUnknown and IEnumFORMATETC interfaces
1589 *ppvObj = NULL;
1591 if(IsEqualIID(riid, &IID_IUnknown))
1593 *ppvObj = This;
1595 else if(IsEqualIID(riid, &IID_IEnumFORMATETC))
1597 *ppvObj = (IDataObject*)This;
1600 if(*ppvObj)
1602 IEnumFORMATETC_AddRef((IEnumFORMATETC*)*ppvObj);
1603 TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
1604 return S_OK;
1607 TRACE("-- Interface: E_NOINTERFACE\n");
1608 return E_NOINTERFACE;
1611 /************************************************************************
1612 * OLEClipbrd_IEnumFORMATETC_AddRef (IUnknown)
1614 * Since enumerating formats only makes sense when our data object is around,
1615 * we insure that it stays as long as we stay by calling our parents IUnknown
1616 * for AddRef and Release. But since we are not controlled by the lifetime of
1617 * the outer object, we still keep our own reference count in order to
1618 * free ourselves.
1620 static ULONG WINAPI OLEClipbrd_IEnumFORMATETC_AddRef(LPENUMFORMATETC iface)
1622 IEnumFORMATETCImpl *This = (IEnumFORMATETCImpl *)iface;
1623 TRACE("(%p)->(count=%u)\n",This, This->ref);
1625 if (This->pUnkDataObj)
1626 IUnknown_AddRef(This->pUnkDataObj);
1628 return InterlockedIncrement(&This->ref);
1631 /************************************************************************
1632 * OLEClipbrd_IEnumFORMATETC_Release (IUnknown)
1634 * See Windows documentation for more details on IUnknown methods.
1636 static ULONG WINAPI OLEClipbrd_IEnumFORMATETC_Release(LPENUMFORMATETC iface)
1638 IEnumFORMATETCImpl *This = (IEnumFORMATETCImpl *)iface;
1639 LPMALLOC pIMalloc;
1640 ULONG ref;
1642 TRACE("(%p)->(count=%u)\n",This, This->ref);
1644 if (This->pUnkDataObj)
1645 IUnknown_Release(This->pUnkDataObj); /* Release parent data object */
1647 ref = InterlockedDecrement(&This->ref);
1648 if (!ref)
1650 TRACE("() - destroying IEnumFORMATETC(%p)\n",This);
1651 if (SUCCEEDED(CoGetMalloc(MEMCTX_TASK, &pIMalloc)))
1653 IMalloc_Free(pIMalloc, This->pFmt);
1654 IMalloc_Release(pIMalloc);
1657 HeapFree(GetProcessHeap(),0,This);
1659 return ref;
1662 /************************************************************************
1663 * OLEClipbrd_IEnumFORMATETC_Next (IEnumFORMATETC)
1665 * Standard enumerator members for IEnumFORMATETC
1667 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Next
1668 (LPENUMFORMATETC iface, ULONG celt, FORMATETC *rgelt, ULONG *pceltFethed)
1670 IEnumFORMATETCImpl *This = (IEnumFORMATETCImpl *)iface;
1671 UINT cfetch;
1672 HRESULT hres = S_FALSE;
1674 TRACE("(%p)->(pos=%u)\n", This, This->posFmt);
1676 if (This->posFmt < This->countFmt)
1678 cfetch = This->countFmt - This->posFmt;
1679 if (cfetch >= celt)
1681 cfetch = celt;
1682 hres = S_OK;
1685 memcpy(rgelt, &This->pFmt[This->posFmt], cfetch * sizeof(FORMATETC));
1686 This->posFmt += cfetch;
1688 else
1690 cfetch = 0;
1693 if (pceltFethed)
1695 *pceltFethed = cfetch;
1698 return hres;
1701 /************************************************************************
1702 * OLEClipbrd_IEnumFORMATETC_Skip (IEnumFORMATETC)
1704 * Standard enumerator members for IEnumFORMATETC
1706 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Skip(LPENUMFORMATETC iface, ULONG celt)
1708 IEnumFORMATETCImpl *This = (IEnumFORMATETCImpl *)iface;
1709 TRACE("(%p)->(num=%u)\n", This, celt);
1711 This->posFmt += celt;
1712 if (This->posFmt > This->countFmt)
1714 This->posFmt = This->countFmt;
1715 return S_FALSE;
1717 return S_OK;
1720 /************************************************************************
1721 * OLEClipbrd_IEnumFORMATETC_Reset (IEnumFORMATETC)
1723 * Standard enumerator members for IEnumFORMATETC
1725 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Reset(LPENUMFORMATETC iface)
1727 IEnumFORMATETCImpl *This = (IEnumFORMATETCImpl *)iface;
1728 TRACE("(%p)->()\n", This);
1730 This->posFmt = 0;
1731 return S_OK;
1734 /************************************************************************
1735 * OLEClipbrd_IEnumFORMATETC_Clone (IEnumFORMATETC)
1737 * Standard enumerator members for IEnumFORMATETC
1739 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Clone
1740 (LPENUMFORMATETC iface, LPENUMFORMATETC* ppenum)
1742 IEnumFORMATETCImpl *This = (IEnumFORMATETCImpl *)iface;
1743 HRESULT hr = S_OK;
1745 TRACE("(%p)->(ppenum=%p)\n", This, ppenum);
1747 if ( !ppenum )
1748 return E_INVALIDARG;
1750 *ppenum = OLEClipbrd_IEnumFORMATETC_Construct(This->countFmt,
1751 This->pFmt,
1752 This->pUnkDataObj);
1754 if (FAILED( hr = IEnumFORMATETC_AddRef(*ppenum)))
1755 return ( hr );
1757 return (*ppenum) ? S_OK : E_OUTOFMEMORY;