From 9dcc21e3e79bf4b3dcfab233fb57348112de31d5 Mon Sep 17 00:00:00 2001 From: Vincent Povirk Date: Mon, 14 Jan 2013 13:35:53 -0600 Subject: [PATCH] winex11.drv: Don't join INCR data until the transfer finishes. --- dlls/winex11.drv/clipboard.c | 68 ++++++++++++++++++++++++++++-------- 1 file changed, 54 insertions(+), 14 deletions(-) diff --git a/dlls/winex11.drv/clipboard.c b/dlls/winex11.drv/clipboard.c index 0df355a117..730b6c94d3 100644 --- a/dlls/winex11.drv/clipboard.c +++ b/dlls/winex11.drv/clipboard.c @@ -2347,6 +2347,12 @@ static BOOL X11DRV_CLIPBOARD_GetProperty(Display *display, Window w, Atom prop, } +struct clipboard_data_packet { + struct list entry; + unsigned long size; + unsigned char *data; +}; + /************************************************************************** * X11DRV_CLIPBOARD_ReadProperty * Reads the contents of the X selection property. @@ -2368,13 +2374,21 @@ static BOOL X11DRV_CLIPBOARD_ReadProperty(Display *display, Window w, Atom prop, if (atype == x11drv_atom(INCR)) { - unsigned char *buf = *data; + unsigned char *buf; unsigned long bufsize = 0; + struct list packets; + struct clipboard_data_packet *packet, *packet2; + BOOL res; + + HeapFree(GetProcessHeap(), 0, *data); + *data = NULL; + + list_init(&packets); for (;;) { int i; - unsigned char *prop_data, *tmp; + unsigned char *prop_data; unsigned long prop_size; /* Wait until PropertyNotify is received */ @@ -2392,32 +2406,58 @@ static BOOL X11DRV_CLIPBOARD_ReadProperty(Display *display, Window w, Atom prop, if (i >= SELECTION_RETRIES || !X11DRV_CLIPBOARD_GetProperty(display, w, prop, &atype, &prop_data, &prop_size)) { - HeapFree(GetProcessHeap(), 0, buf); - return FALSE; + res = FALSE; + break; } /* Retrieved entire data. */ if (prop_size == 0) { HeapFree(GetProcessHeap(), 0, prop_data); - *data = buf; - *datasize = bufsize; - return TRUE; + res = TRUE; + break; } - tmp = HeapReAlloc(GetProcessHeap(), 0, buf, bufsize + prop_size + 1); - if (!tmp) + packet = HeapAlloc(GetProcessHeap(), 0, sizeof(*packet)); + if (!packet) { - HeapFree(GetProcessHeap(), 0, buf); HeapFree(GetProcessHeap(), 0, prop_data); - return FALSE; + res = FALSE; + break; } - buf = tmp; - memcpy(buf + bufsize, prop_data, prop_size + 1); + packet->size = prop_size; + packet->data = prop_data; + list_add_tail(&packets, &packet->entry); bufsize += prop_size; - HeapFree(GetProcessHeap(), 0, prop_data); } + + if (res) + { + buf = HeapAlloc(GetProcessHeap(), 0, bufsize + 1); + if (buf) + { + unsigned long bytes_copied = 0; + *datasize = bufsize; + LIST_FOR_EACH_ENTRY( packet, &packets, struct clipboard_data_packet, entry) + { + memcpy(&buf[bytes_copied], packet->data, packet->size); + bytes_copied += packet->size; + } + buf[bufsize] = 0; + *data = buf; + } + else + res = FALSE; + } + + LIST_FOR_EACH_ENTRY_SAFE( packet, packet2, &packets, struct clipboard_data_packet, entry) + { + HeapFree(GetProcessHeap(), 0, packet->data); + HeapFree(GetProcessHeap(), 0, packet); + } + + return res; } return TRUE;