From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/ntuser_private.h | 1 - dlls/win32u/win32u_private.h | 4 ++ dlls/win32u/window.c | 110 +++++++++++++++++++---------------- dlls/win32u/winstation.c | 6 +- server/protocol.def | 3 - server/window.c | 3 - 6 files changed, 66 insertions(+), 61 deletions(-)
diff --git a/dlls/win32u/ntuser_private.h b/dlls/win32u/ntuser_private.h index 1e989771934..33b5cdc3b27 100644 --- a/dlls/win32u/ntuser_private.h +++ b/dlls/win32u/ntuser_private.h @@ -65,7 +65,6 @@ typedef struct tagWND HICON hIconSmall; /* window's small icon */ HICON hIconSmall2; /* window's secondary small icon, derived from hIcon */ HIMC imc; /* window's input context */ - UINT dpi_context; /* window DPI awareness context */ struct window_surface *surface; /* Window surface if any */ struct list vulkan_surfaces; /* list of vulkan surfaces created for this window */ struct tagDIALOGINFO *dlgInfo; /* Dialog additional info (dialogs only) */ diff --git a/dlls/win32u/win32u_private.h b/dlls/win32u/win32u_private.h index a7bee5bd93a..22a6ff1145c 100644 --- a/dlls/win32u/win32u_private.h +++ b/dlls/win32u/win32u_private.h @@ -219,6 +219,10 @@ struct object_lock #define __SHARED_READ_FENCE __atomic_thread_fence( __ATOMIC_ACQUIRE ) #endif
+extern const shared_object_t *find_shared_session_object( object_id_t id, mem_size_t offset ); +extern void shared_object_acquire_seqlock( const shared_object_t *object, UINT64 *seq ); +extern BOOL shared_object_release_seqlock( const shared_object_t *object, UINT64 seq ); + /* Get shared session object's data pointer, must be called in a loop while STATUS_PENDING * is returned, lock must be initialized with OBJECT_LOCK_INIT. * diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c index 6937809f3d0..ca1d8e864a0 100644 --- a/dlls/win32u/window.c +++ b/dlls/win32u/window.c @@ -123,6 +123,55 @@ static BOOL get_user_entry_at( WORD index, unsigned short type, struct user_entr return TRUE; }
+static NTSTATUS try_get_user_object_shm( HANDLE handle, unsigned int type, struct object_lock *lock, + const object_shm_t **object_shm ) +{ + const shared_object_t *object; + UINT status = STATUS_SUCCESS; + BOOL valid = TRUE; + + if (lock->id) + { + assert( *object_shm != NULL ); + object = CONTAINING_RECORD( *object_shm, shared_object_t, shm ); + /* check object validity by comparing ids, within the object seqlock */ + valid = lock->id == object->id; + } + else + { + struct user_entry entry; + + if (!get_user_entry( handle, type, &entry, &handle )) object = NULL; + else object = find_shared_session_object( entry.id, entry.offset ); + + if (!object) status = STATUS_INVALID_HANDLE; + } + + if (!status && (!lock->id || !shared_object_release_seqlock( object, lock->seq ))) + { + shared_object_acquire_seqlock( object, &lock->seq ); + if (!(lock->id = object->id)) lock->id = -1; + *object_shm = &object->shm; + return STATUS_PENDING; + } + + if (!valid) memset( lock, 0, sizeof(*lock) ); /* object has been invalidated, clear the lock and start over */ + return status; +} + +static NTSTATUS get_shared_window( HWND hwnd, struct object_lock *lock, const window_shm_t **window_shm ) +{ + const object_shm_t **object_shm = (const object_shm_t **)window_shm; + UINT status = STATUS_SUCCESS; + + TRACE( "hwnd %p, lock %p, window_shm %p\n", hwnd, lock, window_shm ); + + do { status = try_get_user_object_shm( hwnd, NTUSER_OBJ_WINDOW, lock, object_shm ); } + while (!status && !lock->id); + + return status; +} + /*********************************************************************** * get_user_handle_ptr */ @@ -441,7 +490,6 @@ HWND WINAPI NtUserSetParent( HWND hwnd, HWND parent ) { old_parent = wine_server_ptr_handle( reply->old_parent ); win->parent = parent = wine_server_ptr_handle( reply->full_parent ); - win->dpi_context = reply->dpi_context; }
} @@ -851,63 +899,25 @@ BOOL is_window_enabled( HWND hwnd ) /* see GetWindowDpiAwarenessContext */ UINT get_window_dpi_awareness_context( HWND hwnd ) { - UINT ret = 0; - WND *win; + struct object_lock lock = OBJECT_LOCK_INIT; + const window_shm_t *window_shm; + UINT status, ctx = 0;
- if (!(win = get_win_ptr( hwnd ))) + while ((status = get_shared_window( hwnd, &lock, &window_shm )) == STATUS_PENDING) + ctx = window_shm->dpi_context; + if (status) { RtlSetLastWin32Error( ERROR_INVALID_WINDOW_HANDLE ); return 0; } - if (win == WND_DESKTOP) return NTUSER_DPI_PER_MONITOR_AWARE; - if (win != WND_OTHER_PROCESS) - { - ret = win->dpi_context; - release_win_ptr( win ); - } - else - { - SERVER_START_REQ( get_window_info ) - { - req->handle = wine_server_user_handle( hwnd ); - if (!wine_server_call_err( req )) ret = reply->dpi_context; - } - SERVER_END_REQ; - } - return ret; + + return ctx; }
/* see GetDpiForWindow */ UINT get_dpi_for_window( HWND hwnd ) { - WND *win; - UINT raw_dpi, context = 0; - - if (!(win = get_win_ptr( hwnd ))) - { - RtlSetLastWin32Error( ERROR_INVALID_WINDOW_HANDLE ); - return 0; - } - if (win == WND_DESKTOP) - { - RECT rect = {0}; - return monitor_dpi_from_rect( rect, get_thread_dpi(), &raw_dpi ); - } - if (win != WND_OTHER_PROCESS) - { - context = win->dpi_context; - release_win_ptr( win ); - } - else - { - SERVER_START_REQ( get_window_info ) - { - req->handle = wine_server_user_handle( hwnd ); - if (!wine_server_call_err( req )) context = reply->dpi_context; - } - SERVER_END_REQ; - } - + UINT raw_dpi, context = get_window_dpi_awareness_context( hwnd ); if (NTUSER_DPI_CONTEXT_IS_MONITOR_AWARE( context )) return get_win_monitor_dpi( hwnd, &raw_dpi ); return NTUSER_DPI_CONTEXT_GET_DPI( context ); } @@ -5279,7 +5289,6 @@ static WND *create_window_handle( HWND parent, HWND owner, UNICODE_STRING *name, full_parent = wine_server_ptr_handle( reply->parent ); full_owner = wine_server_ptr_handle( reply->owner ); extra_bytes = reply->extra; - dpi_context = reply->dpi_context; class = wine_server_get_ptr( reply->class_ptr ); } } @@ -5330,7 +5339,6 @@ static WND *create_window_handle( HWND parent, HWND owner, UNICODE_STRING *name, win->class = class; win->winproc = get_class_winproc( class ); win->cbWndExtra = extra_bytes; - win->dpi_context = dpi_context; list_init( &win->vulkan_surfaces ); set_user_handle_ptr( handle, win ); if (is_winproc_unicode( win->winproc, !ansi )) win->flags |= WIN_ISUNICODE; @@ -5583,9 +5591,9 @@ HWND WINAPI NtUserCreateWindowEx( DWORD ex_style, UNICODE_STRING *class_name, } else NtUserSetWindowLongPtr( hwnd, GWLP_ID, (ULONG_PTR)cs.hMenu, FALSE );
- win_dpi = NTUSER_DPI_CONTEXT_GET_DPI( win->dpi_context ); release_win_ptr( win );
+ win_dpi = get_dpi_for_window( hwnd ); if (parent) map_dpi_create_struct( &cs, win_dpi );
context = set_thread_dpi_awareness_context( get_window_dpi_awareness_context( hwnd )); diff --git a/dlls/win32u/winstation.c b/dlls/win32u/winstation.c index 2b04536d38f..eac7ed3602d 100644 --- a/dlls/win32u/winstation.c +++ b/dlls/win32u/winstation.c @@ -80,13 +80,13 @@ static struct session_thread_data *get_session_thread_data(void) return thread_info->session_data; }
-static void shared_object_acquire_seqlock( const shared_object_t *object, UINT64 *seq ) +void shared_object_acquire_seqlock( const shared_object_t *object, UINT64 *seq ) { while ((*seq = ReadNoFence64( &object->seq )) & 1) YieldProcessor(); __SHARED_READ_FENCE; }
-static BOOL shared_object_release_seqlock( const shared_object_t *object, UINT64 seq ) +BOOL shared_object_release_seqlock( const shared_object_t *object, UINT64 seq ) { __SHARED_READ_FENCE; return ReadNoFence64( &object->seq ) == seq; @@ -173,7 +173,7 @@ static NTSTATUS find_shared_session_block( SIZE_T offset, SIZE_T size, struct se return status; }
-static const shared_object_t *find_shared_session_object( object_id_t id, mem_size_t offset ) +const shared_object_t *find_shared_session_object( object_id_t id, mem_size_t offset ) { struct session_block *block = NULL; const shared_object_t *object; diff --git a/server/protocol.def b/server/protocol.def index 7ed53f618d3..58c88d34666 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -2555,7 +2555,6 @@ enum message_type user_handle_t owner; /* full handle of owner */ int extra; /* number of extra bytes */ client_ptr_t class_ptr; /* pointer to class in client address space */ - unsigned int dpi_context; /* window DPI context */ @END
@@ -2590,7 +2589,6 @@ enum message_type @REPLY user_handle_t last_active; /* last active popup */ int is_unicode; /* ANSI or unicode */ - unsigned int dpi_context; /* window DPI context */ @END
@@ -2630,7 +2628,6 @@ enum message_type @REPLY user_handle_t old_parent; /* old parent window */ user_handle_t full_parent; /* full handle of new parent */ - unsigned int dpi_context; /* new DPI context */ @END
diff --git a/server/window.c b/server/window.c index 78245b93707..1b0786835c0 100644 --- a/server/window.c +++ b/server/window.c @@ -2234,7 +2234,6 @@ DECL_HANDLER(create_window) reply->parent = win->parent ? win->parent->handle : 0; reply->owner = win->owner; reply->extra = win->nb_extra_bytes; - reply->dpi_context = win->shared->dpi_context; reply->class_ptr = get_class_client_ptr( win->class ); }
@@ -2255,7 +2254,6 @@ DECL_HANDLER(set_parent) reply->old_parent = win->parent->handle; reply->full_parent = parent ? parent->handle : 0; set_parent_window( win, parent ); - reply->dpi_context = win->shared->dpi_context; }
@@ -2349,7 +2347,6 @@ DECL_HANDLER(get_window_info)
reply->last_active = win->handle; reply->is_unicode = win->is_unicode; - reply->dpi_context = win->shared->dpi_context;
if (get_user_object( win->last_active, NTUSER_OBJ_WINDOW )) reply->last_active = win->last_active; }