[PATCH v2 09/12] winex11: Use data-only NtUserGetClipboardData to export clipboard data.

Huw Davies huw at codeweavers.com
Tue Apr 26 10:06:08 CDT 2022


From: Jacek Caban <jacek at codeweavers.com>

Signed-off-by: Jacek Caban <jacek at codeweavers.com>
Signed-off-by: Huw Davies <huw at codeweavers.com>
---
 dlls/winex11.drv/clipboard.c | 167 ++++++++++++++++-------------------
 1 file changed, 75 insertions(+), 92 deletions(-)

diff --git a/dlls/winex11.drv/clipboard.c b/dlls/winex11.drv/clipboard.c
index 02456ef3870..ec0392f3ec8 100644
--- a/dlls/winex11.drv/clipboard.c
+++ b/dlls/winex11.drv/clipboard.c
@@ -97,7 +97,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(clipboard);
 
 #define SELECTION_UPDATE_DELAY 2000   /* delay between checks of the X11 selection */
 
-typedef BOOL (*EXPORTFUNC)( Display *display, Window win, Atom prop, Atom target, HANDLE handle );
+typedef BOOL (*EXPORTFUNC)( Display *display, Window win, Atom prop, Atom target, void *data, size_t size );
 typedef HANDLE (*IMPORTFUNC)( Atom type, const void *data, size_t size );
 
 struct clipboard_format
@@ -121,19 +121,18 @@ static HANDLE import_text_html( Atom type, const void *data, size_t size );
 static HANDLE import_text_uri_list( Atom type, const void *data, size_t size );
 static HANDLE import_targets( Atom type, const void *data, size_t size );
 
-static BOOL export_data( Display *display, Window win, Atom prop, Atom target, HANDLE handle );
-static BOOL export_string( Display *display, Window win, Atom prop, Atom target, HANDLE handle );
-static BOOL export_utf8_string( Display *display, Window win, Atom prop, Atom target, HANDLE handle );
-static BOOL export_text( Display *display, Window win, Atom prop, Atom target, HANDLE handle );
-static BOOL export_compound_text( Display *display, Window win, Atom prop, Atom target, HANDLE handle );
-static BOOL export_pixmap( Display *display, Window win, Atom prop, Atom target, HANDLE handle );
-static BOOL export_image_bmp( Display *display, Window win, Atom prop, Atom target, HANDLE handle );
-static BOOL export_enhmetafile( Display *display, Window win, Atom prop, Atom target, HANDLE handle );
-static BOOL export_text_html( Display *display, Window win, Atom prop, Atom target, HANDLE handle );
-static BOOL export_hdrop( Display *display, Window win, Atom prop, Atom target, HANDLE handle );
-static BOOL export_targets( Display *display, Window win, Atom prop, Atom target, HANDLE handle );
-static BOOL export_multiple( Display *display, Window win, Atom prop, Atom target, HANDLE handle );
-static BOOL export_timestamp( Display *display, Window win, Atom prop, Atom target, HANDLE handle );
+static BOOL export_data( Display *display, Window win, Atom prop, Atom target, void *data, size_t size );
+static BOOL export_string( Display *display, Window win, Atom prop, Atom target, void *data, size_t size );
+static BOOL export_utf8_string( Display *display, Window win, Atom prop, Atom target, void *data, size_t size );
+static BOOL export_text( Display *display, Window win, Atom prop, Atom target, void *data, size_t size );
+static BOOL export_compound_text( Display *display, Window win, Atom prop, Atom target, void *data, size_t size );
+static BOOL export_pixmap( Display *display, Window win, Atom prop, Atom target, void *data, size_t size );
+static BOOL export_image_bmp( Display *display, Window win, Atom prop, Atom target, void *data, size_t size );
+static BOOL export_text_html( Display *display, Window win, Atom prop, Atom target, void *data, size_t size );
+static BOOL export_hdrop( Display *display, Window win, Atom prop, Atom target, void *data, size_t size );
+static BOOL export_targets( Display *display, Window win, Atom prop, Atom target, void *data, size_t size );
+static BOOL export_multiple( Display *display, Window win, Atom prop, Atom target, void *data, size_t size );
+static BOOL export_timestamp( Display *display, Window win, Atom prop, Atom target, void *data, size_t size );
 
 static BOOL read_property( Display *display, Window w, Atom prop,
                            Atom *type, unsigned char **data, unsigned long *datasize );
