From 1b847dff822bb3f43d3a82b1c08e97192372c431 Mon Sep 17 00:00:00 2001 From: Jacek Caban Date: Wed, 16 Mar 2022 15:35:25 +0100 Subject: [PATCH] win32u: Move NtUsetSetWindowLong implementation from user32. Signed-off-by: Jacek Caban Signed-off-by: Huw Davies Signed-off-by: Alexandre Julliard --- dlls/user32/driver.c | 7 +- dlls/user32/message.c | 2 - dlls/user32/user32.spec | 2 +- dlls/user32/win.c | 307 +-------------------------------- dlls/user32/win.h | 1 - dlls/win32u/class.c | 11 ++ dlls/win32u/gdiobj.c | 3 + dlls/win32u/message.c | 2 + dlls/win32u/ntuser_private.h | 1 + dlls/win32u/win32u.spec | 6 +- dlls/win32u/win32u_private.h | 5 + dlls/win32u/window.c | 317 +++++++++++++++++++++++++++++++++++ dlls/win32u/wrappers.c | 18 ++ include/ntuser.h | 3 + 14 files changed, 369 insertions(+), 316 deletions(-) diff --git a/dlls/user32/driver.c b/dlls/user32/driver.c index 1d6c36c5434..72ea5ad17bd 100644 --- a/dlls/user32/driver.c +++ b/dlls/user32/driver.c @@ -95,10 +95,6 @@ static void CDECL nulldrv_SetWindowIcon( HWND hwnd, UINT type, HICON icon ) { } -static void CDECL nulldrv_SetWindowStyle( HWND hwnd, INT offset, STYLESTRUCT *style ) -{ -} - static void CDECL nulldrv_SetWindowText( HWND hwnd, LPCWSTR text ) { } @@ -190,7 +186,7 @@ static struct user_driver_funcs lazy_load_driver = NULL, NULL, nulldrv_SetWindowIcon, - nulldrv_SetWindowStyle, + NULL, nulldrv_SetWindowText, nulldrv_ShowWindow, nulldrv_SysCommand, @@ -230,7 +226,6 @@ void CDECL __wine_set_user_driver( const struct user_driver_funcs *funcs, UINT v SET_USER_FUNC(DestroyWindow); SET_USER_FUNC(MsgWaitForMultipleObjectsEx); SET_USER_FUNC(SetWindowIcon); - SET_USER_FUNC(SetWindowStyle); SET_USER_FUNC(SetWindowText); SET_USER_FUNC(ShowWindow); SET_USER_FUNC(SysCommand); diff --git a/dlls/user32/message.c b/dlls/user32/message.c index 5867b6b4009..c5bdc0efccc 100644 --- a/dlls/user32/message.c +++ b/dlls/user32/message.c @@ -1864,8 +1864,6 @@ LRESULT handle_internal_message( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lpar case WM_WINE_SHOWWINDOW: if (is_desktop_window( hwnd )) return 0; return ShowWindow( hwnd, wparam ); - case WM_WINE_SETWINDOWLONG: - return WIN_SetWindowLong( hwnd, (short)LOWORD(wparam), HIWORD(wparam), lparam, TRUE ); default: { MSG m; diff --git a/dlls/user32/user32.spec b/dlls/user32/user32.spec index bde66708a15..a70ac8605d7 100644 --- a/dlls/user32/user32.spec +++ b/dlls/user32/user32.spec @@ -730,7 +730,7 @@ @ stdcall SetWindowStationUser(long long) @ stdcall SetWindowTextA(long str) @ stdcall SetWindowTextW(long wstr) -@ stdcall SetWindowWord(long long long) +@ stdcall SetWindowWord(long long long) NtUserSetWindowWord @ stdcall SetWindowsHookA(long ptr) @ stdcall SetWindowsHookExA(long long long long) @ stdcall SetWindowsHookExW(long long long long) diff --git a/dlls/user32/win.c b/dlls/user32/win.c index bb6df478b1b..2c241aad7d2 100644 --- a/dlls/user32/win.c +++ b/dlls/user32/win.c @@ -39,51 +39,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(win); static DWORD process_layout = ~0u; -/**********************************************************************/ - -/* helper for Get/SetWindowLong */ -static inline LONG_PTR get_win_data( const void *ptr, UINT size ) -{ - if (size == sizeof(WORD)) - { - WORD ret; - memcpy( &ret, ptr, sizeof(ret) ); - return ret; - } - else if (size == sizeof(DWORD)) - { - DWORD ret; - memcpy( &ret, ptr, sizeof(ret) ); - return ret; - } - else - { - LONG_PTR ret; - memcpy( &ret, ptr, sizeof(ret) ); - return ret; - } -} - -/* helper for Get/SetWindowLong */ -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) ); - } -} - - /*********************************************************************** * alloc_user_handle */ @@ -1994,236 +1949,6 @@ UINT WINAPI GetDpiForWindow( HWND hwnd ) } -/********************************************************************** - * WIN_SetWindowLong - * - * Helper function for SetWindowLong(). - * - * 0 is the failure code. However, in the case of failure SetLastError - * must be set to distinguish between a 0 return value and a failure. - */ -LONG_PTR WIN_SetWindowLong( HWND hwnd, INT offset, UINT size, LONG_PTR newval, BOOL unicode ) -{ - STYLESTRUCT style; - BOOL ok, made_visible = FALSE; - LONG_PTR retval = 0; - WND *wndPtr; - - TRACE( "%p %d %lx %c\n", hwnd, offset, newval, unicode ? 'W' : 'A' ); - - if (is_broadcast(hwnd)) - { - SetLastError( ERROR_INVALID_PARAMETER ); - return FALSE; - } - - if (!(wndPtr = WIN_GetPtr( hwnd ))) - { - SetLastError( ERROR_INVALID_WINDOW_HANDLE ); - return 0; - } - if (wndPtr == WND_DESKTOP) - { - /* can't change anything on the desktop window */ - SetLastError( ERROR_ACCESS_DENIED ); - return 0; - } - if (wndPtr == WND_OTHER_PROCESS) - { - if (offset == GWLP_WNDPROC) - { - SetLastError( ERROR_ACCESS_DENIED ); - return 0; - } - if (offset > 32767 || offset < -32767) - { - SetLastError( ERROR_INVALID_INDEX ); - return 0; - } - return SendMessageW( hwnd, WM_WINE_SETWINDOWLONG, MAKEWPARAM( offset, size ), newval ); - } - - /* first some special cases */ - switch( offset ) - { - case GWL_STYLE: - style.styleOld = wndPtr->dwStyle; - style.styleNew = newval; - WIN_ReleasePtr( wndPtr ); - SendMessageW( hwnd, WM_STYLECHANGING, GWL_STYLE, (LPARAM)&style ); - if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0; - newval = style.styleNew; - /* WS_CLIPSIBLINGS can't be reset on top-level windows */ - if (wndPtr->parent == GetDesktopWindow()) newval |= WS_CLIPSIBLINGS; - /* WS_MINIMIZE can't be reset */ - if (wndPtr->dwStyle & WS_MINIMIZE) newval |= WS_MINIMIZE; - break; - case GWL_EXSTYLE: - style.styleOld = wndPtr->dwExStyle; - style.styleNew = newval; - WIN_ReleasePtr( wndPtr ); - SendMessageW( hwnd, WM_STYLECHANGING, GWL_EXSTYLE, (LPARAM)&style ); - if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0; - /* WS_EX_TOPMOST can only be changed through SetWindowPos */ - newval = (style.styleNew & ~WS_EX_TOPMOST) | (wndPtr->dwExStyle & WS_EX_TOPMOST); - newval = fix_exstyle(wndPtr->dwStyle, newval); - break; - case GWLP_HWNDPARENT: - if (wndPtr->parent == GetDesktopWindow()) - { - WIN_ReleasePtr( wndPtr ); - return (ULONG_PTR)WIN_SetOwner( hwnd, (HWND)newval ); - } - else - { - WIN_ReleasePtr( wndPtr ); - return (ULONG_PTR)NtUserSetParent( hwnd, (HWND)newval ); - } - case GWLP_WNDPROC: - { - WNDPROC proc; - UINT old_flags = wndPtr->flags; - retval = unicode ? GetWindowLongPtrW( hwnd, offset ) : GetWindowLongPtrA( hwnd, offset ); - proc = WINPROC_AllocProc( (WNDPROC)newval, unicode ); - if (proc) wndPtr->winproc = proc; - if (WINPROC_IsUnicode( proc, unicode )) wndPtr->flags |= WIN_ISUNICODE; - else wndPtr->flags &= ~WIN_ISUNICODE; - if (!((old_flags ^ wndPtr->flags) & WIN_ISUNICODE)) - { - WIN_ReleasePtr( wndPtr ); - return retval; - } - /* update is_unicode flag on the server side */ - break; - } - case GWLP_ID: - case GWLP_HINSTANCE: - case GWLP_USERDATA: - break; - case DWLP_DLGPROC: - if ((wndPtr->cbWndExtra - sizeof(LONG_PTR) >= DWLP_DLGPROC) && - (size == sizeof(LONG_PTR)) && wndPtr->dlgInfo) - { - WNDPROC *ptr = (WNDPROC *)((char *)wndPtr->wExtra + DWLP_DLGPROC); - retval = (ULONG_PTR)WINPROC_GetProc( *ptr, unicode ); - *ptr = WINPROC_AllocProc( (WNDPROC)newval, unicode ); - WIN_ReleasePtr( wndPtr ); - return retval; - } - /* fall through */ - default: - if (offset < 0 || offset > (int)(wndPtr->cbWndExtra - size)) - { - WARN("Invalid offset %d\n", offset ); - WIN_ReleasePtr( wndPtr ); - SetLastError( ERROR_INVALID_INDEX ); - return 0; - } - else if (get_win_data( (char *)wndPtr->wExtra + offset, size ) == newval) - { - /* already set to the same value */ - WIN_ReleasePtr( wndPtr ); - return newval; - } - break; - } - - SERVER_START_REQ( set_window_info ) - { - req->handle = wine_server_user_handle( hwnd ); - req->extra_offset = -1; - switch(offset) - { - case GWL_STYLE: - req->flags = SET_WIN_STYLE | SET_WIN_EXSTYLE; - req->style = newval; - req->ex_style = fix_exstyle(newval, wndPtr->dwExStyle); - break; - case GWL_EXSTYLE: - req->flags = SET_WIN_EXSTYLE; - req->ex_style = newval; - break; - case GWLP_ID: - req->flags = SET_WIN_ID; - req->extra_value = newval; - break; - case GWLP_HINSTANCE: - req->flags = SET_WIN_INSTANCE; - req->instance = wine_server_client_ptr( (void *)newval ); - break; - case GWLP_WNDPROC: - req->flags = SET_WIN_UNICODE; - req->is_unicode = (wndPtr->flags & WIN_ISUNICODE) != 0; - break; - case GWLP_USERDATA: - req->flags = SET_WIN_USERDATA; - req->user_data = newval; - break; - default: - req->flags = SET_WIN_EXTRA; - req->extra_offset = offset; - req->extra_size = size; - set_win_data( &req->extra_value, newval, size ); - } - if ((ok = !wine_server_call_err( req ))) - { - switch(offset) - { - case GWL_STYLE: - wndPtr->dwStyle = newval; - wndPtr->dwExStyle = fix_exstyle(wndPtr->dwStyle, wndPtr->dwExStyle); - retval = reply->old_style; - break; - case GWL_EXSTYLE: - wndPtr->dwExStyle = newval; - retval = reply->old_ex_style; - break; - case GWLP_ID: - wndPtr->wIDmenu = newval; - retval = reply->old_id; - break; - case GWLP_HINSTANCE: - wndPtr->hInstance = (HINSTANCE)newval; - retval = (ULONG_PTR)wine_server_get_ptr( reply->old_instance ); - break; - case GWLP_WNDPROC: - break; - case GWLP_USERDATA: - wndPtr->userdata = newval; - retval = reply->old_user_data; - break; - default: - retval = get_win_data( (char *)wndPtr->wExtra + offset, size ); - set_win_data( (char *)wndPtr->wExtra + offset, newval, size ); - break; - } - } - } - SERVER_END_REQ; - - if ((offset == GWL_STYLE && ((style.styleOld ^ style.styleNew) & WS_VISIBLE)) || - (offset == GWL_EXSTYLE && ((style.styleOld ^ style.styleNew) & WS_EX_LAYERED))) - { - made_visible = (wndPtr->dwStyle & WS_VISIBLE) != 0; - invalidate_dce( wndPtr, NULL ); - } - WIN_ReleasePtr( wndPtr ); - - if (!ok) return 0; - - if (offset == GWL_STYLE || offset == GWL_EXSTYLE) - { - style.styleOld = retval; - style.styleNew = newval; - USER_Driver->pSetWindowStyle( hwnd, offset, &style ); - if (made_visible) update_window_state( hwnd ); - SendMessageW( hwnd, WM_STYLECHANGED, offset, (LPARAM)&style ); - } - - return retval; -} - - /********************************************************************** * GetWindowWord (USER32.@) */ @@ -2275,30 +2000,6 @@ LONG WINAPI GetWindowLongW( HWND hwnd, INT offset ) } -/********************************************************************** - * SetWindowWord (USER32.@) - */ -WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval ) -{ - switch(offset) - { - case GWLP_ID: - case GWLP_HINSTANCE: - case GWLP_HWNDPARENT: - break; - default: - if (offset < 0) - { - WARN("Invalid offset %d\n", offset ); - SetLastError( ERROR_INVALID_INDEX ); - return 0; - } - break; - } - return WIN_SetWindowLong( hwnd, offset, sizeof(WORD), newval, FALSE ); -} - - /********************************************************************** * SetWindowLongA (USER32.@) * @@ -2317,7 +2018,7 @@ LONG WINAPI DECLSPEC_HOTPATCH SetWindowLongA( HWND hwnd, INT offset, LONG newval return 0; #endif default: - return WIN_SetWindowLong( hwnd, offset, sizeof(LONG), newval, FALSE ); + return NtUserSetWindowLong( hwnd, offset, newval, TRUE ); } } @@ -2405,7 +2106,7 @@ LONG WINAPI DECLSPEC_HOTPATCH SetWindowLongW( return 0; #endif default: - return WIN_SetWindowLong( hwnd, offset, sizeof(LONG), newval, TRUE ); + return NtUserSetWindowLong( hwnd, offset, newval, FALSE ); } } @@ -3185,7 +2886,7 @@ LONG_PTR WINAPI GetWindowLongPtrA( HWND hwnd, INT offset ) */ LONG_PTR WINAPI SetWindowLongPtrW( HWND hwnd, INT offset, LONG_PTR newval ) { - return WIN_SetWindowLong( hwnd, offset, sizeof(LONG_PTR), newval, TRUE ); + return NtUserSetWindowLongPtr( hwnd, offset, newval, FALSE ); } /***************************************************************************** @@ -3193,7 +2894,7 @@ LONG_PTR WINAPI SetWindowLongPtrW( HWND hwnd, INT offset, LONG_PTR newval ) */ LONG_PTR WINAPI SetWindowLongPtrA( HWND hwnd, INT offset, LONG_PTR newval ) { - return WIN_SetWindowLong( hwnd, offset, sizeof(LONG_PTR), newval, FALSE ); + return NtUserSetWindowLongPtr( hwnd, offset, newval, TRUE ); } /***************************************************************************** diff --git a/dlls/user32/win.h b/dlls/user32/win.h index 2a865e35ed7..08bb16a0d4a 100644 --- a/dlls/user32/win.h +++ b/dlls/user32/win.h @@ -50,7 +50,6 @@ extern void destroy_thread_windows(void) DECLSPEC_HIDDEN; extern HWND WIN_CreateWindowEx( CREATESTRUCTW *cs, LPCWSTR className, HINSTANCE module, BOOL unicode ) DECLSPEC_HIDDEN; extern BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL ) DECLSPEC_HIDDEN; extern HWND *WIN_ListChildren( HWND hwnd ) DECLSPEC_HIDDEN; -extern LONG_PTR WIN_SetWindowLong( HWND hwnd, INT offset, UINT size, LONG_PTR newval, BOOL unicode ) DECLSPEC_HIDDEN; extern void MDI_CalcDefaultChildPos( HWND hwndClient, INT total, LPPOINT lpPos, INT delta, UINT *id ) DECLSPEC_HIDDEN; extern HDESK open_winstation_desktop( HWINSTA hwinsta, LPCWSTR name, DWORD flags, BOOL inherit, ACCESS_MASK access ) DECLSPEC_HIDDEN; diff --git a/dlls/win32u/class.c b/dlls/win32u/class.c index 3113ef357cf..3a4a00de29b 100644 --- a/dlls/win32u/class.c +++ b/dlls/win32u/class.c @@ -152,6 +152,17 @@ 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; +} + /*********************************************************************** * NtUserInitializeClientPfnArrays (win32u.@) */ diff --git a/dlls/win32u/gdiobj.c b/dlls/win32u/gdiobj.c index 208ebb1da5e..adb162ab7ff 100644 --- a/dlls/win32u/gdiobj.c +++ b/dlls/win32u/gdiobj.c @@ -1203,8 +1203,11 @@ static struct unix_funcs unix_funcs = NtUserSetLayeredWindowAttributes, NtUserSetParent, NtUserSetSysColors, + NtUserSetWindowLong, + NtUserSetWindowLongPtr, NtUserSetWindowPos, NtUserSetWindowRgn, + NtUserSetWindowWord, NtUserShowCursor, NtUserSystemParametersInfo, NtUserSystemParametersInfoForDpi, diff --git a/dlls/win32u/message.c b/dlls/win32u/message.c index 1f0d6e6c297..c28114668b8 100644 --- a/dlls/win32u/message.c +++ b/dlls/win32u/message.c @@ -47,6 +47,8 @@ LRESULT handle_internal_message( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lpar case WM_WINE_SETPARENT: if (is_desktop_window( hwnd )) return 0; return HandleToUlong( NtUserSetParent( hwnd, UlongToHandle(wparam) )); + case WM_WINE_SETWINDOWLONG: + return set_window_long( hwnd, (short)LOWORD(wparam), HIWORD(wparam), lparam, FALSE ); case WM_WINE_SETSTYLE: if (is_desktop_window( hwnd )) return 0; return set_window_style( hwnd, wparam, lparam ); diff --git a/dlls/win32u/ntuser_private.h b/dlls/win32u/ntuser_private.h index 5452b5126d8..6b0345461ea 100644 --- a/dlls/win32u/ntuser_private.h +++ b/dlls/win32u/ntuser_private.h @@ -245,6 +245,7 @@ typedef struct tagCLASS /* class.c */ WNDPROC alloc_winproc( WNDPROC func, BOOL ansi ) DECLSPEC_HIDDEN; WINDOWPROC *get_winproc_ptr( WNDPROC handle ) DECLSPEC_HIDDEN; +BOOL is_winproc_unicode( WNDPROC proc, BOOL def_val ) DECLSPEC_HIDDEN; DWORD get_class_long( HWND hwnd, INT offset, BOOL ansi ) DECLSPEC_HIDDEN; ULONG_PTR get_class_long_ptr( HWND hwnd, INT offset, BOOL ansi ) DECLSPEC_HIDDEN; WORD get_class_word( HWND hwnd, INT offset ) DECLSPEC_HIDDEN; diff --git a/dlls/win32u/win32u.spec b/dlls/win32u/win32u.spec index e37907e7399..2b5e4d71461 100644 --- a/dlls/win32u/win32u.spec +++ b/dlls/win32u/win32u.spec @@ -1246,15 +1246,15 @@ @ stub NtUserSetWindowFNID @ stub NtUserSetWindowFeedbackSetting @ stub NtUserSetWindowGroup -@ stub NtUserSetWindowLong -@ stub NtUserSetWindowLongPtr +@ stdcall NtUserSetWindowLong(long long long long) +@ stdcall NtUserSetWindowLongPtr(long long long long) @ stub NtUserSetWindowPlacement @ stdcall NtUserSetWindowPos(long long long long long long long) @ stdcall NtUserSetWindowRgn(long long long) @ stub NtUserSetWindowRgnEx @ stub NtUserSetWindowShowState @ stub NtUserSetWindowStationUser -@ stub NtUserSetWindowWord +@ stdcall NtUserSetWindowWord(long long long) @ stub NtUserSetWindowsHookAW @ stdcall -syscall NtUserSetWindowsHookEx(ptr ptr long long ptr long) @ stub NtUserShowCaret diff --git a/dlls/win32u/win32u_private.h b/dlls/win32u/win32u_private.h index 67df4490bf3..c943089c462 100644 --- a/dlls/win32u/win32u_private.h +++ b/dlls/win32u/win32u_private.h @@ -251,8 +251,11 @@ struct unix_funcs BOOL (WINAPI *pNtUserSetLayeredWindowAttributes)( HWND hwnd, COLORREF key, BYTE alpha, DWORD flags ); HWND (WINAPI *pNtUserSetParent)( HWND hwnd, HWND parent ); BOOL (WINAPI *pNtUserSetSysColors)( INT count, const INT *colors, const COLORREF *values ); + LONG (WINAPI *pNtUserSetWindowLong)( HWND hwnd, INT offset, LONG newval, BOOL ansi ); + LONG_PTR (WINAPI *pNtUserSetWindowLongPtr)( HWND hwnd, INT offset, LONG_PTR newval, BOOL ansi ); BOOL (WINAPI *pNtUserSetWindowPos)( HWND hwnd, HWND after, INT x, INT y, INT cx, INT cy, UINT flags ); int (WINAPI *pNtUserSetWindowRgn)( HWND hwnd, HRGN hrgn, BOOL redraw ); + WORD (WINAPI *pNtUserSetWindowWord)( HWND hwnd, INT offset, WORD newval ); INT (WINAPI *pNtUserShowCursor)( BOOL show ); BOOL (WINAPI *pNtUserSystemParametersInfo)( UINT action, UINT val, PVOID ptr, UINT winini ); BOOL (WINAPI *pNtUserSystemParametersInfoForDpi)( UINT action, UINT val, PVOID ptr, @@ -360,6 +363,8 @@ extern HWND *list_window_children( HDESK desktop, HWND hwnd, UNICODE_STRING *cla extern int map_window_points( HWND hwnd_from, HWND hwnd_to, POINT *points, UINT count, UINT dpi ) DECLSPEC_HIDDEN; extern void map_window_region( HWND from, HWND to, HRGN hrgn ) DECLSPEC_HIDDEN; +extern LONG_PTR set_window_long( HWND hwnd, INT offset, UINT size, LONG_PTR newval, + BOOL ansi ) DECLSPEC_HIDDEN; extern BOOL set_window_pos( WINDOWPOS *winpos, int parent_x, int parent_y ) DECLSPEC_HIDDEN; extern ULONG set_window_style( HWND hwnd, ULONG set_bits, ULONG clear_bits ) DECLSPEC_HIDDEN; extern void update_window_state( HWND hwnd ) DECLSPEC_HIDDEN; diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c index 01b1f15d158..e4311b49608 100644 --- a/dlls/win32u/window.c +++ b/dlls/win32u/window.c @@ -892,6 +892,25 @@ static LONG_PTR get_win_data( const void *ptr, UINT size ) } } +/* 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; @@ -1104,6 +1123,304 @@ ULONG set_window_style( HWND hwnd, ULONG set_bits, ULONG clear_bits ) return style.styleOld; } +static DWORD fix_exstyle( DWORD style, DWORD exstyle ) +{ + if ((exstyle & WS_EX_DLGMODALFRAME) || + (!(exstyle & WS_EX_STATICEDGE) && (style & (WS_DLGFRAME | WS_THICKFRAME)))) + exstyle |= WS_EX_WINDOWEDGE; + else + exstyle &= ~WS_EX_WINDOWEDGE; + return exstyle; +} + +/* Change the owner of a window. */ +static HWND set_window_owner( HWND hwnd, HWND owner ) +{ + WND *win = get_win_ptr( hwnd ); + HWND ret = 0; + + if (!win || win == WND_DESKTOP) return 0; + if (win == WND_OTHER_PROCESS) + { + if (is_window(hwnd)) ERR( "cannot set owner %p on other process window %p\n", owner, hwnd ); + return 0; + } + SERVER_START_REQ( set_window_owner ) + { + req->handle = wine_server_user_handle( hwnd ); + req->owner = wine_server_user_handle( owner ); + if (!wine_server_call( req )) + { + win->owner = wine_server_ptr_handle( reply->full_owner ); + ret = wine_server_ptr_handle( reply->prev_owner ); + } + } + SERVER_END_REQ; + release_win_ptr( win ); + return ret; +} + +/* Helper function for SetWindowLong(). */ +LONG_PTR set_window_long( HWND hwnd, INT offset, UINT size, LONG_PTR newval, BOOL ansi ) +{ + BOOL ok, made_visible = FALSE; + LONG_PTR retval = 0; + STYLESTRUCT style; + WND *win; + + TRACE( "%p %d %lx %c\n", hwnd, offset, newval, ansi ? 'A' : 'W' ); + + if (is_broadcast(hwnd)) + { + SetLastError( ERROR_INVALID_PARAMETER ); + return FALSE; + } + + if (!(win = get_win_ptr( hwnd ))) + { + SetLastError( ERROR_INVALID_WINDOW_HANDLE ); + return 0; + } + if (win == WND_DESKTOP) + { + /* can't change anything on the desktop window */ + SetLastError( ERROR_ACCESS_DENIED ); + return 0; + } + if (win == WND_OTHER_PROCESS) + { + if (offset == GWLP_WNDPROC) + { + SetLastError( ERROR_ACCESS_DENIED ); + return 0; + } + if (offset > 32767 || offset < -32767) + { + SetLastError( ERROR_INVALID_INDEX ); + return 0; + } + return send_message( hwnd, WM_WINE_SETWINDOWLONG, MAKEWPARAM( offset, size ), newval ); + } + + /* first some special cases */ + switch( offset ) + { + case GWL_STYLE: + style.styleOld = win->dwStyle; + style.styleNew = newval; + release_win_ptr( win ); + send_message( hwnd, WM_STYLECHANGING, GWL_STYLE, (LPARAM)&style ); + if (!(win = get_win_ptr( hwnd )) || win == WND_OTHER_PROCESS) return 0; + newval = style.styleNew; + /* WS_CLIPSIBLINGS can't be reset on top-level windows */ + if (win->parent == get_desktop_window()) newval |= WS_CLIPSIBLINGS; + /* WS_MINIMIZE can't be reset */ + if (win->dwStyle & WS_MINIMIZE) newval |= WS_MINIMIZE; + break; + case GWL_EXSTYLE: + style.styleOld = win->dwExStyle; + style.styleNew = newval; + release_win_ptr( win ); + send_message( hwnd, WM_STYLECHANGING, GWL_EXSTYLE, (LPARAM)&style ); + if (!(win = get_win_ptr( hwnd )) || win == WND_OTHER_PROCESS) return 0; + /* WS_EX_TOPMOST can only be changed through SetWindowPos */ + newval = (style.styleNew & ~WS_EX_TOPMOST) | (win->dwExStyle & WS_EX_TOPMOST); + newval = fix_exstyle(win->dwStyle, newval); + break; + case GWLP_HWNDPARENT: + if (win->parent == get_desktop_window()) + { + release_win_ptr( win ); + return (ULONG_PTR)set_window_owner( hwnd, (HWND)newval ); + } + else + { + release_win_ptr( win ); + 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 */ + break; + } + case GWLP_ID: + case GWLP_HINSTANCE: + case GWLP_USERDATA: + break; + case DWLP_DLGPROC: + if ((win->cbWndExtra - sizeof(LONG_PTR) >= DWLP_DLGPROC) && + (size == sizeof(LONG_PTR)) && win->dlgInfo) + { + WNDPROC *ptr = (WNDPROC *)((char *)win->wExtra + DWLP_DLGPROC); + retval = (ULONG_PTR)get_winproc( *ptr, ansi ); + *ptr = alloc_winproc( (WNDPROC)newval, ansi ); + release_win_ptr( win ); + return retval; + } + /* fall through */ + default: + if (offset < 0 || offset > (int)(win->cbWndExtra - size)) + { + WARN("Invalid offset %d\n", offset ); + release_win_ptr( win ); + SetLastError( ERROR_INVALID_INDEX ); + return 0; + } + else if (get_win_data( (char *)win->wExtra + offset, size ) == newval) + { + /* already set to the same value */ + release_win_ptr( win ); + return newval; + } + break; + } + + SERVER_START_REQ( set_window_info ) + { + req->handle = wine_server_user_handle( hwnd ); + req->extra_offset = -1; + switch(offset) + { + case GWL_STYLE: + req->flags = SET_WIN_STYLE | SET_WIN_EXSTYLE; + req->style = newval; + req->ex_style = fix_exstyle(newval, win->dwExStyle); + break; + case GWL_EXSTYLE: + req->flags = SET_WIN_EXSTYLE; + req->ex_style = newval; + break; + case GWLP_ID: + req->flags = SET_WIN_ID; + req->extra_value = newval; + break; + case GWLP_HINSTANCE: + req->flags = SET_WIN_INSTANCE; + req->instance = wine_server_client_ptr( (void *)newval ); + break; + case GWLP_WNDPROC: + req->flags = SET_WIN_UNICODE; + req->is_unicode = (win->flags & WIN_ISUNICODE) != 0; + break; + case GWLP_USERDATA: + req->flags = SET_WIN_USERDATA; + req->user_data = newval; + break; + default: + req->flags = SET_WIN_EXTRA; + req->extra_offset = offset; + req->extra_size = size; + set_win_data( &req->extra_value, newval, size ); + } + if ((ok = !wine_server_call_err( req ))) + { + switch(offset) + { + case GWL_STYLE: + win->dwStyle = newval; + win->dwExStyle = fix_exstyle(win->dwStyle, win->dwExStyle); + retval = reply->old_style; + break; + case GWL_EXSTYLE: + win->dwExStyle = newval; + retval = reply->old_ex_style; + break; + case GWLP_ID: + win->wIDmenu = newval; + retval = reply->old_id; + break; + case GWLP_HINSTANCE: + win->hInstance = (HINSTANCE)newval; + retval = (ULONG_PTR)wine_server_get_ptr( reply->old_instance ); + break; + case GWLP_WNDPROC: + break; + case GWLP_USERDATA: + win->userdata = newval; + retval = reply->old_user_data; + break; + default: + retval = get_win_data( (char *)win->wExtra + offset, size ); + set_win_data( (char *)win->wExtra + offset, newval, size ); + break; + } + } + } + SERVER_END_REQ; + + if ((offset == GWL_STYLE && ((style.styleOld ^ style.styleNew) & WS_VISIBLE)) || + (offset == GWL_EXSTYLE && ((style.styleOld ^ style.styleNew) & WS_EX_LAYERED))) + { + made_visible = (win->dwStyle & WS_VISIBLE) != 0; + invalidate_dce( win, NULL ); + } + release_win_ptr( win ); + + if (!ok) return 0; + + if (offset == GWL_STYLE || offset == GWL_EXSTYLE) + { + style.styleOld = retval; + style.styleNew = newval; + user_driver->pSetWindowStyle( hwnd, offset, &style ); + if (made_visible) update_window_state( hwnd ); + send_message( hwnd, WM_STYLECHANGED, offset, (LPARAM)&style ); + } + + return retval; +} + +/********************************************************************** + * NtUserSetWindowWord (win32u.@) + */ +WORD WINAPI NtUserSetWindowWord( HWND hwnd, INT offset, WORD newval ) +{ + switch(offset) + { + case GWLP_ID: + case GWLP_HINSTANCE: + case GWLP_HWNDPARENT: + break; + default: + if (offset < 0) + { + WARN("Invalid offset %d\n", offset ); + SetLastError( ERROR_INVALID_INDEX ); + return 0; + } + break; + } + return set_window_long( hwnd, offset, sizeof(WORD), newval, TRUE ); +} + +/********************************************************************** + * NtUserSetWindowLong (win32u.@) + */ +LONG WINAPI NtUserSetWindowLong( HWND hwnd, INT offset, LONG newval, BOOL ansi ) +{ + return set_window_long( hwnd, offset, sizeof(LONG), newval, ansi ); +} + +/***************************************************************************** + * NtUserSetWindowLongPtr (win32u.@) + */ +LONG_PTR WINAPI NtUserSetWindowLongPtr( HWND hwnd, INT offset, LONG_PTR newval, BOOL ansi ) +{ + return set_window_long( hwnd, offset, sizeof(LONG_PTR), newval, ansi ); +} + /*********************************************************************** * NtUserGetProp (win32u.@) * diff --git a/dlls/win32u/wrappers.c b/dlls/win32u/wrappers.c index 9665c8106c4..258483ad8de 100644 --- a/dlls/win32u/wrappers.c +++ b/dlls/win32u/wrappers.c @@ -1033,6 +1033,18 @@ BOOL WINAPI NtUserSetSysColors( INT count, const INT *colors, const COLORREF *va return unix_funcs->pNtUserSetSysColors( count, colors, values ); } +LONG WINAPI NtUserSetWindowLong( HWND hwnd, INT offset, LONG newval, BOOL ansi ) +{ + if (!unix_funcs) return 0; + return unix_funcs->pNtUserSetWindowLong( hwnd, offset, newval, ansi ); +} + +LONG_PTR WINAPI NtUserSetWindowLongPtr( HWND hwnd, INT offset, LONG_PTR newval, BOOL ansi ) +{ + if (!unix_funcs) return 0; + return unix_funcs->pNtUserSetWindowLongPtr( hwnd, offset, newval, ansi ); +} + BOOL WINAPI NtUserSetWindowPos( HWND hwnd, HWND after, INT x, INT y, INT cx, INT cy, UINT flags ) { if (!unix_funcs) return 0; @@ -1045,6 +1057,12 @@ int WINAPI NtUserSetWindowRgn( HWND hwnd, HRGN hrgn, BOOL redraw ) return unix_funcs->pNtUserSetWindowRgn( hwnd, hrgn, redraw ); } +WORD WINAPI NtUserSetWindowWord( HWND hwnd, INT offset, WORD newval ) +{ + if (!unix_funcs) return 0; + return unix_funcs->pNtUserSetWindowWord( hwnd, offset, newval ); +} + INT WINAPI NtUserShowCursor( BOOL show ) { if (!unix_funcs) return 0; diff --git a/include/ntuser.h b/include/ntuser.h index 96f61d2a07a..0e48aea0f9c 100644 --- a/include/ntuser.h +++ b/include/ntuser.h @@ -402,8 +402,11 @@ BOOL WINAPI NtUserSetProcessWindowStation( HWINSTA handle ); BOOL WINAPI NtUserSetProp( HWND hwnd, const WCHAR *str, HANDLE handle ); BOOL WINAPI NtUserSetSysColors( INT count, const INT *colors, const COLORREF *values ); BOOL WINAPI NtUserSetThreadDesktop( HDESK handle ); +LONG WINAPI NtUserSetWindowLong( HWND hwnd, INT offset, LONG newval, BOOL ansi ); +LONG_PTR WINAPI NtUserSetWindowLongPtr( HWND hwnd, INT offset, LONG_PTR newval, BOOL ansi ); BOOL WINAPI NtUserSetWindowPos( HWND hwnd, HWND after, INT x, INT y, INT cx, INT cy, UINT flags ); int WINAPI NtUserSetWindowRgn( HWND hwnd, HRGN hrgn, BOOL redraw ); +WORD WINAPI NtUserSetWindowWord( HWND hwnd, INT offset, WORD newval ); HHOOK WINAPI NtUserSetWindowsHookEx( HINSTANCE inst, UNICODE_STRING *module, DWORD tid, INT id, HOOKPROC proc, BOOL ansi ); HWINEVENTHOOK WINAPI NtUserSetWinEventHook( DWORD event_min, DWORD event_max, HMODULE inst,