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(&current->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, &current->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(&current->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