mshtml: Implement MediaQueryList's addListener method.
[wine.git] / dlls / winex11.drv / xdnd.c
blob86a28ad7bb6344796b8d99aa356ed887ae236a36
1 /*
2 * XDND handler code
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
22 #define COBJMACROS
23 #define NONAMELESSUNION
25 #include "x11drv_dll.h"
26 #include "shellapi.h"
27 #include "shlobj.h"
29 #include "wine/debug.h"
30 #include "wine/list.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(xdnd);
34 static struct format_entry *xdnd_formats, *xdnd_formats_end;
35 static POINT XDNDxy = { 0, 0 };
36 static IDataObject XDNDDataObject;
37 static BOOL XDNDAccepted = FALSE;
38 static DWORD XDNDDropEffect = DROPEFFECT_NONE;
39 /* the last window the mouse was over */
40 static HWND XDNDLastTargetWnd;
41 /* might be an ancestor of XDNDLastTargetWnd */
42 static HWND XDNDLastDropTargetWnd;
44 static BOOL X11DRV_XDND_HasHDROP(void);
45 static HRESULT X11DRV_XDND_SendDropFiles(HWND hwnd);
46 static void X11DRV_XDND_FreeDragDropOp(void);
48 static CRITICAL_SECTION xdnd_cs;
49 static CRITICAL_SECTION_DEBUG critsect_debug =
51 0, 0, &xdnd_cs,
52 { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
53 0, 0, { (DWORD_PTR)(__FILE__ ": xdnd_cs") }
55 static CRITICAL_SECTION xdnd_cs = { &critsect_debug, -1, 0, 0, 0, 0 };
58 static struct format_entry *next_format( struct format_entry *entry )
60 return (struct format_entry *)&entry->data[(entry->size + 7) & ~7];
64 /* Based on functions in dlls/ole32/ole2.c */
65 static HANDLE get_droptarget_local_handle(HWND hwnd)
67 static const WCHAR prop_marshalleddroptarget[] =
68 {'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};
69 HANDLE handle;
70 HANDLE local_handle = 0;
72 handle = GetPropW(hwnd, prop_marshalleddroptarget);
73 if (handle)
75 DWORD pid;
76 HANDLE process;
78 GetWindowThreadProcessId(hwnd, &pid);
79 process = OpenProcess(PROCESS_DUP_HANDLE, FALSE, pid);
80 if (process)
82 DuplicateHandle(process, handle, GetCurrentProcess(), &local_handle, 0, FALSE, DUPLICATE_SAME_ACCESS);
83 CloseHandle(process);
86 return local_handle;
89 static HRESULT create_stream_from_map(HANDLE map, IStream **stream)
91 HRESULT hr = E_OUTOFMEMORY;
92 HGLOBAL hmem;
93 void *data;
94 MEMORY_BASIC_INFORMATION info;
96 data = MapViewOfFile(map, FILE_MAP_READ, 0, 0, 0);
97 if(!data) return hr;
99 VirtualQuery(data, &info, sizeof(info));
100 TRACE("size %d\n", (int)info.RegionSize);
102 hmem = GlobalAlloc(GMEM_MOVEABLE, info.RegionSize);
103 if(hmem)
105 memcpy(GlobalLock(hmem), data, info.RegionSize);
106 GlobalUnlock(hmem);
107 hr = CreateStreamOnHGlobal(hmem, TRUE, stream);
109 UnmapViewOfFile(data);
110 return hr;
113 static IDropTarget* get_droptarget_pointer(HWND hwnd)
115 IDropTarget *droptarget = NULL;
116 HANDLE map;
117 IStream *stream;
119 map = get_droptarget_local_handle(hwnd);
120 if(!map) return NULL;
122 if(SUCCEEDED(create_stream_from_map(map, &stream)))
124 CoUnmarshalInterface(stream, &IID_IDropTarget, (void**)&droptarget);
125 IStream_Release(stream);
127 CloseHandle(map);
128 return droptarget;
132 /* Recursively searches for a window on given coordinates in a drag&drop specific manner.
134 * Don't use WindowFromPoint instead, because it omits the STATIC and transparent
135 * windows, but they can be a valid drop targets if have WS_EX_ACCEPTFILES set.
137 static HWND window_from_point_dnd(HWND hwnd, POINT point)
139 HWND child;
140 ScreenToClient(hwnd, &point);
141 while ((child = ChildWindowFromPointEx(hwnd, point, CWP_SKIPDISABLED | CWP_SKIPINVISIBLE)) && child != hwnd)
143 MapWindowPoints(hwnd, child, &point, 1);
144 hwnd = child;
147 return hwnd;
150 /* Returns the first window down the hierarchy that has WS_EX_ACCEPTFILES set or
151 * returns NULL, if such window does not exists.
153 static HWND window_accepting_files(HWND hwnd)
155 while (hwnd && !(GetWindowLongW(hwnd, GWL_EXSTYLE) & WS_EX_ACCEPTFILES))
156 /* MUST to be GetParent, not GetAncestor, because the owner window
157 * (with WS_EX_ACCEPTFILES) of a window with WS_POPUP is a valid
158 * drop target. GetParent works exactly this way!
160 hwnd = GetParent(hwnd);
161 return hwnd;
164 /**************************************************************************
165 * x11drv_dnd_position_event
167 * Handle an XdndPosition event.
169 NTSTATUS WINAPI x11drv_dnd_position_event( void *arg, ULONG size )
171 struct dnd_position_event_params *params = arg;
172 int accept = 0; /* Assume we're not accepting */
173 IDropTarget *dropTarget = NULL;
174 DWORD effect = params->effect;
175 POINTL pointl = { .x = params->point.x, .y = params->point.y };
176 HWND targetWindow;
177 HRESULT hr;
179 XDNDxy = params->point;
180 targetWindow = window_from_point_dnd( UlongToHandle( params->hwnd ), XDNDxy );
182 if (!XDNDAccepted || XDNDLastTargetWnd != targetWindow)
184 /* Notify OLE of DragEnter. Result determines if we accept */
185 HWND dropTargetWindow;
187 if (XDNDAccepted && XDNDLastDropTargetWnd)
189 dropTarget = get_droptarget_pointer(XDNDLastDropTargetWnd);
190 if (dropTarget)
192 hr = IDropTarget_DragLeave(dropTarget);
193 if (FAILED(hr))
194 WARN("IDropTarget_DragLeave failed, error 0x%08lx\n", hr);
195 IDropTarget_Release(dropTarget);
198 dropTargetWindow = targetWindow;
201 dropTarget = get_droptarget_pointer(dropTargetWindow);
202 } while (dropTarget == NULL && (dropTargetWindow = GetParent(dropTargetWindow)) != NULL);
203 XDNDLastTargetWnd = targetWindow;
204 XDNDLastDropTargetWnd = dropTargetWindow;
205 if (dropTarget)
207 DWORD effect_ignore = effect;
208 hr = IDropTarget_DragEnter(dropTarget, &XDNDDataObject,
209 MK_LBUTTON, pointl, &effect_ignore);
210 if (hr == S_OK)
212 XDNDAccepted = TRUE;
213 TRACE("the application accepted the drop (effect = %ld)\n", effect_ignore);
215 else
217 XDNDAccepted = FALSE;
218 WARN("IDropTarget_DragEnter failed, error 0x%08lx\n", hr);
220 IDropTarget_Release(dropTarget);
223 if (XDNDAccepted && XDNDLastTargetWnd == targetWindow)
225 /* If drag accepted notify OLE of DragOver */
226 dropTarget = get_droptarget_pointer(XDNDLastDropTargetWnd);
227 if (dropTarget)
229 hr = IDropTarget_DragOver(dropTarget, MK_LBUTTON, pointl, &effect);
230 if (hr == S_OK)
231 XDNDDropEffect = effect;
232 else
233 WARN("IDropTarget_DragOver failed, error 0x%08lx\n", hr);
234 IDropTarget_Release(dropTarget);
238 if (XDNDAccepted)
239 accept = 1;
240 else
242 /* fallback search for window able to accept these files. */
244 if (window_accepting_files(targetWindow) && X11DRV_XDND_HasHDROP())
246 accept = 1;
247 effect = DROPEFFECT_COPY;
251 return accept ? effect : 0;
254 NTSTATUS x11drv_dnd_drop_event( UINT arg )
256 IDropTarget *dropTarget;
257 DWORD effect = XDNDDropEffect;
258 int accept = 0; /* Assume we're not accepting */
259 BOOL drop_file = TRUE;
261 /* Notify OLE of Drop */
262 if (XDNDAccepted)
264 dropTarget = get_droptarget_pointer(XDNDLastDropTargetWnd);
265 if (dropTarget && effect!=DROPEFFECT_NONE)
267 HRESULT hr;
268 POINTL pointl;
270 pointl.x = XDNDxy.x;
271 pointl.y = XDNDxy.y;
272 hr = IDropTarget_Drop(dropTarget, &XDNDDataObject, MK_LBUTTON,
273 pointl, &effect);
274 if (hr == S_OK)
276 if (effect != DROPEFFECT_NONE)
278 TRACE("drop succeeded\n");
279 accept = 1;
280 drop_file = FALSE;
282 else
283 TRACE("the application refused the drop\n");
285 else if (FAILED(hr))
286 WARN("drop failed, error 0x%08lx\n", hr);
287 else
289 WARN("drop returned 0x%08lx\n", hr);
290 drop_file = FALSE;
292 IDropTarget_Release(dropTarget);
294 else if (dropTarget)
296 HRESULT hr = IDropTarget_DragLeave(dropTarget);
297 if (FAILED(hr))
298 WARN("IDropTarget_DragLeave failed, error 0x%08lx\n", hr);
299 IDropTarget_Release(dropTarget);
303 if (drop_file)
305 /* Only send WM_DROPFILES if Drop didn't succeed or DROPEFFECT_NONE was set.
306 * Doing both causes winamp to duplicate the dropped files (#29081) */
308 HWND hwnd_drop = window_accepting_files(window_from_point_dnd( UlongToHandle(arg), XDNDxy ));
310 if (hwnd_drop && X11DRV_XDND_HasHDROP())
312 HRESULT hr = X11DRV_XDND_SendDropFiles(hwnd_drop);
313 if (SUCCEEDED(hr))
315 accept = 1;
316 effect = DROPEFFECT_COPY;
321 TRACE("effectRequested(0x%lx) accept(%d) performed(0x%lx) at x(%ld),y(%ld)\n",
322 XDNDDropEffect, accept, effect, XDNDxy.x, XDNDxy.y);
324 return accept ? effect : 0;
327 /**************************************************************************
328 * x11drv_dnd_leave_event
330 * Handle an XdndLeave event.
332 NTSTATUS x11drv_dnd_leave_event( UINT arg )
334 IDropTarget *dropTarget;
336 TRACE("DND Operation canceled\n");
338 /* Notify OLE of DragLeave */
339 if (XDNDAccepted)
341 dropTarget = get_droptarget_pointer(XDNDLastDropTargetWnd);
342 if (dropTarget)
344 HRESULT hr = IDropTarget_DragLeave(dropTarget);
345 if (FAILED(hr))
346 WARN("IDropTarget_DragLeave failed, error 0x%08lx\n", hr);
347 IDropTarget_Release(dropTarget);
351 X11DRV_XDND_FreeDragDropOp();
352 return 0;
356 /**************************************************************************
357 * x11drv_dnd_enter_event
359 NTSTATUS WINAPI x11drv_dnd_enter_event( void *params, ULONG size )
361 struct format_entry *formats = params;
362 XDNDAccepted = FALSE;
363 X11DRV_XDND_FreeDragDropOp(); /* Clear previously cached data */
365 if ((xdnd_formats = HeapAlloc( GetProcessHeap(), 0, size )))
367 memcpy( xdnd_formats, formats, size );
368 xdnd_formats_end = (struct format_entry *)((char *)xdnd_formats + size);
370 return 0;
374 /**************************************************************************
375 * X11DRV_XDND_HasHDROP
377 static BOOL X11DRV_XDND_HasHDROP(void)
379 struct format_entry *iter;
380 BOOL found = FALSE;
382 EnterCriticalSection(&xdnd_cs);
384 /* Find CF_HDROP type if any */
385 for (iter = xdnd_formats; iter < xdnd_formats_end; iter = next_format( iter ))
387 if (iter->format == CF_HDROP)
389 found = TRUE;
390 break;
394 LeaveCriticalSection(&xdnd_cs);
396 return found;
399 /**************************************************************************
400 * X11DRV_XDND_SendDropFiles
402 static HRESULT X11DRV_XDND_SendDropFiles(HWND hwnd)
404 struct format_entry *iter;
405 HRESULT hr;
406 BOOL found = FALSE;
408 EnterCriticalSection(&xdnd_cs);
410 for (iter = xdnd_formats; iter < xdnd_formats_end; iter = next_format( iter ))
412 if (iter->format == CF_HDROP)
414 found = TRUE;
415 break;
418 if (found)
420 HGLOBAL dropHandle = GlobalAlloc(GMEM_FIXED, iter->size);
421 if (dropHandle)
423 RECT rect;
424 DROPFILES *lpDrop = GlobalLock(dropHandle);
425 memcpy(lpDrop, iter->data, iter->size);
426 lpDrop->pt.x = XDNDxy.x;
427 lpDrop->pt.y = XDNDxy.y;
428 lpDrop->fNC = !(ScreenToClient(hwnd, &lpDrop->pt) &&
429 GetClientRect(hwnd, &rect) &&
430 PtInRect(&rect, lpDrop->pt));
431 TRACE("Sending WM_DROPFILES: hWnd=0x%p, fNC=%d, x=%ld, y=%ld, files=%p(%s)\n", hwnd,
432 lpDrop->fNC, lpDrop->pt.x, lpDrop->pt.y, ((char*)lpDrop) + lpDrop->pFiles,
433 debugstr_w((WCHAR*)(((char*)lpDrop) + lpDrop->pFiles)));
434 GlobalUnlock(dropHandle);
435 if (PostMessageW(hwnd, WM_DROPFILES, (WPARAM)dropHandle, 0))
436 hr = S_OK;
437 else
439 hr = HRESULT_FROM_WIN32(GetLastError());
440 GlobalFree(dropHandle);
443 else
444 hr = HRESULT_FROM_WIN32(GetLastError());
446 else
447 hr = E_FAIL;
449 LeaveCriticalSection(&xdnd_cs);
451 return hr;
455 /**************************************************************************
456 * X11DRV_XDND_FreeDragDropOp
458 static void X11DRV_XDND_FreeDragDropOp(void)
460 TRACE("\n");
462 EnterCriticalSection(&xdnd_cs);
464 HeapFree( GetProcessHeap(), 0, xdnd_formats );
465 xdnd_formats = xdnd_formats_end = NULL;
467 XDNDxy.x = XDNDxy.y = 0;
468 XDNDLastTargetWnd = NULL;
469 XDNDLastDropTargetWnd = NULL;
470 XDNDAccepted = FALSE;
472 LeaveCriticalSection(&xdnd_cs);
476 /**************************************************************************
477 * X11DRV_XDND_DescribeClipboardFormat
479 static void X11DRV_XDND_DescribeClipboardFormat(int cfFormat, char *buffer, int size)
481 #define D(x) case x: lstrcpynA(buffer, #x, size); return;
482 switch (cfFormat)
484 D(CF_TEXT)
485 D(CF_BITMAP)
486 D(CF_METAFILEPICT)
487 D(CF_SYLK)
488 D(CF_DIF)
489 D(CF_TIFF)
490 D(CF_OEMTEXT)
491 D(CF_DIB)
492 D(CF_PALETTE)
493 D(CF_PENDATA)
494 D(CF_RIFF)
495 D(CF_WAVE)
496 D(CF_UNICODETEXT)
497 D(CF_ENHMETAFILE)
498 D(CF_HDROP)
499 D(CF_LOCALE)
500 D(CF_DIBV5)
502 #undef D
504 if (CF_PRIVATEFIRST <= cfFormat && cfFormat <= CF_PRIVATELAST)
506 lstrcpynA(buffer, "some private object", size);
507 return;
509 if (CF_GDIOBJFIRST <= cfFormat && cfFormat <= CF_GDIOBJLAST)
511 lstrcpynA(buffer, "some GDI object", size);
512 return;
515 GetClipboardFormatNameA(cfFormat, buffer, size);
519 /* The IDataObject singleton we feed to OLE follows */
521 static HRESULT WINAPI XDNDDATAOBJECT_QueryInterface(IDataObject *dataObject,
522 REFIID riid, void **ppvObject)
524 TRACE("(%p, %s, %p)\n", dataObject, debugstr_guid(riid), ppvObject);
525 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDataObject))
527 *ppvObject = dataObject;
528 IDataObject_AddRef(dataObject);
529 return S_OK;
531 *ppvObject = NULL;
532 return E_NOINTERFACE;
535 static ULONG WINAPI XDNDDATAOBJECT_AddRef(IDataObject *dataObject)
537 TRACE("(%p)\n", dataObject);
538 return 2;
541 static ULONG WINAPI XDNDDATAOBJECT_Release(IDataObject *dataObject)
543 TRACE("(%p)\n", dataObject);
544 return 1;
547 static HRESULT WINAPI XDNDDATAOBJECT_GetData(IDataObject *dataObject,
548 FORMATETC *formatEtc,
549 STGMEDIUM *pMedium)
551 HRESULT hr;
552 char formatDesc[1024];
554 TRACE("(%p, %p, %p)\n", dataObject, formatEtc, pMedium);
555 X11DRV_XDND_DescribeClipboardFormat(formatEtc->cfFormat,
556 formatDesc, sizeof(formatDesc));
557 TRACE("application is looking for %s\n", formatDesc);
559 hr = IDataObject_QueryGetData(dataObject, formatEtc);
560 if (SUCCEEDED(hr))
562 struct format_entry *iter;
564 for (iter = xdnd_formats; iter < xdnd_formats_end; iter = next_format( iter ))
566 if (iter->format == formatEtc->cfFormat)
568 pMedium->tymed = TYMED_HGLOBAL;
569 pMedium->u.hGlobal = GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT, iter->size);
570 if (pMedium->u.hGlobal == NULL)
571 return E_OUTOFMEMORY;
572 memcpy(GlobalLock(pMedium->u.hGlobal), iter->data, iter->size);
573 GlobalUnlock(pMedium->u.hGlobal);
574 pMedium->pUnkForRelease = 0;
575 return S_OK;
579 return hr;
582 static HRESULT WINAPI XDNDDATAOBJECT_GetDataHere(IDataObject *dataObject,
583 FORMATETC *formatEtc,
584 STGMEDIUM *pMedium)
586 FIXME("(%p, %p, %p): stub\n", dataObject, formatEtc, pMedium);
587 return DATA_E_FORMATETC;
590 static HRESULT WINAPI XDNDDATAOBJECT_QueryGetData(IDataObject *dataObject,
591 FORMATETC *formatEtc)
593 struct format_entry *iter;
594 char formatDesc[1024];
596 TRACE("(%p, %p={.tymed=0x%lx, .dwAspect=%ld, .cfFormat=%d}\n",
597 dataObject, formatEtc, formatEtc->tymed, formatEtc->dwAspect, formatEtc->cfFormat);
598 X11DRV_XDND_DescribeClipboardFormat(formatEtc->cfFormat, formatDesc, sizeof(formatDesc));
600 if (formatEtc->tymed && !(formatEtc->tymed & TYMED_HGLOBAL))
602 FIXME("only HGLOBAL medium types supported right now\n");
603 return DV_E_TYMED;
605 /* Windows Explorer ignores .dwAspect and .lindex for CF_HDROP,
606 * and we have no way to implement them on XDnD anyway, so ignore them too.
609 for (iter = xdnd_formats; iter < xdnd_formats_end; iter = next_format( iter ))
611 if (iter->format == formatEtc->cfFormat)
613 TRACE("application found %s\n", formatDesc);
614 return S_OK;
617 TRACE("application didn't find %s\n", formatDesc);
618 return DV_E_FORMATETC;
621 static HRESULT WINAPI XDNDDATAOBJECT_GetCanonicalFormatEtc(IDataObject *dataObject,
622 FORMATETC *formatEtc,
623 FORMATETC *formatEtcOut)
625 FIXME("(%p, %p, %p): stub\n", dataObject, formatEtc, formatEtcOut);
626 formatEtcOut->ptd = NULL;
627 return E_NOTIMPL;
630 static HRESULT WINAPI XDNDDATAOBJECT_SetData(IDataObject *dataObject,
631 FORMATETC *formatEtc,
632 STGMEDIUM *pMedium, BOOL fRelease)
634 FIXME("(%p, %p, %p, %s): stub\n", dataObject, formatEtc,
635 pMedium, fRelease?"TRUE":"FALSE");
636 return E_NOTIMPL;
639 static HRESULT WINAPI XDNDDATAOBJECT_EnumFormatEtc(IDataObject *dataObject,
640 DWORD dwDirection,
641 IEnumFORMATETC **ppEnumFormatEtc)
643 struct format_entry *iter;
644 DWORD count = 0;
645 FORMATETC *formats;
647 TRACE("(%p, %lu, %p)\n", dataObject, dwDirection, ppEnumFormatEtc);
649 if (dwDirection != DATADIR_GET)
651 FIXME("only the get direction is implemented\n");
652 return E_NOTIMPL;
655 for (iter = xdnd_formats; iter < xdnd_formats_end; iter = next_format( iter )) count++;
657 formats = HeapAlloc(GetProcessHeap(), 0, count * sizeof(FORMATETC));
658 if (formats)
660 DWORD i = 0;
661 HRESULT hr;
662 for (iter = xdnd_formats; iter < xdnd_formats_end; iter = next_format( iter ))
664 formats[i].cfFormat = iter->format;
665 formats[i].ptd = NULL;
666 formats[i].dwAspect = DVASPECT_CONTENT;
667 formats[i].lindex = -1;
668 formats[i].tymed = TYMED_HGLOBAL;
669 i++;
671 hr = SHCreateStdEnumFmtEtc(count, formats, ppEnumFormatEtc);
672 HeapFree(GetProcessHeap(), 0, formats);
673 return hr;
675 else
676 return E_OUTOFMEMORY;
679 static HRESULT WINAPI XDNDDATAOBJECT_DAdvise(IDataObject *dataObject,
680 FORMATETC *formatEtc, DWORD advf,
681 IAdviseSink *adviseSink,
682 DWORD *pdwConnection)
684 FIXME("(%p, %p, %lu, %p, %p): stub\n", dataObject, formatEtc, advf,
685 adviseSink, pdwConnection);
686 return OLE_E_ADVISENOTSUPPORTED;
689 static HRESULT WINAPI XDNDDATAOBJECT_DUnadvise(IDataObject *dataObject,
690 DWORD dwConnection)
692 FIXME("(%p, %lu): stub\n", dataObject, dwConnection);
693 return OLE_E_ADVISENOTSUPPORTED;
696 static HRESULT WINAPI XDNDDATAOBJECT_EnumDAdvise(IDataObject *dataObject,
697 IEnumSTATDATA **pEnumAdvise)
699 FIXME("(%p, %p): stub\n", dataObject, pEnumAdvise);
700 return OLE_E_ADVISENOTSUPPORTED;
703 static IDataObjectVtbl xdndDataObjectVtbl =
705 XDNDDATAOBJECT_QueryInterface,
706 XDNDDATAOBJECT_AddRef,
707 XDNDDATAOBJECT_Release,
708 XDNDDATAOBJECT_GetData,
709 XDNDDATAOBJECT_GetDataHere,
710 XDNDDATAOBJECT_QueryGetData,
711 XDNDDATAOBJECT_GetCanonicalFormatEtc,
712 XDNDDATAOBJECT_SetData,
713 XDNDDATAOBJECT_EnumFormatEtc,
714 XDNDDATAOBJECT_DAdvise,
715 XDNDDATAOBJECT_DUnadvise,
716 XDNDDATAOBJECT_EnumDAdvise
719 static IDataObject XDNDDataObject = { &xdndDataObjectVtbl };
721 NTSTATUS WINAPI x11drv_dnd_post_drop( void *data, ULONG size )
723 HDROP handle;
725 if ((handle = GlobalAlloc( GMEM_SHARE, size )))
727 DROPFILES *ptr = GlobalLock( handle );
728 HWND hwnd;
729 memcpy( ptr, data, size );
730 hwnd = UlongToHandle( ptr->fWide );
731 ptr->fWide = TRUE;
732 GlobalUnlock( handle );
733 PostMessageW( hwnd, WM_DROPFILES, (WPARAM)handle, 0 );
736 return 0;