Added/fixed some documentation reported by winapi_check.
[wine/multimedia.git] / dlls / ole32 / clipboard.c
blobef433027dabfcfd3db3829f2f02943ac529e9e26
1 /*
2 * OLE 2 clipboard support
4 * Copyright 1999 Noel Borthwick <noel@macadamian.com>
5 * Copyright 2000 Abey George <abey@macadamian.com>
7 * NOTES:
8 * This file contains the implementation for the OLE Clipboard and its
9 * internal interfaces. The OLE clipboard interacts with an IDataObject
10 * interface via the OleSetClipboard, OleGetClipboard and
11 * OleIsCurrentClipboard API's. An internal IDataObject delegates
12 * to a client supplied IDataObject or the WIN32 clipboard API depending
13 * on whether OleSetClipboard has been invoked.
14 * Here are some operating scenarios:
16 * 1. OleSetClipboard called: In this case the internal IDataObject
17 * delegates to the client supplied IDataObject. Additionally OLE takes
18 * ownership of the Windows clipboard and any HGLOCBAL IDataObject
19 * items are placed on the Windows clipboard. This allows non OLE aware
20 * applications to access these. A local WinProc fields WM_RENDERFORMAT
21 * and WM_RENDERALLFORMATS messages in this case.
23 * 2. OleGetClipboard called without previous OleSetClipboard. Here the internal
24 * IDataObject functionality wraps around the WIN32 clipboard API.
26 * 3. OleGetClipboard called after previous OleSetClipboard. Here the internal
27 * IDataObject delegates to the source IDataObjects functionality directly,
28 * thereby bypassing the Windows clipboard.
30 * Implementation references : Inside OLE 2'nd edition by Kraig Brockschmidt
32 * TODO:
33 * - Support for pasting between different processes. OLE clipboard support
34 * currently works only for in process copy and paste. Since we internally
35 * store a pointer to the source's IDataObject and delegate to that, this
36 * will fail if the IDataObject client belongs to a different process.
37 * - IDataObject::GetDataHere is not implemented
38 * - OleFlushClipboard needs to additionally handle TYMED_IStorage media
39 * by copying the storage into global memory. Subsequently the default
40 * data object exposed through OleGetClipboard must convert this TYMED_HGLOBAL
41 * back to TYMED_IStorage.
42 * - OLE1 compatibility formats to be synthesized from OLE2 formats and put on
43 * clipboard in OleSetClipboard.
47 #include <assert.h>
49 #include "windef.h"
50 #include "wingdi.h"
51 #include "winuser.h"
52 #include "winbase.h"
53 #include "winerror.h"
54 #include "ole2.h"
55 #include "debugtools.h"
56 #include "olestd.h"
58 #include "storage32.h"
60 #define HANDLE_ERROR(err) { hr = err; TRACE("(HRESULT=%lx)\n", (HRESULT)err); goto CLEANUP; }
62 /* For CoGetMalloc (MEMCTX_TASK is currently ignored) */
63 #ifndef MEMCTX_TASK
64 #define MEMCTX_TASK -1
65 #endif
67 DEFAULT_DEBUG_CHANNEL(ole)
69 /****************************************************************************
70 * OLEClipbrd
71 * DO NOT add any members before the VTables declaration!
73 struct OLEClipbrd
76 * List all interface VTables here
78 ICOM_VTABLE(IDataObject)* lpvtbl1; /* IDataObject VTable */
81 * The hidden OLE clipboard window. This window is used as the bridge between the
82 * the OLE and windows clipboard API. (Windows creates one such window per process)
84 HWND hWndClipboard;
87 * Pointer to the source data object (via OleSetClipboard)
89 IDataObject* pIDataObjectSrc;
92 * The registered DataObject clipboard format
94 UINT cfDataObj;
97 * The handle to our ourself
99 UINT hSelf;
102 * Reference count of this object
104 ULONG ref;
107 typedef struct OLEClipbrd OLEClipbrd;
110 /****************************************************************************
111 * IEnumFORMATETC implementation
112 * DO NOT add any members before the VTables declaration!
114 typedef struct
116 /* IEnumFORMATETC VTable */
117 ICOM_VFIELD(IEnumFORMATETC);
119 /* IEnumFORMATETC fields */
120 UINT posFmt; /* current enumerator position */
121 UINT countFmt; /* number of EnumFORMATETC's in array */
122 LPFORMATETC pFmt; /* array of EnumFORMATETC's */
125 * Reference count of this object
127 DWORD ref;
130 * IUnknown implementation of the parent data object.
132 IUnknown* pUnkDataObj;
134 } IEnumFORMATETCImpl;
136 typedef struct PresentationDataHeader
138 BYTE unknown1[28];
139 DWORD dwObjectExtentX;
140 DWORD dwObjectExtentY;
141 DWORD dwSize;
142 } PresentationDataHeader;
145 * The one and only OLEClipbrd object which is created by OLEClipbrd_Initialize()
147 static HGLOBAL hTheOleClipboard = 0;
148 static OLEClipbrd* theOleClipboard = NULL;
152 * Prototypes for the methods of the OLEClipboard class.
154 extern void OLEClipbrd_Initialize();
155 extern void OLEClipbrd_UnInitialize();
156 static OLEClipbrd* OLEClipbrd_Construct();
157 static void OLEClipbrd_Destroy(OLEClipbrd* ptrToDestroy);
158 static HWND OLEClipbrd_CreateWindow();
159 static void OLEClipbrd_DestroyWindow(HWND hwnd);
160 LRESULT CALLBACK OLEClipbrd_WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
161 static HRESULT OLEClipbrd_RenderFormat( IDataObject *pIDataObject, LPFORMATETC pFormatetc );
162 static HGLOBAL OLEClipbrd_GlobalDupMem( HGLOBAL hGlobalSrc );
165 * Prototypes for the methods of the OLEClipboard class
166 * that implement IDataObject methods.
168 static HRESULT WINAPI OLEClipbrd_IDataObject_QueryInterface(
169 IDataObject* iface,
170 REFIID riid,
171 void** ppvObject);
172 static ULONG WINAPI OLEClipbrd_IDataObject_AddRef(
173 IDataObject* iface);
174 static ULONG WINAPI OLEClipbrd_IDataObject_Release(
175 IDataObject* iface);
176 static HRESULT WINAPI OLEClipbrd_IDataObject_GetData(
177 IDataObject* iface,
178 LPFORMATETC pformatetcIn,
179 STGMEDIUM* pmedium);
180 static HRESULT WINAPI OLEClipbrd_IDataObject_GetDataHere(
181 IDataObject* iface,
182 LPFORMATETC pformatetc,
183 STGMEDIUM* pmedium);
184 static HRESULT WINAPI OLEClipbrd_IDataObject_QueryGetData(
185 IDataObject* iface,
186 LPFORMATETC pformatetc);
187 static HRESULT WINAPI OLEClipbrd_IDataObject_GetCanonicalFormatEtc(
188 IDataObject* iface,
189 LPFORMATETC pformatectIn,
190 LPFORMATETC pformatetcOut);
191 static HRESULT WINAPI OLEClipbrd_IDataObject_SetData(
192 IDataObject* iface,
193 LPFORMATETC pformatetc,
194 STGMEDIUM* pmedium,
195 BOOL fRelease);
196 static HRESULT WINAPI OLEClipbrd_IDataObject_EnumFormatEtc(
197 IDataObject* iface,
198 DWORD dwDirection,
199 IEnumFORMATETC** ppenumFormatEtc);
200 static HRESULT WINAPI OLEClipbrd_IDataObject_DAdvise(
201 IDataObject* iface,
202 FORMATETC* pformatetc,
203 DWORD advf,
204 IAdviseSink* pAdvSink,
205 DWORD* pdwConnection);
206 static HRESULT WINAPI OLEClipbrd_IDataObject_DUnadvise(
207 IDataObject* iface,
208 DWORD dwConnection);
209 static HRESULT WINAPI OLEClipbrd_IDataObject_EnumDAdvise(
210 IDataObject* iface,
211 IEnumSTATDATA** ppenumAdvise);
214 * Prototypes for the IEnumFORMATETC methods.
216 static LPENUMFORMATETC OLEClipbrd_IEnumFORMATETC_Construct(UINT cfmt, const FORMATETC afmt[],
217 LPUNKNOWN pUnkDataObj);
218 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_QueryInterface(LPENUMFORMATETC iface, REFIID riid,
219 LPVOID* ppvObj);
220 static ULONG WINAPI OLEClipbrd_IEnumFORMATETC_AddRef(LPENUMFORMATETC iface);
221 static ULONG WINAPI OLEClipbrd_IEnumFORMATETC_Release(LPENUMFORMATETC iface);
222 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Next(LPENUMFORMATETC iface, ULONG celt,
223 FORMATETC* rgelt, ULONG* pceltFethed);
224 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Skip(LPENUMFORMATETC iface, ULONG celt);
225 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Reset(LPENUMFORMATETC iface);
226 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Clone(LPENUMFORMATETC iface, LPENUMFORMATETC* ppenum);
230 * Virtual function table for the OLEClipbrd's exposed IDataObject interface
232 static ICOM_VTABLE(IDataObject) OLEClipbrd_IDataObject_VTable =
234 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
235 OLEClipbrd_IDataObject_QueryInterface,
236 OLEClipbrd_IDataObject_AddRef,
237 OLEClipbrd_IDataObject_Release,
238 OLEClipbrd_IDataObject_GetData,
239 OLEClipbrd_IDataObject_GetDataHere,
240 OLEClipbrd_IDataObject_QueryGetData,
241 OLEClipbrd_IDataObject_GetCanonicalFormatEtc,
242 OLEClipbrd_IDataObject_SetData,
243 OLEClipbrd_IDataObject_EnumFormatEtc,
244 OLEClipbrd_IDataObject_DAdvise,
245 OLEClipbrd_IDataObject_DUnadvise,
246 OLEClipbrd_IDataObject_EnumDAdvise
250 * Virtual function table for IEnumFORMATETC interface
252 static struct ICOM_VTABLE(IEnumFORMATETC) efvt =
254 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
255 OLEClipbrd_IEnumFORMATETC_QueryInterface,
256 OLEClipbrd_IEnumFORMATETC_AddRef,
257 OLEClipbrd_IEnumFORMATETC_Release,
258 OLEClipbrd_IEnumFORMATETC_Next,
259 OLEClipbrd_IEnumFORMATETC_Skip,
260 OLEClipbrd_IEnumFORMATETC_Reset,
261 OLEClipbrd_IEnumFORMATETC_Clone
265 * Name of our registered OLE clipboard window class
267 CHAR OLEClipbrd_WNDCLASS[] = "CLIPBRDWNDCLASS";
270 * If we need to store state info we can store it here.
271 * For now we dont need this functionality.
273 typedef struct tagClipboardWindowInfo
275 } ClipboardWindowInfo;
278 /*---------------------------------------------------------------------*
279 * Win32 OLE clipboard API
280 *---------------------------------------------------------------------*/
282 /***********************************************************************
283 * OleSetClipboard [OLE32.127]
284 * Places a pointer to the specified data object onto the clipboard,
285 * making the data object accessible to the OleGetClipboard function.
287 * RETURNS:
289 * S_OK IDataObject pointer placed on the clipboard
290 * CLIPBRD_E_CANT_OPEN OpenClipboard failed
291 * CLIPBRD_E_CANT_EMPTY EmptyClipboard failed
292 * CLIPBRD_E_CANT_CLOSE CloseClipboard failed
293 * CLIPBRD_E_CANT_SET SetClipboard failed
296 HRESULT WINAPI OleSetClipboard(IDataObject* pDataObj)
298 HRESULT hr = S_OK;
299 IEnumFORMATETC* penumFormatetc = NULL;
300 FORMATETC rgelt;
301 BOOL bClipboardOpen = FALSE;
303 HGLOBAL hDataObject = 0;
304 OLEClipbrd **ppDataObject;
307 TRACE("(%p)\n", pDataObj);
310 * Make sure we have a clipboard object
312 OLEClipbrd_Initialize();
315 * If the Ole clipboard window hasn't been created yet, create it now.
317 if ( !theOleClipboard->hWndClipboard )
318 theOleClipboard->hWndClipboard = OLEClipbrd_CreateWindow();
320 if ( !theOleClipboard->hWndClipboard ) /* sanity check */
321 HANDLE_ERROR( E_FAIL );
324 * Open the Windows clipboard, associating it with our hidden window
326 if ( !(bClipboardOpen = OpenClipboard(theOleClipboard->hWndClipboard)) )
327 HANDLE_ERROR( CLIPBRD_E_CANT_OPEN );
330 * Empty the current clipboard and make our window the clipboard owner
331 * NOTE: This will trigger a WM_DESTROYCLIPBOARD message
333 if ( !EmptyClipboard() )
334 HANDLE_ERROR( CLIPBRD_E_CANT_EMPTY );
337 * If we are already holding on to an IDataObject first release that.
339 if ( theOleClipboard->pIDataObjectSrc )
341 IDataObject_Release(theOleClipboard->pIDataObjectSrc);
342 theOleClipboard->pIDataObjectSrc = NULL;
346 * AddRef the data object passed in and save its pointer.
347 * A NULL value indicates that the clipboard should be emptied.
349 theOleClipboard->pIDataObjectSrc = pDataObj;
350 if ( pDataObj )
352 IDataObject_AddRef(theOleClipboard->pIDataObjectSrc);
356 * Enumerate all HGLOBAL formats supported by the source and make
357 * those formats available using delayed rendering using SetClipboardData.
358 * Only global memory based data items may be made available to non-OLE
359 * applications via the standard Windows clipboard API. Data based on other
360 * mediums(non TYMED_HGLOBAL) can only be accessed via the Ole Clipboard API.
362 * TODO: Do we need to additionally handle TYMED_IStorage media by copying
363 * the storage into global memory?
365 if ( pDataObj )
367 if ( FAILED(hr = IDataObject_EnumFormatEtc( pDataObj,
368 DATADIR_GET,
369 &penumFormatetc )))
371 HANDLE_ERROR( hr );
374 while ( S_OK == IEnumFORMATETC_Next(penumFormatetc, 1, &rgelt, NULL) )
376 if ( rgelt.tymed == TYMED_HGLOBAL )
378 CHAR szFmtName[80];
379 TRACE("(cfFormat=%d:%s)\n", rgelt.cfFormat,
380 GetClipboardFormatNameA(rgelt.cfFormat, szFmtName, sizeof(szFmtName)-1)
381 ? szFmtName : "");
383 SetClipboardData( rgelt.cfFormat, (HANDLE)NULL);
386 IEnumFORMATETC_Release(penumFormatetc);
390 * Windows additionally creates a new "DataObject" clipboard format
391 * and stores in on the clipboard. We could possibly store a pointer
392 * to our internal IDataObject interface on the clipboard. I'm not
393 * sure what the use of this is though.
394 * Enable the code below for this functionality.
397 theOleClipboard->cfDataObj = RegisterClipboardFormatA("DataObject");
398 hDataObject = GlobalAlloc( GMEM_DDESHARE|GMEM_MOVEABLE|GMEM_ZEROINIT,
399 sizeof(OLEClipbrd *));
400 if (hDataObject==0)
401 HANDLE_ERROR( E_OUTOFMEMORY );
403 ppDataObject = (OLEClipbrd**)GlobalLock(hDataObject);
404 *ppDataObject = theOleClipboard;
405 GlobalUnlock(hDataObject);
407 if ( !SetClipboardData( theOleClipboard->cfDataObj, hDataObject ) )
408 HANDLE_ERROR( CLIPBRD_E_CANT_SET );
411 hr = S_OK;
413 CLEANUP:
416 * Close Windows clipboard (It remains associated with our window)
418 if ( bClipboardOpen && !CloseClipboard() )
419 hr = CLIPBRD_E_CANT_CLOSE;
422 * Release the source IDataObject if something failed
424 if ( FAILED(hr) )
426 if (theOleClipboard->pIDataObjectSrc)
428 IDataObject_Release(theOleClipboard->pIDataObjectSrc);
429 theOleClipboard->pIDataObjectSrc = NULL;
433 return hr;
437 /***********************************************************************
438 * OleGetClipboard [OLE32.105]
439 * Returns a pointer to our internal IDataObject which represents the conceptual
440 * state of the Windows clipboard. If the current clipboard already contains
441 * an IDataObject, our internal IDataObject will delegate to this object.
443 HRESULT WINAPI OleGetClipboard(IDataObject** ppDataObj)
445 HRESULT hr = S_OK;
446 TRACE("()\n");
449 * Make sure we have a clipboard object
451 OLEClipbrd_Initialize();
453 if (!theOleClipboard)
454 return E_OUTOFMEMORY;
456 /* Return a reference counted IDataObject */
457 hr = IDataObject_QueryInterface( (IDataObject*)&(theOleClipboard->lpvtbl1),
458 &IID_IDataObject, (void**)ppDataObj);
459 return hr;
462 /***********************************************************************
463 * OleFlushClipboard [OLE2.76]
466 HRESULT WINAPI OleFlushClipboard16(void)
468 return OleFlushClipboard();
472 /******************************************************************************
473 * OleFlushClipboard [OLE32.103]
474 * Renders the data from the source IDataObject into the windows clipboard
476 * TODO: OleFlushClipboard needs to additionally handle TYMED_IStorage media
477 * by copying the storage into global memory. Subsequently the default
478 * data object exposed through OleGetClipboard must convert this TYMED_HGLOBAL
479 * back to TYMED_IStorage.
481 HRESULT WINAPI OleFlushClipboard()
483 IEnumFORMATETC* penumFormatetc = NULL;
484 FORMATETC rgelt;
485 HRESULT hr = S_OK;
486 BOOL bClipboardOpen = FALSE;
487 IDataObject* pIDataObjectSrc = NULL;
489 TRACE("()\n");
492 * Make sure we have a clipboard object
494 OLEClipbrd_Initialize();
497 * Already flushed or no source DataObject? Nothing to do.
499 if (!theOleClipboard->pIDataObjectSrc)
500 return S_OK;
503 * Addref and save the source data object we are holding on to temporarily,
504 * since it will be released when we empty the clipboard.
506 pIDataObjectSrc = theOleClipboard->pIDataObjectSrc;
507 IDataObject_AddRef(pIDataObjectSrc);
510 * Open the Windows clipboard
512 if ( !(bClipboardOpen = OpenClipboard(theOleClipboard->hWndClipboard)) )
513 HANDLE_ERROR( CLIPBRD_E_CANT_OPEN );
516 * Empty the current clipboard
518 if ( !EmptyClipboard() )
519 HANDLE_ERROR( CLIPBRD_E_CANT_EMPTY );
522 * Render all HGLOBAL formats supported by the source into
523 * the windows clipboard.
525 if ( FAILED( hr = IDataObject_EnumFormatEtc( pIDataObjectSrc,
526 DATADIR_GET,
527 &penumFormatetc) ))
529 HANDLE_ERROR( hr );
532 while ( S_OK == IEnumFORMATETC_Next(penumFormatetc, 1, &rgelt, NULL) )
534 if ( rgelt.tymed == TYMED_HGLOBAL )
536 CHAR szFmtName[80];
537 TRACE("(cfFormat=%d:%s)\n", rgelt.cfFormat,
538 GetClipboardFormatNameA(rgelt.cfFormat, szFmtName, sizeof(szFmtName)-1)
539 ? szFmtName : "");
542 * Render the clipboard data
544 if ( FAILED(OLEClipbrd_RenderFormat( pIDataObjectSrc, &rgelt )) )
545 continue;
549 IEnumFORMATETC_Release(penumFormatetc);
552 * Release the source data object we are holding on to
554 IDataObject_Release(pIDataObjectSrc);
556 CLEANUP:
559 * Close Windows clipboard (It remains associated with our window)
561 if ( bClipboardOpen && !CloseClipboard() )
562 hr = CLIPBRD_E_CANT_CLOSE;
564 return hr;
568 /***********************************************************************
569 * OleIsCurrentClipboard [OLE32.110]
571 HRESULT WINAPI OleIsCurrentClipboard ( IDataObject *pDataObject)
573 TRACE("()\n");
575 * Make sure we have a clipboard object
577 OLEClipbrd_Initialize();
579 if (!theOleClipboard)
580 return E_OUTOFMEMORY;
582 return (pDataObject == theOleClipboard->pIDataObjectSrc) ? S_OK : S_FALSE;
586 /*---------------------------------------------------------------------*
587 * Internal implementation methods for the OLE clipboard
588 *---------------------------------------------------------------------*/
590 /***********************************************************************
591 * OLEClipbrd_Initialize()
592 * Initializes the OLE clipboard.
594 void OLEClipbrd_Initialize()
597 * Create the clipboard if necesary
599 if ( !theOleClipboard )
601 TRACE("()\n");
602 theOleClipboard = OLEClipbrd_Construct();
607 /***********************************************************************
608 * OLEClipbrd_UnInitialize()
609 * Un-Initializes the OLE clipboard
611 void OLEClipbrd_UnInitialize()
613 TRACE("()\n");
615 * Destroy the clipboard if no one holds a reference to us.
616 * Note that the clipboard was created with a reference count of 1.
618 if ( theOleClipboard && (theOleClipboard->ref <= 1) )
620 OLEClipbrd_Destroy( theOleClipboard );
622 else
624 WARN( "() : OLEClipbrd_UnInitialize called while client holds an IDataObject reference!\n");
629 /*********************************************************
630 * Construct the OLEClipbrd class.
632 static OLEClipbrd* OLEClipbrd_Construct()
634 OLEClipbrd* newObject = NULL;
635 HGLOBAL hNewObject = 0;
638 * Allocate space for the object. We use GlobalAlloc since we need
639 * an HGLOBAL to expose our DataObject as a registered clipboard type.
641 hNewObject = GlobalAlloc( GMEM_DDESHARE|GMEM_MOVEABLE|GMEM_ZEROINIT,
642 sizeof(OLEClipbrd));
643 if (hNewObject==0)
644 return NULL;
647 * Lock the handle for the entire lifetime of the clipboard.
649 newObject = GlobalLock(hNewObject);
652 * Initialize the virtual function table.
654 newObject->lpvtbl1 = &OLEClipbrd_IDataObject_VTable;
657 * Start with one reference count. The caller of this function
658 * must release the interface pointer when it is done.
660 newObject->ref = 1;
662 newObject->hSelf = hNewObject;
665 * The Ole clipboard is a singleton - save the global handle and pointer
667 theOleClipboard = newObject;
668 hTheOleClipboard = hNewObject;
670 return theOleClipboard;
673 static void OLEClipbrd_Destroy(OLEClipbrd* ptrToDestroy)
675 TRACE("()\n");
677 if ( !ptrToDestroy )
678 return;
681 * Destroy the Ole clipboard window
683 if ( ptrToDestroy->hWndClipboard )
684 OLEClipbrd_DestroyWindow(ptrToDestroy->hWndClipboard);
687 * Free the actual OLE Clipboard structure.
689 TRACE("() - Destroying clipboard data object.\n");
690 GlobalUnlock(ptrToDestroy->hSelf);
691 GlobalFree(ptrToDestroy->hSelf);
694 * The Ole clipboard is a singleton (ptrToDestroy == theOleClipboard)
696 theOleClipboard = NULL;
697 hTheOleClipboard = 0;
701 /***********************************************************************
702 * OLEClipbrd_CreateWindow()
703 * Create the clipboard window
705 static HWND OLEClipbrd_CreateWindow()
707 HWND hwnd = 0;
708 WNDCLASSEXA wcex;
711 * Register the clipboard window class if necessary
713 ZeroMemory( &wcex, sizeof(WNDCLASSEXA));
715 wcex.cbSize = sizeof(WNDCLASSEXA);
716 /* Windows creates this class with a style mask of 0
717 * We dont bother doing this since the FindClassByAtom code
718 * would have to be changed to deal with this idiosyncracy. */
719 wcex.style = CS_GLOBALCLASS;
720 wcex.lpfnWndProc = (WNDPROC)OLEClipbrd_WndProc;
721 wcex.hInstance = 0;
722 wcex.lpszClassName = OLEClipbrd_WNDCLASS;
724 RegisterClassExA(&wcex);
727 * Create a hidden window to receive OLE clipboard messages
731 * If we need to store state info we can store it here.
732 * For now we dont need this functionality.
733 * ClipboardWindowInfo clipboardInfo;
734 * ZeroMemory( &trackerInfo, sizeof(ClipboardWindowInfo));
737 hwnd = CreateWindowA(OLEClipbrd_WNDCLASS,
738 "ClipboardWindow",
739 WS_POPUP | WS_CLIPSIBLINGS | WS_OVERLAPPED,
740 CW_USEDEFAULT, CW_USEDEFAULT,
741 CW_USEDEFAULT, CW_USEDEFAULT,
745 0 /*(LPVOID)&clipboardInfo */);
747 return hwnd;
750 /***********************************************************************
751 * OLEClipbrd_DestroyWindow(HWND)
752 * Destroy the clipboard window and unregister its class
754 static void OLEClipbrd_DestroyWindow(HWND hwnd)
757 * Destroy clipboard window and unregister its WNDCLASS
759 DestroyWindow(hwnd);
760 UnregisterClassA( OLEClipbrd_WNDCLASS, 0 );
763 /***********************************************************************
764 * OLEClipbrd_WndProc(HWND, unsigned, WORD, LONG)
765 * Processes messages sent to the OLE clipboard window.
766 * Note that we will intercept messages in our WndProc only when data
767 * has been placed in the clipboard via OleSetClipboard().
768 * i.e. Only when OLE owns the windows clipboard.
770 LRESULT CALLBACK OLEClipbrd_WndProc
771 (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
773 switch (message)
776 * WM_RENDERFORMAT
777 * We receive this message to allow us to handle delayed rendering of
778 * a specific clipboard format when an application requests data in
779 * that format by calling GetClipboardData.
780 * (Recall that in OleSetClipboard, we used SetClipboardData to
781 * make all HGLOBAL formats supported by the source IDataObject
782 * available using delayed rendering)
783 * On receiving this mesage we must actually render the data in the
784 * specified format and place it on the clipboard by calling the
785 * SetClipboardData function.
787 case WM_RENDERFORMAT:
789 FORMATETC rgelt;
791 ZeroMemory( &rgelt, sizeof(FORMATETC));
794 * Initialize FORMATETC to a Windows clipboard friendly format
796 rgelt.cfFormat = (UINT) wParam;
797 rgelt.dwAspect = DVASPECT_CONTENT;
798 rgelt.lindex = -1;
799 rgelt.tymed = TYMED_HGLOBAL;
801 TRACE("(): WM_RENDERFORMAT(cfFormat=%d)\n", rgelt.cfFormat);
804 * Render the clipboard data.
805 * (We must have a source data object or we wouldn't be in this WndProc)
807 OLEClipbrd_RenderFormat( (IDataObject*)&(theOleClipboard->lpvtbl1), &rgelt );
809 break;
813 * WM_RENDERALLFORMATS
814 * Sent before the clipboard owner window is destroyed.
815 * We should receive this message only when OleUninitialize is called
816 * while we have an IDataObject in the clipboard.
817 * For the content of the clipboard to remain available to other
818 * applications, we must render data in all the formats the source IDataObject
819 * is capable of generating, and place the data on the clipboard by calling
820 * SetClipboardData.
822 case WM_RENDERALLFORMATS:
824 IEnumFORMATETC* penumFormatetc = NULL;
825 FORMATETC rgelt;
827 TRACE("(): WM_RENDERALLFORMATS\n");
830 * Render all HGLOBAL formats supported by the source into
831 * the windows clipboard.
833 if ( FAILED( IDataObject_EnumFormatEtc( (IDataObject*)&(theOleClipboard->lpvtbl1),
834 DATADIR_GET, &penumFormatetc) ) )
836 WARN("(): WM_RENDERALLFORMATS failed to retrieve EnumFormatEtc!\n");
837 return 0;
840 while ( S_OK == IEnumFORMATETC_Next(penumFormatetc, 1, &rgelt, NULL) )
842 if ( rgelt.tymed == TYMED_HGLOBAL )
845 * Render the clipboard data.
847 if ( FAILED(OLEClipbrd_RenderFormat( (IDataObject*)&(theOleClipboard->lpvtbl1), &rgelt )) )
848 continue;
850 TRACE("(): WM_RENDERALLFORMATS(cfFormat=%d)\n", rgelt.cfFormat);
854 IEnumFORMATETC_Release(penumFormatetc);
856 break;
860 * WM_DESTROYCLIPBOARD
861 * This is sent by EmptyClipboard before the clipboard is emptied.
862 * We should release any IDataObject we are holding onto when we receive
863 * this message, since it indicates that the OLE clipboard should be empty
864 * from this point on.
866 case WM_DESTROYCLIPBOARD:
868 TRACE("(): WM_DESTROYCLIPBOARD\n");
870 * Release the data object we are holding on to
872 if ( theOleClipboard->pIDataObjectSrc )
874 IDataObject_Release(theOleClipboard->pIDataObjectSrc);
875 theOleClipboard->pIDataObjectSrc = NULL;
877 break;
881 case WM_ASKCBFORMATNAME:
882 case WM_CHANGECBCHAIN:
883 case WM_DRAWCLIPBOARD:
884 case WM_SIZECLIPBOARD:
885 case WM_HSCROLLCLIPBOARD:
886 case WM_VSCROLLCLIPBOARD:
887 case WM_PAINTCLIPBOARD:
889 default:
890 return DefWindowProcA(hWnd, message, wParam, lParam);
893 return 0;
896 #define MAX_CLIPFORMAT_NAME 80
898 /***********************************************************************
899 * OLEClipbrd_RenderFormat(LPFORMATETC)
900 * Render the clipboard data. Note that this call will delegate to the
901 * source data object.
902 * Note: This function assumes it is passed an HGLOBAL format to render.
904 static HRESULT OLEClipbrd_RenderFormat(IDataObject *pIDataObject, LPFORMATETC pFormatetc)
906 STGMEDIUM std;
907 HGLOBAL hDup;
908 HRESULT hr = S_OK;
909 char szFmtName[MAX_CLIPFORMAT_NAME];
910 ILockBytes *ptrILockBytes = 0;
911 HGLOBAL hStorage = 0;
913 GetClipboardFormatNameA(pFormatetc->cfFormat, szFmtName, MAX_CLIPFORMAT_NAME);
915 /* If embed source */
916 if (!strcmp(szFmtName, CF_EMBEDSOURCE))
918 memset(&std, 0, sizeof(STGMEDIUM));
919 std.tymed = pFormatetc->tymed = TYMED_ISTORAGE;
921 hStorage = GlobalAlloc(GMEM_SHARE|GMEM_MOVEABLE, 0);
922 hr = CreateILockBytesOnHGlobal(hStorage, FALSE, &ptrILockBytes);
923 hr = StgCreateDocfileOnILockBytes(ptrILockBytes, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &std.u.pstg);
925 if (FAILED(hr = IDataObject_GetDataHere(theOleClipboard->pIDataObjectSrc, pFormatetc, &std)))
927 WARN("() : IDataObject_GetDataHere failed to render clipboard data! (%lx)\n", hr);
928 return hr;
931 if (1) /* check whether the presentation data is already -not- present */
933 FORMATETC fmt2;
934 STGMEDIUM std2;
935 METAFILEPICT *mfp = 0;
937 fmt2.cfFormat = CF_METAFILEPICT;
938 fmt2.ptd = 0;
939 fmt2.dwAspect = DVASPECT_CONTENT;
940 fmt2.lindex = -1;
941 fmt2.tymed = TYMED_MFPICT;
943 memset(&std2, 0, sizeof(STGMEDIUM));
944 std2.tymed = TYMED_MFPICT;
946 /* Get the metafile picture out of it */
948 if (!FAILED(hr = IDataObject_GetData(theOleClipboard->pIDataObjectSrc, &fmt2, &std2)))
950 mfp = (METAFILEPICT *)GlobalLock(std2.u.hMetaFilePict);
953 if (mfp)
955 OLECHAR name[]={ 2, 'O', 'l', 'e', 'P', 'r', 'e', 's', '0', '0', '0', 0};
956 IStream *pStream = 0;
957 void *mfBits;
958 PresentationDataHeader pdh;
959 INT nSize;
960 CLSID clsID;
961 LPOLESTR strProgID;
962 CHAR strOleTypeName[51];
963 BYTE OlePresStreamHeader [] =
965 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00,
966 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
967 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
968 0x00, 0x00, 0x00, 0x00
971 nSize = GetMetaFileBitsEx(mfp->hMF, 0, NULL);
973 memset(&pdh, 0, sizeof(PresentationDataHeader));
974 memcpy(&pdh, OlePresStreamHeader, sizeof(OlePresStreamHeader));
976 pdh.dwObjectExtentX = mfp->xExt;
977 pdh.dwObjectExtentY = mfp->yExt;
978 pdh.dwSize = nSize;
980 hr = IStorage_CreateStream(std.u.pstg, name, STGM_CREATE|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, 0, &pStream);
982 hr = IStream_Write(pStream, &pdh, sizeof(PresentationDataHeader), NULL);
984 mfBits = HeapAlloc(GetProcessHeap(), 0, nSize);
985 nSize = GetMetaFileBitsEx(mfp->hMF, nSize, mfBits);
987 hr = IStream_Write(pStream, mfBits, nSize, NULL);
989 IStream_Release(pStream);
991 HeapFree(GetProcessHeap(), 0, mfBits);
993 GlobalUnlock(std2.u.hMetaFilePict);
995 ReadClassStg(std.u.pstg, &clsID);
996 ProgIDFromCLSID(&clsID, &strProgID);
998 lstrcpyWtoA(strOleTypeName, strProgID);
999 OLECONVERT_CreateOleStream(std.u.pstg);
1000 OLECONVERT_CreateCompObjStream(std.u.pstg, strOleTypeName);
1004 else
1006 if (FAILED(hr = IDataObject_GetData(pIDataObject, pFormatetc, &std)))
1008 WARN("() : IDataObject_GetData failed to render clipboard data! (%lx)\n", hr);
1009 return hr;
1012 /* To put a copy back on the clipboard */
1014 hStorage = std.u.hGlobal;
1018 * Put a copy of the rendered data back on the clipboard
1021 if ( !(hDup = OLEClipbrd_GlobalDupMem(hStorage)) )
1022 HANDLE_ERROR( E_OUTOFMEMORY );
1024 if ( !SetClipboardData( pFormatetc->cfFormat, hDup ) )
1026 GlobalFree(hDup);
1027 WARN("() : Failed to set rendered clipboard data into clipboard!\n");
1030 CLEANUP:
1032 ReleaseStgMedium(&std);
1034 return hr;
1038 /***********************************************************************
1039 * OLEClipbrd_GlobalDupMem( HGLOBAL )
1040 * Helper method to duplicate an HGLOBAL chunk of memory
1042 static HGLOBAL OLEClipbrd_GlobalDupMem( HGLOBAL hGlobalSrc )
1044 HGLOBAL hGlobalDest;
1045 PVOID pGlobalSrc, pGlobalDest;
1046 DWORD cBytes;
1048 if ( !hGlobalSrc )
1049 return 0;
1051 cBytes = GlobalSize(hGlobalSrc);
1052 if ( 0 == cBytes )
1053 return 0;
1055 hGlobalDest = GlobalAlloc( GMEM_DDESHARE|GMEM_MOVEABLE,
1056 cBytes );
1057 if ( !hGlobalDest )
1058 return 0;
1060 pGlobalSrc = GlobalLock(hGlobalSrc);
1061 pGlobalDest = GlobalLock(hGlobalDest);
1062 if ( !pGlobalSrc || !pGlobalDest )
1063 return 0;
1065 memcpy(pGlobalDest, pGlobalSrc, cBytes);
1067 GlobalUnlock(hGlobalSrc);
1068 GlobalUnlock(hGlobalDest);
1070 return hGlobalDest;
1074 /*---------------------------------------------------------------------*
1075 * Implementation of the internal IDataObject interface exposed by
1076 * the OLE clipboard.
1077 *---------------------------------------------------------------------*/
1080 /************************************************************************
1081 * OLEClipbrd_IDataObject_QueryInterface (IUnknown)
1083 * See Windows documentation for more details on IUnknown methods.
1085 static HRESULT WINAPI OLEClipbrd_IDataObject_QueryInterface(
1086 IDataObject* iface,
1087 REFIID riid,
1088 void** ppvObject)
1091 * Declare "This" pointer
1093 ICOM_THIS(OLEClipbrd, iface);
1094 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObject);
1097 * Perform a sanity check on the parameters.
1099 if ( (This==0) || (ppvObject==0) )
1100 return E_INVALIDARG;
1103 * Initialize the return parameter.
1105 *ppvObject = 0;
1108 * Compare the riid with the interface IDs implemented by this object.
1110 if (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0)
1112 *ppvObject = iface;
1114 else if (memcmp(&IID_IDataObject, riid, sizeof(IID_IDataObject)) == 0)
1116 *ppvObject = (IDataObject*)&(This->lpvtbl1);
1118 else /* We only support IUnknown and IDataObject */
1120 WARN( "() : asking for unsupported interface %s\n", debugstr_guid(riid));
1121 return E_NOINTERFACE;
1125 * Query Interface always increases the reference count by one when it is
1126 * successful.
1128 IUnknown_AddRef((IUnknown*)*ppvObject);
1130 return S_OK;
1133 /************************************************************************
1134 * OLEClipbrd_IDataObject_AddRef (IUnknown)
1136 * See Windows documentation for more details on IUnknown methods.
1138 static ULONG WINAPI OLEClipbrd_IDataObject_AddRef(
1139 IDataObject* iface)
1142 * Declare "This" pointer
1144 ICOM_THIS(OLEClipbrd, iface);
1146 TRACE("(%p)->(count=%lu)\n",This, This->ref);
1148 This->ref++;
1150 return This->ref;
1153 /************************************************************************
1154 * OLEClipbrd_IDataObject_Release (IUnknown)
1156 * See Windows documentation for more details on IUnknown methods.
1158 static ULONG WINAPI OLEClipbrd_IDataObject_Release(
1159 IDataObject* iface)
1162 * Declare "This" pointer
1164 ICOM_THIS(OLEClipbrd, iface);
1166 TRACE("(%p)->(count=%lu)\n",This, This->ref);
1169 * Decrease the reference count on this object.
1171 This->ref--;
1174 * If the reference count goes down to 0, perform suicide.
1176 if (This->ref==0)
1178 OLEClipbrd_Destroy(This);
1181 return This->ref;
1185 /************************************************************************
1186 * OLEClipbrd_IDataObject_GetData (IDataObject)
1188 * The OLE Clipboard's implementation of this method delegates to
1189 * a data source if there is one or wraps around the windows clipboard
1191 * See Windows documentation for more details on IDataObject methods.
1193 static HRESULT WINAPI OLEClipbrd_IDataObject_GetData(
1194 IDataObject* iface,
1195 LPFORMATETC pformatetcIn,
1196 STGMEDIUM* pmedium)
1198 HANDLE hData = 0;
1199 BOOL bClipboardOpen = FALSE;
1200 HRESULT hr = S_OK;
1203 * Declare "This" pointer
1205 ICOM_THIS(OLEClipbrd, iface);
1207 TRACE("(%p,%p,%p)\n", iface, pformatetcIn, pmedium);
1209 if ( !pformatetcIn || !pmedium )
1210 return E_INVALIDARG;
1213 * If we have a data source placed on the clipboard (via OleSetClipboard)
1214 * simply delegate to the source object's QueryGetData
1215 * NOTE: This code assumes that the IDataObject is in the same address space!
1216 * We will need to add marshalling support when Wine handles multiple processes.
1218 if ( This->pIDataObjectSrc )
1220 return IDataObject_GetData(This->pIDataObjectSrc, pformatetcIn, pmedium);
1223 if ( pformatetcIn->lindex != -1 )
1224 return DV_E_LINDEX;
1225 if ( (pformatetcIn->tymed & TYMED_HGLOBAL) != TYMED_HGLOBAL )
1226 return DV_E_TYMED;
1228 if ( pformatetcIn->dwAspect != DVASPECT_CONTENT )
1229 return DV_E_DVASPECT;
1233 * Otherwise, get the data from the windows clipboard using GetClipboardData
1235 if ( !(bClipboardOpen = OpenClipboard(theOleClipboard->hWndClipboard)) )
1236 HANDLE_ERROR( CLIPBRD_E_CANT_OPEN );
1238 hData = GetClipboardData(pformatetcIn->cfFormat);
1241 * Return the clipboard data in the storage medium structure
1243 pmedium->tymed = (hData == 0) ? TYMED_NULL : TYMED_HGLOBAL;
1244 pmedium->u.hGlobal = (HGLOBAL)hData;
1245 pmedium->pUnkForRelease = NULL;
1247 hr = S_OK;
1249 CLEANUP:
1251 * Close Windows clipboard
1253 if ( bClipboardOpen && !CloseClipboard() )
1254 hr = CLIPBRD_E_CANT_CLOSE;
1256 if ( FAILED(hr) )
1257 return hr;
1258 return (hData == 0) ? DV_E_FORMATETC : S_OK;
1261 static HRESULT WINAPI OLEClipbrd_IDataObject_GetDataHere(
1262 IDataObject* iface,
1263 LPFORMATETC pformatetc,
1264 STGMEDIUM* pmedium)
1266 FIXME(": Stub\n");
1267 return E_NOTIMPL;
1270 /************************************************************************
1271 * OLEClipbrd_IDataObject_QueryGetData (IDataObject)
1273 * The OLE Clipboard's implementation of this method delegates to
1274 * a data source if there is one or wraps around the windows clipboard
1275 * function IsClipboardFormatAvailable() otherwise.
1277 * See Windows documentation for more details on IDataObject methods.
1279 static HRESULT WINAPI OLEClipbrd_IDataObject_QueryGetData(
1280 IDataObject* iface,
1281 LPFORMATETC pformatetc)
1284 * Declare "This" pointer
1286 ICOM_THIS(OLEClipbrd, iface);
1288 TRACE("(%p, %p)\n", iface, pformatetc);
1291 * If we have a data source placed on the clipboard (via OleSetClipboard)
1292 * simply delegate to the source object's QueryGetData
1294 if ( This->pIDataObjectSrc )
1296 return IDataObject_QueryGetData(This->pIDataObjectSrc, pformatetc);
1299 if (!pformatetc)
1300 return E_INVALIDARG;
1302 if ( pformatetc->dwAspect != DVASPECT_CONTENT )
1303 return DV_E_DVASPECT;
1305 if ( pformatetc->lindex != -1 )
1306 return DV_E_LINDEX;
1308 /* TODO: Handle TYMED_IStorage media which were put on the clipboard
1309 * by copying the storage into global memory. We must convert this
1310 * TYMED_HGLOBAL back to TYMED_IStorage.
1312 if ( pformatetc->tymed != TYMED_HGLOBAL )
1313 return DV_E_TYMED;
1316 * Delegate to the Windows clipboard function IsClipboardFormatAvailable
1318 return (IsClipboardFormatAvailable(pformatetc->cfFormat)) ? S_OK : DV_E_FORMATETC;
1321 /************************************************************************
1322 * OLEClipbrd_IDataObject_GetCanonicalFormatEtc (IDataObject)
1324 * See Windows documentation for more details on IDataObject methods.
1326 static HRESULT WINAPI OLEClipbrd_IDataObject_GetCanonicalFormatEtc(
1327 IDataObject* iface,
1328 LPFORMATETC pformatectIn,
1329 LPFORMATETC pformatetcOut)
1331 TRACE("(%p, %p, %p)\n", iface, pformatectIn, pformatetcOut);
1333 if ( !pformatectIn || !pformatetcOut )
1334 return E_INVALIDARG;
1336 memcpy(pformatetcOut, pformatectIn, sizeof(FORMATETC));
1337 return DATA_S_SAMEFORMATETC;
1340 /************************************************************************
1341 * OLEClipbrd_IDataObject_SetData (IDataObject)
1343 * The OLE Clipboard's does not implement this method
1345 * See Windows documentation for more details on IDataObject methods.
1347 static HRESULT WINAPI OLEClipbrd_IDataObject_SetData(
1348 IDataObject* iface,
1349 LPFORMATETC pformatetc,
1350 STGMEDIUM* pmedium,
1351 BOOL fRelease)
1353 TRACE("\n");
1354 return E_NOTIMPL;
1357 /************************************************************************
1358 * OLEClipbrd_IDataObject_EnumFormatEtc (IDataObject)
1360 * See Windows documentation for more details on IDataObject methods.
1362 static HRESULT WINAPI OLEClipbrd_IDataObject_EnumFormatEtc(
1363 IDataObject* iface,
1364 DWORD dwDirection,
1365 IEnumFORMATETC** ppenumFormatEtc)
1367 HRESULT hr = S_OK;
1368 FORMATETC *afmt = NULL;
1369 int cfmt, i;
1370 UINT format;
1371 BOOL bClipboardOpen;
1374 * Declare "This" pointer
1376 ICOM_THIS(OLEClipbrd, iface);
1378 TRACE("(%p, %lx, %p)\n", iface, dwDirection, ppenumFormatEtc);
1381 * If we have a data source placed on the clipboard (via OleSetClipboard)
1382 * simply delegate to the source object's EnumFormatEtc
1384 if ( This->pIDataObjectSrc )
1386 return IDataObject_EnumFormatEtc(This->pIDataObjectSrc,
1387 dwDirection, ppenumFormatEtc);
1391 * Otherwise we must provide our own enumerator which wraps around the
1392 * Windows clipboard function EnumClipboardFormats
1394 if ( !ppenumFormatEtc )
1395 return E_INVALIDARG;
1397 if ( dwDirection != DATADIR_GET ) /* IDataObject_SetData not implemented */
1398 return E_NOTIMPL;
1401 * Store all current clipboard formats in an array of FORMATETC's,
1402 * and create an IEnumFORMATETC enumerator from this list.
1404 cfmt = CountClipboardFormats();
1405 afmt = (FORMATETC *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1406 sizeof(FORMATETC) * cfmt);
1408 * Open the Windows clipboard, associating it with our hidden window
1410 if ( !(bClipboardOpen = OpenClipboard(This->hWndClipboard)) )
1411 HANDLE_ERROR( CLIPBRD_E_CANT_OPEN );
1414 * Store all current clipboard formats in an array of FORMATETC's
1415 * TODO: Handle TYMED_IStorage media which were put on the clipboard
1416 * by copying the storage into global memory. We must convert this
1417 * TYMED_HGLOBAL back to TYMED_IStorage.
1419 for (i = 0, format = 0; i < cfmt; i++)
1421 format = EnumClipboardFormats(format);
1422 if (!format) /* Failed! */
1424 ERR("EnumClipboardFormats failed to return format!\n");
1425 HANDLE_ERROR( E_FAIL );
1428 /* Init the FORMATETC struct */
1429 afmt[i].cfFormat = format;
1430 afmt[i].ptd = NULL;
1431 afmt[i].dwAspect = DVASPECT_CONTENT;
1432 afmt[i].lindex = -1;
1433 afmt[i].tymed = TYMED_HGLOBAL;
1437 * Create an EnumFORMATETC enumerator and return an
1438 * EnumFORMATETC after bumping up its ref count
1440 *ppenumFormatEtc = OLEClipbrd_IEnumFORMATETC_Construct( cfmt, afmt, (LPUNKNOWN)iface);
1441 if (!(*ppenumFormatEtc))
1442 HANDLE_ERROR( E_OUTOFMEMORY );
1444 if (FAILED( hr = IEnumFORMATETC_AddRef(*ppenumFormatEtc)))
1445 HANDLE_ERROR( hr );
1447 hr = S_OK;
1449 CLEANUP:
1451 * Free the array of FORMATETC's
1453 if (afmt)
1454 HeapFree(GetProcessHeap(), 0, afmt);
1457 * Close Windows clipboard
1459 if ( bClipboardOpen && !CloseClipboard() )
1460 hr = CLIPBRD_E_CANT_CLOSE;
1462 return hr;
1465 /************************************************************************
1466 * OLEClipbrd_IDataObject_DAdvise (IDataObject)
1468 * The OLE Clipboard's does not implement this method
1470 * See Windows documentation for more details on IDataObject methods.
1472 static HRESULT WINAPI OLEClipbrd_IDataObject_DAdvise(
1473 IDataObject* iface,
1474 FORMATETC* pformatetc,
1475 DWORD advf,
1476 IAdviseSink* pAdvSink,
1477 DWORD* pdwConnection)
1479 TRACE("\n");
1480 return E_NOTIMPL;
1483 /************************************************************************
1484 * OLEClipbrd_IDataObject_DUnadvise (IDataObject)
1486 * The OLE Clipboard's does not implement this method
1488 * See Windows documentation for more details on IDataObject methods.
1490 static HRESULT WINAPI OLEClipbrd_IDataObject_DUnadvise(
1491 IDataObject* iface,
1492 DWORD dwConnection)
1494 TRACE("\n");
1495 return E_NOTIMPL;
1498 /************************************************************************
1499 * OLEClipbrd_IDataObject_EnumDAdvise (IDataObject)
1501 * The OLE Clipboard does not implement this method
1503 * See Windows documentation for more details on IDataObject methods.
1505 static HRESULT WINAPI OLEClipbrd_IDataObject_EnumDAdvise(
1506 IDataObject* iface,
1507 IEnumSTATDATA** ppenumAdvise)
1509 TRACE("\n");
1510 return E_NOTIMPL;
1514 /*---------------------------------------------------------------------*
1515 * Implementation of the internal IEnumFORMATETC interface returned by
1516 * the OLE clipboard's IDataObject.
1517 *---------------------------------------------------------------------*/
1519 /************************************************************************
1520 * OLEClipbrd_IEnumFORMATETC_Construct (UINT, const FORMATETC, LPUNKNOWN)
1522 * Creates an IEnumFORMATETC enumerator from an array of FORMATETC
1523 * Structures. pUnkOuter is the outer unknown for reference counting only.
1524 * NOTE: this does not AddRef the interface.
1527 LPENUMFORMATETC OLEClipbrd_IEnumFORMATETC_Construct(UINT cfmt, const FORMATETC afmt[],
1528 LPUNKNOWN pUnkDataObj)
1530 IEnumFORMATETCImpl* ef;
1531 DWORD size=cfmt * sizeof(FORMATETC);
1532 LPMALLOC pIMalloc;
1534 ef = (IEnumFORMATETCImpl*)HeapAlloc(GetProcessHeap(),
1535 HEAP_ZERO_MEMORY,
1536 sizeof(IEnumFORMATETCImpl));
1537 if (!ef)
1538 return NULL;
1540 ef->ref = 0;
1541 ICOM_VTBL(ef) = &efvt;
1542 ef->pUnkDataObj = pUnkDataObj;
1544 ef->posFmt = 0;
1545 ef->countFmt = cfmt;
1546 if (FAILED(CoGetMalloc(MEMCTX_TASK, &pIMalloc)))
1547 return NULL;
1548 ef->pFmt = (LPFORMATETC)IMalloc_Alloc(pIMalloc, size);
1549 IMalloc_Release(pIMalloc);
1551 if (ef->pFmt)
1552 memcpy(ef->pFmt, afmt, size);
1554 TRACE("(%p)->()\n",ef);
1555 return (LPENUMFORMATETC)ef;
1559 /************************************************************************
1560 * OLEClipbrd_IEnumFORMATETC_QueryInterface (IUnknown)
1562 * See Windows documentation for more details on IUnknown methods.
1564 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_QueryInterface
1565 (LPENUMFORMATETC iface, REFIID riid, LPVOID* ppvObj)
1567 ICOM_THIS(IEnumFORMATETCImpl,iface);
1569 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
1572 * Since enumerators are seperate objects from the parent data object
1573 * we only need to support the IUnknown and IEnumFORMATETC interfaces
1576 *ppvObj = NULL;
1578 if(IsEqualIID(riid, &IID_IUnknown))
1580 *ppvObj = This;
1582 else if(IsEqualIID(riid, &IID_IEnumFORMATETC))
1584 *ppvObj = (IDataObject*)This;
1587 if(*ppvObj)
1589 IEnumFORMATETC_AddRef((IEnumFORMATETC*)*ppvObj);
1590 TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
1591 return S_OK;
1594 TRACE("-- Interface: E_NOINTERFACE\n");
1595 return E_NOINTERFACE;
1598 /************************************************************************
1599 * OLEClipbrd_IEnumFORMATETC_AddRef (IUnknown)
1601 * Since enumerating formats only makes sense when our data object is around,
1602 * we insure that it stays as long as we stay by calling our parents IUnknown
1603 * for AddRef and Release. But since we are not controlled by the lifetime of
1604 * the outer object, we still keep our own reference count in order to
1605 * free ourselves.
1607 static ULONG WINAPI OLEClipbrd_IEnumFORMATETC_AddRef(LPENUMFORMATETC iface)
1609 ICOM_THIS(IEnumFORMATETCImpl,iface);
1610 TRACE("(%p)->(count=%lu)\n",This, This->ref);
1612 if (This->pUnkDataObj)
1613 IUnknown_AddRef(This->pUnkDataObj);
1615 return ++(This->ref);
1618 /************************************************************************
1619 * OLEClipbrd_IEnumFORMATETC_Release (IUnknown)
1621 * See Windows documentation for more details on IUnknown methods.
1623 static ULONG WINAPI OLEClipbrd_IEnumFORMATETC_Release(LPENUMFORMATETC iface)
1625 ICOM_THIS(IEnumFORMATETCImpl,iface);
1626 LPMALLOC pIMalloc;
1628 TRACE("(%p)->(count=%lu)\n",This, This->ref);
1630 if (This->pUnkDataObj)
1631 IUnknown_Release(This->pUnkDataObj); /* Release parent data object */
1633 if (!--(This->ref))
1635 TRACE("() - destroying IEnumFORMATETC(%p)\n",This);
1636 if (SUCCEEDED(CoGetMalloc(MEMCTX_TASK, &pIMalloc)))
1638 IMalloc_Free(pIMalloc, This->pFmt);
1639 IMalloc_Release(pIMalloc);
1642 HeapFree(GetProcessHeap(),0,This);
1643 return 0;
1646 return This->ref;
1649 /************************************************************************
1650 * OLEClipbrd_IEnumFORMATETC_Next (IEnumFORMATETC)
1652 * Standard enumerator members for IEnumFORMATETC
1654 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Next
1655 (LPENUMFORMATETC iface, ULONG celt, FORMATETC *rgelt, ULONG *pceltFethed)
1657 ICOM_THIS(IEnumFORMATETCImpl,iface);
1658 UINT cfetch;
1659 HRESULT hres = S_FALSE;
1661 TRACE("(%p)->(pos=%u)\n", This, This->posFmt);
1663 if (This->posFmt < This->countFmt)
1665 cfetch = This->countFmt - This->posFmt;
1666 if (cfetch >= celt)
1668 cfetch = celt;
1669 hres = S_OK;
1672 memcpy(rgelt, &This->pFmt[This->posFmt], cfetch * sizeof(FORMATETC));
1673 This->posFmt += cfetch;
1675 else
1677 cfetch = 0;
1680 if (pceltFethed)
1682 *pceltFethed = cfetch;
1685 return hres;
1688 /************************************************************************
1689 * OLEClipbrd_IEnumFORMATETC_Skip (IEnumFORMATETC)
1691 * Standard enumerator members for IEnumFORMATETC
1693 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Skip(LPENUMFORMATETC iface, ULONG celt)
1695 ICOM_THIS(IEnumFORMATETCImpl,iface);
1696 TRACE("(%p)->(num=%lu)\n", This, celt);
1698 This->posFmt += celt;
1699 if (This->posFmt > This->countFmt)
1701 This->posFmt = This->countFmt;
1702 return S_FALSE;
1704 return S_OK;
1707 /************************************************************************
1708 * OLEClipbrd_IEnumFORMATETC_Reset (IEnumFORMATETC)
1710 * Standard enumerator members for IEnumFORMATETC
1712 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Reset(LPENUMFORMATETC iface)
1714 ICOM_THIS(IEnumFORMATETCImpl,iface);
1715 TRACE("(%p)->()\n", This);
1717 This->posFmt = 0;
1718 return S_OK;
1721 /************************************************************************
1722 * OLEClipbrd_IEnumFORMATETC_Clone (IEnumFORMATETC)
1724 * Standard enumerator members for IEnumFORMATETC
1726 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Clone
1727 (LPENUMFORMATETC iface, LPENUMFORMATETC* ppenum)
1729 ICOM_THIS(IEnumFORMATETCImpl,iface);
1730 HRESULT hr = S_OK;
1732 TRACE("(%p)->(ppenum=%p)\n", This, ppenum);
1734 if ( !ppenum )
1735 return E_INVALIDARG;
1737 *ppenum = OLEClipbrd_IEnumFORMATETC_Construct(This->countFmt,
1738 This->pFmt,
1739 This->pUnkDataObj);
1741 if (FAILED( hr = IEnumFORMATETC_AddRef(*ppenum)))
1742 return ( hr );
1744 return (*ppenum) ? S_OK : E_OUTOFMEMORY;