winex11.drv: Don't join INCR data until the transfer finishes.

This commit is contained in:
Vincent Povirk 2013-01-14 13:35:53 -06:00 committed by Alexandre Julliard
parent a71443a884
commit 9dcc21e3e7
1 changed files with 54 additions and 14 deletions

View File

@ -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;