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

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

Initial port of OLE2.
Added regsvr32

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