[PATCH] winex11.drv: Use GMEM_FIXED memory for storing clipboard data.
Rafał Harabień
rafalh1992 at o2.pl
Tue Apr 19 09:16:18 CDT 2016
Tested behavior in Win 10. MSDN says clipboard uses GMEM_SHARED handles but its not true.
Some applications depends on GetClipboardData returning valid pointer to data instead of handle.
Commit fixes pasting from clipboard in Multi Theft Auto: San Andreas.
Signed-off-by: Rafał Harabień <rafalh1992 at o2.pl>
---
dlls/user32/tests/clipboard.c | 58 ++++++++++++++++++++++++++++++++
dlls/winex11.drv/clipboard.c | 77 +++++++++++++++++++++++++++++++++----------
2 files changed, 117 insertions(+), 18 deletions(-)
diff --git a/dlls/user32/tests/clipboard.c b/dlls/user32/tests/clipboard.c
index be6c9bf..7660590 100644
--- a/dlls/user32/tests/clipboard.c
+++ b/dlls/user32/tests/clipboard.c
@@ -402,6 +402,63 @@ static void test_synthesized(void)
ok(r, "gle %d\n", GetLastError());
}
+static void test_fixed_mem(void)
+{
+ HGLOBAL h, htext, htext2;
+ BOOL r;
+ HANDLE data;
+ PVOID data_ptr;
+ DWORD format_id;
+
+ htext = create_text();
+ htext2 = create_text();
+
+ r = OpenClipboard(NULL);
+ ok(r, "gle %d\n", GetLastError());
+ r = EmptyClipboard();
+ ok(r, "gle %d\n", GetLastError());
+ h = SetClipboardData(CF_TEXT, htext);
+ ok(h == htext, "got %p\n", h);
+ format_id = RegisterClipboardFormatA("my_cool_clipboard_format");
+ h = SetClipboardData(format_id, htext2);
+ ok(h == htext2, "got %p\n", h);
+ r = CloseClipboard();
+ ok(r, "gle %d\n", GetLastError());
+
+ r = OpenClipboard(NULL);
+ ok(r, "gle %d\n", GetLastError());
+
+ data = GetClipboardData(CF_TEXT);
+ ok(data != NULL, "couldn't get data\n");
+ data_ptr = GlobalLock(data);
+ ok(data == data_ptr, "expected fixed mem, data %p ptr %p\n", data, data_ptr);
+ GlobalUnlock(data_ptr);
+
+ data = GetClipboardData(CF_OEMTEXT);
+ ok(data != NULL, "couldn't get data\n");
+ data_ptr = GlobalLock(data);
+ ok(data == data_ptr, "expected fixed mem, data %p ptr %p\n", data, data_ptr);
+ GlobalUnlock(data_ptr);
+
+ data = GetClipboardData(CF_UNICODETEXT);
+ ok(data != NULL, "couldn't get data\n");
+ data_ptr = GlobalLock(data);
+ ok(data == data_ptr, "expected fixed mem, data %p ptr %p\n", data, data_ptr);
+ GlobalUnlock(data_ptr);
+
+ data = GetClipboardData(format_id);
+ ok(data != NULL, "couldn't get data, cf %08x\n", format_id);
+ data_ptr = GlobalLock(data);
+ ok(data == data_ptr, "expected fixed mem, data %p ptr %p\n", data, data_ptr);
+ GlobalUnlock(data_ptr);
+
+ r = EmptyClipboard();
+ ok(r, "gle %d\n", GetLastError());
+
+ r = CloseClipboard();
+ ok(r, "gle %d\n", GetLastError());
+}
+
static CRITICAL_SECTION clipboard_cs;
static HWND next_wnd;
static LRESULT CALLBACK clipboard_wnd_proc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
@@ -693,4 +750,5 @@ START_TEST(clipboard)
test_ClipboardOwner();
test_synthesized();
test_messages();
+ test_fixed_mem();
}
diff --git a/dlls/winex11.drv/clipboard.c b/dlls/winex11.drv/clipboard.c
index 5dc5e3c..9da2d24 100644
--- a/dlls/winex11.drv/clipboard.c
+++ b/dlls/winex11.drv/clipboard.c
@@ -871,8 +871,7 @@ static BOOL X11DRV_CLIPBOARD_RenderSynthesizedText(Display *display, UINT wForma
else
alloc_size = dst_chars;
- hData = GlobalAlloc(GMEM_ZEROINIT | GMEM_MOVEABLE |
- GMEM_DDESHARE, alloc_size);
+ hData = GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT, alloc_size);
lpstrT = GlobalLock(hData);
@@ -949,7 +948,7 @@ static HGLOBAL create_dib_from_bitmap(HBITMAP hBmp)
/* Allocate the packed DIB */
TRACE("\tAllocating packed DIB of size %d\n", cPackedSize);
- hPackedDIB = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE /*| GMEM_ZEROINIT*/,
+ hPackedDIB = GlobalAlloc(GMEM_FIXED /*| GMEM_ZEROINIT*/,
cPackedSize );
if ( !hPackedDIB )
{
@@ -1241,7 +1240,7 @@ static HANDLE X11DRV_CLIPBOARD_ImportXAString(Display *display, Window w, Atom p
inlcount++;
}
- if ((hText = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, cbytes + inlcount + 1)))
+ if ((hText = GlobalAlloc(GMEM_FIXED, cbytes + inlcount + 1)))
{
lpstr = GlobalLock(hText);
@@ -1298,7 +1297,7 @@ static HANDLE X11DRV_CLIPBOARD_ImportUTF8(Display *display, Window w, Atom prop)
}
count = MultiByteToWideChar(CP_UTF8, 0, lpstr, -1, NULL, 0);
- hUnicodeText = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, count * sizeof(WCHAR));
+ hUnicodeText = GlobalAlloc(GMEM_FIXED, count * sizeof(WCHAR));
if (hUnicodeText)
{
@@ -1356,7 +1355,7 @@ static HANDLE X11DRV_CLIPBOARD_ImportCompoundText(Display *display, Window w, At
TRACE("lcount = %d, destlen=%d, srcstr %s\n", lcount, destlen, srcstr[0]);
- if ((hUnicodeText = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, (destlen + lcount + 1) * sizeof(WCHAR))))
+ if ((hUnicodeText = GlobalAlloc(GMEM_FIXED, (destlen + lcount + 1) * sizeof(WCHAR))))
{
WCHAR *deststr = GlobalLock(hUnicodeText);
MultiByteToWideChar(CP_UNIXCP, 0, srcstr[0], -1, deststr, destlen);
@@ -1440,7 +1439,7 @@ static HANDLE X11DRV_CLIPBOARD_ImportXAPIXMAP(Display *display, Window w, Atom p
DWORD info_size = bitmap_info_size( info, DIB_RGB_COLORS );
BYTE *ptr;
- hClipData = GlobalAlloc( GMEM_MOVEABLE | GMEM_DDESHARE,
+ hClipData = GlobalAlloc( GMEM_FIXED,
info_size + info->bmiHeader.biSizeImage );
if (hClipData)
{
@@ -1622,7 +1621,7 @@ static HANDLE X11DRV_CLIPBOARD_ImportTextUriList(Display *display, Window w, Ato
if (out && end >= len)
{
DROPFILES *dropFiles;
- handle = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, sizeof(DROPFILES) + (size + 1)*sizeof(WCHAR));
+ handle = GlobalAlloc(GMEM_FIXED, sizeof(DROPFILES) + (size + 1)*sizeof(WCHAR));
if (handle)
{
dropFiles = (DROPFILES*) GlobalLock(handle);
@@ -1658,8 +1657,7 @@ static HANDLE X11DRV_CLIPBOARD_ImportClipboardData(Display *display, Window w, A
{
if (cbytes)
{
- /* Turn on the DDESHARE flag to enable shared 32 bit memory */
- hClipData = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, cbytes);
+ hClipData = GlobalAlloc(GMEM_FIXED, cbytes);
if (hClipData == 0)
{
HeapFree(GetProcessHeap(), 0, lpdata);
@@ -1724,7 +1722,7 @@ static HANDLE X11DRV_CLIPBOARD_ExportClipboardData(Display *display, Window requ
{
datasize = GlobalSize(lpData->hData);
- hClipData = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, datasize);
+ hClipData = GlobalAlloc(GMEM_FIXED, datasize);
if (hClipData == 0) return NULL;
if ((lpClipData = GlobalLock(hClipData)))
@@ -1949,7 +1947,7 @@ static HANDLE X11DRV_CLIPBOARD_ExportXAPIXMAP(Display *display, Window requestor
*lpBytes = sizeof(Pixmap); /* pixmap is a 32bit value */
/* Wrap pixmap so we can return a handle */
- hData = GlobalAlloc(0, *lpBytes);
+ hData = GlobalAlloc(GMEM_FIXED, *lpBytes);
lpData = GlobalLock(hData);
memcpy(lpData, &lpdata->drvData, *lpBytes);
GlobalUnlock(hData);
@@ -1992,7 +1990,7 @@ static HANDLE X11DRV_CLIPBOARD_ExportImageBmp(Display *display, Window requestor
bmpsize = sizeof(BITMAPFILEHEADER) + GlobalSize(hpackeddib);
- hbmpdata = GlobalAlloc(0, bmpsize);
+ hbmpdata = GlobalAlloc(GMEM_FIXED, bmpsize);
if (hbmpdata)
{
@@ -2138,7 +2136,7 @@ static HANDLE X11DRV_CLIPBOARD_ExportTextHtml(Display *display, Window requestor
/* export only the fragment */
htmlsize = fragmentend - fragmentstart + 1;
- hhtmldata = GlobalAlloc(0, htmlsize);
+ hhtmldata = GlobalAlloc(GMEM_FIXED, htmlsize);
if (hhtmldata)
{
@@ -2190,7 +2188,7 @@ static HANDLE X11DRV_CLIPBOARD_ExportHDROP(Display *display, Window requestor, A
ERR("Failed to export %04x format\n", lpdata->wFormatID);
return 0;
}
- hClipData = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, textUriListSize);
+ hClipData = GlobalAlloc(GMEM_FIXED, textUriListSize);
if (hClipData == NULL)
return 0;
hDrop = (HDROP) lpdata->hData;
@@ -2754,7 +2752,7 @@ static HANDLE X11DRV_CLIPBOARD_SerializeMetafile(INT wformat, HANDLE hdata, LPDW
LPMETAFILEPICT lpmfp = GlobalLock(hdata);
unsigned int size = GetMetaFileBitsEx(lpmfp->hMF, 0, NULL);
- h = GlobalAlloc(0, size + sizeof(METAFILEPICT));
+ h = GlobalAlloc(GMEM_FIXED, size + sizeof(METAFILEPICT));
if (h)
{
char *pdata = GlobalLock(h);
@@ -2773,7 +2771,7 @@ static HANDLE X11DRV_CLIPBOARD_SerializeMetafile(INT wformat, HANDLE hdata, LPDW
{
int size = GetEnhMetaFileBits(hdata, 0, NULL);
- h = GlobalAlloc(0, size);
+ h = GlobalAlloc(GMEM_FIXED, size);
if (h)
{
LPVOID pdata = GlobalLock(h);
@@ -2789,7 +2787,7 @@ static HANDLE X11DRV_CLIPBOARD_SerializeMetafile(INT wformat, HANDLE hdata, LPDW
{
if (wformat == CF_METAFILEPICT)
{
- h = GlobalAlloc(0, sizeof(METAFILEPICT));
+ h = GlobalAlloc(GMEM_FIXED, sizeof(METAFILEPICT));
if (h)
{
unsigned int wiresize;
@@ -3015,6 +3013,24 @@ void CDECL X11DRV_EmptyClipboard(void)
empty_clipboard( FALSE );
}
+static BOOLEAN is_global_mem_format(UINT wFormatID)
+{
+ if ((wFormatID >= CF_GDIOBJFIRST &&
+ wFormatID <= CF_GDIOBJLAST) ||
+ wFormatID == CF_BITMAP ||
+ wFormatID == CF_DIB ||
+ wFormatID == CF_PALETTE ||
+ wFormatID == CF_METAFILEPICT ||
+ wFormatID == CF_ENHMETAFILE ||
+ (wFormatID >= CF_PRIVATEFIRST &&
+ wFormatID <= CF_PRIVATELAST))
+ {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
/**************************************************************************
* X11DRV_SetClipboardData
*/
@@ -3022,6 +3038,8 @@ BOOL CDECL X11DRV_SetClipboardData(UINT wFormat, HANDLE hData, BOOL owner)
{
DWORD flags = 0;
BOOL bResult = TRUE;
+ LPVOID pData, pData2;
+ SIZE_T size;
/* If it's not owned, data can only be set if the format data is not already owned
and its rendering is not delayed */
@@ -3039,6 +3057,29 @@ BOOL CDECL X11DRV_SetClipboardData(UINT wFormat, HANDLE hData, BOOL owner)
flags = CF_FLAG_UNOWNED;
}
+ if (is_global_mem_format(wFormat) && hData)
+ {
+ /* Check if memory was allocated with GMEM_FIXED flag */
+ pData = GlobalLock(hData);
+ if (pData != (LPVOID)hData)
+ {
+ /* Convert handle to GMEM_FIXED (GetClipboardData always returns pointer) */
+ size = GlobalSize(hData);
+ pData2 = (LPVOID)GlobalAlloc(GMEM_FIXED, size);
+ if (pData2)
+ {
+ memcpy(pData2, pData, size);
+ GlobalUnlock(hData);
+ GlobalFree(hData);
+ hData = (HANDLE)pData2;
+ }
+ else
+ GlobalUnlock(hData);
+ }
+ else
+ GlobalUnlock(hData);
+ }
+
bResult &= X11DRV_CLIPBOARD_InsertClipboardData(wFormat, hData, flags, NULL, TRUE);
return bResult;
--
1.9.1
More information about the wine-patches
mailing list