[PATCH 1/9] winex11: Introduce x11drv_client_call.

Jacek Caban wine at gitlab.winehq.org
Thu May 5 08:40:38 CDT 2022


From: Jacek Caban <jacek at codeweavers.com>

Signed-off-by: Jacek Caban <jacek at codeweavers.com>
---
 dlls/winex11.drv/dllmain.c     | 38 ++++++++++++++++++++++++++++--
 dlls/winex11.drv/event.c       | 15 ++++--------
 dlls/winex11.drv/unixlib.h     | 42 ++++++++++++++++++++++------------
 dlls/winex11.drv/window.c      |  2 +-
 dlls/winex11.drv/x11drv.h      | 16 +++++++++----
 dlls/winex11.drv/x11drv_main.c | 15 ++++++++++++
 dlls/winex11.drv/xdnd.c        | 41 ++++++++++-----------------------
 include/ntuser.h               |  3 +++
 8 files changed, 110 insertions(+), 62 deletions(-)

diff --git a/dlls/winex11.drv/dllmain.c b/dlls/winex11.drv/dllmain.c
index 6a9f4a57273..751b6ec08a4 100644
--- a/dlls/winex11.drv/dllmain.c
+++ b/dlls/winex11.drv/dllmain.c
@@ -116,23 +116,57 @@ static DWORD WINAPI clipboard_thread( void *arg )
 }
 
 
-void X11DRV_InitClipboard(void)
+static NTSTATUS x11drv_clipboard_init( UINT arg )
 {
     DWORD id;
     HANDLE thread = CreateThread( NULL, 0, clipboard_thread, NULL, 0, &id );
 
     if (thread) CloseHandle( thread );
     else ERR( "failed to create clipboard thread\n" );
+    return 0;
 }
 
 
+typedef NTSTATUS (*callback_func)( UINT arg );
+static const callback_func callback_funcs[] =
+{
+    x11drv_clipboard_init,
+    x11drv_dnd_drop_event,
+    x11drv_dnd_leave_event,
+};
+
+C_ASSERT( ARRAYSIZE(callback_funcs) == client_funcs_count );
+
+static NTSTATUS WINAPI x11drv_callback( void *arg, ULONG size )
+{
+    struct client_callback_params *params = arg;
+    return callback_funcs[params->id]( params->arg );
+}
+
+typedef NTSTATUS (WINAPI *kernel_callback)( void *params, ULONG size );
+static const kernel_callback kernel_callbacks[] =
+{
+    x11drv_callback,
+    x11drv_dnd_enter_event,
+    x11drv_dnd_position_event,
+    x11drv_dnd_post_drop,
+};
+
+C_ASSERT( NtUserDriverCallbackFirst + ARRAYSIZE(kernel_callbacks) == client_func_last );
+
 BOOL WINAPI DllMain( HINSTANCE instance, DWORD reason, void *reserved )
 {
+    void **callback_table;
+
     if (reason != DLL_PROCESS_ATTACH) return TRUE;
 
     DisableThreadLibraryCalls( instance );
     x11drv_module = instance;
-    return !X11DRV_CALL( init, NULL );
+    if (X11DRV_CALL( init, NULL )) return FALSE;
+
+    callback_table = NtCurrentTeb()->Peb->KernelCallbackTable;
+    memcpy( callback_table + NtUserDriverCallbackFirst, kernel_callbacks, sizeof(kernel_callbacks) );
+    return TRUE;
 }
 
 
diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c
index 105caab5deb..cefc86d0902 100644
--- a/dlls/winex11.drv/event.c
+++ b/dlls/winex11.drv/event.c
@@ -1479,7 +1479,7 @@ static HWND find_drop_window( HWND hQueryWnd, LPPOINT lpPt )
 static void post_drop( HWND hwnd, DROPFILES *drop, ULONG size )
 {
     drop->fWide = HandleToUlong( hwnd ); /* abuse fWide to pass window handle */
-    x11drv_post_drop( drop, size );
+    x11drv_client_func( client_func_dnd_post_drop, drop, size );
 }
 
 /**********************************************************************
@@ -1744,7 +1744,7 @@ static void handle_xdnd_enter_event( HWND hWnd, XClientMessageEvent *event )
                                   xdndtypes, count, &size );
     if (data)
     {
-        handle_dnd_enter_event( data, size );
+        x11drv_client_func( client_func_dnd_enter_event, data, size );
         free( data );
     }
 
@@ -1795,12 +1795,11 @@ static void handle_xdnd_position_event( HWND hwnd, XClientMessageEvent *event )
     XClientMessageEvent e;
     DWORD effect;
 
-    params.type = DND_POSITION_EVENT;
     params.hwnd = hwnd;
     params.point = root_to_virtual_screen( event->data.l[2] >> 16, event->data.l[2] & 0xFFFF );
     params.effect = effect = xdnd_action_to_drop_effect( event->data.l[4] );
 
-    effect = handle_dnd_event( &params );
+    effect = x11drv_client_func( client_func_dnd_position_event, &params, sizeof(params) );
 
     TRACE( "actionRequested(%ld) chosen(0x%x) at x(%d),y(%d)\n",
            event->data.l[4], effect, params.point.x, params.point.y );
@@ -1825,13 +1824,10 @@ static void handle_xdnd_position_event( HWND hwnd, XClientMessageEvent *event )
 
 static void handle_xdnd_drop_event( HWND hwnd, XClientMessageEvent *event )
 {
-    struct dnd_drop_event_params params;
     XClientMessageEvent e;
     DWORD effect;
 
-    params.type = DND_DROP_EVENT;
-    params.hwnd = hwnd;
-    effect = handle_dnd_event( &params );
+    effect = x11drv_client_call( client_dnd_drop_event, HandleToUlong( hwnd ));
 
     /* Tell the target we are finished. */
     memset( &e, 0, sizeof(e) );
@@ -1849,8 +1845,7 @@ static void handle_xdnd_drop_event( HWND hwnd, XClientMessageEvent *event )
 
 static void handle_xdnd_leave_event( HWND hwnd, XClientMessageEvent *event )
 {
-    UINT type = DND_LEAVE_EVENT;
-    handle_dnd_event( &type );
+    x11drv_client_call( client_dnd_leave_event, 0 );
 }
 
 
diff --git a/dlls/winex11.drv/unixlib.h b/dlls/winex11.drv/unixlib.h
index 2a957af0f56..ec5f75a1697 100644
--- a/dlls/winex11.drv/unixlib.h
+++ b/dlls/winex11.drv/unixlib.h
@@ -68,33 +68,45 @@ struct xim_preedit_state_params
     BOOL open;
 };
 
-/* DnD support */
+/* driver client callbacks exposed with KernelCallbackTable interface */
+enum x11drv_client_funcs
+{
+    client_func_callback = NtUserDriverCallbackFirst,
+    client_func_dnd_enter_event,
+    client_func_dnd_position_event,
+    client_func_dnd_post_drop,
+    client_func_last
+};
 
-struct format_entry
+C_ASSERT( client_func_last <= NtUserDriverCallbackLast + 1 );
+
+/* simplified interface for client callbacks requiring only a single UINT parameter */
+enum client_callback
 {
-    UINT format;
-    UINT size;
-    char data[1];
+    client_clipboard_init,
+    client_dnd_drop_event,
+    client_dnd_leave_event,
+    client_funcs_count
 };
 
-enum dnd_event_type
+/* x11drv_callback params */
+struct client_callback_params
 {
-    DND_DROP_EVENT,
-    DND_LEAVE_EVENT,
-    DND_POSITION_EVENT,
+    UINT id;
+    UINT arg;
 };
 
-/* DND_DROP_EVENT params */
-struct dnd_drop_event_params
+/* x11drv_dnd_enter_event and x11drv_dnd_post_drop params */
+struct format_entry
 {
-    UINT type;
-    HWND hwnd;
+    UINT format;
+    UINT size;
+    char data[1];
 };
 
-/* DND_POSITION_EVENT params */
+/* x11drv_dnd_position_event params */
 struct dnd_position_event_params
 {
-    UINT  type;
     HWND  hwnd;
     POINT point;
     DWORD effect;
diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c
index de52023c467..7ccec4ee4ec 100644
--- a/dlls/winex11.drv/window.c
+++ b/dlls/winex11.drv/window.c
@@ -1904,7 +1904,7 @@ BOOL X11DRV_CreateWindow( HWND hwnd )
                                            CWOverrideRedirect | CWEventMask, &attr );
         XFlush( data->display );
         NtUserSetProp( hwnd, clip_window_prop, (HANDLE)data->clip_window );
-        X11DRV_InitClipboard();
+        x11drv_client_call( client_clipboard_init, 0 );
         X11DRV_DisplayDevices_RegisterEventHandlers();
     }
     return TRUE;
diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h
index c6e5044c110..02eb67c9cc2 100644
--- a/dlls/winex11.drv/x11drv.h
+++ b/dlls/winex11.drv/x11drv.h
@@ -296,9 +296,6 @@ extern BOOL IME_SetCompositionString(DWORD dwIndex, LPCVOID lpComp,
 extern void IME_SetResultString(LPWSTR lpResult, DWORD dwResultlen) DECLSPEC_HIDDEN;
 
 
-extern void handle_dnd_enter_event( struct format_entry *formats, ULONG size ) DECLSPEC_HIDDEN;
-extern UINT handle_dnd_event( void *params ) DECLSPEC_HIDDEN;
-
 extern struct format_entry *import_xdnd_selection( Display *display, Window win, Atom selection,
                                                    Atom *targets, UINT count,
                                                    size_t *size ) DECLSPEC_HIDDEN;
@@ -677,7 +674,6 @@ extern XContext winContext DECLSPEC_HIDDEN;
 /* X context to associate an X cursor to a Win32 cursor handle */
 extern XContext cursor_context DECLSPEC_HIDDEN;
 
-extern void X11DRV_InitClipboard(void) DECLSPEC_HIDDEN;
 extern void X11DRV_SetFocus( HWND hwnd ) DECLSPEC_HIDDEN;
 extern void set_window_cursor( Window window, HCURSOR handle ) DECLSPEC_HIDDEN;
 extern void sync_window_cursor( Window window ) DECLSPEC_HIDDEN;
@@ -850,7 +846,17 @@ extern NTSTATUS x11drv_tablet_info( void *arg ) DECLSPEC_HIDDEN;
 extern NTSTATUS x11drv_xim_preedit_state( void *arg ) DECLSPEC_HIDDEN;
 extern NTSTATUS x11drv_xim_reset( void *arg ) DECLSPEC_HIDDEN;
 
-extern NTSTATUS WINAPI x11drv_post_drop( void *data, ULONG size ) DECLSPEC_HIDDEN;
+extern NTSTATUS WINAPI x11drv_dnd_enter_event( void *params, ULONG size ) DECLSPEC_HIDDEN;
+extern NTSTATUS WINAPI x11drv_dnd_position_event( void *params, ULONG size ) DECLSPEC_HIDDEN;
+extern NTSTATUS WINAPI x11drv_dnd_post_drop( void *data, ULONG size ) DECLSPEC_HIDDEN;
+
+extern NTSTATUS x11drv_dnd_drop_event( UINT arg ) DECLSPEC_HIDDEN;
+extern NTSTATUS x11drv_dnd_leave_event( UINT arg ) DECLSPEC_HIDDEN;
+
+
+extern NTSTATUS x11drv_client_func( enum x11drv_client_funcs func, const void *params,
+                                    ULONG size ) DECLSPEC_HIDDEN;
+extern NTSTATUS x11drv_client_call( enum client_callback func, UINT arg ) DECLSPEC_HIDDEN;
 
 /* GDI helpers */
 
diff --git a/dlls/winex11.drv/x11drv_main.c b/dlls/winex11.drv/x11drv_main.c
index 5347bc7c1a5..749fe2f761b 100644
--- a/dlls/winex11.drv/x11drv_main.c
+++ b/dlls/winex11.drv/x11drv_main.c
@@ -957,6 +957,21 @@ NTSTATUS CDECL X11DRV_D3DKMTCheckVidPnExclusiveOwnership( const D3DKMT_CHECKVIDP
 }
 
 
+NTSTATUS x11drv_client_func( enum x11drv_client_funcs id, const void *params, ULONG size )
+{
+    /* FIXME: use KeUserModeCallback instead */
+    NTSTATUS (WINAPI *func)( const void *, ULONG ) = ((void **)NtCurrentTeb()->Peb->KernelCallbackTable)[id];
+    return func( params, size );
+}
+
+
+NTSTATUS x11drv_client_call( enum client_callback func, UINT arg )
+{
+    struct client_callback_params params = { .id = func, .arg = arg };
+    return x11drv_client_func( client_func_callback, &params, sizeof(params) );
+}
+
+
 const unixlib_entry_t __wine_unix_call_funcs[] =
 {
     x11drv_clipboard_message,
diff --git a/dlls/winex11.drv/xdnd.c b/dlls/winex11.drv/xdnd.c
index 45205c836be..975fe7a114b 100644
--- a/dlls/winex11.drv/xdnd.c
+++ b/dlls/winex11.drv/xdnd.c
@@ -176,12 +176,13 @@ static HWND window_accepting_files(HWND hwnd)
 }
 
 /**************************************************************************
- * X11DRV_XDND_PositionEvent
+ *           x11drv_dnd_position_event
  *
  * Handle an XdndPosition event.
  */
-static BOOL handle_position_event( struct dnd_position_event_params *params )
+NTSTATUS WINAPI x11drv_dnd_position_event( void *arg, ULONG size )
 {
+    struct dnd_position_event_params *params = arg;
     int accept = 0; /* Assume we're not accepting */
     IDropTarget *dropTarget = NULL;
     DWORD effect = params->effect;
@@ -264,7 +265,7 @@ static BOOL handle_position_event( struct dnd_position_event_params *params )
     return accept ? effect : 0;
 }
 
-static DWORD handle_drop_event( struct dnd_drop_event_params *params )
+NTSTATUS x11drv_dnd_drop_event( UINT arg )
 {
     IDropTarget *dropTarget;
     DWORD effect = XDNDDropEffect;
@@ -318,7 +319,7 @@ static DWORD handle_drop_event( struct dnd_drop_event_params *params )
         /* Only send WM_DROPFILES if Drop didn't succeed or DROPEFFECT_NONE was set.
          * Doing both causes winamp to duplicate the dropped files (#29081) */
 
-        HWND hwnd_drop = window_accepting_files(window_from_point_dnd( params->hwnd, XDNDxy ));
+        HWND hwnd_drop = window_accepting_files(window_from_point_dnd( UlongToHandle(arg), XDNDxy ));
 
         if (hwnd_drop && X11DRV_XDND_HasHDROP())
         {
@@ -338,11 +339,11 @@ static DWORD handle_drop_event( struct dnd_drop_event_params *params )
 }
 
 /**************************************************************************
- * X11DRV_XDND_LeaveEvent
+ *           x11drv_dnd_leave_event
  *
  * Handle an XdndLeave event.
  */
-static NTSTATUS handle_leave_event(void)
+NTSTATUS x11drv_dnd_leave_event( UINT arg )
 {
     IDropTarget *dropTarget;
 
@@ -367,10 +368,11 @@ static NTSTATUS handle_leave_event(void)
 
 
 /**************************************************************************
- *           handle_dnd_enter_event
+ *           x11drv_dnd_enter_event
  */
-void handle_dnd_enter_event( struct format_entry *formats, ULONG size )
+NTSTATUS WINAPI x11drv_dnd_enter_event( void *params, ULONG size )
 {
+    struct format_entry *formats = params;
     XDNDAccepted = FALSE;
     X11DRV_XDND_FreeDragDropOp(); /* Clear previously cached data */
 
@@ -379,6 +381,7 @@ void handle_dnd_enter_event( struct format_entry *formats, ULONG size )
         memcpy( xdnd_formats, formats, size );
         xdnd_formats_end = (struct format_entry *)((char *)xdnd_formats + size);
     }
+    return 0;
 }
 
 
@@ -729,27 +732,7 @@ static IDataObjectVtbl xdndDataObjectVtbl =
 
 static IDataObject XDNDDataObject = { &xdndDataObjectVtbl };
 
-UINT handle_dnd_event( void *params )
-{
-
-    switch (*(UINT *)params)
-    {
-    case DND_DROP_EVENT:
-        return handle_drop_event( params );
-
-    case DND_LEAVE_EVENT:
-        return handle_leave_event();
-
-    case DND_POSITION_EVENT:
-        return handle_position_event( params );
-
-    default:
-        ERR( "invalid event\n" );
-        return 0;
-    }
-}
-
-NTSTATUS WINAPI x11drv_post_drop( void *data, ULONG size )
+NTSTATUS WINAPI x11drv_dnd_post_drop( void *data, ULONG size )
 {
     HDROP handle;
 
diff --git a/include/ntuser.h b/include/ntuser.h
index d11cffb8950..fdc43cac8ed 100644
--- a/include/ntuser.h
+++ b/include/ntuser.h
@@ -42,6 +42,9 @@ enum
     /* Vulkan support */
     NtUserCallVulkanDebugReportCallback,
     NtUserCallVulkanDebugUtilsCallback,
+    /* Driver-specific callbacks */
+    NtUserDriverCallbackFirst,
+    NtUserDriverCallbackLast = NtUserDriverCallbackFirst + 10,
     NtUserCallCount
 };
 
-- 
GitLab


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



More information about the wine-devel mailing list