1 /*
2 * OLE 2 clipboard support
3 *
4 * Copyright 1999 Noel Borthwick <noel@macadamian.com>
5 * Copyright 2000 Abey George <abey@macadamian.com>
6 *
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.
11 *
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.
16 *
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
20 *
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:
29 *
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.
36 *
37 * 2. OleGetClipboard called without previous OleSetClipboard. Here the internal
38 * IDataObject functionality wraps around the WIN32 clipboard API.
39 *
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.
43 *
44 * Implementation references : Inside OLE 2'nd edition by Kraig Brockschmidt
45 *
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.
58 *
59 */
60
61 #include <assert.h>
62 #include <stdarg.h>
63 #include <string.h>
64
65 #define COBJMACROS
66 #define NONAMELESSUNION
67 #define NONAMELESSSTRUCT
68
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"
78
79 #include "storage32.h"
80
81 #include "compobj_private.h"
82
83 #define HANDLE_ERROR(err) do { hr = err; TRACE("(HRESULT=%x)\n", (HRESULT)err); goto CLEANUP; } while (0)
84
85 WINE_DEFAULT_DEBUG_CHANNEL(ole);
86
87 /****************************************************************************
88 * OLEClipbrd
89 * DO NOT add any members before the VTables declaration!
90 */
91 struct OLEClipbrd
92 {
93 /*
94 * List all interface VTables here
95 */
96 const IDataObjectVtbl* lpvtbl1; /* IDataObject VTable */
97
98 /*
99 * The hidden OLE clipboard window. This window is used as the bridge between the
100 * the OLE and windows clipboard API. (Windows creates one such window per process)
101 */
102 HWND hWndClipboard;
103
104 /*
105 * Pointer to the source data object (via OleSetClipboard)
106 */
107 IDataObject* pIDataObjectSrc;
108
109 /*
110 * The registered DataObject clipboard format
111 */
112 UINT cfDataObj;
113
114 /*
115 * The handle to ourself
116 */
117 HGLOBAL hSelf;
118
119 /*
120 * Reference count of this object
121 */
122 LONG ref;
123 };
124
125 typedef struct OLEClipbrd OLEClipbrd;
126
127
128 /****************************************************************************
129 * IEnumFORMATETC implementation
130 * DO NOT add any members before the VTables declaration!
131 */
132 typedef struct
133 {
134 /* IEnumFORMATETC VTable */
135 const IEnumFORMATETCVtbl *lpVtbl;
136
137 /* IEnumFORMATETC fields */
138 UINT posFmt; /* current enumerator position */
139 UINT countFmt; /* number of EnumFORMATETC's in array */
140 LPFORMATETC pFmt; /* array of EnumFORMATETC's */
141
142 /*
143 * Reference count of this object
144 */
145 LONG ref;
146
147 /*
148 * IUnknown implementation of the parent data object.
149 */
150 IUnknown* pUnkDataObj;
151
152 } IEnumFORMATETCImpl;
153
154 typedef struct PresentationDataHeader
155 {
156 BYTE unknown1[28];
157 DWORD dwObjectExtentX;
158 DWORD dwObjectExtentY;
159 DWORD dwSize;
160 } PresentationDataHeader;
161
162 /*
163 * The one and only OLEClipbrd object which is created by OLEClipbrd_Initialize()
164 */
165 static HGLOBAL hTheOleClipboard = 0;
166 static OLEClipbrd* theOleClipboard = NULL;
167
168
169 /*
170 * Prototypes for the methods of the OLEClipboard class.
171 */
172 void OLEClipbrd_Initialize(void);
173 void OLEClipbrd_UnInitialize(void);
174 static OLEClipbrd* OLEClipbrd_Construct(void);
175 static void OLEClipbrd_Destroy(OLEClipbrd* ptrToDestroy);
176 static HWND OLEClipbrd_CreateWindow(void);
177 static void OLEClipbrd_DestroyWindow(HWND hwnd);
178 static LRESULT CALLBACK OLEClipbrd_WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
179 static HRESULT OLEClipbrd_RenderFormat( IDataObject *pIDataObject, LPFORMATETC pFormatetc );
180 static HGLOBAL OLEClipbrd_GlobalDupMem( HGLOBAL hGlobalSrc );
181
182 /*
183 * Prototypes for the methods of the OLEClipboard class
184 * that implement IDataObject methods.
185 */
186 static HRESULT WINAPI OLEClipbrd_IDataObject_QueryInterface(
187 IDataObject* iface,
188 REFIID riid,
189 void** ppvObject);
190 static ULONG WINAPI OLEClipbrd_IDataObject_AddRef(
191 IDataObject* iface);
192 static ULONG WINAPI OLEClipbrd_IDataObject_Release(
193 IDataObject* iface);
194 static HRESULT WINAPI OLEClipbrd_IDataObject_GetData(
195 IDataObject* iface,
196 LPFORMATETC pformatetcIn,
197 STGMEDIUM* pmedium);
198 static HRESULT WINAPI OLEClipbrd_IDataObject_GetDataHere(
199 IDataObject* iface,
200 LPFORMATETC pformatetc,
201 STGMEDIUM* pmedium);
202 static HRESULT WINAPI OLEClipbrd_IDataObject_QueryGetData(
203 IDataObject* iface,
204 LPFORMATETC pformatetc);
205 static HRESULT WINAPI OLEClipbrd_IDataObject_GetCanonicalFormatEtc(
206 IDataObject* iface,
207 LPFORMATETC pformatectIn,
208 LPFORMATETC pformatetcOut);
209 static HRESULT WINAPI OLEClipbrd_IDataObject_SetData(
210 IDataObject* iface,
211 LPFORMATETC pformatetc,
212 STGMEDIUM* pmedium,
213 BOOL fRelease);
214 static HRESULT WINAPI OLEClipbrd_IDataObject_EnumFormatEtc(
215 IDataObject* iface,
216 DWORD dwDirection,
217 IEnumFORMATETC** ppenumFormatEtc);
218 static HRESULT WINAPI OLEClipbrd_IDataObject_DAdvise(
219 IDataObject* iface,
220 FORMATETC* pformatetc,
221 DWORD advf,
222 IAdviseSink* pAdvSink,
223 DWORD* pdwConnection);
224 static HRESULT WINAPI OLEClipbrd_IDataObject_DUnadvise(
225 IDataObject* iface,
226 DWORD dwConnection);
227 static HRESULT WINAPI OLEClipbrd_IDataObject_EnumDAdvise(
228 IDataObject* iface,
229 IEnumSTATDATA** ppenumAdvise);
230
231 /*
232 * Prototypes for the IEnumFORMATETC methods.
233 */
234 static LPENUMFORMATETC OLEClipbrd_IEnumFORMATETC_Construct(UINT cfmt, const FORMATETC afmt[],
235 LPUNKNOWN pUnkDataObj);
236 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_QueryInterface(LPENUMFORMATETC iface, REFIID riid,
237 LPVOID* ppvObj);
238 static ULONG WINAPI OLEClipbrd_IEnumFORMATETC_AddRef(LPENUMFORMATETC iface);
239 static ULONG WINAPI OLEClipbrd_IEnumFORMATETC_Release(LPENUMFORMATETC iface);
240 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Next(LPENUMFORMATETC iface, ULONG celt,
241 FORMATETC* rgelt, ULONG* pceltFethed);
242 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Skip(LPENUMFORMATETC iface, ULONG celt);
243 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Reset(LPENUMFORMATETC iface);
244 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Clone(LPENUMFORMATETC iface, LPENUMFORMATETC* ppenum);
245
246
247 /*
248 * Virtual function table for the OLEClipbrd's exposed IDataObject interface
249 */
250 static const IDataObjectVtbl OLEClipbrd_IDataObject_VTable =
251 {
252 OLEClipbrd_IDataObject_QueryInterface,
253 OLEClipbrd_IDataObject_AddRef,
254 OLEClipbrd_IDataObject_Release,
255 OLEClipbrd_IDataObject_GetData,
256 OLEClipbrd_IDataObject_GetDataHere,
257 OLEClipbrd_IDataObject_QueryGetData,
258 OLEClipbrd_IDataObject_GetCanonicalFormatEtc,
259 OLEClipbrd_IDataObject_SetData,
260 OLEClipbrd_IDataObject_EnumFormatEtc,
261 OLEClipbrd_IDataObject_DAdvise,
262 OLEClipbrd_IDataObject_DUnadvise,
263 OLEClipbrd_IDataObject_EnumDAdvise
264 };
265
266 /*
267 * Virtual function table for IEnumFORMATETC interface
268 */
269 static const IEnumFORMATETCVtbl efvt =
270 {
271 OLEClipbrd_IEnumFORMATETC_QueryInterface,
272 OLEClipbrd_IEnumFORMATETC_AddRef,
273 OLEClipbrd_IEnumFORMATETC_Release,
274 OLEClipbrd_IEnumFORMATETC_Next,
275 OLEClipbrd_IEnumFORMATETC_Skip,
276 OLEClipbrd_IEnumFORMATETC_Reset,
277 OLEClipbrd_IEnumFORMATETC_Clone
278 };
279
280 /*
281 * Name of our registered OLE clipboard window class
282 */
283 static const CHAR OLEClipbrd_WNDCLASS[] = "CLIPBRDWNDCLASS";
284
285 /*
286 * If we need to store state info we can store it here.
287 * For now we don't need this functionality.
288 *
289 typedef struct tagClipboardWindowInfo
290 {
291 } ClipboardWindowInfo;
292 */
293
294 /*---------------------------------------------------------------------*
295 * Win32 OLE clipboard API
296 *---------------------------------------------------------------------*/
297
298 /***********************************************************************
299 * OleSetClipboard [OLE32.@]
300 * Places a pointer to the specified data object onto the clipboard,
301 * making the data object accessible to the OleGetClipboard function.
302 *
303 * RETURNS
304 *
305 * S_OK IDataObject pointer placed on the clipboard
306 * CLIPBRD_E_CANT_OPEN OpenClipboard failed
307 * CLIPBRD_E_CANT_EMPTY EmptyClipboard failed
308 * CLIPBRD_E_CANT_CLOSE CloseClipboard failed
309 * CLIPBRD_E_CANT_SET SetClipboard failed
310 */
311
312 HRESULT WINAPI OleSetClipboard(IDataObject* pDataObj)
313 {
314 HRESULT hr = S_OK;
315 IEnumFORMATETC* penumFormatetc = NULL;
316 FORMATETC rgelt;
317 BOOL bClipboardOpen = FALSE;
318 struct oletls *info = COM_CurrentInfo();
319 /*
320 HGLOBAL hDataObject = 0;
321 OLEClipbrd **ppDataObject;
322 */
323
324 TRACE("(%p)\n", pDataObj);
325
326 if(!info)
327 WARN("Could not allocate tls\n");
328 else
329 if(!info->ole_inits)
330 return CO_E_NOTINITIALIZED;
331
332 /*
333 * Make sure we have a clipboard object
334 */
335 OLEClipbrd_Initialize();
336
337 /*
338 * If the Ole clipboard window hasn't been created yet, create it now.
339 */
340 if ( !theOleClipboard->hWndClipboard )
341 theOleClipboard->hWndClipboard = OLEClipbrd_CreateWindow();
342
343 if ( !theOleClipboard->hWndClipboard ) /* sanity check */
344 HANDLE_ERROR( E_FAIL );
345
346 /*
347 * Open the Windows clipboard, associating it with our hidden window
348 */
349 if ( !(bClipboardOpen = OpenClipboard(theOleClipboard->hWndClipboard)) )
350 HANDLE_ERROR( CLIPBRD_E_CANT_OPEN );
351
352 /*
353 * Empty the current clipboard and make our window the clipboard owner
354 * NOTE: This will trigger a WM_DESTROYCLIPBOARD message
355 */
356 if ( !EmptyClipboard() )
357 HANDLE_ERROR( CLIPBRD_E_CANT_EMPTY );
358
359 /*
360 * If we are already holding on to an IDataObject first release that.
361 */
362 if ( theOleClipboard->pIDataObjectSrc )
363 {
364 IDataObject_Release(theOleClipboard->pIDataObjectSrc);
365 theOleClipboard->pIDataObjectSrc = NULL;
366 }
367
368 /*
369 * AddRef the data object passed in and save its pointer.
370 * A NULL value indicates that the clipboard should be emptied.
371 */
372 theOleClipboard->pIDataObjectSrc = pDataObj;
373 if ( pDataObj )
374 {
375 IDataObject_AddRef(theOleClipboard->pIDataObjectSrc);
376 }
377
378 /*
379 * Enumerate all HGLOBAL formats supported by the source and make
380 * those formats available using delayed rendering using SetClipboardData.
381 * Only global memory based data items may be made available to non-OLE
382 * applications via the standard Windows clipboard API. Data based on other
383 * mediums(non TYMED_HGLOBAL) can only be accessed via the Ole Clipboard API.
384 *
385 * TODO: Do we need to additionally handle TYMED_IStorage media by copying
386 * the storage into global memory?
387 */
388 if ( pDataObj )
389 {
390 if ( FAILED(hr = IDataObject_EnumFormatEtc( pDataObj,
391 DATADIR_GET,
392 &penumFormatetc )))
393 {
394 HANDLE_ERROR( hr );
395 }
396
397 while ( S_OK == IEnumFORMATETC_Next(penumFormatetc, 1, &rgelt, NULL) )
398 {
399 if ( rgelt.tymed == TYMED_HGLOBAL )
400 {
401 CHAR szFmtName[80];
402 TRACE("(cfFormat=%d:%s)\n", rgelt.cfFormat,
403 GetClipboardFormatNameA(rgelt.cfFormat, szFmtName, sizeof(szFmtName)-1)
404 ? szFmtName : "");
405
406 SetClipboardData( rgelt.cfFormat, NULL);
407 }
408 }
409 IEnumFORMATETC_Release(penumFormatetc);
410 }
411
412 /*
413 * Windows additionally creates a new "DataObject" clipboard format
414 * and stores in on the clipboard. We could possibly store a pointer
415 * to our internal IDataObject interface on the clipboard. I'm not
416 * sure what the use of this is though.
417 * Enable the code below for this functionality.
418 */
419 /*
420 theOleClipboard->cfDataObj = RegisterClipboardFormatA("DataObject");
421 hDataObject = GlobalAlloc( GMEM_DDESHARE|GMEM_MOVEABLE|GMEM_ZEROINIT,
422 sizeof(OLEClipbrd *));
423 if (hDataObject==0)
424 HANDLE_ERROR( E_OUTOFMEMORY );
425
426 ppDataObject = GlobalLock(hDataObject);
427 *ppDataObject = theOleClipboard;
428 GlobalUnlock(hDataObject);
429
430 if ( !SetClipboardData( theOleClipboard->cfDataObj, hDataObject ) )
431 HANDLE_ERROR( CLIPBRD_E_CANT_SET );
432 */
433
434 hr = S_OK;
435
436 CLEANUP:
437
438 /*
439 * Close Windows clipboard (It remains associated with our window)
440 */
441 if ( bClipboardOpen && !CloseClipboard() )
442 hr = CLIPBRD_E_CANT_CLOSE;
443
444 /*
445 * Release the source IDataObject if something failed
446 */
447 if ( FAILED(hr) )
448 {
449 if (theOleClipboard->pIDataObjectSrc)
450 {
451 IDataObject_Release(theOleClipboard->pIDataObjectSrc);
452 theOleClipboard->pIDataObjectSrc = NULL;
453 }
454 }
455
456 return hr;
457 }
458
459
460 /***********************************************************************
461 * OleGetClipboard [OLE32.@]
462 * Returns a pointer to our internal IDataObject which represents the conceptual
463 * state of the Windows clipboard. If the current clipboard already contains
464 * an IDataObject, our internal IDataObject will delegate to this object.
465 */
466 HRESULT WINAPI OleGetClipboard(IDataObject** ppDataObj)
467 {
468 HRESULT hr = S_OK;
469 TRACE("()\n");
470
471 /*
472 * Make sure we have a clipboard object
473 */
474 OLEClipbrd_Initialize();
475
476 if (!theOleClipboard)
477 return E_OUTOFMEMORY;
478
479 /* Return a reference counted IDataObject */
480 hr = IDataObject_QueryInterface( (IDataObject*)&(theOleClipboard->lpvtbl1),
481 &IID_IDataObject, (void**)ppDataObj);
482 return hr;
483 }
484
485 /******************************************************************************
486 * OleFlushClipboard [OLE32.@]
487 * Renders the data from the source IDataObject into the windows clipboard
488 *
489 * TODO: OleFlushClipboard needs to additionally handle TYMED_IStorage media
490 * by copying the storage into global memory. Subsequently the default
491 * data object exposed through OleGetClipboard must convert this TYMED_HGLOBAL
492 * back to TYMED_IStorage.
493 */
494 HRESULT WINAPI OleFlushClipboard(void)
495 {
496 IEnumFORMATETC* penumFormatetc = NULL;
497 FORMATETC rgelt;
498 HRESULT hr = S_OK;
499 BOOL bClipboardOpen = FALSE;
500 IDataObject* pIDataObjectSrc = NULL;
501
502 TRACE("()\n");
503
504 /*
505 * Make sure we have a clipboard object
506 */
507 OLEClipbrd_Initialize();
508
509 /*
510 * Already flushed or no source DataObject? Nothing to do.
511 */
512 if (!theOleClipboard->pIDataObjectSrc)
513 return S_OK;
514
515 /*
516 * Addref and save the source data object we are holding on to temporarily,
517 * since it will be released when we empty the clipboard.
518 */
519 pIDataObjectSrc = theOleClipboard->pIDataObjectSrc;
520 IDataObject_AddRef(pIDataObjectSrc);
521
522 /*
523 * Open the Windows clipboard
524 */
525 if ( !(bClipboardOpen = OpenClipboard(theOleClipboard->hWndClipboard)) )
526 HANDLE_ERROR( CLIPBRD_E_CANT_OPEN );
527
528 /*
529 * Empty the current clipboard
530 */
531 if ( !EmptyClipboard() )
532 HANDLE_ERROR( CLIPBRD_E_CANT_EMPTY );
533
534 /*
535 * Render all HGLOBAL formats supported by the source into
536 * the windows clipboard.
537 */
538 if ( FAILED( hr = IDataObject_EnumFormatEtc( pIDataObjectSrc,
539 DATADIR_GET,
540 &penumFormatetc) ))
541 {
542 HANDLE_ERROR( hr );
543 }
544
545 while ( S_OK == IEnumFORMATETC_Next(penumFormatetc, 1, &rgelt, NULL) )
546 {
547 if ( rgelt.tymed == TYMED_HGLOBAL )
548 {
549 CHAR szFmtName[80];
550 TRACE("(cfFormat=%d:%s)\n", rgelt.cfFormat,
551 GetClipboardFormatNameA(rgelt.cfFormat, szFmtName, sizeof(szFmtName)-1)
552 ? szFmtName : "");
553
554 /*
555 * Render the clipboard data
556 */
557 if ( FAILED(OLEClipbrd_RenderFormat( pIDataObjectSrc, &rgelt )) )
558 continue;
559 }
560 }
561
562 IEnumFORMATETC_Release(penumFormatetc);
563
564 /*
565 * Release the source data object we are holding on to
566 */
567 IDataObject_Release(pIDataObjectSrc);
568
569 CLEANUP:
570
571 /*
572 * Close Windows clipboard (It remains associated with our window)
573 */
574 if ( bClipboardOpen && !CloseClipboard() )
575 hr = CLIPBRD_E_CANT_CLOSE;
576
577 return hr;
578 }
579
580
581 /***********************************************************************
582 * OleIsCurrentClipboard [OLE32.@]
583 */
584 HRESULT WINAPI OleIsCurrentClipboard(IDataObject *pDataObject)
585 {
586 TRACE("()\n");
587 /*
588 * Make sure we have a clipboard object
589 */
590 OLEClipbrd_Initialize();
591
592 if (!theOleClipboard)
593 return E_OUTOFMEMORY;
594
595 if (pDataObject == NULL)
596 return S_FALSE;
597
598 return (pDataObject == theOleClipboard->pIDataObjectSrc) ? S_OK : S_FALSE;
599 }
600
601
602 /*---------------------------------------------------------------------*
603 * Internal implementation methods for the OLE clipboard
604 *---------------------------------------------------------------------*/
605
606 /***********************************************************************
607 * OLEClipbrd_Initialize()
608 * Initializes the OLE clipboard.
609 */
610 void OLEClipbrd_Initialize(void)
611 {
612 /*
613 * Create the clipboard if necessary
614 */
615 if ( !theOleClipboard )
616 {
617 TRACE("()\n");
618 theOleClipboard = OLEClipbrd_Construct();
619 }
620 }
621
622
623 /***********************************************************************
624 * OLEClipbrd_UnInitialize()
625 * Un-Initializes the OLE clipboard
626 */
627 void OLEClipbrd_UnInitialize(void)
628 {
629 TRACE("()\n");
630 /*
631 * Destroy the clipboard if no one holds a reference to us.
632 * Note that the clipboard was created with a reference count of 1.
633 */
634 if ( theOleClipboard && (theOleClipboard->ref <= 1) )
635 {
636 OLEClipbrd_Destroy( theOleClipboard );
637 }
638 else
639 {
640 WARN( "() : OLEClipbrd_UnInitialize called while client holds an IDataObject reference!\n");
641 }
642 }
643
644
645 /*********************************************************
646 * Construct the OLEClipbrd class.
647 */
648 static OLEClipbrd* OLEClipbrd_Construct(void)
649 {
650 OLEClipbrd* newObject = NULL;
651 HGLOBAL hNewObject = 0;
652
653 /*
654 * Allocate space for the object. We use GlobalAlloc since we need
655 * an HGLOBAL to expose our DataObject as a registered clipboard type.
656 */
657 hNewObject = GlobalAlloc( GMEM_DDESHARE|GMEM_MOVEABLE|GMEM_ZEROINIT,
658 sizeof(OLEClipbrd));
659 if (hNewObject==0)
660 return NULL;
661
662 /*
663 * Lock the handle for the entire lifetime of the clipboard.
664 */
665 newObject = GlobalLock(hNewObject);
666
667 /*
668 * Initialize the virtual function table.
669 */
670 newObject->lpvtbl1 = &OLEClipbrd_IDataObject_VTable;
671
672 /*
673 * Start with one reference count. The caller of this function
674 * must release the interface pointer when it is done.
675 */
676 newObject->ref = 1;
677
678 newObject->hSelf = hNewObject;
679
680 /*
681 * The Ole clipboard is a singleton - save the global handle and pointer
682 */
683 theOleClipboard = newObject;
684 hTheOleClipboard = hNewObject;
685
686 return theOleClipboard;
687 }
688
689 static void OLEClipbrd_Destroy(OLEClipbrd* ptrToDestroy)
690 {
691 TRACE("()\n");
692
693 if ( !ptrToDestroy )
694 return;
695
696 /*
697 * Destroy the Ole clipboard window
698 */
699 if ( ptrToDestroy->hWndClipboard )
700 OLEClipbrd_DestroyWindow(ptrToDestroy->hWndClipboard);
701
702 /*
703 * Free the actual OLE Clipboard structure.
704 */
705 TRACE("() - Destroying clipboard data object.\n");
706 GlobalUnlock(ptrToDestroy->hSelf);
707 GlobalFree(ptrToDestroy->hSelf);
708
709 /*
710 * The Ole clipboard is a singleton (ptrToDestroy == theOleClipboard)
711 */
712 theOleClipboard = NULL;
713 hTheOleClipboard = 0;
714 }
715
716
717 /***********************************************************************
718 * OLEClipbrd_CreateWindow()
719 * Create the clipboard window
720 */
721 static HWND OLEClipbrd_CreateWindow(void)
722 {
723 HWND hwnd = 0;
724 WNDCLASSEXA wcex;
725
726 /*
727 * Register the clipboard window class if necessary
728 */
729 ZeroMemory( &wcex, sizeof(WNDCLASSEXA));
730
731 wcex.cbSize = sizeof(WNDCLASSEXA);
732 /* Windows creates this class with a style mask of 0
733 * We don't bother doing this since the FindClassByAtom code
734 * would have to be changed to deal with this idiosyncrasy. */
735 wcex.style = CS_GLOBALCLASS;
736 wcex.lpfnWndProc = OLEClipbrd_WndProc;
737 wcex.hInstance = 0;
738 wcex.lpszClassName = OLEClipbrd_WNDCLASS;
739
740 RegisterClassExA(&wcex);
741
742 /*
743 * Create a hidden window to receive OLE clipboard messages
744 */
745
746 /*
747 * If we need to store state info we can store it here.
748 * For now we don't need this functionality.
749 * ClipboardWindowInfo clipboardInfo;
750 * ZeroMemory( &trackerInfo, sizeof(ClipboardWindowInfo));
751 */
752
753 hwnd = CreateWindowA(OLEClipbrd_WNDCLASS,
754 "ClipboardWindow",
755 WS_POPUP | WS_CLIPSIBLINGS | WS_OVERLAPPED,
756 CW_USEDEFAULT, CW_USEDEFAULT,
757 CW_USEDEFAULT, CW_USEDEFAULT,
758 0,
759 0,
760 0,
761 0 /*(LPVOID)&clipboardInfo */);
762
763 return hwnd;
764 }
765
766 /***********************************************************************
767 * OLEClipbrd_DestroyWindow(HWND)
768 * Destroy the clipboard window and unregister its class
769 */
770 static void OLEClipbrd_DestroyWindow(HWND hwnd)
771 {
772 /*
773 * Destroy clipboard window and unregister its WNDCLASS
774 */
775 DestroyWindow(hwnd);
776 UnregisterClassA( OLEClipbrd_WNDCLASS, 0 );
777 }
778
779 /***********************************************************************
780 * OLEClipbrd_WndProc(HWND, unsigned, WORD, LONG)
781 * Processes messages sent to the OLE clipboard window.
782 * Note that we will intercept messages in our WndProc only when data
783 * has been placed in the clipboard via OleSetClipboard().
784 * i.e. Only when OLE owns the windows clipboard.
785 */
786 static LRESULT CALLBACK OLEClipbrd_WndProc
787 (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
788 {
789 switch (message)
790 {
791 /*
792 * WM_RENDERFORMAT
793 * We receive this message to allow us to handle delayed rendering of
794 * a specific clipboard format when an application requests data in
795 * that format by calling GetClipboardData.
796 * (Recall that in OleSetClipboard, we used SetClipboardData to
797 * make all HGLOBAL formats supported by the source IDataObject
798 * available using delayed rendering)
799 * On receiving this message we must actually render the data in the
800 * specified format and place it on the clipboard by calling the
801 * SetClipboardData function.
802 */
803 case WM_RENDERFORMAT:
804 {
805 FORMATETC rgelt;
806
807 ZeroMemory( &rgelt, sizeof(FORMATETC));
808
809 /*
810 * Initialize FORMATETC to a Windows clipboard friendly format
811 */
812 rgelt.cfFormat = (UINT) wParam;
813 rgelt.dwAspect = DVASPECT_CONTENT;
814 rgelt.lindex = -1;
815 rgelt.tymed = TYMED_HGLOBAL;
816
817 TRACE("(): WM_RENDERFORMAT(cfFormat=%d)\n", rgelt.cfFormat);
818
819 /*
820 * Render the clipboard data.
821 * (We must have a source data object or we wouldn't be in this WndProc)
822 */
823 OLEClipbrd_RenderFormat( (IDataObject*)&(theOleClipboard->lpvtbl1), &rgelt );
824
825 break;
826 }
827
828 /*
829 * WM_RENDERALLFORMATS
830 * Sent before the clipboard owner window is destroyed.
831 * We should receive this message only when OleUninitialize is called
832 * while we have an IDataObject in the clipboard.
833 * For the content of the clipboard to remain available to other
834 * applications, we must render data in all the formats the source IDataObject
835 * is capable of generating, and place the data on the clipboard by calling
836 * SetClipboardData.
837 */
838 case WM_RENDERALLFORMATS:
839 {
840 IEnumFORMATETC* penumFormatetc = NULL;
841 FORMATETC rgelt;
842
843 TRACE("(): WM_RENDERALLFORMATS\n");
844
845 /*
846 * Render all HGLOBAL formats supported by the source into
847 * the windows clipboard.
848 */
849 if ( FAILED( IDataObject_EnumFormatEtc( (IDataObject*)&(theOleClipboard->lpvtbl1),
850 DATADIR_GET, &penumFormatetc) ) )
851 {
852 WARN("(): WM_RENDERALLFORMATS failed to retrieve EnumFormatEtc!\n");
853 return 0;
854 }
855
856 while ( S_OK == IEnumFORMATETC_Next(penumFormatetc, 1, &rgelt, NULL) )
857 {
858 if ( rgelt.tymed == TYMED_HGLOBAL )
859 {
860 /*
861 * Render the clipboard data.
862 */
863 if ( FAILED(OLEClipbrd_RenderFormat( (IDataObject*)&(theOleClipboard->lpvtbl1), &rgelt )) )
864 continue;
865
866 TRACE("(): WM_RENDERALLFORMATS(cfFormat=%d)\n", rgelt.cfFormat);
867 }
868 }
869
870 IEnumFORMATETC_Release(penumFormatetc);
871
872 break;
873 }
874
875 /*
876 * WM_DESTROYCLIPBOARD
877 * This is sent by EmptyClipboard before the clipboard is emptied.
878 * We should release any IDataObject we are holding onto when we receive
879 * this message, since it indicates that the OLE clipboard should be empty
880 * from this point on.
881 */
882 case WM_DESTROYCLIPBOARD:
883 {
884 TRACE("(): WM_DESTROYCLIPBOARD\n");
885 /*
886 * Release the data object we are holding on to
887 */
888 if ( theOleClipboard->pIDataObjectSrc )
889 {
890 IDataObject_Release(theOleClipboard->pIDataObjectSrc);
891 theOleClipboard->pIDataObjectSrc = NULL;
892 }
893 break;
894 }
895
896 /*
897 case WM_ASKCBFORMATNAME:
898 case WM_CHANGECBCHAIN:
899 case WM_DRAWCLIPBOARD:
900 case WM_SIZECLIPBOARD:
901 case WM_HSCROLLCLIPBOARD:
902 case WM_VSCROLLCLIPBOARD:
903 case WM_PAINTCLIPBOARD:
904 */
905 default:
906 return DefWindowProcA(hWnd, message, wParam, lParam);
907 }
908
909 return 0;
910 }
911
912 #define MAX_CLIPFORMAT_NAME 80
913
914 /***********************************************************************
915 * OLEClipbrd_RenderFormat(LPFORMATETC)
916 * Render the clipboard data. Note that this call will delegate to the
917 * source data object.
918 * Note: This function assumes it is passed an HGLOBAL format to render.
919 */
920 static HRESULT OLEClipbrd_RenderFormat(IDataObject *pIDataObject, LPFORMATETC pFormatetc)
921 {
922 STGMEDIUM std;
923 HGLOBAL hDup;
924 HRESULT hr = S_OK;
925 char szFmtName[MAX_CLIPFORMAT_NAME];
926 ILockBytes *ptrILockBytes = 0;
927 HGLOBAL hStorage = 0;
928
929 if (!GetClipboardFormatNameA(pFormatetc->cfFormat, szFmtName, MAX_CLIPFORMAT_NAME))
930 szFmtName[0] = '\0';
931
932 /* If embed source */
933 if (!strcmp(szFmtName, CF_EMBEDSOURCE))
934 {
935 memset(&std, 0, sizeof(STGMEDIUM));
936 std.tymed = pFormatetc->tymed = TYMED_ISTORAGE;
937
938 hStorage = GlobalAlloc(GMEM_SHARE|GMEM_MOVEABLE, 0);
939 if (hStorage == NULL)
940 HANDLE_ERROR( E_OUTOFMEMORY );
941 hr = CreateILockBytesOnHGlobal(hStorage, FALSE, &ptrILockBytes);
942 hr = StgCreateDocfileOnILockBytes(ptrILockBytes, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &std.u.pstg);
943
944 if (FAILED(hr = IDataObject_GetDataHere(theOleClipboard->pIDataObjectSrc, pFormatetc, &std)))
945 {
946 WARN("() : IDataObject_GetDataHere failed to render clipboard data! (%x)\n", hr);
947 GlobalFree(hStorage);
948 return hr;
949 }
950
951 if (1) /* check whether the presentation data is already -not- present */
952 {
953 FORMATETC fmt2;
954 STGMEDIUM std2;
955 METAFILEPICT *mfp = 0;
956
957 fmt2.cfFormat = CF_METAFILEPICT;
958 fmt2.ptd = 0;
959 fmt2.dwAspect = DVASPECT_CONTENT;
960 fmt2.lindex = -1;
961 fmt2.tymed = TYMED_MFPICT;
962
963 memset(&std2, 0, sizeof(STGMEDIUM));
964 std2.tymed = TYMED_MFPICT;
965
966 /* Get the metafile picture out of it */
967
968 if (SUCCEEDED(hr = IDataObject_GetData(theOleClipboard->pIDataObjectSrc, &fmt2, &std2)))
969 {
970 mfp = GlobalLock(std2.u.hGlobal);
971 }
972
973 if (mfp)
974 {
975 OLECHAR name[]={ 2, 'O', 'l', 'e', 'P', 'r', 'e', 's', '', '', '', 0};
976 IStream *pStream = 0;
977 void *mfBits;
978 PresentationDataHeader pdh;
979 INT nSize;
980 CLSID clsID;
981 LPOLESTR strProgID;
982 CHAR strOleTypeName[51];
983 BYTE OlePresStreamHeader [] =
984 {
985 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00,
986 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
987 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
988 0x00, 0x00, 0x00, 0x00
989 };
990
991 nSize = GetMetaFileBitsEx(mfp->hMF, 0, NULL);
992
993 memset(&pdh, 0, sizeof(PresentationDataHeader));
994 memcpy(&pdh, OlePresStreamHeader, sizeof(OlePresStreamHeader));
995
996 pdh.dwObjectExtentX = mfp->xExt;
997 pdh.dwObjectExtentY = mfp->yExt;
998 pdh.dwSize = nSize;
999
1000 hr = IStorage_CreateStream(std.u.pstg, name, STGM_CREATE|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, 0, &pStream);
1001
1002 hr = IStream_Write(pStream, &pdh, sizeof(PresentationDataHeader), NULL);
1003
1004 mfBits = HeapAlloc(GetProcessHeap(), 0, nSize);
1005 nSize = GetMetaFileBitsEx(mfp->hMF, nSize, mfBits);
1006
1007 hr = IStream_Write(pStream, mfBits, nSize, NULL);
1008
1009 IStream_Release(pStream);
1010
1011 HeapFree(GetProcessHeap(), 0, mfBits);
1012
1013 GlobalUnlock(std2.u.hGlobal);
1014
1015 ReadClassStg(std.u.pstg, &clsID);
1016 ProgIDFromCLSID(&clsID, &strProgID);
1017
1018 WideCharToMultiByte( CP_ACP, 0, strProgID, -1, strOleTypeName, sizeof(strOleTypeName), NULL, NULL );
1019 OLECONVERT_CreateOleStream(std.u.pstg);
1020 OLECONVERT_CreateCompObjStream(std.u.pstg, strOleTypeName);
1021 }
1022 }
1023 }
1024 else
1025 {
1026 if (FAILED(hr = IDataObject_GetData(pIDataObject, pFormatetc, &std)))
1027 {
1028 WARN("() : IDataObject_GetData failed to render clipboard data! (%x)\n", hr);
1029 GlobalFree(hStorage);
1030 return hr;
1031 }
1032
1033 /* To put a copy back on the clipboard */
1034
1035 hStorage = std.u.hGlobal;
1036 }
1037
1038 /*
1039 * Put a copy of the rendered data back on the clipboard
1040 */
1041
1042 if ( !(hDup = OLEClipbrd_GlobalDupMem(hStorage)) )
1043 HANDLE_ERROR( E_OUTOFMEMORY );
1044
1045 if ( !SetClipboardData( pFormatetc->cfFormat, hDup ) )
1046 {
1047 GlobalFree(hDup);
1048 WARN("() : Failed to set rendered clipboard data into clipboard!\n");
1049 }
1050
1051 CLEANUP:
1052
1053 ReleaseStgMedium(&std);
1054
1055 return hr;
1056 }
1057
1058
1059 /***********************************************************************
1060 * OLEClipbrd_GlobalDupMem( HGLOBAL )
1061 * Helper method to duplicate an HGLOBAL chunk of memory
1062 */
1063 static HGLOBAL OLEClipbrd_GlobalDupMem( HGLOBAL hGlobalSrc )
1064 {
1065 HGLOBAL hGlobalDest;
1066 PVOID pGlobalSrc, pGlobalDest;
1067 DWORD cBytes;
1068
1069 if ( !hGlobalSrc )
1070 return 0;
1071
1072 cBytes = GlobalSize(hGlobalSrc);
1073 if ( 0 == cBytes )
1074 return 0;
1075
1076 hGlobalDest = GlobalAlloc( GMEM_DDESHARE|GMEM_MOVEABLE,
1077 cBytes );
1078 if ( !hGlobalDest )
1079 return 0;
1080
1081 pGlobalSrc = GlobalLock(hGlobalSrc);
1082 pGlobalDest = GlobalLock(hGlobalDest);
1083 if ( !pGlobalSrc || !pGlobalDest )
1084 {
1085 GlobalFree(hGlobalDest);
1086 return 0;
1087 }
1088
1089 memcpy(pGlobalDest, pGlobalSrc, cBytes);
1090
1091 GlobalUnlock(hGlobalSrc);
1092 GlobalUnlock(hGlobalDest);
1093
1094 return hGlobalDest;
1095 }
1096
1097
1098 /*---------------------------------------------------------------------*
1099 * Implementation of the internal IDataObject interface exposed by
1100 * the OLE clipboard.
1101 *---------------------------------------------------------------------*/
1102
1103
1104 /************************************************************************
1105 * OLEClipbrd_IDataObject_QueryInterface (IUnknown)
1106 *
1107 * See Windows documentation for more details on IUnknown methods.
1108 */
1109 static HRESULT WINAPI OLEClipbrd_IDataObject_QueryInterface(
1110 IDataObject* iface,
1111 REFIID riid,
1112 void** ppvObject)
1113 {
1114 /*
1115 * Declare "This" pointer
1116 */
1117 OLEClipbrd *This = (OLEClipbrd *)iface;
1118 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObject);
1119
1120 /*
1121 * Perform a sanity check on the parameters.
1122 */
1123 if ( (This==0) || (ppvObject==0) )
1124 return E_INVALIDARG;
1125
1126 /*
1127 * Initialize the return parameter.
1128 */
1129 *ppvObject = 0;
1130
1131 /*
1132 * Compare the riid with the interface IDs implemented by this object.
1133 */
1134 if (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0)
1135 {
1136 *ppvObject = iface;
1137 }
1138 else if (memcmp(&IID_IDataObject, riid, sizeof(IID_IDataObject)) == 0)
1139 {
1140 *ppvObject = (IDataObject*)&(This->lpvtbl1);
1141 }
1142 else /* We only support IUnknown and IDataObject */
1143 {
1144 WARN( "() : asking for unsupported interface %s\n", debugstr_guid(riid));
1145 return E_NOINTERFACE;
1146 }
1147
1148 /*
1149 * Query Interface always increases the reference count by one when it is
1150 * successful.
1151 */
1152 IUnknown_AddRef((IUnknown*)*ppvObject);
1153
1154 return S_OK;
1155 }
1156
1157 /************************************************************************
1158 * OLEClipbrd_IDataObject_AddRef (IUnknown)
1159 *
1160 * See Windows documentation for more details on IUnknown methods.
1161 */
1162 static ULONG WINAPI OLEClipbrd_IDataObject_AddRef(
1163 IDataObject* iface)
1164 {
1165 /*
1166 * Declare "This" pointer
1167 */
1168 OLEClipbrd *This = (OLEClipbrd *)iface;
1169
1170 TRACE("(%p)->(count=%u)\n",This, This->ref);
1171
1172 return InterlockedIncrement(&This->ref);
1173
1174 }
1175
1176 /************************************************************************
1177 * OLEClipbrd_IDataObject_Release (IUnknown)
1178 *
1179 * See Windows documentation for more details on IUnknown methods.
1180 */
1181 static ULONG WINAPI OLEClipbrd_IDataObject_Release(
1182 IDataObject* iface)
1183 {
1184 /*
1185 * Declare "This" pointer
1186 */
1187 OLEClipbrd *This = (OLEClipbrd *)iface;
1188 ULONG ref;
1189
1190 TRACE("(%p)->(count=%u)\n",This, This->ref);
1191
1192 /*
1193 * Decrease the reference count on this object.
1194 */
1195 ref = InterlockedDecrement(&This->ref);
1196
1197 /*
1198 * If the reference count goes down to 0, perform suicide.
1199 */
1200 if (ref == 0)
1201 {
1202 OLEClipbrd_Destroy(This);
1203 }
1204
1205 return ref;
1206 }
1207
1208
1209 /************************************************************************
1210 * OLEClipbrd_IDataObject_GetData (IDataObject)
1211 *
1212 * The OLE Clipboard's implementation of this method delegates to
1213 * a data source if there is one or wraps around the windows clipboard
1214 *
1215 * See Windows documentation for more details on IDataObject methods.
1216 */
1217 static HRESULT WINAPI OLEClipbrd_IDataObject_GetData(
1218 IDataObject* iface,
1219 LPFORMATETC pformatetcIn,
1220 STGMEDIUM* pmedium)
1221 {
1222 HANDLE hData = 0;
1223 BOOL bClipboardOpen = FALSE;
1224 HRESULT hr = S_OK;
1225 LPVOID src;
1226
1227 /*
1228 * Declare "This" pointer
1229 */
1230 OLEClipbrd *This = (OLEClipbrd *)iface;
1231
1232 TRACE("(%p,%p,%p)\n", iface, pformatetcIn, pmedium);
1233
1234 if ( !pformatetcIn || !pmedium )
1235 return E_INVALIDARG;
1236
1237 /*
1238 * If we have a data source placed on the clipboard (via OleSetClipboard)
1239 * simply delegate to the source object's QueryGetData
1240 * NOTE: This code assumes that the IDataObject is in the same address space!
1241 * We will need to add marshalling support when Wine handles multiple processes.
1242 */
1243 if ( This->pIDataObjectSrc )
1244 {
1245 return IDataObject_GetData(This->pIDataObjectSrc, pformatetcIn, pmedium);
1246 }
1247
1248 if ( pformatetcIn->lindex != -1 )
1249 return DV_E_FORMATETC;
1250
1251 if ( (pformatetcIn->tymed & TYMED_HGLOBAL) != TYMED_HGLOBAL )
1252 return DV_E_TYMED;
1253 /*
1254 if ( pformatetcIn->dwAspect != DVASPECT_CONTENT )
1255 return DV_E_DVASPECT;
1256 */
1257
1258 /*
1259 * Otherwise, get the data from the windows clipboard using GetClipboardData
1260 */
1261 if ( !(bClipboardOpen = OpenClipboard(theOleClipboard->hWndClipboard)) )
1262 HANDLE_ERROR( CLIPBRD_E_CANT_OPEN );
1263
1264 hData = GetClipboardData(pformatetcIn->cfFormat);
1265
1266 /* Must make a copy of global handle returned by GetClipboardData; it
1267 * is not valid after we call CloseClipboard
1268 * Application is responsible for freeing the memory (Forte Agent does this)
1269 */
1270 src = GlobalLock(hData);
1271 if(src) {
1272 LPVOID dest;
1273 ULONG size;
1274 HANDLE hDest;
1275
1276 size = GlobalSize(hData);
1277 hDest = GlobalAlloc(GHND, size);
1278 dest = GlobalLock(hDest);
1279 memcpy(dest, src, size);
1280 GlobalUnlock(hDest);
1281 GlobalUnlock(hData);
1282 hData = hDest;
1283 }
1284
1285 /*
1286 * Return the clipboard data in the storage medium structure
1287 */
1288 pmedium->tymed = (hData == 0) ? TYMED_NULL : TYMED_HGLOBAL;
1289 pmedium->u.hGlobal = hData;
1290 pmedium->pUnkForRelease = NULL;
1291
1292 hr = S_OK;
1293
1294 CLEANUP:
1295 /*
1296 * Close Windows clipboard
1297 */
1298 if ( bClipboardOpen && !CloseClipboard() )
1299 hr = CLIPBRD_E_CANT_CLOSE;
1300
1301 if ( FAILED(hr) )
1302 return hr;
1303 return (hData == 0) ? DV_E_FORMATETC : S_OK;
1304 }
1305
1306 static HRESULT WINAPI OLEClipbrd_IDataObject_GetDataHere(
1307 IDataObject* iface,
1308 LPFORMATETC pformatetc,
1309 STGMEDIUM* pmedium)
1310 {
1311 FIXME(": Stub\n");
1312 return E_NOTIMPL;
1313 }
1314
1315 /************************************************************************
1316 * OLEClipbrd_IDataObject_QueryGetData (IDataObject)
1317 *
1318 * The OLE Clipboard's implementation of this method delegates to
1319 * a data source if there is one or wraps around the windows clipboard
1320 * function IsClipboardFormatAvailable() otherwise.
1321 *
1322 * See Windows documentation for more details on IDataObject methods.
1323 */
1324 static HRESULT WINAPI OLEClipbrd_IDataObject_QueryGetData(
1325 IDataObject* iface,
1326 LPFORMATETC pformatetc)
1327 {
1328 TRACE("(%p, %p)\n", iface, pformatetc);
1329
1330 if (!pformatetc)
1331 return E_INVALIDARG;
1332
1333 if ( pformatetc->dwAspect != DVASPECT_CONTENT )
1334 return DV_E_FORMATETC;
1335
1336 if ( pformatetc->lindex != -1 )
1337 return DV_E_FORMATETC;
1338
1339 /*
1340 * Delegate to the Windows clipboard function IsClipboardFormatAvailable
1341 */
1342 return (IsClipboardFormatAvailable(pformatetc->cfFormat)) ? S_OK : DV_E_CLIPFORMAT;
1343 }
1344
1345 /************************************************************************
1346 * OLEClipbrd_IDataObject_GetCanonicalFormatEtc (IDataObject)
1347 *
1348 * See Windows documentation for more details on IDataObject methods.
1349 */
1350 static HRESULT WINAPI OLEClipbrd_IDataObject_GetCanonicalFormatEtc(
1351 IDataObject* iface,
1352 LPFORMATETC pformatectIn,
1353 LPFORMATETC pformatetcOut)
1354 {
1355 TRACE("(%p, %p, %p)\n", iface, pformatectIn, pformatetcOut);
1356
1357 if ( !pformatectIn || !pformatetcOut )
1358 return E_INVALIDARG;
1359
1360 *pformatetcOut = *pformatectIn;
1361 return DATA_S_SAMEFORMATETC;
1362 }
1363
1364 /************************************************************************
1365 * OLEClipbrd_IDataObject_SetData (IDataObject)
1366 *
1367 * The OLE Clipboard's does not implement this method
1368 *
1369 * See Windows documentation for more details on IDataObject methods.
1370 */
1371 static HRESULT WINAPI OLEClipbrd_IDataObject_SetData(
1372 IDataObject* iface,
1373 LPFORMATETC pformatetc,
1374 STGMEDIUM* pmedium,
1375 BOOL fRelease)
1376 {
1377 TRACE("\n");
1378 return E_NOTIMPL;
1379 }
1380
1381 /************************************************************************
1382 * OLEClipbrd_IDataObject_EnumFormatEtc (IDataObject)
1383 *
1384 * See Windows documentation for more details on IDataObject methods.
1385 */
1386 static HRESULT WINAPI OLEClipbrd_IDataObject_EnumFormatEtc(
1387 IDataObject* iface,
1388 DWORD dwDirection,
1389 IEnumFORMATETC** ppenumFormatEtc)
1390 {
1391 HRESULT hr = S_OK;
1392 FORMATETC *afmt = NULL;
1393 int cfmt, i;
1394 UINT format;
1395 BOOL bClipboardOpen;
1396
1397 /*
1398 * Declare "This" pointer
1399 */
1400 OLEClipbrd *This = (OLEClipbrd *)iface;
1401
1402 TRACE("(%p, %x, %p)\n", iface, dwDirection, ppenumFormatEtc);
1403
1404 /*
1405 * If we have a data source placed on the clipboard (via OleSetClipboard)
1406 * simply delegate to the source object's EnumFormatEtc
1407 */
1408 if ( This->pIDataObjectSrc )
1409 {
1410 return IDataObject_EnumFormatEtc(This->pIDataObjectSrc,
1411 dwDirection, ppenumFormatEtc);
1412 }
1413
1414 /*
1415 * Otherwise we must provide our own enumerator which wraps around the
1416 * Windows clipboard function EnumClipboardFormats
1417 */
1418 if ( !ppenumFormatEtc )
1419 return E_INVALIDARG;
1420
1421 if ( dwDirection != DATADIR_GET ) /* IDataObject_SetData not implemented */
1422 return E_NOTIMPL;
1423
1424 /*
1425 * Store all current clipboard formats in an array of FORMATETC's,
1426 * and create an IEnumFORMATETC enumerator from this list.
1427 */
1428 cfmt = CountClipboardFormats();
1429 afmt = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1430 sizeof(FORMATETC) * cfmt);
1431 /*
1432 * Open the Windows clipboard, associating it with our hidden window
1433 */
1434 if ( !(bClipboardOpen = OpenClipboard(This->hWndClipboard)) )
1435 HANDLE_ERROR( CLIPBRD_E_CANT_OPEN );
1436
1437 /*
1438 * Store all current clipboard formats in an array of FORMATETC's
1439 * TODO: Handle TYMED_IStorage media which were put on the clipboard
1440 * by copying the storage into global memory. We must convert this
1441 * TYMED_HGLOBAL back to TYMED_IStorage.
1442 */
1443 for (i = 0, format = 0; i < cfmt; i++)
1444 {
1445 format = EnumClipboardFormats(format);
1446 if (!format) /* Failed! */
1447 {
1448 ERR("EnumClipboardFormats failed to return format!\n");
1449 HANDLE_ERROR( E_FAIL );
1450 }
1451
1452 /* Init the FORMATETC struct */
1453 afmt[i].cfFormat = format;
1454 afmt[i].ptd = NULL;
1455 afmt[i].dwAspect = DVASPECT_CONTENT;
1456 afmt[i].lindex = -1;
1457 afmt[i].tymed = TYMED_HGLOBAL;
1458 }
1459
1460 /*
1461 * Create an EnumFORMATETC enumerator and return an
1462 * EnumFORMATETC after bumping up its ref count
1463 */
1464 *ppenumFormatEtc = OLEClipbrd_IEnumFORMATETC_Construct( cfmt, afmt, (LPUNKNOWN)iface);
1465 if (!(*ppenumFormatEtc))
1466 HANDLE_ERROR( E_OUTOFMEMORY );
1467
1468 if (FAILED( hr = IEnumFORMATETC_AddRef(*ppenumFormatEtc)))
1469 HANDLE_ERROR( hr );
1470
1471 hr = S_OK;
1472
1473 CLEANUP:
1474 /*
1475 * Free the array of FORMATETC's
1476 */
1477 HeapFree(GetProcessHeap(), 0, afmt);
1478
1479 /*
1480 * Close Windows clipboard
1481 */
1482 if ( bClipboardOpen && !CloseClipboard() )
1483 hr = CLIPBRD_E_CANT_CLOSE;
1484
1485 return hr;
1486 }
1487
1488 /************************************************************************
1489 * OLEClipbrd_IDataObject_DAdvise (IDataObject)
1490 *
1491 * The OLE Clipboard's does not implement this method
1492 *
1493 * See Windows documentation for more details on IDataObject methods.
1494 */
1495 static HRESULT WINAPI OLEClipbrd_IDataObject_DAdvise(
1496 IDataObject* iface,
1497 FORMATETC* pformatetc,
1498 DWORD advf,
1499 IAdviseSink* pAdvSink,
1500 DWORD* pdwConnection)
1501 {
1502 TRACE("\n");
1503 return E_NOTIMPL;
1504 }
1505
1506 /************************************************************************
1507 * OLEClipbrd_IDataObject_DUnadvise (IDataObject)
1508 *
1509 * The OLE Clipboard's does not implement this method
1510 *
1511 * See Windows documentation for more details on IDataObject methods.
1512 */
1513 static HRESULT WINAPI OLEClipbrd_IDataObject_DUnadvise(
1514 IDataObject* iface,
1515 DWORD dwConnection)
1516 {
1517 TRACE("\n");
1518 return E_NOTIMPL;
1519 }
1520
1521 /************************************************************************
1522 * OLEClipbrd_IDataObject_EnumDAdvise (IDataObject)
1523 *
1524 * The OLE Clipboard does not implement this method
1525 *
1526 * See Windows documentation for more details on IDataObject methods.
1527 */
1528 static HRESULT WINAPI OLEClipbrd_IDataObject_EnumDAdvise(
1529 IDataObject* iface,
1530 IEnumSTATDATA** ppenumAdvise)
1531 {
1532 TRACE("\n");
1533 return E_NOTIMPL;
1534 }
1535
1536
1537 /*---------------------------------------------------------------------*
1538 * Implementation of the internal IEnumFORMATETC interface returned by
1539 * the OLE clipboard's IDataObject.
1540 *---------------------------------------------------------------------*/
1541
1542 /************************************************************************
1543 * OLEClipbrd_IEnumFORMATETC_Construct (UINT, const FORMATETC, LPUNKNOWN)
1544 *
1545 * Creates an IEnumFORMATETC enumerator from an array of FORMATETC
1546 * Structures. pUnkOuter is the outer unknown for reference counting only.
1547 * NOTE: this does not AddRef the interface.
1548 */
1549
1550 static LPENUMFORMATETC OLEClipbrd_IEnumFORMATETC_Construct(UINT cfmt, const FORMATETC afmt[],
1551 LPUNKNOWN pUnkDataObj)
1552 {
1553 IEnumFORMATETCImpl* ef;
1554 DWORD size=cfmt * sizeof(FORMATETC);
1555 LPMALLOC pIMalloc;
1556
1557 ef = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IEnumFORMATETCImpl));
1558 if (!ef)
1559 return NULL;
1560
1561 ef->ref = 0;
1562 ef->lpVtbl = &efvt;
1563 ef->pUnkDataObj = pUnkDataObj;
1564
1565 ef->posFmt = 0;
1566 ef->countFmt = cfmt;
1567 if (FAILED(CoGetMalloc(MEMCTX_TASK, &pIMalloc))) {
1568 HeapFree(GetProcessHeap(), 0, ef);
1569 return NULL;
1570 }
1571 ef->pFmt = (LPFORMATETC)IMalloc_Alloc(pIMalloc, size);
1572 IMalloc_Release(pIMalloc);
1573
1574 if (ef->pFmt)
1575 memcpy(ef->pFmt, afmt, size);
1576
1577 TRACE("(%p)->()\n",ef);
1578 return (LPENUMFORMATETC)ef;
1579 }
1580
1581
1582 /************************************************************************
1583 * OLEClipbrd_IEnumFORMATETC_QueryInterface (IUnknown)
1584 *
1585 * See Windows documentation for more details on IUnknown methods.
1586 */
1587 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_QueryInterface
1588 (LPENUMFORMATETC iface, REFIID riid, LPVOID* ppvObj)
1589 {
1590 IEnumFORMATETCImpl *This = (IEnumFORMATETCImpl *)iface;
1591
1592 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
1593
1594 /*
1595 * Since enumerators are separate objects from the parent data object
1596 * we only need to support the IUnknown and IEnumFORMATETC interfaces
1597 */
1598
1599 *ppvObj = NULL;
1600
1601 if(IsEqualIID(riid, &IID_IUnknown))
1602 {
1603 *ppvObj = This;
1604 }
1605 else if(IsEqualIID(riid, &IID_IEnumFORMATETC))
1606 {
1607 *ppvObj = (IDataObject*)This;
1608 }
1609
1610 if(*ppvObj)
1611 {
1612 IEnumFORMATETC_AddRef((IEnumFORMATETC*)*ppvObj);
1613 TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
1614 return S_OK;
1615 }
1616
1617 TRACE("-- Interface: E_NOINTERFACE\n");
1618 return E_NOINTERFACE;
1619 }
1620
1621 /************************************************************************
1622 * OLEClipbrd_IEnumFORMATETC_AddRef (IUnknown)
1623 *
1624 * Since enumerating formats only makes sense when our data object is around,
1625 * we insure that it stays as long as we stay by calling our parents IUnknown
1626 * for AddRef and Release. But since we are not controlled by the lifetime of
1627 * the outer object, we still keep our own reference count in order to
1628 * free ourselves.
1629 */
1630 static ULONG WINAPI OLEClipbrd_IEnumFORMATETC_AddRef(LPENUMFORMATETC iface)
1631 {
1632 IEnumFORMATETCImpl *This = (IEnumFORMATETCImpl *)iface;
1633 TRACE("(%p)->(count=%u)\n",This, This->ref);
1634
1635 if (This->pUnkDataObj)
1636 IUnknown_AddRef(This->pUnkDataObj);
1637
1638 return InterlockedIncrement(&This->ref);
1639 }
1640
1641 /************************************************************************
1642 * OLEClipbrd_IEnumFORMATETC_Release (IUnknown)
1643 *
1644 * See Windows documentation for more details on IUnknown methods.
1645 */
1646 static ULONG WINAPI OLEClipbrd_IEnumFORMATETC_Release(LPENUMFORMATETC iface)
1647 {
1648 IEnumFORMATETCImpl *This = (IEnumFORMATETCImpl *)iface;
1649 LPMALLOC pIMalloc;
1650 ULONG ref;
1651
1652 TRACE("(%p)->(count=%u)\n",This, This->ref);
1653
1654 if (This->pUnkDataObj)
1655 IUnknown_Release(This->pUnkDataObj); /* Release parent data object */
1656
1657 ref = InterlockedDecrement(&This->ref);
1658 if (!ref)
1659 {
1660 TRACE("() - destroying IEnumFORMATETC(%p)\n",This);
1661 if (SUCCEEDED(CoGetMalloc(MEMCTX_TASK, &pIMalloc)))
1662 {
1663 IMalloc_Free(pIMalloc, This->pFmt);
1664 IMalloc_Release(pIMalloc);
1665 }
1666
1667 HeapFree(GetProcessHeap(),0,This);
1668 }
1669 return ref;
1670 }
1671
1672 /************************************************************************
1673 * OLEClipbrd_IEnumFORMATETC_Next (IEnumFORMATETC)
1674 *
1675 * Standard enumerator members for IEnumFORMATETC
1676 */
1677 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Next
1678 (LPENUMFORMATETC iface, ULONG celt, FORMATETC *rgelt, ULONG *pceltFethed)
1679 {
1680 IEnumFORMATETCImpl *This = (IEnumFORMATETCImpl *)iface;
1681 UINT cfetch;
1682 HRESULT hres = S_FALSE;
1683
1684 TRACE("(%p)->(pos=%u)\n", This, This->posFmt);
1685
1686 if (This->posFmt < This->countFmt)
1687 {
1688 cfetch = This->countFmt - This->posFmt;
1689 if (cfetch >= celt)
1690 {
1691 cfetch = celt;
1692 hres = S_OK;
1693 }
1694
1695 memcpy(rgelt, &This->pFmt[This->posFmt], cfetch * sizeof(FORMATETC));
1696 This->posFmt += cfetch;
1697 }
1698 else
1699 {
1700 cfetch = 0;
1701 }
1702
1703 if (pceltFethed)
1704 {
1705 *pceltFethed = cfetch;
1706 }
1707
1708 return hres;
1709 }
1710
1711 /************************************************************************
1712 * OLEClipbrd_IEnumFORMATETC_Skip (IEnumFORMATETC)
1713 *
1714 * Standard enumerator members for IEnumFORMATETC
1715 */
1716 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Skip(LPENUMFORMATETC iface, ULONG celt)
1717 {
1718 IEnumFORMATETCImpl *This = (IEnumFORMATETCImpl *)iface;
1719 TRACE("(%p)->(num=%u)\n", This, celt);
1720
1721 This->posFmt += celt;
1722 if (This->posFmt > This->countFmt)
1723 {
1724 This->posFmt = This->countFmt;
1725 return S_FALSE;
1726 }
1727 return S_OK;
1728 }
1729
1730 /************************************************************************
1731 * OLEClipbrd_IEnumFORMATETC_Reset (IEnumFORMATETC)
1732 *
1733 * Standard enumerator members for IEnumFORMATETC
1734 */
1735 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Reset(LPENUMFORMATETC iface)
1736 {
1737 IEnumFORMATETCImpl *This = (IEnumFORMATETCImpl *)iface;
1738 TRACE("(%p)->()\n", This);
1739
1740 This->posFmt = 0;
1741 return S_OK;
1742 }
1743
1744 /************************************************************************
1745 * OLEClipbrd_IEnumFORMATETC_Clone (IEnumFORMATETC)
1746 *
1747 * Standard enumerator members for IEnumFORMATETC
1748 */
1749 static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Clone
1750 (LPENUMFORMATETC iface, LPENUMFORMATETC* ppenum)
1751 {
1752 IEnumFORMATETCImpl *This = (IEnumFORMATETCImpl *)iface;
1753 HRESULT hr = S_OK;
1754
1755 TRACE("(%p)->(ppenum=%p)\n", This, ppenum);
1756
1757 if ( !ppenum )
1758 return E_INVALIDARG;
1759
1760 *ppenum = OLEClipbrd_IEnumFORMATETC_Construct(This->countFmt,
1761 This->pFmt,
1762 This->pUnkDataObj);
1763
1764 if (FAILED( hr = IEnumFORMATETC_AddRef(*ppenum)))
1765 return ( hr );
1766
1767 return (*ppenum) ? S_OK : E_OUTOFMEMORY;
1768 }
1769
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.