4 * Copyright 2003 Ulrich Czekalla
5 * Copyright 2007 Damjan Jovanovic
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #include "wine/port.h"
32 #define NONAMELESSUNION
42 #include "shlobj.h" /* DROPFILES */
46 #include "wine/unicode.h"
47 #include "wine/debug.h"
48 #include "wine/list.h"
50 WINE_DEFAULT_DEBUG_CHANNEL(xdnd
);
52 /* Maximum wait time for selection notify */
53 #define SELECTION_RETRIES 500 /* wait for .1 seconds */
54 #define SELECTION_WAIT 1000 /* us */
56 typedef struct tagXDNDDATA
62 } XDNDDATA
, *LPXDNDDATA
;
64 static struct list xdndData
= LIST_INIT(xdndData
);
65 static POINT XDNDxy
= { 0, 0 };
66 static IDataObject XDNDDataObject
;
67 static BOOL XDNDAccepted
= FALSE
;
68 static DWORD XDNDDropEffect
= DROPEFFECT_NONE
;
69 /* the last window the mouse was over */
70 static HWND XDNDLastTargetWnd
;
71 /* might be an ancestor of XDNDLastTargetWnd */
72 static HWND XDNDLastDropTargetWnd
;
74 static void X11DRV_XDND_InsertXDNDData(int property
, int format
, HANDLE contents
);
75 static void X11DRV_XDND_ResolveProperty(Display
*display
, Window xwin
, Time tm
,
76 Atom
*types
, unsigned long count
);
77 static BOOL
X11DRV_XDND_HasHDROP(void);
78 static HRESULT
X11DRV_XDND_SendDropFiles(HWND hwnd
);
79 static void X11DRV_XDND_FreeDragDropOp(void);
81 static CRITICAL_SECTION xdnd_cs
;
82 static CRITICAL_SECTION_DEBUG critsect_debug
=
85 { &critsect_debug
.ProcessLocksList
, &critsect_debug
.ProcessLocksList
},
86 0, 0, { (DWORD_PTR
)(__FILE__
": xdnd_cs") }
88 static CRITICAL_SECTION xdnd_cs
= { &critsect_debug
, -1, 0, 0, 0, 0 };
91 /* Based on functions in dlls/ole32/ole2.c */
92 static HANDLE
get_droptarget_local_handle(HWND hwnd
)
94 static const WCHAR prop_marshalleddroptarget
[] =
95 {'W','i','n','e','M','a','r','s','h','a','l','l','e','d','D','r','o','p','T','a','r','g','e','t',0};
97 HANDLE local_handle
= 0;
99 handle
= GetPropW(hwnd
, prop_marshalleddroptarget
);
105 GetWindowThreadProcessId(hwnd
, &pid
);
106 process
= OpenProcess(PROCESS_DUP_HANDLE
, FALSE
, pid
);
109 DuplicateHandle(process
, handle
, GetCurrentProcess(), &local_handle
, 0, FALSE
, DUPLICATE_SAME_ACCESS
);
110 CloseHandle(process
);
116 static HRESULT
create_stream_from_map(HANDLE map
, IStream
**stream
)
118 HRESULT hr
= E_OUTOFMEMORY
;
121 MEMORY_BASIC_INFORMATION info
;
123 data
= MapViewOfFile(map
, FILE_MAP_READ
, 0, 0, 0);
126 VirtualQuery(data
, &info
, sizeof(info
));
127 TRACE("size %d\n", (int)info
.RegionSize
);
129 hmem
= GlobalAlloc(GMEM_MOVEABLE
, info
.RegionSize
);
132 memcpy(GlobalLock(hmem
), data
, info
.RegionSize
);
134 hr
= CreateStreamOnHGlobal(hmem
, TRUE
, stream
);
136 UnmapViewOfFile(data
);
140 static IDropTarget
* get_droptarget_pointer(HWND hwnd
)
142 IDropTarget
*droptarget
= NULL
;
146 map
= get_droptarget_local_handle(hwnd
);
147 if(!map
) return NULL
;
149 if(SUCCEEDED(create_stream_from_map(map
, &stream
)))
151 CoUnmarshalInterface(stream
, &IID_IDropTarget
, (void**)&droptarget
);
152 IStream_Release(stream
);
158 /**************************************************************************
159 * X11DRV_XDND_XdndActionToDROPEFFECT
161 static DWORD
X11DRV_XDND_XdndActionToDROPEFFECT(long action
)
163 /* In Windows, nothing but the given effects is allowed.
164 * In X the given action is just a hint, and you can always
165 * XdndActionCopy and XdndActionPrivate, so be more permissive. */
166 if (action
== x11drv_atom(XdndActionCopy
))
167 return DROPEFFECT_COPY
;
168 else if (action
== x11drv_atom(XdndActionMove
))
169 return DROPEFFECT_MOVE
| DROPEFFECT_COPY
;
170 else if (action
== x11drv_atom(XdndActionLink
))
171 return DROPEFFECT_LINK
| DROPEFFECT_COPY
;
172 else if (action
== x11drv_atom(XdndActionAsk
))
173 /* FIXME: should we somehow ask the user what to do here? */
174 return DROPEFFECT_COPY
| DROPEFFECT_MOVE
| DROPEFFECT_LINK
;
175 FIXME("unknown action %ld, assuming DROPEFFECT_COPY\n", action
);
176 return DROPEFFECT_COPY
;
179 /**************************************************************************
180 * X11DRV_XDND_DROPEFFECTToXdndAction
182 static long X11DRV_XDND_DROPEFFECTToXdndAction(DWORD effect
)
184 if (effect
== DROPEFFECT_COPY
)
185 return x11drv_atom(XdndActionCopy
);
186 else if (effect
== DROPEFFECT_MOVE
)
187 return x11drv_atom(XdndActionMove
);
188 else if (effect
== DROPEFFECT_LINK
)
189 return x11drv_atom(XdndActionLink
);
190 FIXME("unknown drop effect %u, assuming XdndActionCopy\n", effect
);
191 return x11drv_atom(XdndActionCopy
);
194 /**************************************************************************
195 * X11DRV_XDND_EnterEvent
197 * Handle an XdndEnter event.
199 void X11DRV_XDND_EnterEvent( HWND hWnd
, XClientMessageEvent
*event
)
203 unsigned long count
= 0;
205 version
= (event
->data
.l
[1] & 0xFF000000) >> 24;
206 TRACE("ver(%d) check-XdndTypeList(%ld) data=%ld,%ld,%ld,%ld,%ld\n",
207 version
, (event
->data
.l
[1] & 1),
208 event
->data
.l
[0], event
->data
.l
[1], event
->data
.l
[2],
209 event
->data
.l
[3], event
->data
.l
[4]);
211 if (version
> WINE_XDND_VERSION
)
213 TRACE("Ignores unsupported version\n");
217 XDNDAccepted
= FALSE
;
219 /* If the source supports more than 3 data types we retrieve
220 * the entire list. */
221 if (event
->data
.l
[1] & 1)
225 unsigned long bytesret
;
227 /* Request supported formats from source window */
228 XGetWindowProperty(event
->display
, event
->data
.l
[0], x11drv_atom(XdndTypeList
),
229 0, 65535, FALSE
, AnyPropertyType
, &acttype
, &actfmt
, &count
,
230 &bytesret
, (unsigned char**)&xdndtypes
);
235 xdndtypes
= (Atom
*) &event
->data
.l
[2];
242 for (i
= 0; i
< count
; i
++)
244 if (xdndtypes
[i
] != 0)
246 char * pn
= XGetAtomName(event
->display
, xdndtypes
[i
]);
247 TRACE("XDNDEnterAtom %ld: %s\n", xdndtypes
[i
], pn
);
253 /* Do a one-time data read and cache results */
254 X11DRV_XDND_ResolveProperty(event
->display
, event
->window
,
255 event
->data
.l
[1], xdndtypes
, count
);
257 if (event
->data
.l
[1] & 1)
261 /**************************************************************************
262 * X11DRV_XDND_PositionEvent
264 * Handle an XdndPosition event.
266 void X11DRV_XDND_PositionEvent( HWND hWnd
, XClientMessageEvent
*event
)
268 XClientMessageEvent e
;
269 int accept
= 0; /* Assume we're not accepting */
270 IDropTarget
*dropTarget
= NULL
;
276 XDNDxy
= root_to_virtual_screen( event
->data
.l
[2] >> 16, event
->data
.l
[2] & 0xFFFF );
277 targetWindow
= WindowFromPoint(XDNDxy
);
281 effect
= X11DRV_XDND_XdndActionToDROPEFFECT(event
->data
.l
[4]);
283 if (!XDNDAccepted
|| XDNDLastTargetWnd
!= targetWindow
)
285 /* Notify OLE of DragEnter. Result determines if we accept */
286 HWND dropTargetWindow
;
288 if (XDNDAccepted
&& XDNDLastDropTargetWnd
)
290 dropTarget
= get_droptarget_pointer(XDNDLastDropTargetWnd
);
293 hr
= IDropTarget_DragLeave(dropTarget
);
295 WARN("IDropTarget_DragLeave failed, error 0x%08X\n", hr
);
296 IDropTarget_Release(dropTarget
);
299 dropTargetWindow
= targetWindow
;
302 dropTarget
= get_droptarget_pointer(dropTargetWindow
);
303 } while (dropTarget
== NULL
&& (dropTargetWindow
= GetParent(dropTargetWindow
)) != NULL
);
304 XDNDLastTargetWnd
= targetWindow
;
305 XDNDLastDropTargetWnd
= dropTargetWindow
;
308 DWORD effect_ignore
= effect
;
309 hr
= IDropTarget_DragEnter(dropTarget
, &XDNDDataObject
,
310 MK_LBUTTON
, pointl
, &effect
);
314 TRACE("the application accepted the drop (effect = %d)\n", effect_ignore
);
318 XDNDAccepted
= FALSE
;
319 WARN("IDropTarget_DragEnter failed, error 0x%08X\n", hr
);
321 IDropTarget_Release(dropTarget
);
324 if (XDNDAccepted
&& XDNDLastTargetWnd
== targetWindow
)
326 /* If drag accepted notify OLE of DragOver */
327 dropTarget
= get_droptarget_pointer(XDNDLastDropTargetWnd
);
330 hr
= IDropTarget_DragOver(dropTarget
, MK_LBUTTON
, pointl
, &effect
);
332 XDNDDropEffect
= effect
;
334 WARN("IDropTarget_DragOver failed, error 0x%08X\n", hr
);
335 IDropTarget_Release(dropTarget
);
341 else if ((GetWindowLongW( hWnd
, GWL_EXSTYLE
) & WS_EX_ACCEPTFILES
) &&
342 X11DRV_XDND_HasHDROP())
345 effect
= DROPEFFECT_COPY
;
348 TRACE("action req: %ld accept(%d) at x(%d),y(%d)\n",
349 event
->data
.l
[4], accept
, XDNDxy
.x
, XDNDxy
.y
);
352 * Let source know if we're accepting the drop by
353 * sending a status message.
355 e
.type
= ClientMessage
;
356 e
.display
= event
->display
;
357 e
.window
= event
->data
.l
[0];
358 e
.message_type
= x11drv_atom(XdndStatus
);
360 e
.data
.l
[0] = event
->window
;
361 e
.data
.l
[1] = accept
;
362 e
.data
.l
[2] = 0; /* Empty Rect */
363 e
.data
.l
[3] = 0; /* Empty Rect */
365 e
.data
.l
[4] = X11DRV_XDND_DROPEFFECTToXdndAction(effect
);
368 XSendEvent(event
->display
, event
->data
.l
[0], False
, NoEventMask
, (XEvent
*)&e
);
371 /**************************************************************************
372 * X11DRV_XDND_DropEvent
374 * Handle an XdndDrop event.
376 void X11DRV_XDND_DropEvent( HWND hWnd
, XClientMessageEvent
*event
)
378 XClientMessageEvent e
;
379 IDropTarget
*dropTarget
;
380 DWORD effect
= XDNDDropEffect
;
381 int accept
= 0; /* Assume we're not accepting */
382 BOOL drop_file
= TRUE
;
386 /* Notify OLE of Drop */
389 dropTarget
= get_droptarget_pointer(XDNDLastDropTargetWnd
);
390 if (dropTarget
&& effect
!=DROPEFFECT_NONE
)
397 hr
= IDropTarget_Drop(dropTarget
, &XDNDDataObject
, MK_LBUTTON
,
401 if (effect
!= DROPEFFECT_NONE
)
403 TRACE("drop succeeded\n");
408 TRACE("the application refused the drop\n");
411 WARN("drop failed, error 0x%08X\n", hr
);
414 WARN("drop returned 0x%08X\n", hr
);
417 IDropTarget_Release(dropTarget
);
421 HRESULT hr
= IDropTarget_DragLeave(dropTarget
);
423 WARN("IDropTarget_DragLeave failed, error 0x%08X\n", hr
);
424 IDropTarget_Release(dropTarget
);
430 /* Only send WM_DROPFILES if Drop didn't succeed or DROPEFFECT_NONE was set.
431 * Doing both causes winamp to duplicate the dropped files (#29081) */
432 if ((GetWindowLongW( hWnd
, GWL_EXSTYLE
) & WS_EX_ACCEPTFILES
) &&
433 X11DRV_XDND_HasHDROP())
435 HRESULT hr
= X11DRV_XDND_SendDropFiles( hWnd
);
439 effect
= DROPEFFECT_COPY
;
444 X11DRV_XDND_FreeDragDropOp();
446 /* Tell the target we are finished. */
447 memset(&e
, 0, sizeof(e
));
448 e
.type
= ClientMessage
;
449 e
.display
= event
->display
;
450 e
.window
= event
->data
.l
[0];
451 e
.message_type
= x11drv_atom(XdndFinished
);
453 e
.data
.l
[0] = event
->window
;
454 e
.data
.l
[1] = accept
;
456 e
.data
.l
[2] = X11DRV_XDND_DROPEFFECTToXdndAction(effect
);
459 XSendEvent(event
->display
, event
->data
.l
[0], False
, NoEventMask
, (XEvent
*)&e
);
462 /**************************************************************************
463 * X11DRV_XDND_LeaveEvent
465 * Handle an XdndLeave event.
467 void X11DRV_XDND_LeaveEvent( HWND hWnd
, XClientMessageEvent
*event
)
469 IDropTarget
*dropTarget
;
471 TRACE("DND Operation canceled\n");
473 /* Notify OLE of DragLeave */
476 dropTarget
= get_droptarget_pointer(XDNDLastDropTargetWnd
);
479 HRESULT hr
= IDropTarget_DragLeave(dropTarget
);
481 WARN("IDropTarget_DragLeave failed, error 0x%08X\n", hr
);
482 IDropTarget_Release(dropTarget
);
486 X11DRV_XDND_FreeDragDropOp();
490 /**************************************************************************
491 * X11DRV_XDND_ResolveProperty
493 * Resolve all MIME types to windows clipboard formats. All data is cached.
495 static void X11DRV_XDND_ResolveProperty(Display
*display
, Window xwin
, Time tm
,
496 Atom
*types
, unsigned long count
)
501 XDNDDATA
*current
, *next
;
502 BOOL haveHDROP
= FALSE
;
504 TRACE("count(%ld)\n", count
);
506 X11DRV_XDND_FreeDragDropOp(); /* Clear previously cached data */
508 for (i
= 0; i
< count
; i
++)
513 TRACE("requesting atom %ld from xwin %ld\n", types
[i
], xwin
);
518 XConvertSelection(display
, x11drv_atom(XdndSelection
), types
[i
],
519 x11drv_atom(XdndTarget
), xwin
, /*tm*/CurrentTime
);
522 * Wait for SelectionNotify
524 for (j
= 0; j
< SELECTION_RETRIES
; j
++)
526 res
= XCheckTypedWindowEvent(display
, xwin
, SelectionNotify
, &xe
);
527 if (res
&& xe
.xselection
.selection
== x11drv_atom(XdndSelection
)) break;
529 usleep(SELECTION_WAIT
);
532 if (xe
.xselection
.property
== None
)
535 contents
= X11DRV_CLIPBOARD_ImportSelection(display
, types
[i
], xwin
, x11drv_atom(XdndTarget
), &windowsFormat
);
537 X11DRV_XDND_InsertXDNDData(types
[i
], windowsFormat
, contents
);
540 /* On Windows when there is a CF_HDROP, there are no other CF_ formats.
541 * foobar2000 relies on this (spaces -> %20's without it).
543 LIST_FOR_EACH_ENTRY(current
, &xdndData
, XDNDDATA
, entry
)
545 if (current
->cf_win
== CF_HDROP
)
553 LIST_FOR_EACH_ENTRY_SAFE(current
, next
, &xdndData
, XDNDDATA
, entry
)
555 if (current
->cf_win
!= CF_HDROP
&& current
->cf_win
< CF_MAX
)
557 list_remove(¤t
->entry
);
558 GlobalFree(current
->contents
);
559 HeapFree(GetProcessHeap(), 0, current
);
566 /**************************************************************************
567 * X11DRV_XDND_InsertXDNDData
569 * Cache available XDND property
571 static void X11DRV_XDND_InsertXDNDData(int property
, int format
, HANDLE contents
)
573 LPXDNDDATA current
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(XDNDDATA
));
577 EnterCriticalSection(&xdnd_cs
);
578 current
->cf_xdnd
= property
;
579 current
->cf_win
= format
;
580 current
->contents
= contents
;
581 list_add_tail(&xdndData
, ¤t
->entry
);
582 LeaveCriticalSection(&xdnd_cs
);
587 /**************************************************************************
588 * X11DRV_XDND_HasHDROP
590 static BOOL
X11DRV_XDND_HasHDROP(void)
592 LPXDNDDATA current
= NULL
;
595 EnterCriticalSection(&xdnd_cs
);
597 /* Find CF_HDROP type if any */
598 LIST_FOR_EACH_ENTRY(current
, &xdndData
, XDNDDATA
, entry
)
600 if (current
->cf_win
== CF_HDROP
)
607 LeaveCriticalSection(&xdnd_cs
);
612 /**************************************************************************
613 * X11DRV_XDND_SendDropFiles
615 static HRESULT
X11DRV_XDND_SendDropFiles(HWND hwnd
)
618 LPXDNDDATA current
= NULL
;
621 EnterCriticalSection(&xdnd_cs
);
623 LIST_FOR_EACH_ENTRY(current
, &xdndData
, XDNDDATA
, entry
)
625 if (current
->cf_win
== CF_HDROP
)
633 HGLOBAL dropHandle
= GlobalAlloc(GMEM_FIXED
, GlobalSize(current
->contents
));
636 DROPFILES
*lpDrop
= GlobalLock(dropHandle
);
637 memcpy(lpDrop
, GlobalLock(current
->contents
), GlobalSize(current
->contents
));
638 GlobalUnlock(current
->contents
);
639 lpDrop
->pt
.x
= XDNDxy
.x
;
640 lpDrop
->pt
.y
= XDNDxy
.y
;
641 lpDrop
->fNC
= !ScreenToClient(hwnd
, &lpDrop
->pt
);
642 TRACE("Sending WM_DROPFILES: hWnd=0x%p, fNC=%d, x=%d, y=%d, files=%p(%s)\n", hwnd
,
643 lpDrop
->fNC
, lpDrop
->pt
.x
, lpDrop
->pt
.y
, ((char*)lpDrop
) + lpDrop
->pFiles
,
644 debugstr_w((WCHAR
*)(((char*)lpDrop
) + lpDrop
->pFiles
)));
645 GlobalUnlock(dropHandle
);
646 if (PostMessageW(hwnd
, WM_DROPFILES
, (WPARAM
)dropHandle
, 0))
650 hr
= HRESULT_FROM_WIN32(GetLastError());
651 GlobalFree(dropHandle
);
655 hr
= HRESULT_FROM_WIN32(GetLastError());
660 LeaveCriticalSection(&xdnd_cs
);
666 /**************************************************************************
667 * X11DRV_XDND_FreeDragDropOp
669 static void X11DRV_XDND_FreeDragDropOp(void)
676 EnterCriticalSection(&xdnd_cs
);
678 /** Free data cache */
679 LIST_FOR_EACH_ENTRY_SAFE(current
, next
, &xdndData
, XDNDDATA
, entry
)
681 list_remove(¤t
->entry
);
682 GlobalFree(current
->contents
);
683 HeapFree(GetProcessHeap(), 0, current
);
686 XDNDxy
.x
= XDNDxy
.y
= 0;
687 XDNDLastTargetWnd
= NULL
;
688 XDNDLastDropTargetWnd
= NULL
;
689 XDNDAccepted
= FALSE
;
691 LeaveCriticalSection(&xdnd_cs
);
695 /**************************************************************************
696 * X11DRV_XDND_DescribeClipboardFormat
698 static void X11DRV_XDND_DescribeClipboardFormat(int cfFormat
, char *buffer
, int size
)
700 #define D(x) case x: lstrcpynA(buffer, #x, size); return;
723 if (CF_PRIVATEFIRST
<= cfFormat
&& cfFormat
<= CF_PRIVATELAST
)
725 lstrcpynA(buffer
, "some private object", size
);
728 if (CF_GDIOBJFIRST
<= cfFormat
&& cfFormat
<= CF_GDIOBJLAST
)
730 lstrcpynA(buffer
, "some GDI object", size
);
734 GetClipboardFormatNameA(cfFormat
, buffer
, size
);
738 /* The IDataObject singleton we feed to OLE follows */
740 static HRESULT WINAPI
XDNDDATAOBJECT_QueryInterface(IDataObject
*dataObject
,
741 REFIID riid
, void **ppvObject
)
743 TRACE("(%p, %s, %p)\n", dataObject
, debugstr_guid(riid
), ppvObject
);
744 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDataObject
))
746 *ppvObject
= dataObject
;
747 IDataObject_AddRef(dataObject
);
751 return E_NOINTERFACE
;
754 static ULONG WINAPI
XDNDDATAOBJECT_AddRef(IDataObject
*dataObject
)
756 TRACE("(%p)\n", dataObject
);
760 static ULONG WINAPI
XDNDDATAOBJECT_Release(IDataObject
*dataObject
)
762 TRACE("(%p)\n", dataObject
);
766 static HRESULT WINAPI
XDNDDATAOBJECT_GetData(IDataObject
*dataObject
,
767 FORMATETC
*formatEtc
,
771 char formatDesc
[1024];
773 TRACE("(%p, %p, %p)\n", dataObject
, formatEtc
, pMedium
);
774 X11DRV_XDND_DescribeClipboardFormat(formatEtc
->cfFormat
,
775 formatDesc
, sizeof(formatDesc
));
776 TRACE("application is looking for %s\n", formatDesc
);
778 hr
= IDataObject_QueryGetData(dataObject
, formatEtc
);
782 LIST_FOR_EACH_ENTRY(current
, &xdndData
, XDNDDATA
, entry
)
784 if (current
->cf_win
== formatEtc
->cfFormat
)
786 pMedium
->tymed
= TYMED_HGLOBAL
;
787 pMedium
->u
.hGlobal
= GlobalAlloc(GMEM_FIXED
| GMEM_ZEROINIT
, GlobalSize(current
->contents
));
788 if (pMedium
->u
.hGlobal
== NULL
)
789 return E_OUTOFMEMORY
;
790 memcpy(GlobalLock(pMedium
->u
.hGlobal
), GlobalLock(current
->contents
), GlobalSize(current
->contents
));
791 GlobalUnlock(pMedium
->u
.hGlobal
);
792 GlobalUnlock(current
->contents
);
793 pMedium
->pUnkForRelease
= 0;
801 static HRESULT WINAPI
XDNDDATAOBJECT_GetDataHere(IDataObject
*dataObject
,
802 FORMATETC
*formatEtc
,
805 FIXME("(%p, %p, %p): stub\n", dataObject
, formatEtc
, pMedium
);
806 return DATA_E_FORMATETC
;
809 static HRESULT WINAPI
XDNDDATAOBJECT_QueryGetData(IDataObject
*dataObject
,
810 FORMATETC
*formatEtc
)
812 char formatDesc
[1024];
815 TRACE("(%p, %p={.tymed=0x%x, .dwAspect=%d, .cfFormat=%d}\n",
816 dataObject
, formatEtc
, formatEtc
->tymed
, formatEtc
->dwAspect
, formatEtc
->cfFormat
);
817 X11DRV_XDND_DescribeClipboardFormat(formatEtc
->cfFormat
, formatDesc
, sizeof(formatDesc
));
819 if (formatEtc
->tymed
&& !(formatEtc
->tymed
& TYMED_HGLOBAL
))
821 FIXME("only HGLOBAL medium types supported right now\n");
824 if (formatEtc
->dwAspect
!= DVASPECT_CONTENT
)
826 FIXME("only the content aspect is supported right now\n");
830 LIST_FOR_EACH_ENTRY(current
, &xdndData
, XDNDDATA
, entry
)
832 if (current
->cf_win
== formatEtc
->cfFormat
)
834 TRACE("application found %s\n", formatDesc
);
838 TRACE("application didn't find %s\n", formatDesc
);
839 return DV_E_FORMATETC
;
842 static HRESULT WINAPI
XDNDDATAOBJECT_GetCanonicalFormatEtc(IDataObject
*dataObject
,
843 FORMATETC
*formatEtc
,
844 FORMATETC
*formatEtcOut
)
846 FIXME("(%p, %p, %p): stub\n", dataObject
, formatEtc
, formatEtcOut
);
847 formatEtcOut
->ptd
= NULL
;
851 static HRESULT WINAPI
XDNDDATAOBJECT_SetData(IDataObject
*dataObject
,
852 FORMATETC
*formatEtc
,
853 STGMEDIUM
*pMedium
, BOOL fRelease
)
855 FIXME("(%p, %p, %p, %s): stub\n", dataObject
, formatEtc
,
856 pMedium
, fRelease
?"TRUE":"FALSE");
860 static HRESULT WINAPI
XDNDDATAOBJECT_EnumFormatEtc(IDataObject
*dataObject
,
862 IEnumFORMATETC
**ppEnumFormatEtc
)
867 TRACE("(%p, %u, %p)\n", dataObject
, dwDirection
, ppEnumFormatEtc
);
869 if (dwDirection
!= DATADIR_GET
)
871 FIXME("only the get direction is implemented\n");
875 count
= list_count(&xdndData
);
876 formats
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(FORMATETC
));
882 LIST_FOR_EACH_ENTRY(current
, &xdndData
, XDNDDATA
, entry
)
884 formats
[i
].cfFormat
= current
->cf_win
;
885 formats
[i
].ptd
= NULL
;
886 formats
[i
].dwAspect
= DVASPECT_CONTENT
;
887 formats
[i
].lindex
= -1;
888 formats
[i
].tymed
= TYMED_HGLOBAL
;
891 hr
= SHCreateStdEnumFmtEtc(count
, formats
, ppEnumFormatEtc
);
892 HeapFree(GetProcessHeap(), 0, formats
);
896 return E_OUTOFMEMORY
;
899 static HRESULT WINAPI
XDNDDATAOBJECT_DAdvise(IDataObject
*dataObject
,
900 FORMATETC
*formatEtc
, DWORD advf
,
901 IAdviseSink
*adviseSink
,
902 DWORD
*pdwConnection
)
904 FIXME("(%p, %p, %u, %p, %p): stub\n", dataObject
, formatEtc
, advf
,
905 adviseSink
, pdwConnection
);
906 return OLE_E_ADVISENOTSUPPORTED
;
909 static HRESULT WINAPI
XDNDDATAOBJECT_DUnadvise(IDataObject
*dataObject
,
912 FIXME("(%p, %u): stub\n", dataObject
, dwConnection
);
913 return OLE_E_ADVISENOTSUPPORTED
;
916 static HRESULT WINAPI
XDNDDATAOBJECT_EnumDAdvise(IDataObject
*dataObject
,
917 IEnumSTATDATA
**pEnumAdvise
)
919 FIXME("(%p, %p): stub\n", dataObject
, pEnumAdvise
);
920 return OLE_E_ADVISENOTSUPPORTED
;
923 static IDataObjectVtbl xdndDataObjectVtbl
=
925 XDNDDATAOBJECT_QueryInterface
,
926 XDNDDATAOBJECT_AddRef
,
927 XDNDDATAOBJECT_Release
,
928 XDNDDATAOBJECT_GetData
,
929 XDNDDATAOBJECT_GetDataHere
,
930 XDNDDATAOBJECT_QueryGetData
,
931 XDNDDATAOBJECT_GetCanonicalFormatEtc
,
932 XDNDDATAOBJECT_SetData
,
933 XDNDDATAOBJECT_EnumFormatEtc
,
934 XDNDDATAOBJECT_DAdvise
,
935 XDNDDATAOBJECT_DUnadvise
,
936 XDNDDATAOBJECT_EnumDAdvise
939 static IDataObject XDNDDataObject
= { &xdndDataObjectVtbl
};