source: trunk/src/ole32/old/oleClip.cpp

Last change on this file was 5601, checked in by sandervl, 24 years ago

created

File size: 51.9 KB
Line 
1/* $Id: oleClip.cpp,v 1.1 2001-04-26 19:26:13 sandervl 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 "storage32.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_CreateOleStream(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 BOOL bClipboardOpen = FALSE;
1237 HRESULT hr = S_OK;
1238
1239 /*
1240 * Declare "This" pointer
1241 */
1242 ICOM_THIS(OLEClipbrd, iface);
1243
1244 if ( !pformatetcIn || !pformatetcIn || !pmedium )
1245 return E_INVALIDARG;
1246
1247 dprintf(("OLE32: OLEClipbrd_IDataObject_GetData(%p, %p)\n", iface, pformatetcIn));
1248
1249 /*
1250 * If we have a data source placed on the clipboard (via OleSetClipboard)
1251 * simply delegate to the source object's QueryGetData
1252 * NOTE: This code assumes that the IDataObject is in the same address space!
1253 * We will need to add marshalling support when Wine handles multiple processes.
1254 */
1255 if ( This->pIDataObjectSrc )
1256 {
1257 return IDataObject_GetData(This->pIDataObjectSrc, pformatetcIn, pmedium);
1258 }
1259
1260 if ( pformatetcIn->lindex != -1 )
1261 return DV_E_LINDEX;
1262 if ( (pformatetcIn->tymed & TYMED_HGLOBAL) != TYMED_HGLOBAL )
1263 return DV_E_TYMED;
1264/*
1265 if ( pformatetcIn->dwAspect != DVASPECT_CONTENT )
1266 return DV_E_DVASPECT;
1267*/
1268
1269 /*
1270 * Otherwise, delegate to the Windows clipboard function GetClipboardData
1271 */
1272 if ( !(bClipboardOpen = OpenClipboard(theOleClipboard->hWndClipboard)) )
1273 HANDLE_ERROR( CLIPBRD_E_CANT_OPEN );
1274
1275 hData = GetClipboardData(pformatetcIn->cfFormat);
1276
1277 /*
1278 * Return the clipboard data in the storage medium structure
1279 */
1280 pmedium->tymed = (hData == 0) ? TYMED_NULL : TYMED_HGLOBAL;
1281 pmedium->u.hGlobal = (HGLOBAL)hData;
1282 pmedium->pUnkForRelease = NULL;
1283
1284 hr = S_OK;
1285
1286CLEANUP:
1287 /*
1288 * Close Windows clipboard
1289 */
1290 if ( bClipboardOpen && !CloseClipboard() )
1291 hr = CLIPBRD_E_CANT_CLOSE;
1292
1293 if ( FAILED(hr) )
1294 return hr;
1295 return (hData == 0) ? DV_E_FORMATETC : S_OK;
1296}
1297
1298static HRESULT WIN32API OLEClipbrd_IDataObject_GetDataHere(
1299 IDataObject* iface,
1300 LPFORMATETC pformatetc,
1301 STGMEDIUM* pmedium)
1302{
1303 dprintf(("OLE32: OLEClipbrd_IDataObject_GetDataHere - stub"));
1304 return E_NOTIMPL;
1305}
1306
1307/************************************************************************
1308 * OLEClipbrd_IDataObject_QueryGetData (IDataObject)
1309 *
1310 * The OLE Clipboard's implementation of this method delegates to
1311 * a data source if there is one or wraps around the windows clipboard
1312 * function IsClipboardFormatAvailable() otherwise.
1313 *
1314 * See Windows documentation for more details on IDataObject methods.
1315 */
1316static HRESULT WIN32API OLEClipbrd_IDataObject_QueryGetData(
1317 IDataObject* iface,
1318 LPFORMATETC pformatetc)
1319{
1320 /*
1321 * Declare "This" pointer
1322 */
1323 ICOM_THIS(OLEClipbrd, iface);
1324
1325 dprintf(("OLE32: OLEClipbrd_IDataObject_QueryGetData(%p, %p)\n", iface, pformatetc));
1326
1327 /*
1328 * If we have a data source placed on the clipboard (via OleSetClipboard)
1329 * simply delegate to the source object's QueryGetData
1330 */
1331 if ( This->pIDataObjectSrc )
1332 {
1333 return IDataObject_QueryGetData(This->pIDataObjectSrc, pformatetc);
1334 }
1335
1336 if (!pformatetc)
1337 return E_INVALIDARG;
1338/*
1339 if ( pformatetc->dwAspect != DVASPECT_CONTENT )
1340 return DV_E_DVASPECT;
1341*/
1342 if ( pformatetc->lindex != -1 )
1343 return DV_E_LINDEX;
1344
1345 /* TODO: Handle TYMED_IStorage media which were put on the clipboard
1346 * by copying the storage into global memory. We must convert this
1347 * TYMED_HGLOBAL back to TYMED_IStorage.
1348 */
1349 if ( pformatetc->tymed != TYMED_HGLOBAL )
1350 return DV_E_TYMED;
1351
1352 /*
1353 * Delegate to the Windows clipboard function IsClipboardFormatAvailable
1354 */
1355 return (IsClipboardFormatAvailable(pformatetc->cfFormat)) ? S_OK : DV_E_FORMATETC;
1356}
1357
1358/************************************************************************
1359 * OLEClipbrd_IDataObject_GetCanonicalFormatEtc (IDataObject)
1360 *
1361 * See Windows documentation for more details on IDataObject methods.
1362 */
1363static HRESULT WIN32API OLEClipbrd_IDataObject_GetCanonicalFormatEtc(
1364 IDataObject* iface,
1365 LPFORMATETC pformatectIn,
1366 LPFORMATETC pformatetcOut)
1367{
1368 dprintf(("OLE32: OLEClipbrd_IDataObject_GetCanonicalFormatEtc(%p, %p, %p)\n", iface, pformatectIn, pformatetcOut));
1369
1370 if ( !pformatectIn || !pformatetcOut )
1371 return E_INVALIDARG;
1372
1373 memcpy(pformatetcOut, pformatectIn, sizeof(FORMATETC));
1374 return DATA_S_SAMEFORMATETC;
1375}
1376
1377/************************************************************************
1378 * OLEClipbrd_IDataObject_SetData (IDataObject)
1379 *
1380 * The OLE Clipboard's does not implement this method
1381 *
1382 * See Windows documentation for more details on IDataObject methods.
1383 */
1384static HRESULT WIN32API OLEClipbrd_IDataObject_SetData(
1385 IDataObject* iface,
1386 LPFORMATETC pformatetc,
1387 STGMEDIUM* pmedium,
1388 BOOL fRelease)
1389{
1390 dprintf(("OLE32: OLEClipbrd_IDataObject_SetData - stub"));
1391 return E_NOTIMPL;
1392}
1393
1394/************************************************************************
1395 * OLEClipbrd_IDataObject_EnumFormatEtc (IDataObject)
1396 *
1397 * See Windows documentation for more details on IDataObject methods.
1398 */
1399static HRESULT WIN32API OLEClipbrd_IDataObject_EnumFormatEtc(
1400 IDataObject* iface,
1401 DWORD dwDirection,
1402 IEnumFORMATETC** ppenumFormatEtc)
1403{
1404 HRESULT hr = S_OK;
1405 FORMATETC *afmt = NULL;
1406 int cfmt, i;
1407 UINT format;
1408 BOOL bClipboardOpen;
1409
1410 /*
1411 * Declare "This" pointer
1412 */
1413 ICOM_THIS(OLEClipbrd, iface);
1414
1415 dprintf(("OLE32: OLEClipbrd_IDataObject_EnumFormatEtc(%p, %lx, %p)\n", iface, dwDirection, ppenumFormatEtc));
1416
1417 /*
1418 * If we have a data source placed on the clipboard (via OleSetClipboard)
1419 * simply delegate to the source object's EnumFormatEtc
1420 */
1421 if ( This->pIDataObjectSrc )
1422 {
1423 return IDataObject_EnumFormatEtc(This->pIDataObjectSrc,
1424 dwDirection, ppenumFormatEtc);
1425 }
1426
1427 /*
1428 * Otherwise we must provide our own enumerator which wraps around the
1429 * Windows clipboard function EnumClipboardFormats
1430 */
1431 if ( !ppenumFormatEtc )
1432 return E_INVALIDARG;
1433
1434 if ( dwDirection != DATADIR_GET ) /* IDataObject_SetData not implemented */
1435 return E_NOTIMPL;
1436
1437 /*
1438 * Store all current clipboard formats in an array of FORMATETC's,
1439 * and create an IEnumFORMATETC enumerator from this list.
1440 */
1441 cfmt = CountClipboardFormats();
1442 afmt = (FORMATETC *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1443 sizeof(FORMATETC) * cfmt);
1444 /*
1445 * Open the Windows clipboard, associating it with our hidden window
1446 */
1447 if ( !(bClipboardOpen = OpenClipboard(This->hWndClipboard)) )
1448 HANDLE_ERROR( CLIPBRD_E_CANT_OPEN );
1449
1450 /*
1451 * Store all current clipboard formats in an array of FORMATETC's
1452 * TODO: Handle TYMED_IStorage media which were put on the clipboard
1453 * by copying the storage into global memory. We must convert this
1454 * TYMED_HGLOBAL back to TYMED_IStorage.
1455 */
1456 for (i = 0, format = 0; i < cfmt; i++)
1457 {
1458 format = EnumClipboardFormats(format);
1459 if (!format) /* Failed! */
1460 {
1461 dprintf(("OLE32: Error: EnumClipboardFormats failed to return format!"));
1462 HANDLE_ERROR( E_FAIL );
1463 }
1464
1465 /* Init the FORMATETC struct */
1466 afmt[i].cfFormat = format;
1467 afmt[i].ptd = NULL;
1468 afmt[i].dwAspect = DVASPECT_CONTENT;
1469 afmt[i].lindex = -1;
1470 afmt[i].tymed = TYMED_HGLOBAL;
1471 }
1472
1473 /*
1474 * Create an EnumFORMATETC enumerator and return an
1475 * EnumFORMATETC after bumping up its ref count
1476 */
1477 *ppenumFormatEtc = OLEClipbrd_IEnumFORMATETC_Construct( cfmt, afmt, (LPUNKNOWN)iface);
1478 if (!(*ppenumFormatEtc))
1479 HANDLE_ERROR( E_OUTOFMEMORY );
1480
1481 if (FAILED( hr = IEnumFORMATETC_AddRef(*ppenumFormatEtc)))
1482 HANDLE_ERROR( hr );
1483
1484 hr = S_OK;
1485
1486CLEANUP:
1487 /*
1488 * Free the array of FORMATETC's
1489 */
1490 if (afmt)
1491 HeapFree(GetProcessHeap(), 0, afmt);
1492
1493 /*
1494 * Close Windows clipboard
1495 */
1496 if ( bClipboardOpen && !CloseClipboard() )
1497 hr = CLIPBRD_E_CANT_CLOSE;
1498
1499 return hr;
1500}
1501
1502/************************************************************************
1503 * OLEClipbrd_IDataObject_DAdvise (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_DAdvise(
1510 IDataObject* iface,
1511 FORMATETC* pformatetc,
1512 DWORD advf,
1513 IAdviseSink* pAdvSink,
1514 DWORD* pdwConnection)
1515{
1516 return E_NOTIMPL;
1517}
1518
1519/************************************************************************
1520 * OLEClipbrd_IDataObject_DUnadvise (IDataObject)
1521 *
1522 * The OLE Clipboard's does not implement this method
1523 *
1524 * See Windows documentation for more details on IDataObject methods.
1525 */
1526static HRESULT WIN32API OLEClipbrd_IDataObject_DUnadvise(
1527 IDataObject* iface,
1528 DWORD dwConnection)
1529{
1530 return E_NOTIMPL;
1531}
1532
1533/************************************************************************
1534 * OLEClipbrd_IDataObject_EnumDAdvise (IDataObject)
1535 *
1536 * The OLE Clipboard does not implement this method
1537 *
1538 * See Windows documentation for more details on IDataObject methods.
1539 */
1540static HRESULT WIN32API OLEClipbrd_IDataObject_EnumDAdvise(
1541 IDataObject* iface,
1542 IEnumSTATDATA** ppenumAdvise)
1543{
1544 return E_NOTIMPL;
1545}
1546
1547
1548/*---------------------------------------------------------------------*
1549 * Implementation of the internal IEnumFORMATETC interface returned by
1550 * the OLE clipboard's IDataObject.
1551 *---------------------------------------------------------------------*/
1552
1553/************************************************************************
1554 * OLEClipbrd_IEnumFORMATETC_Construct (UINT, const FORMATETC, LPUNKNOWN)
1555 *
1556 * Creates an IEnumFORMATETC enumerator from an array of FORMATETC
1557 * Structures. pUnkOuter is the outer unknown for reference counting only.
1558 * NOTE: this does not AddRef the interface.
1559 */
1560
1561LPENUMFORMATETC OLEClipbrd_IEnumFORMATETC_Construct(UINT cfmt, const FORMATETC afmt[],
1562 LPUNKNOWN pUnkDataObj)
1563{
1564 IEnumFORMATETCImpl* ef;
1565 DWORD size=cfmt * sizeof(FORMATETC);
1566 LPMALLOC pIMalloc;
1567
1568 ef = (IEnumFORMATETCImpl*)HeapAlloc(GetProcessHeap(),
1569 HEAP_ZERO_MEMORY,
1570 sizeof(IEnumFORMATETCImpl));
1571 if (!ef)
1572 return NULL;
1573
1574 ef->ref = 0;
1575 ef->lpvtbl = &efvt;
1576 ef->pUnkDataObj = pUnkDataObj;
1577
1578 ef->posFmt = 0;
1579 ef->countFmt = cfmt;
1580 if (FAILED(CoGetMalloc(MEMCTX_TASK, &pIMalloc)))
1581 return NULL;
1582 ef->pFmt = (LPFORMATETC)IMalloc_Alloc(pIMalloc, size);
1583 IMalloc_Release(pIMalloc);
1584
1585 if (ef->pFmt)
1586 memcpy(ef->pFmt, afmt, size);
1587
1588 dprintf(("OLE32: OLEClipbrd_IEnumFORMATETC_Construct(%p)->()\n",ef));
1589 return (LPENUMFORMATETC)ef;
1590}
1591
1592
1593/************************************************************************
1594 * OLEClipbrd_IEnumFORMATETC_QueryInterface (IUnknown)
1595 *
1596 * See Windows documentation for more details on IUnknown methods.
1597 */
1598static HRESULT WIN32API OLEClipbrd_IEnumFORMATETC_QueryInterface
1599 (LPENUMFORMATETC iface, REFIID riid, LPVOID* ppvObj)
1600{
1601 ICOM_THIS(IEnumFORMATETCImpl,iface);
1602 char xriid[50];
1603
1604 WINE_StringFromCLSID((LPCLSID)riid,xriid);
1605 dprintf(("OLE32: OLEClipbrd_IEnumFORMATETC_QueryInterface(%p)->(\n\tIID:\t%s,%p)\n",This,xriid,ppvObj));
1606
1607 /*
1608 * Since enumerators are seperate objects from the parent data object
1609 * we only need to support the IUnknown and IEnumFORMATETC interfaces
1610 */
1611
1612 *ppvObj = NULL;
1613
1614 if(IsEqualIID(riid, &IID_IUnknown))
1615 {
1616 *ppvObj = This;
1617 }
1618 else if(IsEqualIID(riid, &IID_IEnumFORMATETC))
1619 {
1620 *ppvObj = (IDataObject*)This;
1621 }
1622
1623 if(*ppvObj)
1624 {
1625 IEnumFORMATETC_AddRef((IEnumFORMATETC*)*ppvObj);
1626 dprintf(("OLE32: OLEClipbrd_IEnumFORMATETC_QueryInterface - Interface: (%p)->(%p)\n",ppvObj,*ppvObj));
1627 return S_OK;
1628 }
1629
1630 dprintf(("OLE32: OLEClipbrd_IEnumFORMATETC_QueryInterface - Interface: E_NOINTERFACE\n"));
1631 return E_NOINTERFACE;
1632}
1633
1634/************************************************************************
1635 * OLEClipbrd_IEnumFORMATETC_AddRef (IUnknown)
1636 *
1637 * Since enumerating formats only makes sense when our data object is around,
1638 * we insure that it stays as long as we stay by calling our parents IUnknown
1639 * for AddRef and Release. But since we are not controlled by the lifetime of
1640 * the outer object, we still keep our own reference count in order to
1641 * free ourselves.
1642 */
1643static ULONG WIN32API OLEClipbrd_IEnumFORMATETC_AddRef(LPENUMFORMATETC iface)
1644{
1645 ICOM_THIS(IEnumFORMATETCImpl,iface);
1646 dprintf(("OLE32: OLEClipbrd_IEnumFORMATETC_AddRef(%p)->(count=%lu)\n",This, This->ref));
1647
1648 if (This->pUnkDataObj)
1649 IUnknown_AddRef(This->pUnkDataObj);
1650
1651 return ++(This->ref);
1652}
1653
1654/************************************************************************
1655 * OLEClipbrd_IEnumFORMATETC_Release (IUnknown)
1656 *
1657 * See Windows documentation for more details on IUnknown methods.
1658 */
1659static ULONG WIN32API OLEClipbrd_IEnumFORMATETC_Release(LPENUMFORMATETC iface)
1660{
1661 ICOM_THIS(IEnumFORMATETCImpl,iface);
1662 LPMALLOC pIMalloc;
1663
1664 dprintf(("OLE32: OLEClipbrd_IEnumFORMATETC_Release(%p)->(count=%lu)\n",This, This->ref));
1665
1666 if (This->pUnkDataObj)
1667 IUnknown_Release(This->pUnkDataObj); /* Release parent data object */
1668
1669 if (!--(This->ref))
1670 {
1671 dprintf(("OLE32: OLEClipbrd_IEnumFORMATETC_Release() - destroying IEnumFORMATETC(%p)\n",This));
1672 if (SUCCEEDED(CoGetMalloc(MEMCTX_TASK, &pIMalloc)))
1673 {
1674 IMalloc_Free(pIMalloc, This->pFmt);
1675 IMalloc_Release(pIMalloc);
1676 }
1677
1678 HeapFree(GetProcessHeap(),0,This);
1679 return 0;
1680 }
1681
1682 return This->ref;
1683}
1684
1685/************************************************************************
1686 * OLEClipbrd_IEnumFORMATETC_Next (IEnumFORMATETC)
1687 *
1688 * Standard enumerator members for IEnumFORMATETC
1689 */
1690static HRESULT WIN32API OLEClipbrd_IEnumFORMATETC_Next
1691 (LPENUMFORMATETC iface, ULONG celt, FORMATETC *rgelt, ULONG *pceltFethed)
1692{
1693 ICOM_THIS(IEnumFORMATETCImpl,iface);
1694 UINT cfetch;
1695 HRESULT hres = S_FALSE;
1696
1697 dprintf(("OLE32: OLEClipbrd_IEnumFORMATETC_Next(%p)->(pos=%u)\n", This, This->posFmt));
1698
1699 if (This->posFmt < This->countFmt)
1700 {
1701 cfetch = This->countFmt - This->posFmt;
1702 if (cfetch >= celt)
1703 {
1704 cfetch = celt;
1705 hres = S_OK;
1706 }
1707
1708 memcpy(rgelt, &This->pFmt[This->posFmt], cfetch * sizeof(FORMATETC));
1709 This->posFmt += cfetch;
1710 }
1711 else
1712 {
1713 cfetch = 0;
1714 }
1715
1716 if (pceltFethed)
1717 {
1718 *pceltFethed = cfetch;
1719 }
1720
1721 return hres;
1722}
1723
1724/************************************************************************
1725 * OLEClipbrd_IEnumFORMATETC_Skip (IEnumFORMATETC)
1726 *
1727 * Standard enumerator members for IEnumFORMATETC
1728 */
1729static HRESULT WIN32API OLEClipbrd_IEnumFORMATETC_Skip(LPENUMFORMATETC iface, ULONG celt)
1730{
1731 ICOM_THIS(IEnumFORMATETCImpl,iface);
1732 dprintf(("OLE32: OLEClipbrd_IEnumFORMATETC_Skip(%p)->(num=%lu)\n", This, celt));
1733
1734 This->posFmt += celt;
1735 if (This->posFmt > This->countFmt)
1736 {
1737 This->posFmt = This->countFmt;
1738 return S_FALSE;
1739 }
1740 return S_OK;
1741}
1742
1743/************************************************************************
1744 * OLEClipbrd_IEnumFORMATETC_Reset (IEnumFORMATETC)
1745 *
1746 * Standard enumerator members for IEnumFORMATETC
1747 */
1748static HRESULT WIN32API OLEClipbrd_IEnumFORMATETC_Reset(LPENUMFORMATETC iface)
1749{
1750 ICOM_THIS(IEnumFORMATETCImpl,iface);
1751 dprintf(("OLE32: OLEClipbrd_IEnumFORMATETC_Reset(%p)->()\n", This));
1752
1753 This->posFmt = 0;
1754 return S_OK;
1755}
1756
1757/************************************************************************
1758 * OLEClipbrd_IEnumFORMATETC_Clone (IEnumFORMATETC)
1759 *
1760 * Standard enumerator members for IEnumFORMATETC
1761 */
1762static HRESULT WIN32API OLEClipbrd_IEnumFORMATETC_Clone
1763 (LPENUMFORMATETC iface, LPENUMFORMATETC* ppenum)
1764{
1765 ICOM_THIS(IEnumFORMATETCImpl,iface);
1766 HRESULT hr = S_OK;
1767
1768 dprintf(("OLE32: OLEClipbrd_IEnumFORMATETC_Clone(%p)->(ppenum=%p)\n", This, ppenum));
1769
1770 if ( !ppenum )
1771 return E_INVALIDARG;
1772
1773 *ppenum = OLEClipbrd_IEnumFORMATETC_Construct(This->countFmt,
1774 This->pFmt,
1775 This->pUnkDataObj);
1776
1777 if (FAILED( hr = IEnumFORMATETC_AddRef(*ppenum)))
1778 return ( hr );
1779
1780 return (*ppenum) ? S_OK : E_OUTOFMEMORY;
1781}
1782
Note: See TracBrowser for help on using the repository browser.