From: Jacek Caban jacek@codeweavers.com
Signed-off-by: Jacek Caban jacek@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; }