winex11.drv: merge the clipboard and drag-and-drop import functions
Damjan Jovanovic
damjan.jov at gmail.com
Sun Apr 27 04:20:47 CDT 2014
* Merges the X selection import functions used by the clipboard and
drag-and-drop, now allowing files to be copied-and-pasted from X11
apps into Wine apps, and new types (eg. images) to be
dragged-and-dropped from X11 apps into Wine apps (instead of just
files and text like before). Also has the benefit of now allowing
drag-and-drop to use INCR for large data transfers.
* Fixes several memory leaks in xdnd.c
* Uses GlobalAlloc() instead of HeapAlloc() for STGMEDIUM's hGlobal.
* De-duplicates considerable shared code.
Damjan Jovanovic
-------------- next part --------------
diff --git a/dlls/winex11.drv/clipboard.c b/dlls/winex11.drv/clipboard.c
index 730b6c9..f4220e1 100644
--- a/dlls/winex11.drv/clipboard.c
+++ b/dlls/winex11.drv/clipboard.c
@@ -78,6 +78,7 @@
#include "windef.h"
#include "winbase.h"
+#include "shlobj.h"
#include "x11drv.h"
#include "wine/list.h"
#include "wine/debug.h"
@@ -104,29 +105,6 @@ typedef struct
UINT flags;
} CLIPBOARDINFO, *LPCLIPBOARDINFO;
-struct tagWINE_CLIPDATA; /* Forward */
-
-typedef HANDLE (*DRVEXPORTFUNC)(Display *display, Window requestor, Atom aTarget, Atom rprop,
- struct tagWINE_CLIPDATA* lpData, LPDWORD lpBytes);
-typedef HANDLE (*DRVIMPORTFUNC)(Display *d, Window w, Atom prop);
-
-typedef struct tagWINE_CLIPFORMAT {
- struct list entry;
- UINT wFormatID;
- UINT drvData;
- DRVIMPORTFUNC lpDrvImportFunc;
- DRVEXPORTFUNC lpDrvExportFunc;
-} WINE_CLIPFORMAT, *LPWINE_CLIPFORMAT;
-
-typedef struct tagWINE_CLIPDATA {
- struct list entry;
- UINT wFormatID;
- HANDLE hData;
- UINT wFlags;
- UINT drvData;
- LPWINE_CLIPFORMAT lpFormat;
-} WINE_CLIPDATA, *LPWINE_CLIPDATA;
-
#define CF_FLAG_UNOWNED 0x0001 /* cached data is not owned */
#define CF_FLAG_SYNTHESIZED 0x0002 /* Implicitly converted data */
@@ -144,6 +122,7 @@ static HANDLE X11DRV_CLIPBOARD_ImportImageBmp(Display *d, Window w, Atom prop);
static HANDLE X11DRV_CLIPBOARD_ImportXAString(Display *d, Window w, Atom prop);
static HANDLE X11DRV_CLIPBOARD_ImportUTF8(Display *d, Window w, Atom prop);
static HANDLE X11DRV_CLIPBOARD_ImportCompoundText(Display *d, Window w, Atom prop);
+static HANDLE X11DRV_CLIPBOARD_ImportTextUriList(Display *display, Window w, Atom prop);
static HANDLE X11DRV_CLIPBOARD_ExportClipboardData(Display *display, Window requestor, Atom aTarget,
Atom rprop, LPWINE_CLIPDATA lpData, LPDWORD lpBytes);
static HANDLE X11DRV_CLIPBOARD_ExportString(Display *display, Window requestor, Atom aTarget,
@@ -202,6 +181,7 @@ static const struct
{ CF_UNICODETEXT, XATOM_COMPOUND_TEXT, X11DRV_CLIPBOARD_ImportCompoundText, X11DRV_CLIPBOARD_ExportString },
{ CF_ENHMETAFILE, XATOM_WCF_ENHMETAFILE, X11DRV_CLIPBOARD_ImportEnhMetaFile, X11DRV_CLIPBOARD_ExportEnhMetaFile },
{ CF_HDROP, XATOM_WCF_HDROP, X11DRV_CLIPBOARD_ImportClipboardData, X11DRV_CLIPBOARD_ExportClipboardData },
+ { CF_HDROP, XATOM_text_uri_list, X11DRV_CLIPBOARD_ImportTextUriList, X11DRV_CLIPBOARD_ExportClipboardData},
{ CF_LOCALE, XATOM_WCF_LOCALE, X11DRV_CLIPBOARD_ImportClipboardData, X11DRV_CLIPBOARD_ExportClipboardData },
{ CF_DIBV5, XATOM_WCF_DIBV5, X11DRV_CLIPBOARD_ImportClipboardData, X11DRV_CLIPBOARD_ExportClipboardData },
{ CF_OWNERDISPLAY, XATOM_WCF_OWNERDISPLAY, X11DRV_CLIPBOARD_ImportClipboardData, X11DRV_CLIPBOARD_ExportClipboardData },
@@ -409,7 +389,7 @@ static WINE_CLIPFORMAT *register_format( UINT id, Atom prop )
/**************************************************************************
* X11DRV_CLIPBOARD_LookupProperty
*/
-static LPWINE_CLIPFORMAT X11DRV_CLIPBOARD_LookupProperty(LPWINE_CLIPFORMAT current, UINT drvData)
+LPWINE_CLIPFORMAT X11DRV_CLIPBOARD_LookupProperty(LPWINE_CLIPFORMAT current, UINT drvData)
{
for (;;)
{
@@ -1004,6 +984,90 @@ static HGLOBAL create_dib_from_bitmap(HBITMAP hBmp)
}
+/***********************************************************************
+ * uri_to_dos
+ *
+ * Converts a text/uri-list URI to DOS filename.
+ */
+static WCHAR* uri_to_dos(char *encodedURI)
+{
+ WCHAR *ret = NULL;
+ int i;
+ int j = 0;
+ char *uri = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, strlen(encodedURI) + 1);
+ if (uri == NULL)
+ return NULL;
+ for (i = 0; encodedURI[i]; ++i)
+ {
+ if (encodedURI[i] == '%')
+ {
+ if (encodedURI[i+1] && encodedURI[i+2])
+ {
+ char buffer[3];
+ int number;
+ buffer[0] = encodedURI[i+1];
+ buffer[1] = encodedURI[i+2];
+ buffer[2] = '\0';
+ sscanf(buffer, "%x", &number);
+ uri[j++] = number;
+ i += 2;
+ }
+ else
+ {
+ WARN("invalid URI encoding in %s\n", debugstr_a(encodedURI));
+ HeapFree(GetProcessHeap(), 0, uri);
+ return NULL;
+ }
+ }
+ else
+ uri[j++] = encodedURI[i];
+ }
+
+ /* Read http://www.freedesktop.org/wiki/Draganddropwarts and cry... */
+ if (strncmp(uri, "file:/", 6) == 0)
+ {
+ if (uri[6] == '/')
+ {
+ if (uri[7] == '/')
+ {
+ /* file:///path/to/file (nautilus, thunar) */
+ ret = wine_get_dos_file_name(&uri[7]);
+ }
+ else if (uri[7])
+ {
+ /* file://hostname/path/to/file (X file drag spec) */
+ char hostname[256];
+ char *path = strchr(&uri[7], '/');
+ if (path)
+ {
+ *path = '\0';
+ if (strcmp(&uri[7], "localhost") == 0)
+ {
+ *path = '/';
+ ret = wine_get_dos_file_name(path);
+ }
+ else if (gethostname(hostname, sizeof(hostname)) == 0)
+ {
+ if (strcmp(hostname, &uri[7]) == 0)
+ {
+ *path = '/';
+ ret = wine_get_dos_file_name(path);
+ }
+ }
+ }
+ }
+ }
+ else if (uri[6])
+ {
+ /* file:/path/to/file (konqueror) */
+ ret = wine_get_dos_file_name(&uri[5]);
+ }
+ }
+ HeapFree(GetProcessHeap(), 0, uri);
+ return ret;
+}
+
+
/**************************************************************************
* X11DRV_CLIPBOARD_RenderSynthesizedDIB
*
@@ -1477,6 +1541,92 @@ static HANDLE X11DRV_CLIPBOARD_ImportEnhMetaFile(Display *display, Window w, Ato
/**************************************************************************
+ * X11DRV_CLIPBOARD_ImportTextUriList
+ *
+ * Import text/uri-list.
+ */
+static HANDLE X11DRV_CLIPBOARD_ImportTextUriList(Display *display, Window w, Atom prop)
+{
+ char *uriList;
+ unsigned long len;
+ char *uri;
+ WCHAR *path;
+ WCHAR *out = NULL;
+ int size = 0;
+ int capacity = 4096;
+ int start = 0;
+ int end = 0;
+ HANDLE handle = NULL;
+
+ if (!X11DRV_CLIPBOARD_ReadProperty(display, w, prop, (LPBYTE*)&uriList, &len))
+ return 0;
+
+ out = HeapAlloc(GetProcessHeap(), 0, capacity * sizeof(WCHAR));
+ if (out == NULL)
+ return 0;
+
+ while (end < len)
+ {
+ while (end < len && uriList[end] != '\r')
+ ++end;
+ if (end < (len - 1) && uriList[end+1] != '\n')
+ {
+ WARN("URI list line doesn't end in \\r\\n\n");
+ break;
+ }
+
+ uri = HeapAlloc(GetProcessHeap(), 0, end - start + 1);
+ if (uri == NULL)
+ break;
+ lstrcpynA(uri, &uriList[start], end - start + 1);
+ path = uri_to_dos(uri);
+ TRACE("converted URI %s to DOS path %s\n", debugstr_a(uri), debugstr_w(path));
+ HeapFree(GetProcessHeap(), 0, uri);
+
+ if (path)
+ {
+ int pathSize = strlenW(path) + 1;
+ if (pathSize > capacity-size)
+ {
+ capacity = 2*capacity + pathSize;
+ out = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, out, (capacity + 1)*sizeof(WCHAR));
+ if (out == NULL)
+ goto done;
+ }
+ memcpy(&out[size], path, pathSize * sizeof(WCHAR));
+ size += pathSize;
+ done:
+ HeapFree(GetProcessHeap(), 0, path);
+ if (out == NULL)
+ break;
+ }
+
+ start = end + 2;
+ end = start;
+ }
+ if (out && end >= len)
+ {
+ DROPFILES *dropFiles;
+ handle = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, sizeof(DROPFILES) + (size + 1)*sizeof(WCHAR));
+ if (handle)
+ {
+ dropFiles = (DROPFILES*) GlobalLock(handle);
+ dropFiles->pFiles = sizeof(DROPFILES);
+ dropFiles->pt.x = 0;
+ dropFiles->pt.y = 0;
+ dropFiles->fNC = 0;
+ dropFiles->fWide = TRUE;
+ out[size] = '\0';
+ memcpy(((char*)dropFiles) + dropFiles->pFiles, out, (size + 1)*sizeof(WCHAR));
+ GlobalUnlock(handle);
+ }
+ }
+ HeapFree(GetProcessHeap(), 0, out);
+ return handle;
+}
+
+
+/**************************************************************************
* X11DRV_ImportClipbordaData
*
* Generic import clipboard data routine.
diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h
index 7a3374d..408db71 100644
--- a/dlls/winex11.drv/x11drv.h
+++ b/dlls/winex11.drv/x11drv.h
@@ -141,6 +141,31 @@ static inline void add_bounds_rect( RECT *bounds, const RECT *rect )
bounds->bottom = max( bounds->bottom, rect->bottom );
}
+struct tagWINE_CLIPDATA; /* Forward */
+
+typedef HANDLE (*DRVEXPORTFUNC)(Display *display, Window requestor, Atom aTarget, Atom rprop,
+ struct tagWINE_CLIPDATA* lpData, LPDWORD lpBytes);
+typedef HANDLE (*DRVIMPORTFUNC)(Display *d, Window w, Atom prop);
+
+typedef struct tagWINE_CLIPFORMAT {
+ struct list entry;
+ UINT wFormatID;
+ UINT drvData;
+ DRVIMPORTFUNC lpDrvImportFunc;
+ DRVEXPORTFUNC lpDrvExportFunc;
+} WINE_CLIPFORMAT, *LPWINE_CLIPFORMAT;
+
+typedef struct tagWINE_CLIPDATA {
+ struct list entry;
+ UINT wFormatID;
+ HANDLE hData;
+ UINT wFlags;
+ UINT drvData;
+ LPWINE_CLIPFORMAT lpFormat;
+} WINE_CLIPDATA, *LPWINE_CLIPDATA;
+
+LPWINE_CLIPFORMAT X11DRV_CLIPBOARD_LookupProperty(LPWINE_CLIPFORMAT current, UINT drvData) DECLSPEC_HIDDEN;
+
/* Wine driver X11 functions */
extern BOOL X11DRV_Arc( PHYSDEV dev, INT left, INT top, INT right,
diff --git a/dlls/winex11.drv/xdnd.c b/dlls/winex11.drv/xdnd.c
index 5d37495..046537f 100644
--- a/dlls/winex11.drv/xdnd.c
+++ b/dlls/winex11.drv/xdnd.c
@@ -56,8 +56,7 @@ typedef struct tagXDNDDATA
{
int cf_win;
Atom cf_xdnd;
- void *data;
- unsigned int size;
+ HANDLE handle;
struct list entry;
} XDNDDATA, *LPXDNDDATA;
@@ -71,11 +70,7 @@ static HWND XDNDLastTargetWnd;
/* might be an ancestor of XDNDLastTargetWnd */
static HWND XDNDLastDropTargetWnd;
-static void X11DRV_XDND_InsertXDNDData(int property, int format, void* data, unsigned int len);
-static int X11DRV_XDND_DeconstructTextURIList(int property, void* data, int len);
-static int X11DRV_XDND_DeconstructTextPlain(int property, void* data, int len);
-static int X11DRV_XDND_DeconstructTextHTML(int property, void* data, int len);
-static int X11DRV_XDND_MapFormat(unsigned int property, unsigned char *data, int len);
+static void X11DRV_XDND_InsertXDNDData(int property, int format, HANDLE handle);
static void X11DRV_XDND_ResolveProperty(Display *display, Window xwin, Time tm,
Atom *types, unsigned long *count);
static void X11DRV_XDND_SendDropFiles(HWND hwnd);
@@ -459,11 +454,6 @@ static void X11DRV_XDND_ResolveProperty(Display *display, Window xwin, Time tm,
unsigned int i, j;
BOOL res;
XEvent xe;
- Atom acttype;
- int actfmt;
- unsigned long bytesret, icount;
- int entries = 0;
- unsigned char* data = NULL;
XDNDDATA *current, *next;
BOOL haveHDROP = FALSE;
@@ -473,6 +463,8 @@ static void X11DRV_XDND_ResolveProperty(Display *display, Window xwin, Time tm,
for (i = 0; i < *count; i++)
{
+ WINE_CLIPFORMAT *clipFormat;
+
TRACE("requesting atom %ld from xwin %ld\n", types[i], xwin);
if (types[i] == 0)
@@ -495,11 +487,17 @@ static void X11DRV_XDND_ResolveProperty(Display *display, Window xwin, Time tm,
if (xe.xselection.property == None)
continue;
- XGetWindowProperty(display, xwin, x11drv_atom(XdndTarget), 0, 65535, FALSE,
- AnyPropertyType, &acttype, &actfmt, &icount, &bytesret, &data);
-
- entries += X11DRV_XDND_MapFormat(types[i], data, get_property_size( actfmt, icount ));
- XFree(data);
+ clipFormat = X11DRV_CLIPBOARD_LookupProperty(NULL, types[i]);
+ if (clipFormat)
+ {
+ HANDLE handle = clipFormat->lpDrvImportFunc(display, xwin, x11drv_atom(XdndTarget));
+ if (handle)
+ {
+ X11DRV_XDND_InsertXDNDData(clipFormat->drvData, clipFormat->wFormatID, handle);
+ }
+ else
+ ERR("import failed\n");
+ }
}
/* On Windows when there is a CF_HDROP, there are no other CF_ formats.
@@ -520,14 +518,11 @@ static void X11DRV_XDND_ResolveProperty(Display *display, Window xwin, Time tm,
if (current->cf_win != CF_HDROP && current->cf_win < CF_MAX)
{
list_remove(¤t->entry);
- HeapFree(GetProcessHeap(), 0, current->data);
+ GlobalFree(current->handle);
HeapFree(GetProcessHeap(), 0, current);
- --entries;
}
}
}
-
- *count = entries;
}
@@ -536,7 +531,7 @@ static void X11DRV_XDND_ResolveProperty(Display *display, Window xwin, Time tm,
*
* Cache available XDND property
*/
-static void X11DRV_XDND_InsertXDNDData(int property, int format, void* data, unsigned int len)
+static void X11DRV_XDND_InsertXDNDData(int property, int format, HANDLE handle)
{
LPXDNDDATA current = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(XDNDDATA));
@@ -545,8 +540,7 @@ static void X11DRV_XDND_InsertXDNDData(int property, int format, void* data, uns
EnterCriticalSection(&xdnd_cs);
current->cf_xdnd = property;
current->cf_win = format;
- current->data = data;
- current->size = len;
+ current->handle = handle;
list_add_tail(&xdndData, ¤t->entry);
LeaveCriticalSection(&xdnd_cs);
}
@@ -554,158 +548,6 @@ static void X11DRV_XDND_InsertXDNDData(int property, int format, void* data, uns
/**************************************************************************
- * X11DRV_XDND_MapFormat
- *
- * Map XDND MIME format to windows clipboard format.
- */
-static int X11DRV_XDND_MapFormat(unsigned int property, unsigned char *data, int len)
-{
- void* xdata;
- int count = 0;
-
- TRACE("%d: %s\n", property, data);
-
- /* Always include the raw type */
- xdata = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len);
- memcpy(xdata, data, len);
- X11DRV_XDND_InsertXDNDData(property, property, xdata, len);
- count++;
-
- if (property == x11drv_atom(text_uri_list))
- count += X11DRV_XDND_DeconstructTextURIList(property, data, len);
- else if (property == x11drv_atom(text_plain))
- count += X11DRV_XDND_DeconstructTextPlain(property, data, len);
- else if (property == x11drv_atom(text_html))
- count += X11DRV_XDND_DeconstructTextHTML(property, data, len);
-
- return count;
-}
-
-
-/**************************************************************************
- * X11DRV_XDND_DeconstructTextURIList
- *
- * Interpret text/uri-list data and add records to <dndfmt> linked list
- */
-static int X11DRV_XDND_DeconstructTextURIList(int property, void* data, int len)
-{
- char *uriList = data;
- char *uri;
- WCHAR *path;
-
- WCHAR *out = NULL;
- int size = 0;
- int capacity = 4096;
-
- int count = 0;
- int start = 0;
- int end = 0;
-
- out = HeapAlloc(GetProcessHeap(), 0, capacity * sizeof(WCHAR));
- if (out == NULL)
- return 0;
-
- while (end < len)
- {
- while (end < len && uriList[end] != '\r')
- ++end;
- if (end < (len - 1) && uriList[end+1] != '\n')
- {
- WARN("URI list line doesn't end in \\r\\n\n");
- break;
- }
-
- uri = HeapAlloc(GetProcessHeap(), 0, end - start + 1);
- if (uri == NULL)
- break;
- lstrcpynA(uri, &uriList[start], end - start + 1);
- path = X11DRV_XDND_URIToDOS(uri);
- TRACE("converted URI %s to DOS path %s\n", debugstr_a(uri), debugstr_w(path));
- HeapFree(GetProcessHeap(), 0, uri);
-
- if (path)
- {
- int pathSize = strlenW(path) + 1;
- if (pathSize > capacity-size)
- {
- capacity = 2*capacity + pathSize;
- out = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, out, (capacity + 1)*sizeof(WCHAR));
- if (out == NULL)
- goto done;
- }
- memcpy(&out[size], path, pathSize * sizeof(WCHAR));
- size += pathSize;
- done:
- HeapFree(GetProcessHeap(), 0, path);
- if (out == NULL)
- break;
- }
-
- start = end + 2;
- end = start;
- }
- if (out && end >= len)
- {
- DROPFILES *dropFiles;
- dropFiles = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DROPFILES) + (size + 1)*sizeof(WCHAR));
- if (dropFiles)
- {
- dropFiles->pFiles = sizeof(DROPFILES);
- dropFiles->pt.x = XDNDxy.x;
- dropFiles->pt.y = XDNDxy.y;
- dropFiles->fNC = 0;
- dropFiles->fWide = TRUE;
- out[size] = '\0';
- memcpy(((char*)dropFiles) + dropFiles->pFiles, out, (size + 1)*sizeof(WCHAR));
- X11DRV_XDND_InsertXDNDData(property, CF_HDROP, dropFiles, sizeof(DROPFILES) + (size + 1)*sizeof(WCHAR));
- count = 1;
- }
- }
- HeapFree(GetProcessHeap(), 0, out);
- return count;
-}
-
-
-/**************************************************************************
- * X11DRV_XDND_DeconstructTextPlain
- *
- * Interpret text/plain Data and add records to <dndfmt> linked list
- */
-static int X11DRV_XDND_DeconstructTextPlain(int property, void* data, int len)
-{
- char* dostext;
-
- /* Always supply plain text */
- X11DRV_XDND_UnixToDos(&dostext, data, len);
- X11DRV_XDND_InsertXDNDData(property, CF_TEXT, dostext, strlen(dostext));
-
- TRACE("CF_TEXT (%d): %s\n", CF_TEXT, dostext);
-
- return 1;
-}
-
-
-/**************************************************************************
- * X11DRV_XDND_DeconstructTextHTML
- *
- * Interpret text/html data and add records to <dndfmt> linked list
- */
-static int X11DRV_XDND_DeconstructTextHTML(int property, void* data, int len)
-{
- char* dostext;
-
- X11DRV_XDND_UnixToDos(&dostext, data, len);
-
- X11DRV_XDND_InsertXDNDData(property,
- RegisterClipboardFormatA("UniformResourceLocator"), dostext, strlen(dostext));
-
- TRACE("UniformResourceLocator: %s\n", dostext);
-
- return 1;
-}
-
-
-/**************************************************************************
* X11DRV_XDND_SendDropFiles
*/
static void X11DRV_XDND_SendDropFiles(HWND hwnd)
@@ -727,7 +569,7 @@ static void X11DRV_XDND_SendDropFiles(HWND hwnd)
if (found)
{
- DROPFILES *lpDrop = current->data;
+ DROPFILES *lpDrop = GlobalLock(current->handle);
if (lpDrop)
{
@@ -738,6 +580,7 @@ static void X11DRV_XDND_SendDropFiles(HWND hwnd)
((char*)lpDrop) + lpDrop->pFiles, debugstr_w((WCHAR*)(((char*)lpDrop) + lpDrop->pFiles)));
PostMessageW(hwnd, WM_DROPFILES, (WPARAM)lpDrop, 0L);
+ GlobalUnlock(current->handle);
}
}
@@ -761,6 +604,7 @@ static void X11DRV_XDND_FreeDragDropOp(void)
LIST_FOR_EACH_ENTRY_SAFE(current, next, &xdndData, XDNDDATA, entry)
{
list_remove(¤t->entry);
+ GlobalFree(current->handle);
HeapFree(GetProcessHeap(), 0, current);
}
@@ -773,122 +617,6 @@ static void X11DRV_XDND_FreeDragDropOp(void)
}
-
-/**************************************************************************
- * X11DRV_XDND_UnixToDos
- */
-static unsigned int X11DRV_XDND_UnixToDos(char** lpdest, char* lpsrc, int len)
-{
- int i;
- unsigned int destlen, lines;
-
- for (i = 0, lines = 0; i <= len; i++)
- {
- if (lpsrc[i] == '\n')
- lines++;
- }
-
- destlen = len + lines + 1;
-
- if (lpdest)
- {
- char* lpstr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, destlen);
- for (i = 0, lines = 0; i <= len; i++)
- {
- if (lpsrc[i] == '\n')
- lpstr[++lines + i] = '\r';
- lpstr[lines + i] = lpsrc[i];
- }
-
- *lpdest = lpstr;
- }
-
- return lines;
-}
-
-
-/**************************************************************************
- * X11DRV_XDND_URIToDOS
- */
-static WCHAR* X11DRV_XDND_URIToDOS(char *encodedURI)
-{
- WCHAR *ret = NULL;
- int i;
- int j = 0;
- char *uri = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, strlen(encodedURI) + 1);
- if (uri == NULL)
- return NULL;
- for (i = 0; encodedURI[i]; ++i)
- {
- if (encodedURI[i] == '%')
- {
- if (encodedURI[i+1] && encodedURI[i+2])
- {
- char buffer[3];
- int number;
- buffer[0] = encodedURI[i+1];
- buffer[1] = encodedURI[i+2];
- buffer[2] = '\0';
- sscanf(buffer, "%x", &number);
- uri[j++] = number;
- i += 2;
- }
- else
- {
- WARN("invalid URI encoding in %s\n", debugstr_a(encodedURI));
- HeapFree(GetProcessHeap(), 0, uri);
- return NULL;
- }
- }
- else
- uri[j++] = encodedURI[i];
- }
-
- /* Read http://www.freedesktop.org/wiki/Draganddropwarts and cry... */
- if (strncmp(uri, "file:/", 6) == 0)
- {
- if (uri[6] == '/')
- {
- if (uri[7] == '/')
- {
- /* file:///path/to/file (nautilus, thunar) */
- ret = wine_get_dos_file_name(&uri[7]);
- }
- else if (uri[7])
- {
- /* file://hostname/path/to/file (X file drag spec) */
- char hostname[256];
- char *path = strchr(&uri[7], '/');
- if (path)
- {
- *path = '\0';
- if (strcmp(&uri[7], "localhost") == 0)
- {
- *path = '/';
- ret = wine_get_dos_file_name(path);
- }
- else if (gethostname(hostname, sizeof(hostname)) == 0)
- {
- if (strcmp(hostname, &uri[7]) == 0)
- {
- *path = '/';
- ret = wine_get_dos_file_name(path);
- }
- }
- }
- }
- }
- else if (uri[6])
- {
- /* file:/path/to/file (konqueror) */
- ret = wine_get_dos_file_name(&uri[5]);
- }
- }
- HeapFree(GetProcessHeap(), 0, uri);
- return ret;
-}
-
-
/**************************************************************************
* X11DRV_XDND_DescribeClipboardFormat
*/
@@ -981,10 +709,12 @@ static HRESULT WINAPI XDNDDATAOBJECT_GetData(IDataObject *dataObject,
if (current->cf_win == formatEtc->cfFormat)
{
pMedium->tymed = TYMED_HGLOBAL;
- pMedium->u.hGlobal = HeapAlloc(GetProcessHeap(), 0, current->size);
+ pMedium->u.hGlobal = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, GlobalSize(current->handle));
if (pMedium->u.hGlobal == NULL)
return E_OUTOFMEMORY;
- memcpy(pMedium->u.hGlobal, current->data, current->size);
+ memcpy(GlobalLock(pMedium->u.hGlobal), GlobalLock(current->handle), GlobalSize(current->handle));
+ GlobalUnlock(pMedium->u.hGlobal);
+ GlobalUnlock(current->handle);
pMedium->pUnkForRelease = 0;
return S_OK;
}
--------------1.8.0--
More information about the wine-patches
mailing list