@@ -167,7 +166,7 @@ static const struct
     { 0, CF_PENDATA,         XATOM_WCF_PENDATA,         import_data,          export_data },
     { 0, CF_RIFF,            XATOM_WCF_RIFF,            import_data,          export_data },
     { 0, CF_WAVE,            XATOM_WCF_WAVE,            import_data,          export_data },
-    { 0, CF_ENHMETAFILE,     XATOM_WCF_ENHMETAFILE,     import_enhmetafile,   export_enhmetafile },
+    { 0, CF_ENHMETAFILE,     XATOM_WCF_ENHMETAFILE,     import_enhmetafile,   export_data },
     { 0, CF_HDROP,           XATOM_text_uri_list,       import_text_uri_list, export_hdrop },
     { 0, CF_DIB,             XATOM_image_bmp,           import_image_bmp,     export_image_bmp },
     { RichTextFormatW, 0,    XATOM_text_rtf,            import_data,          export_data },
@@ -1099,13 +1098,9 @@ static HANDLE render_format( UINT id )
  *
  *  Generic export clipboard data routine.
  */
-static BOOL export_data( Display *display, Window win, Atom prop, Atom target, HANDLE handle )
+static BOOL export_data( Display *display, Window win, Atom prop, Atom target, void *data, size_t size )
 {
-    void *ptr = GlobalLock( handle );
-
-    if (!ptr) return FALSE;
-    put_property( display, win, prop, target, 8, ptr, GlobalSize( handle ));
-    GlobalUnlock( handle );
+    put_property( display, win, prop, target, 8, data, size );
     return TRUE;
 }
 
