source: trunk/src/ole32/oleClip.cpp@ 4274

Last change on this file since 4274 was 4274, checked in by davidr, 25 years ago

Updates from wine

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