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

Last change on this file since 872 was 872, checked in by davidr, 26 years ago

Added CVS ID lines to all source files

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