@@ -1115,18 +1110,19 @@ static BOOL export_data( Display *display, Window win, Atom prop, Atom target, H
  *
  * Convert CF_UNICODETEXT data to a string in the specified codepage.
  */
-static char *string_from_unicode_text( UINT codepage, HANDLE handle, UINT *size )
+static char *string_from_unicode_text( UINT codepage, const WCHAR *string, size_t string_size, size_t *size )
 {
     UINT i, j;
     char *str;
-    WCHAR *strW = GlobalLock( handle );
-    UINT lenW = GlobalSize( handle ) / sizeof(WCHAR);
-    DWORD len = WideCharToMultiByte( codepage, 0, strW, lenW, NULL, 0, NULL, NULL );
+    UINT lenW = string_size / sizeof(WCHAR);
+    DWORD len;
+
+    if (!string_size) return NULL;
 
+    len = WideCharToMultiByte( codepage, 0, string, lenW, NULL, 0, NULL, NULL );
     if ((str = malloc( len )))
     {
-        WideCharToMultiByte( codepage, 0, strW, lenW, str, len, NULL, NULL);
-        GlobalUnlock( handle );
+        WideCharToMultiByte( codepage, 0, string, lenW, str, len, NULL, NULL);
 
         /* remove carriage returns */
         for (i = j = 0; i < len; i++)
@@ -1138,7 +1134,6 @@ static char *string_from_unicode_text( UINT codepage, HANDLE handle, UINT *size
         *size = j;
         TRACE( "returning %s\n", debugstr_an( str, j ));
     }
-    GlobalUnlock( handle );
     return str;
 }
 
@@ -1148,15 +1143,13 @@ static char *string_from_unicode_text( UINT codepage, HANDLE handle, UINT *size
  *
  * Export CF_UNICODETEXT converting the string to XA_STRING.
  */
-static BOOL export_string( Display *display, Window win, Atom prop, Atom target, HANDLE handle )
+static BOOL export_string( Display *display, Window win, Atom prop, Atom target, void *data, size_t size )
 {
-    UINT size;
-    char *text = string_from_unicode_text( 28591, handle, &size );
+    char *text = string_from_unicode_text( 28591, data, size, &size );
 
     if (!text) return FALSE;
     put_property( display, win, prop, target, 8, text, size );
     free( text );
-    GlobalUnlock( handle );
     return TRUE;
 }
 
@@ -1166,15 +1159,14 @@ static BOOL export_string( Display *display, Window win, Atom prop, Atom target,
  *
  *  Export CF_UNICODE converting the string to UTF8.
  */
-static BOOL export_utf8_string( Display *display, Window win, Atom prop, Atom target, HANDLE handle )
+static BOOL export_utf8_string( Display *display, Window win, Atom prop, Atom target,
+                                void *data, size_t size )
 {
-    UINT size;
-    char *text = string_from_unicode_text( CP_UTF8, handle, &size );
+    char *text = string_from_unicode_text( CP_UTF8, data, size, &size );
 
     if (!text) return FALSE;
     put_property( display, win, prop, target, 8, text, size );
     free( text );
-    GlobalUnlock( handle );
     return TRUE;
 }
 
@@ -1184,9 +1176,9 @@ static BOOL export_utf8_string( Display *display, Window win, Atom prop, Atom ta
  *
  *  Export CF_UNICODE to the polymorphic TEXT type, using UTF8.
  */
-static BOOL export_text( Display *display, Window win, Atom prop, Atom target, HANDLE handle )
+static BOOL export_text( Display *display, Window win, Atom prop, Atom target, void *data, size_t size )
 {
-    return export_utf8_string( display, win, prop, x11drv_atom(UTF8_STRING), handle );
+    return export_utf8_string( display, win, prop, x11drv_atom(UTF8_STRING), data, size );
 }
 
 
@@ -1195,12 +1187,12 @@ static BOOL export_text( Display *display, Window win, Atom prop, Atom target, H
  *
  *  Export CF_UNICODE to COMPOUND_TEXT
  */
-static BOOL export_compound_text( Display *display, Window win, Atom prop, Atom target, HANDLE handle )
+static BOOL export_compound_text( Display *display, Window win, Atom prop, Atom target,
+                                  void *data, size_t size )
 {
     XTextProperty textprop;
     XICCEncodingStyle style;
-    UINT size;
-    char *text = string_from_unicode_text( CP_UNIXCP, handle, &size );
+    char *text = string_from_unicode_text( CP_UNIXCP, data, size, &size );
 
     if (!text) return FALSE;
     if (target == x11drv_atom(COMPOUND_TEXT))
@@ -1225,18 +1217,16 @@ static BOOL export_compound_text( Display *display, Window win, Atom prop, Atom
  *
  *  Export CF_DIB to XA_PIXMAP.
  */
-static BOOL export_pixmap( Display *display, Window win, Atom prop, Atom target, HANDLE handle )
+static BOOL export_pixmap( Display *display, Window win, Atom prop, Atom target, void *data, size_t size )
 {
     Pixmap pixmap;
-    BITMAPINFO *pbmi;
+    BITMAPINFO *pbmi = data;
     struct gdi_image_bits bits;
 
-    pbmi = GlobalLock( handle );
     bits.ptr = (LPBYTE)pbmi + bitmap_info_size( pbmi, DIB_RGB_COLORS );
     bits.free = NULL;
     bits.is_copy = FALSE;
     pixmap = create_pixmap_from_image( 0, &default_visual, pbmi, &bits, DIB_RGB_COLORS );
-    GlobalUnlock( handle );
 
     put_property( display, win, prop, target, 32, &pixmap, 1 );
     /* FIXME: free the pixmap when the property is deleted */
@@ -1249,13 +1239,13 @@ static BOOL export_pixmap( Display *display, Window win, Atom prop, Atom target,
  *
  *  Export CF_DIB to image/bmp.
  */
-static BOOL export_image_bmp( Display *display, Window win, Atom prop, Atom target, HANDLE handle )
+static BOOL export_image_bmp( Display *display, Window win, Atom prop, Atom target, void *data, size_t size )
 {
-    LPBYTE dibdata = GlobalLock( handle );
+    LPBYTE dibdata = data;
     UINT bmpsize;
     BITMAPFILEHEADER *bfh;
 
-    bmpsize = sizeof(BITMAPFILEHEADER) + GlobalSize( handle );
+    bmpsize = sizeof(BITMAPFILEHEADER) + size;
     bfh = malloc( bmpsize );
     if (bfh)
     {
@@ -1269,33 +1259,12 @@ static BOOL export_image_bmp( Display *display, Window win, Atom prop, Atom targ
         /* rest of bitmap is the same as the packed dib */
         memcpy(bfh+1, dibdata, bmpsize-sizeof(BITMAPFILEHEADER));
     }
-    GlobalUnlock( handle );
     put_property( display, win, prop, target, 8, bfh, bmpsize );
     free( bfh );
     return TRUE;
 }
 
 
-/**************************************************************************
- *		export_enhmetafile
- *
- *  Export EnhMetaFile.
- */
-static BOOL export_enhmetafile( Display *display, Window win, Atom prop, Atom target, HANDLE handle )
-{
-    unsigned int size;
-    void *ptr;
-
-    if (!(size = GetEnhMetaFileBits( handle, 0, NULL ))) return FALSE;
-    if (!(ptr = malloc( size ))) return FALSE;
-
-    GetEnhMetaFileBits( handle, size, ptr );
-    put_property( display, win, prop, target, 8, ptr, size );
-    free( ptr );
-    return TRUE;
-}
-
-
 /**************************************************************************
  *		export_text_html
  *
@@ -1303,14 +1272,12 @@ static BOOL export_enhmetafile( Display *display, Window win, Atom prop, Atom ta
  *
  * FIXME: We should attempt to add an <a base> tag and convert windows paths.
  */
-static BOOL export_text_html( Display *display, Window win, Atom prop, Atom target, HANDLE handle )
+static BOOL export_text_html( Display *display, Window win, Atom prop, Atom target, void *data, size_t size )
 {
-    const char *p, *data;
+    const char *p;
     UINT start = 0, end = 0;
     BOOL ret = TRUE;
 
-    if (!(data = GlobalLock( handle ))) return FALSE;
-
     p = data;
     while (*p && *p != '<')
     {
@@ -1319,12 +1286,11 @@ static BOOL export_text_html( Display *display, Window win, Atom prop, Atom targ
         if (!(p = strpbrk( p, "\r\n" ))) break;
         while (*p == '\r' || *p == '\n') p++;
     }
-    if (start && start < end && end <= GlobalSize( handle ))
-        put_property( display, win, prop, target, 8, data + start, end - start );
+    if (start && start < end && end <= size)
+        put_property( display, win, prop, target, 8, (char *)data + start, end - start );
     else
         ret = FALSE;
 
-    GlobalUnlock( handle );
     return ret;
 }
 
@@ -1334,14 +1300,13 @@ static BOOL export_text_html( Display *display, Window win, Atom prop, Atom targ
  *
  *  Export CF_HDROP format to text/uri-list.
  */
-static BOOL export_hdrop( Display *display, Window win, Atom prop, Atom target, HANDLE handle )
+static BOOL export_hdrop( Display *display, Window win, Atom prop, Atom target, void *data, size_t size )
 {
     char *textUriList = NULL;
     UINT textUriListSize = 32;
     UINT next = 0;
     const WCHAR *ptr;
     WCHAR *unicode_data = NULL;
-    void *data = GlobalLock( handle );
     DROPFILES *drop_files = data;
 
     if (!drop_files->fWide)
@@ -1406,7 +1371,6 @@ static BOOL export_hdrop( Display *display, Window win, Atom prop, Atom target,
     return TRUE;
 
 failed:
-    GlobalUnlock( handle );
     free( unicode_data );
     free( textUriList );
     return FALSE;
@@ -1454,7 +1418,7 @@ static BOOL is_format_available( UINT format, const UINT *ids, unsigned int coun
  *
  *  Service a TARGETS selection request event
  */
-static BOOL export_targets( Display *display, Window win, Atom prop, Atom target, HANDLE handle )
+static BOOL export_targets( Display *display, Window win, Atom prop, Atom target, void *data, size_t size )
 {
     struct clipboard_format *format;
     UINT pos, count, *formats;
@@ -1493,9 +1457,10 @@ static BOOL export_targets( Display *display, Window win, Atom prop, Atom target
  */
 static BOOL export_selection( Display *display, Window win, Atom prop, Atom target )
 {
+    struct get_clipboard_params params = { .data_only = TRUE };
     struct clipboard_format *format;
-    HANDLE handle = 0;
     BOOL open = FALSE, ret = FALSE;
+    size_t buffer_size = 0;
 
     LIST_FOR_EACH_ENTRY( format, &format_list, struct clipboard_format, entry )
     {
@@ -1504,26 +1469,44 @@ static BOOL export_selection( Display *display, Window win, Atom prop, Atom targ
         if (!format->id)
         {
             TRACE( "win %lx prop %s target %s\n", win, debugstr_xatom( prop ), debugstr_xatom( target ));
-            ret = format->export( display, win, prop, target, 0 );
+            ret = format->export( display, win, prop, target, NULL, 0 );
             break;
         }
-        if (!open && !(open = OpenClipboard( clipboard_hwnd )))
+        if (!open && !(open = NtUserOpenClipboard( clipboard_hwnd, 0 )))
         {
             ERR( "failed to open clipboard for %s\n", debugstr_xatom( target ));
             return FALSE;
         }
-        if ((handle = GetClipboardData( format->id )))
+
+        if (!buffer_size)
         {
-            TRACE( "win %lx prop %s target %s exporting %s %p\n",
-                   win, debugstr_xatom( prop ), debugstr_xatom( target ),
-                   debugstr_format( format->id ), handle );
+            buffer_size = 1024;
+            if (!(params.data = malloc( buffer_size ))) break;
+        }
 
-            ret = format->export( display, win, prop, target, handle );
-            break;
+        for (;;)
+        {
+            params.size = buffer_size;
+            if (NtUserGetClipboardData( format->id, &params ))
+            {
+                TRACE( "win %lx prop %s target %s exporting %s\n",
+                       win, debugstr_xatom( prop ), debugstr_xatom( target ),
+                       debugstr_format( format->id ) );
+
+                ret = format->export( display, win, prop, target, params.data, params.size );
+                goto done;
+            }
+            if (!params.data_size) break;
+            free( params.data );
+            if (!(params.data = malloc( params.data_size ))) goto done;
+            buffer_size = params.data_size;
+            params.data_size = 0;
         }
         /* keep looking for another Win32 format mapping to the same target */
     }
-    if (open) CloseClipboard();
+done:
+    free( params.data );
+    if (open) NtUserCloseClipboard();
     return ret;
 }
 
@@ -1541,7 +1524,7 @@ static BOOL export_selection( Display *display, Window win, Atom prop, Atom targ
  *  2. If we fail to convert the target named by an atom in the MULTIPLE property,
  *  we replace the atom in the property by None.
  */
-static BOOL export_multiple( Display *display, Window win, Atom prop, Atom target, HANDLE handle )
+static BOOL export_multiple( Display *display, Window win, Atom prop, Atom target, void *data, size_t size )
 {
     Atom atype;
     int aformat;
@@ -1587,7 +1570,7 @@ static BOOL export_multiple( Display *display, Window win, Atom prop, Atom targe
  *
  * Export the timestamp that was used to acquire the selection
  */
-static BOOL export_timestamp( Display *display, Window win, Atom prop, Atom target, HANDLE handle )
+static BOOL export_timestamp( Display *display, Window win, Atom prop, Atom target, void *data, size_t size )
 {
     Time time = CurrentTime;  /* FIXME */
     put_property( display, win, prop, XA_INTEGER, 32, &time, 1 );
-- 
2.25.1




More information about the wine-devel mailing list