[PATCH 6/6] winemac: Use window messages instead of named pipe for macdrv_UpdateClipboard implementation.

Jacek Caban wine at gitlab.winehq.org
Mon May 30 07:42:19 CDT 2022


From: Jacek Caban <jacek at codeweavers.com>

Signed-off-by: Jacek Caban <jacek at codeweavers.com>
---
 dlls/winemac.drv/clipboard.c | 261 +++--------------------------------
 1 file changed, 22 insertions(+), 239 deletions(-)

diff --git a/dlls/winemac.drv/clipboard.c b/dlls/winemac.drv/clipboard.c
index dca62997028..d431728036e 100644
--- a/dlls/winemac.drv/clipboard.c
+++ b/dlls/winemac.drv/clipboard.c
@@ -87,6 +87,9 @@ static CFDataRef export_unicodetext_to_utf16(void *data, size_t size);
  *              Static Variables
  **************************************************************************/
 
+static const WCHAR clipboard_classname[] =
+    {'_','_','w','i','n','e','_','c','l','i','p','b','o','a','r','d','_','m','a','n','a','g','e','r',0};
+
 /* Clipboard formats */
 static struct list format_list = LIST_INIT(format_list);
 
@@ -194,7 +197,6 @@ static ULONG last_clipboard_update;
 static DWORD last_get_seqno;
 static WINE_CLIPFORMAT **current_mac_formats;
 static unsigned int nb_current_mac_formats;
-static WCHAR clipboard_pipe_name[256];
 
 
 /**************************************************************************
@@ -1605,6 +1607,9 @@ static LRESULT CALLBACK clipboard_wndproc(HWND hwnd, UINT msg, WPARAM wp, LPARAM
             is_clipboard_owner = FALSE;
             KillTimer(hwnd, 1);
             break;
+        case WM_USER:
+            update_clipboard();
+            break;
     }
     return DefWindowProcW(hwnd, msg, wp, lp);
 }
@@ -1639,42 +1644,6 @@ static BOOL wait_clipboard_mutex(void)
 }
 
 
-/**************************************************************************
- *              init_pipe_name
- *
- * Init-once helper for get_pipe_name.
- */
-static BOOL CALLBACK init_pipe_name(INIT_ONCE* once, void* param, void** context)
-{
-    static const WCHAR prefix[] = {'\\','\\','.','\\','p','i','p','e','\\','_','_','w','i','n','e','_','c','l','i','p','b','o','a','r','d','_'};
-
-    memcpy(clipboard_pipe_name, prefix, sizeof(prefix));
-    if (!GetUserObjectInformationW(GetProcessWindowStation(), UOI_NAME,
-                                   clipboard_pipe_name + ARRAY_SIZE(prefix),
-                                   sizeof(clipboard_pipe_name) - sizeof(prefix), NULL))
-    {
-        ERR("failed to get winstation name\n");
-        return FALSE;
-    }
-
-    return TRUE;
-}
-
-
-/**************************************************************************
- *              get_pipe_name
- *
- * Get the name of the pipe used to communicate with the per-window-station
- * clipboard manager thread.
- */
-static const WCHAR* get_pipe_name(void)
-{
-    static INIT_ONCE once = INIT_ONCE_STATIC_INIT;
-    InitOnceExecuteOnce(&once, init_pipe_name, NULL, NULL);
-    return clipboard_pipe_name[0] ? clipboard_pipe_name : NULL;
-}
-
-
 /**************************************************************************
  *              clipboard_thread
  *
@@ -1682,14 +1651,8 @@ static const WCHAR* get_pipe_name(void)
  */
 static DWORD WINAPI clipboard_thread(void *arg)
 {
-    static const WCHAR clipboard_classname[] = {'_','_','w','i','n','e','_','c','l','i','p','b','o','a','r','d','_','m','a','n','a','g','e','r',0};
     WNDCLASSW class;
     struct macdrv_window_features wf;
-    const WCHAR* pipe_name;
-    HANDLE pipe = NULL;
-    HANDLE event = NULL;
-    OVERLAPPED overlapped;
-    BOOL need_connect = TRUE, pending = FALSE;
     MSG msg;
 
     if (!wait_clipboard_mutex()) return 0;
@@ -1719,103 +1682,15 @@ static DWORD WINAPI clipboard_thread(void *arg)
         goto done;
     }
 
