[PATCH v3 0/6] MR11106: server: Move window extra info / id / instance / user data to shared memory.
-- v3: server: Move window user data to shared memory. server: Move window instance to the shared memory. server: Move window id / menu to the shared memory. win32u: Return value directly from get_window_extra. server: Move window extra data to the shared memory. win32u: Introduce a server_set_window_info helper. https://gitlab.winehq.org/wine/wine/-/merge_requests/11106
From: Rémi Bernon <rbernon@codeweavers.com> --- dlls/win32u/class.c | 8 ++-- dlls/win32u/window.c | 100 ++++++++++++++++++++++--------------------- 2 files changed, 56 insertions(+), 52 deletions(-) diff --git a/dlls/win32u/class.c b/dlls/win32u/class.c index bc8d6a9d5d2..adcbadcd119 100644 --- a/dlls/win32u/class.c +++ b/dlls/win32u/class.c @@ -922,7 +922,7 @@ INT WINAPI NtUserGetClassName( HWND hwnd, BOOL real, UNICODE_STRING *name ) } /* Set class info with the wine server. */ -static BOOL set_server_info( HWND hwnd, INT offset, LONG_PTR newval, UINT size, ULONG_PTR *oldval ) +static BOOL server_set_class_info( HWND hwnd, INT offset, LONG_PTR newval, UINT size, ULONG_PTR *oldval ) { BOOL ret; @@ -956,18 +956,18 @@ static ULONG_PTR set_class_long_size( HWND hwnd, INT offset, LONG_PTR newval, UI case GCLP_HICONSM: case GCLP_HMODULE: case GCLP_MENUNAME: - set_server_info( hwnd, offset, newval, size, &retval ); + server_set_class_info( hwnd, offset, newval, size, &retval ); break; case GCLP_WNDPROC: newval = (ULONG_PTR)alloc_winproc( (WNDPROC)newval, ansi ); - if (!set_server_info( hwnd, offset, newval, size, &retval )) break; + if (!server_set_class_info( hwnd, offset, newval, size, &retval )) break; retval = (ULONG_PTR)get_winproc( (WNDPROC)retval, ansi ); break; case GCL_CBCLSEXTRA: /* cannot change this one */ RtlSetLastWin32Error( ERROR_INVALID_PARAMETER ); break; default: - if (offset >= 0) set_server_info( hwnd, offset, newval, size, &retval ); + if (offset >= 0) server_set_class_info( hwnd, offset, newval, size, &retval ); else RtlSetLastWin32Error( ERROR_INVALID_INDEX ); break; } diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c index 3e47becca16..6df31fa9120 100644 --- a/dlls/win32u/window.c +++ b/dlls/win32u/window.c @@ -1289,10 +1289,29 @@ static WORD get_window_word( HWND hwnd, INT offset ) return get_window_long_size( hwnd, offset, sizeof(WORD), TRUE, FALSE ); } +/* Set window info with the wine server. */ +static BOOL server_set_window_info( HWND hwnd, INT offset, LONG_PTR newval, UINT size, LONG_PTR *oldval ) +{ + BOOL ret; + + SERVER_START_REQ( set_window_info ) + { + req->handle = wine_server_user_handle( hwnd ); + req->offset = offset; + req->size = size; + req->new_info = newval; + ret = !wine_server_call_err( req ); + *oldval = reply->old_info; + } + SERVER_END_REQ; + return ret; +} + UINT set_window_style_bits( HWND hwnd, UINT set_bits, UINT clear_bits ) { BOOL ok, made_visible = FALSE; STYLESTRUCT style; + LONG_PTR oldval; WND *win = get_win_ptr( hwnd ); if (!win || win == WND_DESKTOP) return 0; @@ -1309,18 +1328,11 @@ UINT set_window_style_bits( HWND hwnd, UINT set_bits, UINT clear_bits ) release_win_ptr( win ); return style.styleNew; } - SERVER_START_REQ( set_window_info ) + if ((ok = server_set_window_info( hwnd, GWL_STYLE, style.styleNew, 0, &oldval ))) { - req->handle = wine_server_user_handle( hwnd ); - req->offset = GWL_STYLE; - req->new_info = style.styleNew; - if ((ok = !wine_server_call( req ))) - { - style.styleOld = reply->old_info; - win->dwStyle = style.styleNew; - } + style.styleOld = oldval; + win->dwStyle = style.styleNew; } - SERVER_END_REQ; if (ok && ((style.styleOld ^ style.styleNew) & WS_VISIBLE)) { @@ -1390,7 +1402,7 @@ static LONG_PTR set_window_long_internal( HWND hwnd, INT offset, UINT size, LONG_PTR newval, BOOL ansi, BOOL internal ) { BOOL ok, made_visible = FALSE, layered = FALSE; - LONG_PTR retval = 0; + LONG_PTR retval = 0, oldval; STYLESTRUCT style; WND *win; @@ -1503,47 +1515,39 @@ static LONG_PTR set_window_long_internal( HWND hwnd, INT offset, UINT size, if (offset == GWLP_WNDPROC) newval = !!(win->flags & WIN_ISUNICODE); if (offset == GWLP_USERDATA && size == sizeof(WORD)) newval = MAKELONG( newval, win->userdata >> 16 ); - SERVER_START_REQ( set_window_info ) + if ((ok = server_set_window_info( hwnd, offset, newval, size, &oldval ))) { - req->handle = wine_server_user_handle( hwnd ); - req->offset = offset; - req->new_info = newval; - req->size = size; - if ((ok = !wine_server_call_err( req ))) + switch (offset) { - switch (offset) - { - case GWL_STYLE: - win->dwStyle = newval; - win->dwExStyle = fix_exstyle(win->dwStyle, win->dwExStyle); - retval = reply->old_info; - break; - case GWL_EXSTYLE: - win->dwExStyle = newval; - retval = reply->old_info; - break; - case GWLP_ID: - win->wIDmenu = newval; - retval = reply->old_info; - break; - case GWLP_HINSTANCE: - win->hInstance = (HINSTANCE)newval; - retval = reply->old_info; - break; - case GWLP_WNDPROC: - break; - case GWLP_USERDATA: - win->userdata = newval; - retval = reply->old_info; - break; - default: - set_win_data( (char *)win->wExtra + offset, newval, size ); - retval = reply->old_info; - break; - } + case GWL_STYLE: + win->dwStyle = newval; + win->dwExStyle = fix_exstyle(win->dwStyle, win->dwExStyle); + retval = oldval; + break; + case GWL_EXSTYLE: + win->dwExStyle = newval; + retval = oldval; + break; + case GWLP_ID: + win->wIDmenu = newval; + retval = oldval; + break; + case GWLP_HINSTANCE: + win->hInstance = (HINSTANCE)newval; + retval = oldval; + break; + case GWLP_WNDPROC: + break; + case GWLP_USERDATA: + win->userdata = newval; + retval = oldval; + break; + default: + set_win_data( (char *)win->wExtra + offset, newval, size ); + retval = oldval; + break; } } - SERVER_END_REQ; if (offset == GWL_EXSTYLE && ((style.styleOld ^ style.styleNew) & WS_EX_LAYERED)) layered = TRUE; if ((offset == GWL_STYLE && ((style.styleOld ^ style.styleNew) & WS_VISIBLE)) || layered) -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11106
From: Rémi Bernon <rbernon@codeweavers.com> --- dlls/win32u/ntuser_private.h | 2 - dlls/win32u/window.c | 71 +++++---------------- server/protocol.def | 4 +- server/window.c | 115 +++++++++++++++-------------------- 4 files changed, 69 insertions(+), 123 deletions(-) diff --git a/dlls/win32u/ntuser_private.h b/dlls/win32u/ntuser_private.h index 45545dcd554..6db740c2d75 100644 --- a/dlls/win32u/ntuser_private.h +++ b/dlls/win32u/ntuser_private.h @@ -74,9 +74,7 @@ typedef struct tagWND int swap_interval; /* OpenGL surface swap interval */ int pixel_format; /* Pixel format set by the graphics driver */ int clip_clients; /* Has client surfaces that needs to be clipped out */ - unsigned int cbWndExtra; /* class cbWndExtra at window creation */ DWORD_PTR userdata; /* User private data */ - DWORD wExtra[1]; /* Window extra bytes */ } WND; /* WND flags values */ diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c index 6df31fa9120..6b2c0ea87d8 100644 --- a/dlls/win32u/window.c +++ b/dlls/win32u/window.c @@ -1113,7 +1113,7 @@ static HWND get_last_active_popup( HWND hwnd ) return retval; } -static BOOL get_window_extra( HWND hwnd, WND *win, UINT offset, UINT size, LONG_PTR *ret, BOOL internal ) +static BOOL get_window_extra( HWND hwnd, UINT offset, UINT size, LONG_PTR *ret, BOOL internal ) { struct object_lock lock = OBJECT_LOCK_INIT; const window_shm_t *window_shm = NULL; @@ -1122,9 +1122,9 @@ static BOOL get_window_extra( HWND hwnd, WND *win, UINT offset, UINT size, LONG_ while ((status = get_shared_window( hwnd, &lock, &window_shm )) == STATUS_PENDING) { - valid = size <= win->cbWndExtra && offset <= win->cbWndExtra - size && + valid = size <= window_shm->extra_size && offset <= window_shm->extra_size - size && (internal || offset >= window_shm->private_size); - if (valid) memcpy( ret, (char *)win->wExtra + offset, size ); + if (valid) memcpy( ret, (char *)window_shm->extra + offset, size ); } if (status) RtlSetLastWin32Error( ERROR_INVALID_WINDOW_HANDLE ); @@ -1132,25 +1132,6 @@ static BOOL get_window_extra( HWND hwnd, WND *win, UINT offset, UINT size, LONG_ return valid; } -/* helper for set_window_long */ -static inline void set_win_data( void *ptr, LONG_PTR val, UINT size ) -{ - if (size == sizeof(WORD)) - { - WORD newval = val; - memcpy( ptr, &newval, sizeof(newval) ); - } - else if (size == sizeof(DWORD)) - { - DWORD newval = val; - memcpy( ptr, &newval, sizeof(newval) ); - } - else - { - memcpy( ptr, &val, sizeof(val) ); - } -} - BOOL is_iconic( HWND hwnd ) { return (get_window_long( hwnd, GWL_STYLE ) & WS_MINIMIZE) != 0; @@ -1177,13 +1158,20 @@ static LONG_PTR get_window_long_size( HWND hwnd, INT offset, UINT size, BOOL ans LONG_PTR retval = 0; WND *win; - if (offset == GWLP_HWNDPARENT) + switch (offset) + { + default: + if (offset < 0) break; + if (!get_window_extra( hwnd, offset, size, &retval, internal )) return 0; + return retval; + case GWLP_HWNDPARENT: { HWND parent = NtUserGetAncestor( hwnd, GA_PARENT ); if (parent == get_desktop_window()) parent = get_window_relative( hwnd, GW_OWNER ); return (ULONG_PTR)parent; } + } if (!(win = get_win_ptr( hwnd ))) { @@ -1233,13 +1221,6 @@ static LONG_PTR get_window_long_size( HWND hwnd, INT offset, UINT size, BOOL ans /* now we have a valid win */ - if (offset >= 0) - { - if (!get_window_extra( hwnd, win, offset, size, &retval, internal )) retval = 0; - release_win_ptr( win ); - return retval; - } - switch(offset) { case GWLP_USERDATA: retval = win->userdata; break; @@ -1290,7 +1271,7 @@ static WORD get_window_word( HWND hwnd, INT offset ) } /* Set window info with the wine server. */ -static BOOL server_set_window_info( HWND hwnd, INT offset, LONG_PTR newval, UINT size, LONG_PTR *oldval ) +static BOOL server_set_window_info( HWND hwnd, INT offset, LONG_PTR newval, UINT size, LONG_PTR *oldval, BOOL internal ) { BOOL ret; @@ -1300,6 +1281,7 @@ static BOOL server_set_window_info( HWND hwnd, INT offset, LONG_PTR newval, UINT req->offset = offset; req->size = size; req->new_info = newval; + req->internal = internal; ret = !wine_server_call_err( req ); *oldval = reply->old_info; } @@ -1328,7 +1310,7 @@ UINT set_window_style_bits( HWND hwnd, UINT set_bits, UINT clear_bits ) release_win_ptr( win ); return style.styleNew; } - if ((ok = server_set_window_info( hwnd, GWL_STYLE, style.styleNew, 0, &oldval ))) + if ((ok = server_set_window_info( hwnd, GWL_STYLE, style.styleNew, 0, &oldval, FALSE ))) { style.styleOld = oldval; win->dwStyle = style.styleNew; @@ -1493,29 +1475,12 @@ static LONG_PTR set_window_long_internal( HWND hwnd, INT offset, UINT size, /* update is_unicode flag on the server side */ break; } - case GWLP_ID: - case GWLP_HINSTANCE: - case GWLP_USERDATA: - break; - default: - if (!get_window_extra( hwnd, win, offset, size, &retval, internal )) - { - release_win_ptr( win ); - return 0; - } - if (retval == newval) - { - /* already set to the same value */ - release_win_ptr( win ); - return newval; - } - break; } if (offset == GWLP_WNDPROC) newval = !!(win->flags & WIN_ISUNICODE); if (offset == GWLP_USERDATA && size == sizeof(WORD)) newval = MAKELONG( newval, win->userdata >> 16 ); - if ((ok = server_set_window_info( hwnd, offset, newval, size, &oldval ))) + if ((ok = server_set_window_info( hwnd, offset, newval, size, &oldval, internal ))) { switch (offset) { @@ -1543,7 +1508,6 @@ static LONG_PTR set_window_long_internal( HWND hwnd, INT offset, UINT size, retval = oldval; break; default: - set_win_data( (char *)win->wExtra + offset, newval, size ); retval = oldval; break; } @@ -5529,7 +5493,6 @@ static WND *create_window_handle( HWND parent, HWND owner, UNICODE_STRING *name, UINT dpi_context = get_thread_dpi_awareness_context(); HWND handle = 0, full_parent = 0, full_owner = 0; struct tagCLASS *class = NULL; - int extra_bytes = 0; WND *win; SERVER_START_REQ( create_window ) @@ -5547,7 +5510,6 @@ static WND *create_window_handle( HWND parent, HWND owner, UNICODE_STRING *name, handle = wine_server_ptr_handle( reply->handle ); full_parent = wine_server_ptr_handle( reply->parent ); full_owner = wine_server_ptr_handle( reply->owner ); - extra_bytes = reply->extra; class = wine_server_get_ptr( reply->class_ptr ); } } @@ -5559,7 +5521,7 @@ static WND *create_window_handle( HWND parent, HWND owner, UNICODE_STRING *name, return NULL; } - if (!(win = calloc( 1, FIELD_OFFSET(WND, wExtra) + extra_bytes ))) + if (!(win = calloc( 1, sizeof(*win) ))) { SERVER_START_REQ( destroy_window ) { @@ -5597,7 +5559,6 @@ static WND *create_window_handle( HWND parent, HWND owner, UNICODE_STRING *name, win->class = class; win->winproc = get_class_winproc( class ); win->hInstance = instance; - win->cbWndExtra = extra_bytes; set_user_handle_ptr( handle, win ); if (is_winproc_unicode( win->winproc, !ansi )) win->flags |= WIN_ISUNICODE; return win; diff --git a/server/protocol.def b/server/protocol.def index e7d966613ac..44620b18018 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -1069,6 +1069,8 @@ typedef volatile struct unsigned int dpi_context; /* DPI awareness context */ unsigned int fnid; /* builtin class FNID, or 0 */ data_size_t private_size; /* length of private extra bytes range */ + data_size_t extra_size; /* size of the extra info */ + char extra[]; /* extra bytes storage */ } window_shm_t; typedef volatile union @@ -2632,7 +2634,6 @@ enum message_type user_handle_t handle; /* created window */ user_handle_t parent; /* full handle of parent */ 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 */ @END @@ -2690,6 +2691,7 @@ enum message_type int offset; /* offset of the info */ data_size_t size; /* size of the info value to write */ lparam_t new_info; /* new window info value */ + unsigned int internal; /* set internal control info */ @REPLY lparam_t old_info; /* previous window info value */ @END diff --git a/server/window.c b/server/window.c index 897034159a9..ab5b05a5952 100644 --- a/server/window.c +++ b/server/window.c @@ -92,11 +92,11 @@ struct window int prop_inuse; /* number of in-use window properties */ int prop_alloc; /* number of allocated window properties */ struct property *properties; /* window properties array */ - int nb_extra_bytes; /* number of extra bytes */ - char *extra_bytes; /* extra bytes storage */ window_shm_t *shared; /* window in session shared memory */ }; +C_ASSERT( sizeof(window_shm_t) == offsetof(window_shm_t, extra[0]) ); + static void window_dump( struct object *obj, int verbose ); static void window_destroy( struct object *obj ); @@ -177,12 +177,6 @@ static void window_destroy( struct object *obj ) if (win->class) release_class( win->class ); free( win->text ); - if (win->nb_extra_bytes) - { - memset( win->extra_bytes, 0x55, win->nb_extra_bytes ); - free( win->extra_bytes ); - } - if (win->shared) free_shared_object( win->shared ); } @@ -616,7 +610,7 @@ void post_desktop_message( struct desktop *desktop, unsigned int message, static struct window *create_window( struct window *parent, struct window *owner, atom_t atom, mod_handle_t class_instance, mod_handle_t instance ) { - data_size_t extra_bytes, private_size; + data_size_t extra_size, private_size; struct window *win = NULL; struct desktop *desktop; struct window_class *class; @@ -630,7 +624,7 @@ static struct window *create_window( struct window *parent, struct window *owner release_object( desktop ); return NULL; } - fnid = get_class_fnid( class, &extra_bytes, &private_size ); + fnid = get_class_fnid( class, &extra_size, &private_size ); if (!parent) /* null parent is only allowed for desktop or HWND_MESSAGE top window */ { @@ -679,29 +673,23 @@ static struct window *create_window( struct window *parent, struct window *owner win->prop_inuse = 0; win->prop_alloc = 0; win->properties = NULL; - win->nb_extra_bytes = 0; - win->extra_bytes = NULL; win->shared = NULL; win->window_rect = win->visible_rect = win->surface_rect = win->client_rect = empty_rect; list_init( &win->children ); list_init( &win->unlinked ); - if (!(win->shared = alloc_shared_object( sizeof(*win->shared) ))) goto failed; + if (!(win->shared = alloc_shared_object( offsetof(window_shm_t, extra[extra_size]) ))) goto failed; SHARED_WRITE_BEGIN( win->shared, window_shm_t ) { shared->class = class_locator; shared->dpi_context = NTUSER_DPI_PER_MONITOR_AWARE; shared->fnid = fnid; shared->private_size = private_size; + shared->extra_size = extra_size; + memset( (void *)shared->extra, 0, extra_size ); } SHARED_WRITE_END; - if (extra_bytes) - { - if (!(win->extra_bytes = mem_alloc( extra_bytes ))) goto failed; - memset( win->extra_bytes, 0, extra_bytes ); - win->nb_extra_bytes = extra_bytes; - } if (!(win->handle = alloc_user_handle( win, win->shared, NTUSER_OBJ_WINDOW ))) goto failed; win->last_active = win->handle; @@ -2273,7 +2261,6 @@ DECL_HANDLER(create_window) reply->handle = win->handle; reply->parent = win->parent ? win->parent->handle : 0; reply->owner = win->owner; - reply->extra = win->nb_extra_bytes; reply->class_ptr = get_class_client_ptr( win->class ); } @@ -2281,7 +2268,7 @@ DECL_HANDLER(create_window) /* Set the window builtin class FNID */ DECL_HANDLER(set_window_fnid) { - data_size_t extra_bytes, private_size; + data_size_t extra_size, private_size; struct obj_locator class_locator; struct window_class *class; struct window *win; @@ -2291,7 +2278,7 @@ DECL_HANDLER(set_window_fnid) if (is_desktop_window( win ) && win->thread != current) return set_error( STATUS_ACCESS_DENIED ); if (!(class = grab_class( current->process, req->atom, 0, &class_locator ))) return; - fnid = get_class_fnid( class, &extra_bytes, &private_size ); + fnid = get_class_fnid( class, &extra_size, &private_size ); if (win->shared->fnid && win->shared->fnid != fnid) set_error( STATUS_INVALID_PARAMETER ); else SHARED_WRITE_BEGIN( win->shared, window_shm_t ) @@ -2425,14 +2412,7 @@ DECL_HANDLER(get_window_info) case GWLP_WNDPROC: reply->info = win->is_unicode; break; case GWLP_USERDATA: reply->info = win->user_data; break; default: - if (req->size > sizeof(reply->info) || req->offset < 0 || - req->offset > win->nb_extra_bytes - (int)req->size || - req->offset < win->shared->private_size) - { - set_win32_error( ERROR_INVALID_INDEX ); - break; - } - memcpy( &reply->info, win->extra_bytes + req->offset, req->size ); + if (req->size) set_win32_error( ERROR_INVALID_INDEX ); break; } } @@ -2465,46 +2445,51 @@ DECL_HANDLER(set_window_info) return; } - switch (req->offset) + SHARED_WRITE_BEGIN( win->shared, window_shm_t ) { - case GWL_STYLE: - reply->old_info = win->style; - win->style = req->new_info; - fix_window_ex_style( win ); - /* changing window style triggers a non-client paint */ - win->paint_flags |= PAINT_NONCLIENT; - break; - case GWL_EXSTYLE: - reply->old_info = win->ex_style; - set_window_ex_style( win, req->new_info ); - break; - case GWLP_ID: - reply->old_info = win->id; - win->id = req->new_info; - break; - case GWLP_HINSTANCE: - reply->old_info = win->instance; - win->instance = req->new_info; - break; - case GWLP_WNDPROC: - reply->old_info = win->is_unicode; - win->is_unicode = req->new_info; - break; - case GWLP_USERDATA: - reply->old_info = win->user_data; - win->user_data = req->new_info; - break; - default: - if (req->size > sizeof(req->new_info) || req->offset < 0 || - req->offset > win->nb_extra_bytes - (int)req->size) + switch (req->offset) { - set_win32_error( ERROR_INVALID_INDEX ); + case GWL_STYLE: + reply->old_info = win->style; + win->style = req->new_info; + fix_window_ex_style( win ); + /* changing window style triggers a non-client paint */ + win->paint_flags |= PAINT_NONCLIENT; + break; + case GWL_EXSTYLE: + reply->old_info = win->ex_style; + set_window_ex_style( win, req->new_info ); + break; + case GWLP_ID: + reply->old_info = win->id; + win->id = req->new_info; + break; + case GWLP_HINSTANCE: + reply->old_info = win->instance; + win->instance = req->new_info; + break; + case GWLP_WNDPROC: + reply->old_info = win->is_unicode; + win->is_unicode = req->new_info; + break; + case GWLP_USERDATA: + reply->old_info = win->user_data; + win->user_data = req->new_info; + break; + default: + if (req->size > sizeof(req->new_info) || req->offset < 0 || + req->offset > shared->extra_size - (int)req->size || + (!req->internal && req->offset < shared->private_size)) + { + set_win32_error( ERROR_INVALID_INDEX ); + break; + } + memcpy( &reply->old_info, (char *)shared->extra + req->offset, req->size ); + memcpy( (char *)shared->extra + req->offset, &req->new_info, req->size ); break; } - memcpy( &reply->old_info, win->extra_bytes + req->offset, req->size ); - memcpy( win->extra_bytes + req->offset, &req->new_info, req->size ); - break; } + SHARED_WRITE_END; } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11106
From: Rémi Bernon <rbernon@codeweavers.com> --- dlls/win32u/window.c | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c index 6b2c0ea87d8..447c7f119dd 100644 --- a/dlls/win32u/window.c +++ b/dlls/win32u/window.c @@ -1113,23 +1113,33 @@ static HWND get_last_active_popup( HWND hwnd ) return retval; } -static BOOL get_window_extra( HWND hwnd, UINT offset, UINT size, LONG_PTR *ret, BOOL internal ) +static LONG_PTR get_window_long_shm( HWND hwnd, UINT offset, UINT size, BOOL internal ) { struct object_lock lock = OBJECT_LOCK_INIT; const window_shm_t *window_shm = NULL; BOOL valid = FALSE; - UINT status; + LONG_PTR ret = 0; + NTSTATUS status; while ((status = get_shared_window( hwnd, &lock, &window_shm )) == STATUS_PENDING) { valid = size <= window_shm->extra_size && offset <= window_shm->extra_size - size && (internal || offset >= window_shm->private_size); - if (valid) memcpy( ret, (char *)window_shm->extra + offset, size ); + if (valid) memcpy( &ret, (char *)window_shm->extra + offset, size ); + } + if (status) + { + RtlSetLastWin32Error( ERROR_INVALID_WINDOW_HANDLE ); + return 0; + } + if (!valid) + { + WARN( "Invalid window %p offset %d size %u\n", hwnd, offset, size ); + RtlSetLastWin32Error( ERROR_INVALID_INDEX ); + return 0; } - if (status) RtlSetLastWin32Error( ERROR_INVALID_WINDOW_HANDLE ); - else if (!valid) RtlSetLastWin32Error( ERROR_INVALID_INDEX ); - return valid; + return ret; } BOOL is_iconic( HWND hwnd ) @@ -1162,8 +1172,7 @@ static LONG_PTR get_window_long_size( HWND hwnd, INT offset, UINT size, BOOL ans { default: if (offset < 0) break; - if (!get_window_extra( hwnd, offset, size, &retval, internal )) return 0; - return retval; + return get_window_long_shm( hwnd, offset, size, internal ); case GWLP_HWNDPARENT: { HWND parent = NtUserGetAncestor( hwnd, GA_PARENT ); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11106
From: Rémi Bernon <rbernon@codeweavers.com> --- dlls/win32u/ntuser_private.h | 1 - dlls/win32u/window.c | 32 +++++++++++++++++++------------- server/protocol.def | 6 ++++++ server/window.c | 8 +++----- 4 files changed, 28 insertions(+), 19 deletions(-) diff --git a/dlls/win32u/ntuser_private.h b/dlls/win32u/ntuser_private.h index 6db740c2d75..426d074f935 100644 --- a/dlls/win32u/ntuser_private.h +++ b/dlls/win32u/ntuser_private.h @@ -58,7 +58,6 @@ typedef struct tagWND struct win_scroll_bar_info *pScroll; /* Scroll-bar info */ UINT dwStyle; /* Window style (from CreateWindow) */ UINT dwExStyle; /* Extended style (from CreateWindowEx) */ - UINT_PTR wIDmenu; /* ID or hmenu (from CreateWindow) */ UINT helpContext; /* Help context ID */ UINT flags; /* Misc. flags (see below) */ HMENU hSysMenu; /* window's copy of System Menu */ diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c index 447c7f119dd..56e7093a93a 100644 --- a/dlls/win32u/window.c +++ b/dlls/win32u/window.c @@ -1117,15 +1117,21 @@ static LONG_PTR get_window_long_shm( HWND hwnd, UINT offset, UINT size, BOOL int { struct object_lock lock = OBJECT_LOCK_INIT; const window_shm_t *window_shm = NULL; - BOOL valid = FALSE; + BOOL valid = TRUE; LONG_PTR ret = 0; NTSTATUS status; while ((status = get_shared_window( hwnd, &lock, &window_shm )) == STATUS_PENDING) { - valid = size <= window_shm->extra_size && offset <= window_shm->extra_size - size && - (internal || offset >= window_shm->private_size); - if (valid) memcpy( &ret, (char *)window_shm->extra + offset, size ); + switch (offset) + { + case GWLP_ID: ret = window_shm->info.id; break; + default: + valid = size <= window_shm->extra_size && offset <= window_shm->extra_size - size && + (internal || offset >= window_shm->private_size); + if (valid) memcpy( &ret, (char *)window_shm->extra + offset, size ); + break; + } } if (status) { @@ -1172,6 +1178,8 @@ static LONG_PTR get_window_long_size( HWND hwnd, INT offset, UINT size, BOOL ans { default: if (offset < 0) break; + /* fallthrough */ + case GWLP_ID: return get_window_long_shm( hwnd, offset, size, internal ); case GWLP_HWNDPARENT: { @@ -1199,7 +1207,6 @@ static LONG_PTR get_window_long_size( HWND hwnd, INT offset, UINT size, BOOL ans return retval; case GWL_EXSTYLE: case GWLP_USERDATA: - case GWLP_ID: case GWLP_HINSTANCE: return 0; case GWLP_WNDPROC: @@ -1235,7 +1242,6 @@ static LONG_PTR get_window_long_size( HWND hwnd, INT offset, UINT size, BOOL ans case GWLP_USERDATA: retval = win->userdata; break; case GWL_STYLE: retval = win->dwStyle; break; case GWL_EXSTYLE: retval = win->dwExStyle; break; - case GWLP_ID: retval = win->wIDmenu; break; case GWLP_HINSTANCE: retval = (ULONG_PTR)win->hInstance; break; case GWLP_WNDPROC: /* This looks like a hack only for the edit control (see tests). This makes these controls @@ -1268,6 +1274,11 @@ ULONG_PTR get_window_long_ptr( HWND hwnd, INT offset, BOOL ansi ) return get_window_long_size( hwnd, offset, sizeof(LONG_PTR), ansi, FALSE ); } +static HMENU get_window_menu( HWND hwnd ) +{ + return (HMENU)get_window_long_ptr( hwnd, GWLP_ID, FALSE ); +} + /* see GetWindowWord */ static WORD get_window_word( HWND hwnd, INT offset ) { @@ -1502,10 +1513,6 @@ static LONG_PTR set_window_long_internal( HWND hwnd, INT offset, UINT size, win->dwExStyle = newval; retval = oldval; break; - case GWLP_ID: - win->wIDmenu = newval; - retval = oldval; - break; case GWLP_HINSTANCE: win->hInstance = (HINSTANCE)newval; retval = oldval; @@ -5295,7 +5302,7 @@ LRESULT destroy_window( HWND hwnd ) if (!(win = get_win_ptr( hwnd )) || win == WND_OTHER_PROCESS) return 0; if ((win->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD) - menu = (HMENU)win->wIDmenu; + menu = get_window_menu( hwnd ); sys_menu = win->hSysMenu; free_dce( win->dce, hwnd, &drawables ); win->dce = NULL; @@ -5447,7 +5454,7 @@ void destroy_thread_windows(void) /* recycle the WND struct as a destroy_entry struct */ entry = (struct destroy_entry *)win; tmp.handle = win->handle; - if (!is_child) tmp.menu = (HMENU)win->wIDmenu; + if (!is_child) tmp.menu = get_window_menu( handle ); tmp.sys_menu = win->hSysMenu; tmp.current_drawable = win->current_drawable; tmp.unused_drawable = win->unused_drawable; @@ -5744,7 +5751,6 @@ HWND WINAPI NtUserCreateWindowEx( DWORD ex_style, UNICODE_STRING *class_name, win->text = NULL; win->dwStyle = style; win->dwExStyle = ex_style; - win->wIDmenu = 0; win->helpContext = 0; win->pScroll = NULL; win->userdata = 0; diff --git a/server/protocol.def b/server/protocol.def index 44620b18018..973f091ecab 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -1063,6 +1063,11 @@ typedef volatile struct char extra[]; /* extra bytes storage */ } class_shm_t; +struct window_info +{ + lparam_t id; /* window id */ +}; + typedef volatile struct { struct obj_locator class; /* object locator for the window class shared object */ @@ -1070,6 +1075,7 @@ typedef volatile struct unsigned int fnid; /* builtin class FNID, or 0 */ data_size_t private_size; /* length of private extra bytes range */ data_size_t extra_size; /* size of the extra info */ + struct window_info info; /* window info (GWLP_*) */ char extra[]; /* extra bytes storage */ } window_shm_t; diff --git a/server/window.c b/server/window.c index ab5b05a5952..1302291be64 100644 --- a/server/window.c +++ b/server/window.c @@ -74,7 +74,6 @@ struct window struct region *update_region; /* update region (relative to window rect) */ unsigned int style; /* window style */ unsigned int ex_style; /* window extended style */ - lparam_t id; /* window id */ mod_handle_t instance; /* creator instance */ unsigned int is_unicode : 1; /* ANSI or unicode */ unsigned int is_linked : 1; /* is it linked into the parent z-order list? */ @@ -658,7 +657,6 @@ static struct window *create_window( struct window *parent, struct window *owner win->update_region = NULL; win->style = 0; win->ex_style = 0; - win->id = 0; win->instance = instance; win->is_unicode = 1; win->is_linked = 0; @@ -686,6 +684,7 @@ static struct window *create_window( struct window *parent, struct window *owner shared->fnid = fnid; shared->private_size = private_size; shared->extra_size = extra_size; + memset( (void *)&shared->info, 0, sizeof(shared->info) ); memset( (void *)shared->extra, 0, extra_size ); } SHARED_WRITE_END; @@ -2407,7 +2406,6 @@ DECL_HANDLER(get_window_info) { case GWL_STYLE: reply->info = win->style; break; case GWL_EXSTYLE: reply->info = win->ex_style; break; - case GWLP_ID: reply->info = win->id; break; case GWLP_HINSTANCE: reply->info = win->instance; break; case GWLP_WNDPROC: reply->info = win->is_unicode; break; case GWLP_USERDATA: reply->info = win->user_data; break; @@ -2461,8 +2459,8 @@ DECL_HANDLER(set_window_info) set_window_ex_style( win, req->new_info ); break; case GWLP_ID: - reply->old_info = win->id; - win->id = req->new_info; + reply->old_info = shared->info.id; + shared->info.id = req->new_info; break; case GWLP_HINSTANCE: reply->old_info = win->instance; -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11106
From: Rémi Bernon <rbernon@codeweavers.com> --- dlls/win32u/ntuser_private.h | 1 - dlls/win32u/window.c | 9 ++------- server/protocol.def | 1 + server/window.c | 18 ++++++++---------- 4 files changed, 11 insertions(+), 18 deletions(-) diff --git a/dlls/win32u/ntuser_private.h b/dlls/win32u/ntuser_private.h index 426d074f935..8cf372340f3 100644 --- a/dlls/win32u/ntuser_private.h +++ b/dlls/win32u/ntuser_private.h @@ -48,7 +48,6 @@ typedef struct tagWND struct tagCLASS *class; /* Window class */ struct dce *dce; /* DCE pointer */ WNDPROC winproc; /* Window procedure */ - HINSTANCE hInstance; /* Window hInstance (from CreateWindow) */ struct window_rects rects; /* window rects in window DPI, relative to the parent client area */ RECT normal_rect; /* Normal window rect saved when maximized/minimized */ RECT present_rect; /* present rect for exclusive fullscreen mode */ diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c index 56e7093a93a..a236bfb309d 100644 --- a/dlls/win32u/window.c +++ b/dlls/win32u/window.c @@ -1126,6 +1126,7 @@ static LONG_PTR get_window_long_shm( HWND hwnd, UINT offset, UINT size, BOOL int switch (offset) { case GWLP_ID: ret = window_shm->info.id; break; + case GWLP_HINSTANCE: ret = window_shm->info.instance; break; default: valid = size <= window_shm->extra_size && offset <= window_shm->extra_size - size && (internal || offset >= window_shm->private_size); @@ -1180,6 +1181,7 @@ static LONG_PTR get_window_long_size( HWND hwnd, INT offset, UINT size, BOOL ans if (offset < 0) break; /* fallthrough */ case GWLP_ID: + case GWLP_HINSTANCE: return get_window_long_shm( hwnd, offset, size, internal ); case GWLP_HWNDPARENT: { @@ -1207,7 +1209,6 @@ static LONG_PTR get_window_long_size( HWND hwnd, INT offset, UINT size, BOOL ans return retval; case GWL_EXSTYLE: case GWLP_USERDATA: - case GWLP_HINSTANCE: return 0; case GWLP_WNDPROC: RtlSetLastWin32Error( ERROR_ACCESS_DENIED ); @@ -1242,7 +1243,6 @@ static LONG_PTR get_window_long_size( HWND hwnd, INT offset, UINT size, BOOL ans case GWLP_USERDATA: retval = win->userdata; break; case GWL_STYLE: retval = win->dwStyle; break; case GWL_EXSTYLE: retval = win->dwExStyle; break; - case GWLP_HINSTANCE: retval = (ULONG_PTR)win->hInstance; break; case GWLP_WNDPROC: /* This looks like a hack only for the edit control (see tests). This makes these controls * more tolerant to A/W mismatches. The lack of W->A->W conversion for such a mismatch suggests @@ -1513,10 +1513,6 @@ static LONG_PTR set_window_long_internal( HWND hwnd, INT offset, UINT size, win->dwExStyle = newval; retval = oldval; break; - case GWLP_HINSTANCE: - win->hInstance = (HINSTANCE)newval; - retval = oldval; - break; case GWLP_WNDPROC: break; case GWLP_USERDATA: @@ -5574,7 +5570,6 @@ static WND *create_window_handle( HWND parent, HWND owner, UNICODE_STRING *name, win->owner = full_owner; win->class = class; win->winproc = get_class_winproc( class ); - win->hInstance = instance; set_user_handle_ptr( handle, win ); if (is_winproc_unicode( win->winproc, !ansi )) win->flags |= WIN_ISUNICODE; return win; diff --git a/server/protocol.def b/server/protocol.def index 973f091ecab..2f11acd4385 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -1066,6 +1066,7 @@ typedef volatile struct struct window_info { lparam_t id; /* window id */ + mod_handle_t instance; /* creator instance */ }; typedef volatile struct diff --git a/server/window.c b/server/window.c index 1302291be64..8af6625af47 100644 --- a/server/window.c +++ b/server/window.c @@ -74,7 +74,6 @@ struct window struct region *update_region; /* update region (relative to window rect) */ unsigned int style; /* window style */ unsigned int ex_style; /* window extended style */ - mod_handle_t instance; /* creator instance */ unsigned int is_unicode : 1; /* ANSI or unicode */ unsigned int is_linked : 1; /* is it linked into the parent z-order list? */ unsigned int is_layered : 1; /* has layered info been set? */ @@ -607,7 +606,7 @@ void post_desktop_message( struct desktop *desktop, unsigned int message, /* create a new window structure (note: the window is not linked in the window tree) */ static struct window *create_window( struct window *parent, struct window *owner, atom_t atom, - mod_handle_t class_instance, mod_handle_t instance ) + mod_handle_t class_instance ) { data_size_t extra_size, private_size; struct window *win = NULL; @@ -657,7 +656,6 @@ static struct window *create_window( struct window *parent, struct window *owner win->update_region = NULL; win->style = 0; win->ex_style = 0; - win->instance = instance; win->is_unicode = 1; win->is_linked = 0; win->is_layered = 0; @@ -2239,7 +2237,7 @@ DECL_HANDLER(create_window) if (!atom) atom = find_atom( table, &cls_name ); - if (!(win = create_window( parent, owner, atom, req->class_instance, req->instance ))) return; + if (!(win = create_window( parent, owner, atom, req->class_instance ))) return; if (parent && !is_desktop_window( parent )) dpi_context = parent->shared->dpi_context; @@ -2250,7 +2248,8 @@ DECL_HANDLER(create_window) SHARED_WRITE_BEGIN( win->shared, window_shm_t ) { - shared->dpi_context = dpi_context; + shared->dpi_context = dpi_context; + shared->info.instance = req->instance; } SHARED_WRITE_END; @@ -2336,7 +2335,7 @@ DECL_HANDLER(get_desktop_window) if (!desktop->top_window && req->force) /* create it */ { - if ((desktop->top_window = create_window( NULL, NULL, DESKTOP_ATOM, 0, 0 ))) + if ((desktop->top_window = create_window( NULL, NULL, DESKTOP_ATOM, 0 ))) { detach_window_thread( desktop->top_window ); desktop->top_window->style = WS_POPUP | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN; @@ -2349,7 +2348,7 @@ DECL_HANDLER(get_desktop_window) static const struct unicode_str name = { messageW, sizeof(messageW) }; struct atom_table *table = get_user_atom_table(); atom_t atom = add_atom( table, &name ); - if (atom && (desktop->msg_window = create_window( NULL, NULL, atom, 0, 0 ))) + if (atom && (desktop->msg_window = create_window( NULL, NULL, atom, 0 ))) { detach_window_thread( desktop->msg_window ); desktop->msg_window->style = WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN; @@ -2406,7 +2405,6 @@ DECL_HANDLER(get_window_info) { case GWL_STYLE: reply->info = win->style; break; case GWL_EXSTYLE: reply->info = win->ex_style; break; - case GWLP_HINSTANCE: reply->info = win->instance; break; case GWLP_WNDPROC: reply->info = win->is_unicode; break; case GWLP_USERDATA: reply->info = win->user_data; break; default: @@ -2463,8 +2461,8 @@ DECL_HANDLER(set_window_info) shared->info.id = req->new_info; break; case GWLP_HINSTANCE: - reply->old_info = win->instance; - win->instance = req->new_info; + reply->old_info = shared->info.instance; + shared->info.instance = req->new_info; break; case GWLP_WNDPROC: reply->old_info = win->is_unicode; -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11106
From: Rémi Bernon <rbernon@codeweavers.com> --- dlls/win32u/ntuser_private.h | 1 - dlls/win32u/window.c | 10 ++-------- server/protocol.def | 1 + server/window.c | 8 +++----- 4 files changed, 6 insertions(+), 14 deletions(-) diff --git a/dlls/win32u/ntuser_private.h b/dlls/win32u/ntuser_private.h index 8cf372340f3..0c7f4802351 100644 --- a/dlls/win32u/ntuser_private.h +++ b/dlls/win32u/ntuser_private.h @@ -72,7 +72,6 @@ typedef struct tagWND int swap_interval; /* OpenGL surface swap interval */ int pixel_format; /* Pixel format set by the graphics driver */ int clip_clients; /* Has client surfaces that needs to be clipped out */ - DWORD_PTR userdata; /* User private data */ } WND; /* WND flags values */ diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c index a236bfb309d..7afd444a027 100644 --- a/dlls/win32u/window.c +++ b/dlls/win32u/window.c @@ -1127,6 +1127,7 @@ static LONG_PTR get_window_long_shm( HWND hwnd, UINT offset, UINT size, BOOL int { case GWLP_ID: ret = window_shm->info.id; break; case GWLP_HINSTANCE: ret = window_shm->info.instance; break; + case GWLP_USERDATA: memcpy( &ret, (void *)&window_shm->info.user_data, size ); break; default: valid = size <= window_shm->extra_size && offset <= window_shm->extra_size - size && (internal || offset >= window_shm->private_size); @@ -1182,6 +1183,7 @@ static LONG_PTR get_window_long_size( HWND hwnd, INT offset, UINT size, BOOL ans /* fallthrough */ case GWLP_ID: case GWLP_HINSTANCE: + case GWLP_USERDATA: return get_window_long_shm( hwnd, offset, size, internal ); case GWLP_HWNDPARENT: { @@ -1208,7 +1210,6 @@ static LONG_PTR get_window_long_size( HWND hwnd, INT offset, UINT size, BOOL ans retval |= WS_VISIBLE; return retval; case GWL_EXSTYLE: - case GWLP_USERDATA: return 0; case GWLP_WNDPROC: RtlSetLastWin32Error( ERROR_ACCESS_DENIED ); @@ -1240,7 +1241,6 @@ static LONG_PTR get_window_long_size( HWND hwnd, INT offset, UINT size, BOOL ans switch(offset) { - case GWLP_USERDATA: retval = win->userdata; break; case GWL_STYLE: retval = win->dwStyle; break; case GWL_EXSTYLE: retval = win->dwExStyle; break; case GWLP_WNDPROC: @@ -1498,7 +1498,6 @@ static LONG_PTR set_window_long_internal( HWND hwnd, INT offset, UINT size, } if (offset == GWLP_WNDPROC) newval = !!(win->flags & WIN_ISUNICODE); - if (offset == GWLP_USERDATA && size == sizeof(WORD)) newval = MAKELONG( newval, win->userdata >> 16 ); if ((ok = server_set_window_info( hwnd, offset, newval, size, &oldval, internal ))) { @@ -1515,10 +1514,6 @@ static LONG_PTR set_window_long_internal( HWND hwnd, INT offset, UINT size, break; case GWLP_WNDPROC: break; - case GWLP_USERDATA: - win->userdata = newval; - retval = oldval; - break; default: retval = oldval; break; @@ -5748,7 +5743,6 @@ HWND WINAPI NtUserCreateWindowEx( DWORD ex_style, UNICODE_STRING *class_name, win->dwExStyle = ex_style; win->helpContext = 0; win->pScroll = NULL; - win->userdata = 0; win->hIcon = 0; win->hIconSmall = 0; win->hIconSmall2 = 0; diff --git a/server/protocol.def b/server/protocol.def index 2f11acd4385..e8fe6f1db58 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -1067,6 +1067,7 @@ struct window_info { lparam_t id; /* window id */ mod_handle_t instance; /* creator instance */ + lparam_t user_data; /* user-specific data */ }; typedef volatile struct diff --git a/server/window.c b/server/window.c index 8af6625af47..9665af1069f 100644 --- a/server/window.c +++ b/server/window.c @@ -83,7 +83,6 @@ struct window unsigned int alpha; /* alpha value for a layered window */ unsigned int layered_flags; /* flags for a layered window */ unsigned int monitor_dpi; /* DPI of the window monitor */ - lparam_t user_data; /* user-specific data */ WCHAR *text; /* window caption text */ data_size_t text_len; /* length of window caption */ unsigned int paint_flags; /* various painting flags */ @@ -662,7 +661,6 @@ static struct window *create_window( struct window *parent, struct window *owner win->is_orphan = 0; win->set_foreground = 0; win->monitor_dpi = USER_DEFAULT_SCREEN_DPI; - win->user_data = 0; win->text = NULL; win->text_len = 0; win->paint_flags = 0; @@ -2406,7 +2404,6 @@ DECL_HANDLER(get_window_info) case GWL_STYLE: reply->info = win->style; break; case GWL_EXSTYLE: reply->info = win->ex_style; break; case GWLP_WNDPROC: reply->info = win->is_unicode; break; - case GWLP_USERDATA: reply->info = win->user_data; break; default: if (req->size) set_win32_error( ERROR_INVALID_INDEX ); break; @@ -2469,8 +2466,9 @@ DECL_HANDLER(set_window_info) win->is_unicode = req->new_info; break; case GWLP_USERDATA: - reply->old_info = win->user_data; - win->user_data = req->new_info; + reply->old_info = shared->info.user_data; + if (req->size > sizeof(WORD)) shared->info.user_data = req->new_info; + else shared->info.user_data = MAKELONG(req->new_info, shared->info.user_data >> 16); break; default: if (req->size > sizeof(req->new_info) || req->offset < 0 || -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11106
v2: Add some struct alignment assertions, drop now unused helper, fix user data partial copy with `SetWindowWord`. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/11106#note_142638
participants (2)
-
Rémi Bernon -
Rémi Bernon (@rbernon)