[PATCH 05/11] winemac: Use unixlib interface for macdrv_dnd_get_data.

Jacek Caban wine at gitlab.winehq.org
Thu Jun 2 19:51:20 CDT 2022


From: Jacek Caban <jacek at codeweavers.com>

Signed-off-by: Jacek Caban <jacek at codeweavers.com>
---
 dlls/winemac.drv/clipboard.c   | 29 ++++++++++++++---------------
 dlls/winemac.drv/dragdrop.c    | 24 ++++++++++++++++++++++--
 dlls/winemac.drv/macdrv.h      |  2 +-
 dlls/winemac.drv/macdrv_main.c |  1 +
 dlls/winemac.drv/unixlib.h     | 10 ++++++++++
 5 files changed, 48 insertions(+), 18 deletions(-)

diff --git a/dlls/winemac.drv/clipboard.c b/dlls/winemac.drv/clipboard.c
index f46bb389cc9..8a795e61724 100644
--- a/dlls/winemac.drv/clipboard.c
+++ b/dlls/winemac.drv/clipboard.c
@@ -1128,24 +1128,26 @@ static CFDataRef export_unicodetext_to_utf16(void *data, size_t size)
 
 
 /**************************************************************************
- *              macdrv_get_pasteboard_data
+ *              macdrv_dnd_get_data
  */