-    pipe_name = get_pipe_name();
-    if (!pipe_name)
-    {
-        ERR("failed to get pipe name\n");
-        goto done;
-    }
-
-    pipe = CreateNamedPipeW(pipe_name, PIPE_ACCESS_OUTBOUND | FILE_FLAG_OVERLAPPED,
-                            PIPE_TYPE_BYTE, PIPE_UNLIMITED_INSTANCES, 1, 1, 0, NULL);
-    if (!pipe)
-    {
-        ERR("failed to create named pipe: %u\n", GetLastError());
-        goto done;
-    }
-
-    event = CreateEventW(NULL, TRUE, FALSE, NULL);
-    if (!event)
-    {
-        ERR("failed to create event: %d\n", GetLastError());
-        goto done;
-    }
-
     clipboard_thread_id = GetCurrentThreadId();
     NtUserAddClipboardFormatListener(clipboard_hwnd);
     register_builtin_formats();
     grab_win32_clipboard();
 
     TRACE("clipboard thread %04x running\n", GetCurrentThreadId());
-    while (1)
-    {
-        DWORD result;
-
-        if (need_connect)
-        {
-            pending = FALSE;
-            memset(&overlapped, 0, sizeof(overlapped));
-            overlapped.hEvent = event;
-            if (ConnectNamedPipe(pipe, &overlapped))
-            {
-                ERR("asynchronous ConnectNamedPipe unexpectedly returned true: %d\n", GetLastError());
-                ResetEvent(event);
-            }
-            else
-            {
-                result = GetLastError();
-                switch (result)
-                {
-                    case ERROR_PIPE_CONNECTED:
-                    case ERROR_NO_DATA:
-                        SetEvent(event);
-                        need_connect = FALSE;
-                        break;
-                    case ERROR_IO_PENDING:
-                        need_connect = FALSE;
-                        pending = TRUE;
-                        break;
-                    default:
-                        ERR("failed to initiate pipe connection: %d\n", result);
-                        break;
-                }
-            }
-        }
-
-        result = MsgWaitForMultipleObjectsEx(1, &event, INFINITE, QS_ALLINPUT, MWMO_ALERTABLE | MWMO_INPUTAVAILABLE);
-        switch (result)
-        {
-            case WAIT_OBJECT_0:
-            {
-                DWORD written;
-
-                if (pending && !GetOverlappedResult(pipe, &overlapped, &written, FALSE))
-                    ERR("failed to connect pipe: %d\n", GetLastError());
-
-                update_clipboard();
-                DisconnectNamedPipe(pipe);
-                need_connect = TRUE;
-                break;
-            }
-            case WAIT_OBJECT_0 + 1:
-                while (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE))
-                {
-                    if (msg.message == WM_QUIT)
-                        goto done;
-                    DispatchMessageW(&msg);
-                }
-                break;
-            case WAIT_IO_COMPLETION:
-                break;
-            default:
-                ERR("failed to wait for connection or input: %d\n", GetLastError());
-                break;
-        }
-    }
+    while (GetMessageW(&msg, 0, 0, 0)) DispatchMessageW(&msg);
 
 done:
-    if (event) CloseHandle(event);
-    if (pipe) CloseHandle(pipe);
     macdrv_destroy_cocoa_window(clipboard_cocoa_window);
     DestroyWindow(clipboard_hwnd);
     return 0;
@@ -1833,124 +1708,32 @@ done:
 void macdrv_UpdateClipboard(void)
 {
     static ULONG last_update;
-    ULONG now, end;
-    const WCHAR* pipe_name;
-    HANDLE pipe;
-    BYTE dummy;
-    DWORD count;
-    OVERLAPPED overlapped = { 0 };
-    BOOL canceled = FALSE;
+    static HWND clipboard_manager;
+    ULONG now;
+    DWORD_PTR ret;
 
     if (GetCurrentThreadId() == clipboard_thread_id) return;
 
     TRACE("\n");
 
-    now = GetTickCount();
-    if ((int)(now - last_update) <= CLIPBOARD_UPDATE_DELAY) return;
-    last_update = now;
-
-    if (!(pipe_name = get_pipe_name())) return;
-    pipe = CreateFileW(pipe_name, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL,
-                       OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);
-    if (pipe == INVALID_HANDLE_VALUE)
-    {
-        WARN("failed to open pipe to clipboard manager: %d\n", GetLastError());
-        return;
-    }
-
-    overlapped.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
-    if (!overlapped.hEvent)
-    {
-        ERR("failed to create event: %d\n", GetLastError());
-        goto done;
-    }
-
-    /* We expect the read to fail because the server just closes our connection.  This
-       is just waiting for that close to happen. */
-    if (ReadFile(pipe, &dummy, sizeof(dummy), NULL, &overlapped))
-    {
-        WARN("asynchronous ReadFile unexpectedly returned true: %d\n", GetLastError());
-        goto done;
-    }
-    else
-    {
-        DWORD error = GetLastError();
-        if (error == ERROR_PIPE_NOT_CONNECTED || error == ERROR_BROKEN_PIPE)
-        {
-            /* The server accepted, handled, and closed our connection before we
-               attempted the read, which is fine. */
-            goto done;
-        }
-        else if (error != ERROR_IO_PENDING)
-        {
-            ERR("failed to initiate read from pipe: %d\n", error);
-            goto done;
-        }
-    }
+    now = NtGetTickCount();
+    if (last_update && (int)(now - last_update) <= CLIPBOARD_UPDATE_DELAY) return;
 
-    end = now + 500;
-    while (1)
+    if (!NtUserIsWindow(clipboard_manager))
     {
-        DWORD result, timeout;
-
-        if (canceled)
-            timeout = INFINITE;
-        else
+        UNICODE_STRING str;
+        RtlInitUnicodeString(&str, clipboard_classname);
+        clipboard_manager = NtUserFindWindowEx(NULL, NULL, &str, NULL, 0);
+        if (!clipboard_manager)
         {
-            now = GetTickCount();
-            timeout = end - now;
-            if ((int)timeout < 0)
-                timeout = 0;
-        }
-
-        result = MsgWaitForMultipleObjectsEx(1, &overlapped.hEvent, timeout, QS_SENDMESSAGE, MWMO_ALERTABLE);
-        switch (result)
-        {
-            case WAIT_OBJECT_0:
-            {
-                if (GetOverlappedResult(pipe, &overlapped, &count, FALSE))
-                    WARN("unexpectedly succeeded in reading from pipe\n");
-                else
-                {
-                    result = GetLastError();
-                    if (result != ERROR_BROKEN_PIPE && result != ERROR_OPERATION_ABORTED &&
-                        result != ERROR_HANDLES_CLOSED)
-                        WARN("failed to read from pipe: %d\n", result);
-                }
-
-                goto done;
-            }
-            case WAIT_OBJECT_0 + 1:
-            {
-                MSG msg;
-                while (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE | PM_QS_SENDMESSAGE))
-                    DispatchMessageW(&msg);
-                break;
-            }
-            case WAIT_IO_COMPLETION:
-                break;
-            case WAIT_TIMEOUT:
-                WARN("timed out waiting for read\n");
-                CancelIoEx(pipe, &overlapped);
-                canceled = TRUE;
-                break;
-            default:
-                if (canceled)
-                {
-                    ERR("failed to wait for cancel: %d\n", GetLastError());
-                    goto done;
-                }
-
-                ERR("failed to wait for read: %d\n", GetLastError());
-                CancelIoEx(pipe, &overlapped);
-                canceled = TRUE;
-                break;
+            ERR("clipboard manager not found\n");
+            return;
         }
     }
 
-done:
-    if (overlapped.hEvent) CloseHandle(overlapped.hEvent);
-    CloseHandle(pipe);
+    send_message_timeout(clipboard_manager, WM_USER, 0, 0,
+                         SMTO_ABORTIFHUNG, 5000, &ret);
+    last_update = now;
 }
 
 
-- 
GitLab

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



More information about the wine-devel mailing list