source: branches/gcc-kmk/src/ole32/clipboard.c@ 21855

Last change on this file since 21855 was 21855, checked in by dmik, 13 years ago

Port OLE32 and REGSVR32 to GCC/kBuild.

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