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