-HANDLE macdrv_get_pasteboard_data(CFTypeRef pasteboard, UINT desired_format)
+NTSTATUS macdrv_dnd_get_data(void *arg)
 {
+    struct dnd_get_data_params *params = arg;
+    CFTypeRef pasteboard = pasteboard_from_handle(params->handle);
     CFArrayRef types;
     CFIndex count;
     CFIndex i;
     CFStringRef type, best_type;
     WINE_CLIPFORMAT* best_format = NULL;
-    HANDLE data = NULL;
+    NTSTATUS status = STATUS_SUCCESS;
 
-    TRACE("pasteboard %p, desired_format %s\n", pasteboard, debugstr_format(desired_format));
+    TRACE("pasteboard %p, desired_format %s\n", pasteboard, debugstr_format(params->format));
 
     types = macdrv_copy_pasteboard_types(pasteboard);
     if (!types)
     {
         WARN("Failed to copy pasteboard types\n");
-        return NULL;
+        return STATUS_NO_MEMORY;
     }
 
     count = CFArrayGetCount(types);
@@ -1161,7 +1163,7 @@ HANDLE macdrv_get_pasteboard_data(CFTypeRef pasteboard, UINT desired_format)
         {
             TRACE("for type %s got format %p/%s\n", debugstr_cf(type), format, debugstr_format(format->format_id));
 
-            if (format->format_id == desired_format)
+            if (format->format_id == params->format)
             {
                 /* The best format is the matching one which is not synthesized.  Failing that,
                    the best format is the first matching synthesized format. */
@@ -1183,15 +1185,12 @@ HANDLE macdrv_get_pasteboard_data(CFTypeRef pasteboard, UINT desired_format)
         if (pasteboard_data)
         {
             size_t size;
-            void *import = best_format->import_func(pasteboard_data, &size), *ptr;
+            void *import = best_format->import_func(pasteboard_data, &size);
             if (import)
             {
-                data = GlobalAlloc(GMEM_FIXED, size);
-                if (data && (ptr = GlobalLock(data)))
-                {
-                    memcpy(ptr, import, size);
-                    GlobalUnlock(data);
-                }
+                if (size > params->size) status = STATUS_BUFFER_OVERFLOW;
+                else memcpy(params->data, import, size);
+                params->size = size;
                 free(import);
             }
             CFRelease(pasteboard_data);
@@ -1199,8 +1198,8 @@ HANDLE macdrv_get_pasteboard_data(CFTypeRef pasteboard, UINT desired_format)
     }
 
     CFRelease(types);
-    TRACE(" -> %p\n", data);
-    return data;
+    TRACE(" -> %#x\n", status);
+    return status;
 }
 
 
diff --git a/dlls/winemac.drv/dragdrop.c b/dlls/winemac.drv/dragdrop.c
index 962a9d8c24b..aec8b1f4790 100644
--- a/dlls/winemac.drv/dragdrop.c
+++ b/dlls/winemac.drv/dragdrop.c
@@ -24,6 +24,8 @@
 
 #define NONAMELESSUNION
 
+#include "ntstatus.h"
+#define WIN32_NO_STATUS
 #include "macdrv.h"
 
 #define COBJMACROS
@@ -92,6 +94,24 @@ static inline DragDropDataObject *impl_from_IDataObject(IDataObject *iface)
 }
 
 
+static HANDLE get_pasteboard_data(UINT64 pasteboard, UINT desired_format)
+{
+    struct dnd_get_data_params params = { .handle = pasteboard, .format = desired_format, .size = 2048 };
+    HANDLE handle;
+    NTSTATUS status;
+
+    for (;;)
+    {
+        if (!(handle = GlobalAlloc(GMEM_FIXED, params.size))) return 0;
+        params.data = GlobalLock(handle);
+        status = MACDRV_CALL(dnd_get_data, &params);
+        GlobalUnlock(handle);
+        if (!status) return GlobalReAlloc(handle, params.size, 0);
+        GlobalFree(handle);
+        if (status != STATUS_BUFFER_OVERFLOW) return 0;
+    }
+}
+
 static HRESULT WINAPI dddo_QueryInterface(IDataObject* iface, REFIID riid, LPVOID *ppvObj)
 {
     DragDropDataObject *This = impl_from_IDataObject(iface);
@@ -148,7 +168,7 @@ static HRESULT WINAPI dddo_GetData(IDataObject* iface, FORMATETC* formatEtc, STG
     if (SUCCEEDED(hr))
     {
         medium->tymed = TYMED_HGLOBAL;
-        medium->u.hGlobal = macdrv_get_pasteboard_data((void *)(UINT_PTR)This->pasteboard, formatEtc->cfFormat);
+        medium->u.hGlobal = get_pasteboard_data(This->pasteboard, formatEtc->cfFormat);
         medium->pUnkForRelease = NULL;
         hr = medium->u.hGlobal ? S_OK : E_OUTOFMEMORY;
     }
@@ -454,7 +474,7 @@ NTSTATUS WINAPI macdrv_dnd_query_drop(void *arg, ULONG size)
             hwnd = GetParent(hwnd);
         if (hwnd)
         {
-            HDROP hdrop = macdrv_get_pasteboard_data((void *)(UINT_PTR)params->handle, CF_HDROP);
+            HDROP hdrop = get_pasteboard_data(params->handle, CF_HDROP);
             DROPFILES *dropfiles = GlobalLock(hdrop);
             if (dropfiles)
             {
diff --git a/dlls/winemac.drv/macdrv.h b/dlls/winemac.drv/macdrv.h
index 4c1a21a3fe8..a841465486e 100644
--- a/dlls/winemac.drv/macdrv.h
+++ b/dlls/winemac.drv/macdrv.h
@@ -255,7 +255,6 @@ extern void macdrv_displays_changed(const macdrv_event *event) DECLSPEC_HIDDEN;
 extern void macdrv_UpdateClipboard(void) DECLSPEC_HIDDEN;
 extern BOOL query_pasteboard_data(HWND hwnd, CFStringRef type) DECLSPEC_HIDDEN;
 extern void macdrv_lost_pasteboard_ownership(HWND hwnd) DECLSPEC_HIDDEN;
-extern HANDLE macdrv_get_pasteboard_data(CFTypeRef pasteboard, UINT desired_format) DECLSPEC_HIDDEN;
 
 extern struct opengl_funcs *macdrv_wine_get_wgl_driver(UINT version) DECLSPEC_HIDDEN;
 extern const struct vulkan_funcs *macdrv_wine_get_vulkan_driver(UINT version) DECLSPEC_HIDDEN;
@@ -285,6 +284,7 @@ extern NTSTATUS WINAPI macdrv_ime_query_char_rect(void *params, ULONG size) DECL
 
 /* unixlib interface */
 
+extern NTSTATUS macdrv_dnd_get_data(void *arg) DECLSPEC_HIDDEN;
 extern NTSTATUS macdrv_dnd_get_formats(void *arg) DECLSPEC_HIDDEN;
 extern NTSTATUS macdrv_dnd_have_format(void *arg) DECLSPEC_HIDDEN;
 extern NTSTATUS macdrv_dnd_release(void *arg) DECLSPEC_HIDDEN;
diff --git a/dlls/winemac.drv/macdrv_main.c b/dlls/winemac.drv/macdrv_main.c
index a0b29604e62..61195d408c8 100644
--- a/dlls/winemac.drv/macdrv_main.c
+++ b/dlls/winemac.drv/macdrv_main.c
@@ -630,6 +630,7 @@ static NTSTATUS macdrv_ime_using_input_method(void *arg)
 
 const unixlib_entry_t __wine_unix_call_funcs[] =
 {
+    macdrv_dnd_get_data,
     macdrv_dnd_get_formats,
     macdrv_dnd_have_format,
     macdrv_dnd_release,
diff --git a/dlls/winemac.drv/unixlib.h b/dlls/winemac.drv/unixlib.h
index b29bf99e7f4..0bfc61321d0 100644
--- a/dlls/winemac.drv/unixlib.h
+++ b/dlls/winemac.drv/unixlib.h
@@ -21,6 +21,7 @@
 
 enum macdrv_funcs
 {
+    unix_dnd_get_data,
     unix_dnd_get_formats,
     unix_dnd_have_format,
     unix_dnd_release,
@@ -37,6 +38,15 @@ enum macdrv_funcs
 extern NTSTATUS unix_call(enum macdrv_funcs code, void *params) DECLSPEC_HIDDEN;
 #define MACDRV_CALL(func, params) unix_call( unix_ ## func, params )
 
+/* macdrv_dnd_get_data params */
+struct dnd_get_data_params
+{
+    UINT64 handle;
+    UINT format;
+    size_t size;
+    void *data;
+};
+
 /* macdrv_dnd_get_formats params */
 struct dnd_get_formats_params
 {
-- 
GitLab


https://gitlab.winehq.org/wine/wine/-/merge_requests/177



More information about the wine-devel mailing list