Jacek Caban : explorer: Create clipboard manager thread when creating a desktop.

Alexandre Julliard julliard at winehq.org
Tue May 31 15:58:00 CDT 2022


Module: wine
Branch: master
Commit: d8a74e5cf9f259c5ec9480e74d286c93609b8d9c
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=d8a74e5cf9f259c5ec9480e74d286c93609b8d9c

Author: Jacek Caban <jacek at codeweavers.com>
Date:   Tue May 31 14:11:50 2022 +0200

explorer: Create clipboard manager thread when creating a desktop.

Based on winex11.drv. Drivers that don't implement ClipboardWindowProc entry point will disable it by failing to create the window.

Signed-off-by: Jacek Caban <jacek at codeweavers.com>

---

 programs/explorer/Makefile.in |  2 +-
 programs/explorer/desktop.c   | 90 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 91 insertions(+), 1 deletion(-)

diff --git a/programs/explorer/Makefile.in b/programs/explorer/Makefile.in
index 5507d747bb1..3a2ddec3fd4 100644
--- a/programs/explorer/Makefile.in
+++ b/programs/explorer/Makefile.in
@@ -1,5 +1,5 @@
 MODULE    = explorer.exe
-IMPORTS   = rpcrt4 user32 gdi32 advapi32
+IMPORTS   = rpcrt4 user32 gdi32 advapi32 win32u
 DELAYIMPORTS = comctl32 shell32 oleaut32 ole32 shlwapi
 
 EXTRADLLFLAGS = -mwindows -municode
diff --git a/programs/explorer/desktop.c b/programs/explorer/desktop.c
index 400cc1d560e..96673adc254 100644
--- a/programs/explorer/desktop.c
+++ b/programs/explorer/desktop.c
@@ -29,6 +29,7 @@
 #include <rpc.h>
 #include <shlobj.h>
 #include <shellapi.h>
+#include <ntuser.h>
 #include "exdisp.h"
 
 #include "wine/debug.h"
@@ -618,6 +619,91 @@ static void initialize_launchers( HWND hwnd )
     }
 }
 
+/**************************************************************************
+ *		wait_clipboard_mutex
+ *
+ * Make sure that there's only one clipboard thread per window station.
+ */
+static BOOL wait_clipboard_mutex(void)
+{
+    static const WCHAR prefix[] = L"__wine_clipboard_";
+    WCHAR buffer[MAX_PATH + ARRAY_SIZE( prefix )];
+    HANDLE mutex;
+
+    memcpy( buffer, prefix, sizeof(prefix) );
+    if (!GetUserObjectInformationW( GetProcessWindowStation(), UOI_NAME,
+                                    buffer + ARRAY_SIZE( prefix ) - 1,
+                                    sizeof(buffer) - sizeof(prefix), NULL ))
+    {
+        ERR( "failed to get winstation name\n" );
+        return FALSE;
+    }
+    mutex = CreateMutexW( NULL, TRUE, buffer );
+    if (GetLastError() == ERROR_ALREADY_EXISTS)
+    {
+        TRACE( "waiting for mutex %s\n", debugstr_w( buffer ));
+        WaitForSingleObject( mutex, INFINITE );
+    }
+    return TRUE;
+}
+
+
+/**************************************************************************
+ *		clipboard_wndproc
+ *
+ * Window procedure for the clipboard manager.
+ */
+static LRESULT CALLBACK clipboard_wndproc( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp )
+{
+    switch (msg)
+    {
+    case WM_NCCREATE:
+    case WM_CLIPBOARDUPDATE:
+    case WM_RENDERFORMAT:
+    case WM_TIMER:
+    case WM_DESTROYCLIPBOARD:
+    case WM_USER:
+        return NtUserMessageCall( hwnd, msg, wp, lp, 0, NtUserClipboardWindowProc, FALSE );
+    }
+
+    return DefWindowProcW( hwnd, msg, wp, lp );
+}
+
+
+/**************************************************************************
+ *		clipboard_thread
+ *
+ * Thread running inside the desktop process to manage the clipboard
+ */
+static DWORD WINAPI clipboard_thread( void *arg )
+{
+    static const WCHAR clipboard_classname[] = L"__wine_clipboard_manager";
+    WNDCLASSW class;
+    ATOM atom;
+    MSG msg;
+
+    if (!wait_clipboard_mutex()) return 0;
+
+    memset( &class, 0, sizeof(class) );
+    class.lpfnWndProc   = clipboard_wndproc;
+    class.lpszClassName = clipboard_classname;
+
+    if (!(atom = RegisterClassW( &class )) && GetLastError() != ERROR_CLASS_ALREADY_EXISTS)
+    {
+        ERR( "could not register clipboard window class err %lu\n", GetLastError() );
+        return 0;
+    }
+    if (!CreateWindowW( clipboard_classname, NULL, 0, 0, 0, 0, 0, HWND_MESSAGE, 0, 0, NULL ))
+    {
+        TRACE( "failed to create clipboard window err %lu\n", GetLastError() );
+        UnregisterClassW( MAKEINTRESOURCEW(atom), NULL );
+        return 0;
+    }
+
+    while (GetMessageW( &msg, 0, 0, 0 )) DispatchMessageW( &msg );
+    return 0;
+}
+
 static WNDPROC desktop_orig_wndproc;
 
 /* window procedure for the desktop window */
@@ -961,6 +1047,8 @@ void manage_desktop( WCHAR *arg )
     BOOL enable_shell = FALSE;
     void (WINAPI *pShellDDEInit)( BOOL ) = NULL;
     HMODULE shell32;
+    HANDLE thread;
+    DWORD id;
 
     /* get the rest of the command line (if any) */
     while (*p && !is_whitespace(*p)) p++;
@@ -1025,6 +1113,8 @@ void manage_desktop( WCHAR *arg )
         SetWindowPos( hwnd, 0, GetSystemMetrics(SM_XVIRTUALSCREEN), GetSystemMetrics(SM_YVIRTUALSCREEN),
                       GetSystemMetrics(SM_CXVIRTUALSCREEN), GetSystemMetrics(SM_CYVIRTUALSCREEN),
                       SWP_SHOWWINDOW );
+        thread = CreateThread( NULL, 0, clipboard_thread, NULL, 0, &id );
+        if (thread) CloseHandle( thread );
         SystemParametersInfoW( SPI_SETDESKWALLPAPER, 0, NULL, FALSE );
         ClipCursor( NULL );
         initialize_display_settings();




More information about the wine-cvs mailing list