From: Rémi Bernon <rbernon@codeweavers.com> --- dlls/win32u/class.c | 27 ------- dlls/win32u/message.c | 6 +- dlls/win32u/ntuser_private.h | 6 +- dlls/win32u/window.c | 135 +++++++++++++++-------------------- server/class.c | 13 ++++ server/protocol.def | 8 ++- server/user.h | 1 + server/window.c | 23 +++--- 8 files changed, 93 insertions(+), 126 deletions(-) diff --git a/dlls/win32u/class.c b/dlls/win32u/class.c index 1d474a1867b..24f7e64b46b 100644 --- a/dlls/win32u/class.c +++ b/dlls/win32u/class.c @@ -274,17 +274,6 @@ WNDPROC get_winproc( WNDPROC proc, BOOL ansi ) } } -/* Return the window procedure type, or the default value if not a winproc handle. */ -BOOL is_winproc_unicode( WNDPROC proc, BOOL def_val ) -{ - WINDOWPROC *ptr = get_winproc_ptr( proc ); - - if (!ptr) return def_val; - if (ptr == WINPROC_PROC16) return FALSE; /* 16-bit is always A */ - if (ptr->procA && ptr->procW) return def_val; /* can be both */ - return ptr->procW != NULL; -} - void get_winproc_params( struct win_proc_params *params, BOOL fixup_ansi_dst ) { WINDOWPROC *proc = get_winproc_ptr( params->func ); @@ -572,22 +561,6 @@ static CLASS *find_class( HINSTANCE module, UNICODE_STRING *name ) return NULL; } -/*********************************************************************** - * get_class_winproc - */ -WNDPROC get_class_winproc( CLASS *class ) -{ - 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->info.wndproc ); - if (status) return 0; - return wndproc; -} - /*********************************************************************** * get_class_dce */ diff --git a/dlls/win32u/message.c b/dlls/win32u/message.c index 1428ff586f4..b6cdd3efa0e 100644 --- a/dlls/win32u/message.c +++ b/dlls/win32u/message.c @@ -434,7 +434,7 @@ static BOOL init_win_proc_params( struct win_proc_params *params, HWND hwnd, UIN static BOOL init_window_call_params( struct win_proc_params *params, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, BOOL ansi, enum wm_char_mapping mapping ) { - BOOL is_dialog; + BOOL is_dialog, is_ansi; WND *win; user_check_not_lock(); @@ -442,8 +442,8 @@ static BOOL init_window_call_params( struct win_proc_params *params, HWND hwnd, if (!is_current_thread_window( hwnd )) return FALSE; if (!(win = get_win_ptr( hwnd ))) return FALSE; if (win == WND_OTHER_PROCESS || win == WND_DESKTOP) return FALSE; - params->func = win->winproc; - params->ansi_dst = !(win->flags & WIN_ISUNICODE); + params->func = get_window_wndproc_handle( hwnd, &is_ansi ); + params->ansi_dst = is_ansi; is_dialog = win->dlgInfo != NULL; release_win_ptr( win ); diff --git a/dlls/win32u/ntuser_private.h b/dlls/win32u/ntuser_private.h index e066ef4b5d6..978700a37aa 100644 --- a/dlls/win32u/ntuser_private.h +++ b/dlls/win32u/ntuser_private.h @@ -47,7 +47,6 @@ typedef struct tagWND HWND owner; /* Window owner */ struct tagCLASS *class; /* Window class */ struct dce *dce; /* DCE pointer */ - WNDPROC winproc; /* Window procedure */ 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 */ @@ -79,7 +78,6 @@ typedef struct tagWND #define WIN_NEED_SIZE 0x0002 /* Internal WM_SIZE is needed */ #define WIN_NCACTIVATED 0x0004 /* last WM_NCACTIVATE was positive */ #define WIN_ISMDICLIENT 0x0008 /* Window is an MDIClient */ -#define WIN_ISUNICODE 0x0010 /* Window is Unicode */ #define WIN_NEEDS_SHOW_OWNEDPOPUP 0x0020 /* WM_SHOWWINDOW:SC_SHOW must be sent in the next ShowOwnedPopup call */ #define WIN_CHILDREN_MOVED 0x0040 /* children may have moved, ignore stored positions */ #define WIN_HAS_IME_WIN 0x0080 /* the window has been registered with imm32 */ @@ -152,6 +150,7 @@ struct scroll_info BOOL painted; /* Whether the scroll bar is painted by DefWinProc() */ }; +/* also defined in server/class.c */ #define MAKE_WNDPROC(index) ((WNDPROC)(UINT_PTR)(UINT)MAKELONG(index, 0xffff)) #define MAX_ATOM_LEN 255 @@ -172,9 +171,7 @@ extern void spy_exit_message( INT flag, HWND hwnd, UINT msg, /* class.c */ extern HINSTANCE user32_module; WNDPROC alloc_winproc( WNDPROC func, BOOL ansi ); -BOOL is_winproc_unicode( WNDPROC proc, BOOL def_val ); DWORD get_class_long( HWND hwnd, INT offset, BOOL ansi ); -WNDPROC get_class_winproc( struct tagCLASS *class ); ULONG_PTR get_class_long_ptr( HWND hwnd, INT offset, BOOL ansi ); WORD get_class_word( HWND hwnd, INT offset ); DLGPROC get_dialog_proc( DLGPROC proc, BOOL ansi ); @@ -235,5 +232,6 @@ struct obj_locator get_window_class_locator( HWND hwnd ); WND *get_win_ptr( HWND hwnd ); BOOL is_child( HWND parent, HWND child ); BOOL is_window( HWND hwnd ); +extern WNDPROC get_window_wndproc_handle( HWND hwnd, BOOL *ansi ); #endif /* __WINE_NTUSER_PRIVATE_H */ diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c index 70204bf4adb..c3a32dde6cf 100644 --- a/dlls/win32u/window.c +++ b/dlls/win32u/window.c @@ -185,6 +185,25 @@ struct obj_locator get_window_class_locator( HWND hwnd ) return locator; } +/*********************************************************************** + * get_window_wndproc_handle + */ +WNDPROC get_window_wndproc_handle( HWND hwnd, BOOL *ansi ) +{ + struct object_lock lock = OBJECT_LOCK_INIT; + const window_shm_t *window_shm = NULL; + WNDPROC wndproc = NULL; + NTSTATUS status; + + while ((status = get_shared_window( hwnd, &lock, &window_shm )) == STATUS_PENDING) + { + wndproc = wine_server_get_ptr( window_shm->info.wndproc ); + *ansi = window_shm->ansi; + } + if (status) return 0; + return wndproc; +} + /*********************************************************************** * get_user_handle_ptr */ @@ -980,28 +999,9 @@ BOOL is_window_drawable( HWND hwnd, BOOL icon ) /* see IsWindowUnicode */ BOOL is_window_unicode( HWND hwnd ) { - WND *win; - BOOL ret = FALSE; - - if (!(win = get_win_ptr(hwnd))) return FALSE; - - if (win == WND_DESKTOP) return TRUE; - - if (win != WND_OTHER_PROCESS) - { - ret = (win->flags & WIN_ISUNICODE) != 0; - 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->is_unicode; - } - SERVER_END_REQ; - } - return ret; + BOOL ansi = FALSE; + if (!get_window_wndproc_handle( hwnd, &ansi )) return FALSE; + return !ansi; } /***************************************************************** @@ -1113,14 +1113,30 @@ static HWND get_last_active_popup( HWND hwnd ) return retval; } -static LONG_PTR get_window_long_shm( HWND hwnd, UINT offset, UINT size, BOOL internal ) +static WNDPROC get_window_proc( WNDPROC wndproc, BOOL wndproc_ansi, BOOL ansi ) +{ + /* 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 + * that the hack is in GetWindowLongPtr[AW], not in winprocs. + */ + if (wndproc == MAKE_WNDPROC(NTUSER_WNDPROC_EDIT) && wndproc_ansi != ansi) return wndproc; + return get_winproc( wndproc, ansi ); +} + +static LONG_PTR get_window_long_shm( HWND hwnd, UINT offset, UINT size, BOOL ansi, BOOL internal ) { struct object_lock lock = OBJECT_LOCK_INIT; const window_shm_t *window_shm = NULL; - BOOL valid = TRUE; + BOOL valid = TRUE, window_ansi = FALSE; LONG_PTR ret = 0; NTSTATUS status; + if (offset == GWLP_WNDPROC && !is_current_process_window( hwnd )) + { + RtlSetLastWin32Error( ERROR_ACCESS_DENIED ); + return 0; + } + while ((status = get_shared_window( hwnd, &lock, &window_shm )) == STATUS_PENDING) { switch (offset) @@ -1128,12 +1144,14 @@ 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; + case GWLP_WNDPROC: ret = window_shm->info.wndproc; 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; } + window_ansi = window_shm->ansi; } if (status) { @@ -1147,6 +1165,7 @@ static LONG_PTR get_window_long_shm( HWND hwnd, UINT offset, UINT size, BOOL int return 0; } + if (offset == GWLP_WNDPROC) return (ULONG_PTR)get_window_proc( (WNDPROC)ret, window_ansi, ansi ); return ret; } @@ -1184,7 +1203,8 @@ static LONG_PTR get_window_long_size( HWND hwnd, INT offset, UINT size, BOOL ans case GWLP_ID: case GWLP_HINSTANCE: case GWLP_USERDATA: - return get_window_long_shm( hwnd, offset, size, internal ); + case GWLP_WNDPROC: + return get_window_long_shm( hwnd, offset, size, ansi, internal ); case GWLP_HWNDPARENT: { HWND parent = NtUserGetAncestor( hwnd, GA_PARENT ); @@ -1211,9 +1231,6 @@ static LONG_PTR get_window_long_size( HWND hwnd, INT offset, UINT size, BOOL ans return retval; case GWL_EXSTYLE: return 0; - case GWLP_WNDPROC: - RtlSetLastWin32Error( ERROR_ACCESS_DENIED ); - return 0; } RtlSetLastWin32Error( ERROR_INVALID_INDEX ); return 0; @@ -1221,11 +1238,6 @@ static LONG_PTR get_window_long_size( HWND hwnd, INT offset, UINT size, BOOL ans if (win == WND_OTHER_PROCESS) { - if (offset == GWLP_WNDPROC) - { - RtlSetLastWin32Error( ERROR_ACCESS_DENIED ); - return 0; - } SERVER_START_REQ( get_window_info ) { req->handle = wine_server_user_handle( hwnd ); @@ -1243,20 +1255,6 @@ static LONG_PTR get_window_long_size( HWND hwnd, INT offset, UINT size, BOOL ans { case GWL_STYLE: retval = win->dwStyle; break; case GWL_EXSTYLE: retval = win->dwExStyle; 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 - * that the hack is in GetWindowLongPtr[AW], not in winprocs. - */ - if (win->winproc == MAKE_WNDPROC(NTUSER_WNDPROC_EDIT) && (!!ansi != !(win->flags & WIN_ISUNICODE))) - retval = (ULONG_PTR)win->winproc; - else - retval = (ULONG_PTR)get_winproc( win->winproc, ansi ); - break; - default: - WARN("Unknown offset %d\n", offset ); - RtlSetLastWin32Error( ERROR_INVALID_INDEX ); - break; } release_win_ptr( win ); return retval; @@ -1291,7 +1289,8 @@ 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, BOOL internal ) +static BOOL server_set_window_info( HWND hwnd, INT offset, LONG_PTR newval, UINT size, + LONG_PTR *oldval, BOOL *ansi, BOOL internal ) { BOOL ret; @@ -1301,9 +1300,11 @@ 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->new_ansi = *ansi; req->internal = internal; ret = !wine_server_call_err( req ); *oldval = reply->old_info; + *ansi = reply->old_ansi; } SERVER_END_REQ; return ret; @@ -1311,7 +1312,7 @@ static BOOL server_set_window_info( HWND hwnd, INT offset, LONG_PTR newval, UINT UINT set_window_style_bits( HWND hwnd, UINT set_bits, UINT clear_bits ) { - BOOL ok, made_visible = FALSE; + BOOL ok, ansi = FALSE, made_visible = FALSE; STYLESTRUCT style; LONG_PTR oldval; WND *win = get_win_ptr( hwnd ); @@ -1330,7 +1331,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, FALSE ))) + if ((ok = server_set_window_info( hwnd, GWL_STYLE, style.styleNew, 0, &oldval, &ansi, FALSE ))) { style.styleOld = oldval; win->dwStyle = style.styleNew; @@ -1403,7 +1404,7 @@ static HWND set_window_owner( HWND hwnd, HWND owner ) 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; + BOOL ok, made_visible = FALSE, layered = FALSE, old_ansi = ansi; LONG_PTR retval = 0, oldval; STYLESTRUCT style; WND *win; @@ -1429,11 +1430,6 @@ static LONG_PTR set_window_long_internal( HWND hwnd, INT offset, UINT size, } if (win == WND_OTHER_PROCESS) { - if (offset == GWLP_WNDPROC) - { - RtlSetLastWin32Error( ERROR_ACCESS_DENIED ); - return 0; - } if (offset > 32767 || offset < -32767) { RtlSetLastWin32Error( ERROR_INVALID_INDEX ); @@ -1479,27 +1475,11 @@ static LONG_PTR set_window_long_internal( HWND hwnd, INT offset, UINT size, return (ULONG_PTR)NtUserSetParent( hwnd, (HWND)newval ); } case GWLP_WNDPROC: - { - WNDPROC proc; - UINT old_flags = win->flags; - retval = get_window_long_ptr( hwnd, offset, ansi ); - proc = alloc_winproc( (WNDPROC)newval, ansi ); - if (proc) win->winproc = proc; - if (is_winproc_unicode( proc, !ansi )) win->flags |= WIN_ISUNICODE; - else win->flags &= ~WIN_ISUNICODE; - if (!((old_flags ^ win->flags) & WIN_ISUNICODE)) - { - release_win_ptr( win ); - return retval; - } - /* update is_unicode flag on the server side */ + newval = (ULONG_PTR)alloc_winproc( (WNDPROC)newval, ansi ); break; } - } - - if (offset == GWLP_WNDPROC) newval = !!(win->flags & WIN_ISUNICODE); - if ((ok = server_set_window_info( hwnd, offset, newval, size, &oldval, internal ))) + if ((ok = server_set_window_info( hwnd, offset, newval, size, &oldval, &old_ansi, internal ))) { switch (offset) { @@ -1512,8 +1492,6 @@ static LONG_PTR set_window_long_internal( HWND hwnd, INT offset, UINT size, win->dwExStyle = newval; retval = oldval; break; - case GWLP_WNDPROC: - break; default: retval = oldval; break; @@ -1539,6 +1517,7 @@ static LONG_PTR set_window_long_internal( HWND hwnd, INT offset, UINT size, send_message( hwnd, WM_STYLECHANGED, offset, (LPARAM)&style ); } + if (offset == GWLP_WNDPROC) return (ULONG_PTR)get_window_proc( (WNDPROC)retval, old_ansi, ansi ); return retval; } @@ -5511,6 +5490,7 @@ static WND *create_window_handle( HWND parent, HWND owner, UNICODE_STRING *name, req->dpi_context = dpi_context; req->style = style; req->ex_style = ex_style; + req->ansi = ansi; req->atom = wine_server_add_atom( req, name ); if (!wine_server_call_err( req )) { @@ -5564,9 +5544,7 @@ static WND *create_window_handle( HWND parent, HWND owner, UNICODE_STRING *name, win->parent = full_parent; win->owner = full_owner; win->class = class; - win->winproc = get_class_winproc( class ); set_user_handle_ptr( handle, win ); - if (is_winproc_unicode( win->winproc, !ansi )) win->flags |= WIN_ISUNICODE; return win; } @@ -5805,7 +5783,6 @@ HWND WINAPI NtUserCreateWindowEx( DWORD ex_style, UNICODE_STRING *class_name, req->handle = wine_server_user_handle( hwnd ); req->style = win->dwStyle; req->ex_style = win->dwExStyle; - req->is_unicode = (win->flags & WIN_ISUNICODE) != 0; wine_server_call( req ); } SERVER_END_REQ; diff --git a/server/class.c b/server/class.c index 8a2f56b4473..daaa344f00a 100644 --- a/server/class.c +++ b/server/class.c @@ -38,6 +38,9 @@ #include "winuser.h" #include "winternl.h" +/* also defined in win32u/ntuser_private.h */ +#define MAKE_WNDPROC(index) ((UINT_PTR)(UINT)MAKELONG(index, 0xffff)) + struct window_class { struct list entry; /* entry in process list */ @@ -172,6 +175,16 @@ unsigned int get_class_fnid( struct window_class *class, data_size_t *extra_size return class->fnid; } +client_ptr_t get_class_wndproc( struct window_class *class, bool *is_ansi ) +{ + client_ptr_t wndproc = class->shared->info.wndproc; + UINT index = LOWORD(wndproc); + + /* builtin wndproc can be both ansi or unicode, otherwise use the class wndproc kind */ + if (wndproc != MAKE_WNDPROC(index) || index >= NTUSER_NB_PROCS) *is_ansi = !!class->ansi; + return wndproc; +} + client_ptr_t get_class_client_ptr( struct window_class *class ) { return class->client_ptr; diff --git a/server/protocol.def b/server/protocol.def index 9a105d2536c..7b467618f7a 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -1068,6 +1068,7 @@ struct window_info lparam_t id; /* window id */ mod_handle_t instance; /* creator instance */ lparam_t user_data; /* user-specific data */ + client_ptr_t wndproc; /* window proc */ }; typedef volatile struct @@ -1075,6 +1076,8 @@ typedef volatile struct struct obj_locator class; /* object locator for the window class shared object */ unsigned int dpi_context; /* DPI awareness context */ unsigned int fnid; /* builtin class FNID, or 0 */ + unsigned int ansi; /* window wndproc is ansi */ + int __pad; 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_*) */ @@ -2637,6 +2640,7 @@ enum message_type unsigned int dpi_context; /* thread DPI context */ unsigned int style; /* window style */ unsigned int ex_style; /* window extended style */ + unsigned int ansi; /* window created as ansi */ VARARG(class,unicode_str); /* class name */ @REPLY user_handle_t handle; /* created window */ @@ -2678,7 +2682,6 @@ enum message_type data_size_t size; /* size of the info value to read */ @REPLY user_handle_t last_active; /* last active popup */ - int is_unicode; /* ANSI or unicode */ lparam_t info; /* current window info value */ @END @@ -2688,7 +2691,6 @@ enum message_type user_handle_t handle; /* handle to the window */ unsigned int style; /* window style */ unsigned int ex_style; /* window extended style */ - short int is_unicode; /* ANSI or unicode */ @REPLY @END @@ -2699,9 +2701,11 @@ 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 new_ansi; /* new window info is ansi */ unsigned int internal; /* set internal control info */ @REPLY lparam_t old_info; /* previous window info value */ + unsigned int old_ansi; /* previous window info is ansi */ @END diff --git a/server/user.h b/server/user.h index f527db3e57c..1d16e2aab95 100644 --- a/server/user.h +++ b/server/user.h @@ -195,6 +195,7 @@ extern int is_message_class( struct window_class *class ); extern int get_class_style( struct window_class *class ); extern atom_t get_class_atom( struct window_class *class ); extern unsigned int get_class_fnid( struct window_class *class, data_size_t *extra_size, data_size_t *private_size ); +extern client_ptr_t get_class_wndproc( struct window_class *class, bool *ansi ); extern client_ptr_t get_class_client_ptr( struct window_class *class ); /* windows station functions */ diff --git a/server/window.c b/server/window.c index 9665af1069f..6bff48e7a22 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 */ - 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? */ unsigned int is_orphan : 1; /* is window orphaned */ @@ -605,7 +604,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 class_instance, bool ansi ) { data_size_t extra_size, private_size; struct window *win = NULL; @@ -655,7 +654,6 @@ static struct window *create_window( struct window *parent, struct window *owner win->update_region = NULL; win->style = 0; win->ex_style = 0; - win->is_unicode = 1; win->is_linked = 0; win->is_layered = 0; win->is_orphan = 0; @@ -682,6 +680,8 @@ static struct window *create_window( struct window *parent, struct window *owner shared->extra_size = extra_size; memset( (void *)&shared->info, 0, sizeof(shared->info) ); memset( (void *)shared->extra, 0, extra_size ); + shared->info.wndproc = get_class_wndproc( win->class, &ansi ); + shared->ansi = ansi; } SHARED_WRITE_END; @@ -2235,7 +2235,7 @@ DECL_HANDLER(create_window) if (!atom) atom = find_atom( table, &cls_name ); - if (!(win = create_window( parent, owner, atom, req->class_instance ))) return; + if (!(win = create_window( parent, owner, atom, req->class_instance, !!req->ansi ))) return; if (parent && !is_desktop_window( parent )) dpi_context = parent->shared->dpi_context; @@ -2333,7 +2333,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 ))) + if ((desktop->top_window = create_window( NULL, NULL, DESKTOP_ATOM, 0, false ))) { detach_window_thread( desktop->top_window ); desktop->top_window->style = WS_POPUP | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN; @@ -2346,7 +2346,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 ))) + if (atom && (desktop->msg_window = create_window( NULL, NULL, atom, 0, false ))) { detach_window_thread( desktop->msg_window ); desktop->msg_window->style = WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN; @@ -2396,14 +2396,12 @@ DECL_HANDLER(get_window_info) if (!(win = get_window( req->handle ))) return; reply->last_active = win->handle; - reply->is_unicode = win->is_unicode; if (get_user_object( win->last_active, NTUSER_OBJ_WINDOW )) reply->last_active = win->last_active; switch (req->offset) { 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; default: if (req->size) set_win32_error( ERROR_INVALID_INDEX ); break; @@ -2419,7 +2417,6 @@ DECL_HANDLER(init_window_info) if (!(win = get_window( req->handle ))) return; win->style = req->style; win->ex_style = req->ex_style; - win->is_unicode = req->is_unicode; /* changing window style triggers a non-client paint */ win->paint_flags |= PAINT_NONCLIENT; @@ -2430,6 +2427,7 @@ DECL_HANDLER(init_window_info) DECL_HANDLER(set_window_info) { struct window *win; + bool ansi; if (!(win = get_window( req->handle ))) return; if (is_desktop_window( win ) && win->thread != current) @@ -2462,8 +2460,11 @@ DECL_HANDLER(set_window_info) shared->info.instance = req->new_info; break; case GWLP_WNDPROC: - reply->old_info = win->is_unicode; - win->is_unicode = req->new_info; + reply->old_info = shared->info.wndproc; + reply->old_ansi = shared->ansi; + if (req->new_info) shared->info.wndproc = req->new_info; + else shared->info.wndproc = get_class_wndproc( win->class, &ansi ); + shared->ansi = req->new_ansi; /* class ansi is actually ignored */ break; case GWLP_USERDATA: reply->old_info = shared->info.user_data; -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11123