From: Rémi Bernon <rbernon@codeweavers.com> --- dlls/win32u/class.c | 28 +++++++++++++++++----------- server/class.c | 5 +++++ server/protocol.def | 2 ++ 3 files changed, 24 insertions(+), 11 deletions(-) diff --git a/dlls/win32u/class.c b/dlls/win32u/class.c index 5140430c558..ea814d8696b 100644 --- a/dlls/win32u/class.c +++ b/dlls/win32u/class.c @@ -47,7 +47,6 @@ typedef struct tagCLASS { struct list entry; /* Entry in class list */ BOOL local; /* Local class? */ - WNDPROC winproc; /* Window procedure */ struct dce *dce; /* Opaque pointer to class DCE */ HICON hIcon; /* Default icon */ HICON hIconSm; /* Default small icon */ @@ -485,7 +484,15 @@ static CLASS *find_class( HINSTANCE module, UNICODE_STRING *name ) */ WNDPROC get_class_winproc( CLASS *class ) { - return class->winproc; + struct object_lock lock = OBJECT_LOCK_INIT; + const class_shm_t *class_shm; + WNDPROC wndproc = NULL; + NTSTATUS status; + + while ((status = get_shared_class( class, &lock, &class_shm )) == STATUS_PENDING) + wndproc = wine_server_get_ptr( class_shm->wndproc ); + if (status) return 0; + return wndproc; } /*********************************************************************** @@ -517,6 +524,7 @@ ATOM WINAPI NtUserRegisterClassExWOW( const WNDCLASSEXW *wc, UNICODE_STRING *nam struct obj_locator locator; HICON icon_internal; HINSTANCE instance; + WNDPROC wndproc; CLASS *class; ATOM atom; BOOL ret; @@ -531,6 +539,7 @@ ATOM WINAPI NtUserRegisterClassExWOW( const WNDCLASSEXW *wc, UNICODE_STRING *nam return 0; } if (!(instance = wc->hInstance)) instance = RtlGetCurrentPeb()->ImageBaseAddress; + wndproc = alloc_winproc( wc->lpfnWndProc, ansi ); TRACE( "name=%s hinst=%p style=0x%x clExtr=0x%x winExtr=0x%x\n", debugstr_us(name), instance, wc->style, wc->cbClsExtra, wc->cbWndExtra ); @@ -558,6 +567,7 @@ ATOM WINAPI NtUserRegisterClassExWOW( const WNDCLASSEXW *wc, UNICODE_STRING *nam req->cls_extra = wc->cbClsExtra; req->win_extra = wc->cbWndExtra; req->client_ptr = wine_server_client_ptr( class ); + req->wndproc = wine_server_client_ptr( wndproc ); req->atom = wine_server_add_atom( req, name ); req->name_offset = version->Length / sizeof(WCHAR); ret = !wine_server_call_err( req ); @@ -593,7 +603,6 @@ ATOM WINAPI NtUserRegisterClassExWOW( const WNDCLASSEXW *wc, UNICODE_STRING *nam class->icon_internal = icon_internal; class->hCursor = wc->hCursor; class->hbrBackground = wc->hbrBackground; - class->winproc = alloc_winproc( wc->lpfnWndProc, ansi ); class->menu_name = menu_name; class->shared = shared; release_class_ptr( class ); @@ -670,7 +679,7 @@ ATOM WINAPI NtUserGetClassInfoEx( HINSTANCE instance, UNICODE_STRING *name, WNDC if (wc) { wc->style = class_shm->style; - wc->lpfnWndProc = get_winproc( class->winproc, ansi ); + wc->lpfnWndProc = get_winproc( wine_server_get_ptr( class_shm->wndproc ), ansi ); wc->cbClsExtra = class_shm->cls_extra; wc->cbWndExtra = class_shm->win_extra; wc->hInstance = (instance == user32_module) ? 0 : instance; @@ -832,8 +841,9 @@ static ULONG_PTR set_class_long_size( HWND hwnd, INT offset, LONG_PTR newval, UI class->menu_name = (void *)newval; break; case GCLP_WNDPROC: - retval = (ULONG_PTR)get_winproc( class->winproc, ansi ); - class->winproc = alloc_winproc( (WNDPROC)newval, ansi ); + newval = (ULONG_PTR)alloc_winproc( (WNDPROC)newval, ansi ); + if (!set_server_info( hwnd, offset, newval, size, &retval )) break; + retval = (ULONG_PTR)get_winproc( (WNDPROC)retval, ansi ); break; case GCLP_HBRBACKGROUND: retval = (ULONG_PTR)class->hbrBackground; @@ -920,6 +930,7 @@ static ULONG_PTR get_class_long_shm( HWND hwnd, INT offset, UINT size, BOOL ansi { case GCW_ATOM: ret = class_shm->atom; break; case GCL_STYLE: ret = class_shm->style; break; + case GCLP_WNDPROC: ret = (ULONG_PTR)get_winproc( wine_server_get_ptr( class_shm->wndproc ), ansi ); break; case GCL_CBCLSEXTRA: ret = class_shm->cls_extra; break; case GCL_CBWNDEXTRA: ret = class_shm->win_extra; break; case GCLP_HMODULE: ret = class_shm->instance; break; @@ -952,7 +963,6 @@ static ULONG_PTR get_class_long_size( HWND hwnd, INT offset, UINT size, BOOL ans switch (offset) { case GCLP_HICONSM: - case GCLP_WNDPROC: case GCLP_HICON: case GCLP_HCURSOR: case GCLP_HBRBACKGROUND: @@ -979,7 +989,6 @@ static ULONG_PTR get_class_long_size( HWND hwnd, INT offset, UINT size, BOOL ans case GCLP_HCURSOR: case GCLP_HICON: case GCLP_HICONSM: - case GCLP_WNDPROC: case GCLP_MENUNAME: FIXME( "offset %d not supported on other process window %p\n", offset, hwnd ); break; @@ -1007,9 +1016,6 @@ static ULONG_PTR get_class_long_size( HWND hwnd, INT offset, UINT size, BOOL ans case GCLP_HICONSM: retvalue = (ULONG_PTR)(class->hIconSm ? class->hIconSm : class->icon_internal); break; - case GCLP_WNDPROC: - retvalue = (ULONG_PTR)get_winproc( class->winproc, ansi ); - break; case GCLP_MENUNAME: retvalue = (ULONG_PTR)class->menu_name; break; diff --git a/server/class.c b/server/class.c index a71ee0a332a..1faf8618ebc 100644 --- a/server/class.c +++ b/server/class.c @@ -241,6 +241,7 @@ DECL_HANDLER(create_class) shared->atom = base_atom; shared->instance = req->instance; shared->style = req->style; + shared->wndproc = req->wndproc; shared->win_extra = req->win_extra; shared->cls_extra = req->cls_extra; memset( (void *)shared->extra, 0, req->cls_extra ); @@ -310,6 +311,10 @@ DECL_HANDLER(set_class_info) reply->old_info = shared->instance; shared->instance = req->new_info; break; + case GCLP_WNDPROC: + reply->old_info = shared->wndproc; + shared->wndproc = req->new_info; + break; default: if (req->size > sizeof(req->new_info) || req->offset < 0 || req->offset > class->shared->cls_extra - (int)req->size) diff --git a/server/protocol.def b/server/protocol.def index 3ee3be605d4..a10e2c0ca08 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -1042,6 +1042,7 @@ typedef volatile struct { atom_t atom; /* class atom */ unsigned int style; /* class style */ + client_ptr_t wndproc; /* class window proc */ unsigned int cls_extra; /* number of class extra bytes */ unsigned int win_extra; /* number of window extra bytes */ mod_handle_t instance; /* module instance */ @@ -3271,6 +3272,7 @@ enum caret_state unsigned int style; /* class style */ mod_handle_t instance; /* module instance */ client_ptr_t client_ptr; /* pointer to class in client address space */ + client_ptr_t wndproc; /* class window proc client pointer */ short int cls_extra; /* number of extra class bytes */ short int win_extra; /* number of window extra bytes */ data_size_t name_offset; /* base class name offset for specified atom */ -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10959