Commit a71998d0 authored by Alexandre Julliard's avatar Alexandre Julliard

winex11: Fix X11DRV_CLIPBOARD_ReadProperty to read data in larger chunks and to…

winex11: Fix X11DRV_CLIPBOARD_ReadProperty to read data in larger chunks and to properly null-terminate the buffer.
parent 41ea8f0e
...@@ -72,6 +72,7 @@ ...@@ -72,6 +72,7 @@
# include <unistd.h> # include <unistd.h>
#endif #endif
#include <fcntl.h> #include <fcntl.h>
#include <limits.h>
#include <time.h> #include <time.h>
#include <assert.h> #include <assert.h>
...@@ -2006,71 +2007,55 @@ static BOOL X11DRV_CLIPBOARD_ReadProperty(Window w, Atom prop, ...@@ -2006,71 +2007,55 @@ static BOOL X11DRV_CLIPBOARD_ReadProperty(Window w, Atom prop,
Display *display = thread_display(); Display *display = thread_display();
Atom atype = AnyPropertyType; Atom atype = AnyPropertyType;
int aformat; int aformat;
unsigned long total, nitems, remain, val_cnt; unsigned long pos = 0, nitems, remain, count;
long reqlen, bwc; unsigned char *val = NULL, *buffer;
unsigned char* val;
unsigned char* buffer;
if (prop == None) if (prop == None)
return FALSE; return FALSE;
TRACE("Reading property %d from X window %d\n", TRACE("Reading property %lu from X window %lx\n", prop, w);
(unsigned int)prop, (unsigned int)w);
/* for (;;)
* First request a zero length in order to figure out the request size.
*/
wine_tsx11_lock();
if(XGetWindowProperty(display,w,prop,0,0,False, AnyPropertyType,
&atype, &aformat, &nitems, &remain, &buffer) != Success)
{
wine_tsx11_unlock();
WARN("Failed to get property size\n");
return FALSE;
}
/* Free zero length return data if any */
if (buffer)
{ {
XFree(buffer); wine_tsx11_lock();
buffer = NULL; if (XGetWindowProperty(display, w, prop, pos, INT_MAX / 4, False,
} AnyPropertyType, &atype, &aformat, &nitems, &remain, &buffer) != Success)
{
bwc = aformat/8; wine_tsx11_unlock();
reqlen = remain * bwc; WARN("Failed to read property\n");
HeapFree( GetProcessHeap(), 0, val );
TRACE("Retrieving %ld bytes\n", reqlen); return FALSE;
}
val = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, reqlen);
/* Read property in 4K blocks */ count = nitems * (aformat / 8);
for (total = 0, val_cnt = 0; remain;) if (!val) *data = HeapAlloc( GetProcessHeap(), 0, pos * sizeof(int) + count + 1 );
{ else *data = HeapReAlloc( GetProcessHeap(), 0, val, pos * sizeof(int) + count + 1 );
if (XGetWindowProperty(display, w, prop, (total / 4), 4096, False,
AnyPropertyType, &atype, &aformat, &nitems, &remain, &buffer) != Success)
{
wine_tsx11_unlock();
WARN("Failed to read property\n");
HeapFree(GetProcessHeap(), 0, val);
return FALSE;
}
bwc = aformat/8; if (!*data)
memcpy(&val[val_cnt], buffer, nitems * bwc); {
val_cnt += nitems * bwc; XFree( buffer );
total += nitems*bwc; wine_tsx11_unlock();
XFree(buffer); HeapFree( GetProcessHeap(), 0, val );
return FALSE;
}
val = *data;
memcpy( (int *)val + pos, buffer, count );
XFree( buffer );
wine_tsx11_unlock();
if (!remain)
{
*datasize = pos * sizeof(int) + count;
val[*datasize] = 0;
break;
}
pos += count / sizeof(int);
} }
/* Delete the property on the window now that we are done /* Delete the property on the window now that we are done
* This will send a PropertyNotify event to the selection owner. */ * This will send a PropertyNotify event to the selection owner. */
wine_tsx11_lock();
XDeleteProperty(display, w, prop); XDeleteProperty(display, w, prop);
wine_tsx11_unlock(); wine_tsx11_unlock();
*data = val;
*datasize = total;
return TRUE; return TRUE;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment