win32u: Move GetWindowLong implementation from user32.

Signed-off-by: Jacek Caban <jacek@codeweavers.com>
Signed-off-by: Huw Davies <huw@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Jacek Caban 2022-03-08 14:23:52 +01:00 committed by Alexandre Julliard
parent d312083e0a
commit d174cb2294
6 changed files with 274 additions and 157 deletions

View File

@ -2325,131 +2325,6 @@ UINT WINAPI GetDpiForWindow( HWND hwnd )
}
/**********************************************************************
* WIN_GetWindowLong
*
* Helper function for GetWindowLong().
*/
static LONG_PTR WIN_GetWindowLong( HWND hwnd, INT offset, UINT size, BOOL unicode )
{
LONG_PTR retvalue = 0;
WND *wndPtr;
if (offset == GWLP_HWNDPARENT)
{
HWND parent = GetAncestor( hwnd, GA_PARENT );
if (parent == GetDesktopWindow()) parent = GetWindow( hwnd, GW_OWNER );
return (ULONG_PTR)parent;
}
if (!(wndPtr = WIN_GetPtr( hwnd )))
{
SetLastError( ERROR_INVALID_WINDOW_HANDLE );
return 0;
}
if (wndPtr == WND_DESKTOP)
{
switch (offset)
{
case GWL_STYLE:
retvalue = WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN; /* message parent is not visible */
if (WIN_GetFullHandle( hwnd ) == GetDesktopWindow())
retvalue |= WS_VISIBLE;
return retvalue;
case GWL_EXSTYLE:
case GWLP_USERDATA:
case GWLP_ID:
case GWLP_HINSTANCE:
return 0;
case GWLP_WNDPROC:
SetLastError( ERROR_ACCESS_DENIED );
return 0;
}
SetLastError( ERROR_INVALID_INDEX );
return 0;
}
if (wndPtr == WND_OTHER_PROCESS)
{
if (offset == GWLP_WNDPROC)
{
SetLastError( ERROR_ACCESS_DENIED );
return 0;
}
SERVER_START_REQ( set_window_info )
{
req->handle = wine_server_user_handle( hwnd );
req->flags = 0; /* don't set anything, just retrieve */
req->extra_offset = (offset >= 0) ? offset : -1;
req->extra_size = (offset >= 0) ? size : 0;
if (!wine_server_call_err( req ))
{
switch(offset)
{
case GWL_STYLE: retvalue = reply->old_style; break;
case GWL_EXSTYLE: retvalue = reply->old_ex_style; break;
case GWLP_ID: retvalue = reply->old_id; break;
case GWLP_HINSTANCE: retvalue = (ULONG_PTR)wine_server_get_ptr( reply->old_instance ); break;
case GWLP_USERDATA: retvalue = reply->old_user_data; break;
default:
if (offset >= 0) retvalue = get_win_data( &reply->old_extra_value, size );
else SetLastError( ERROR_INVALID_INDEX );
break;
}
}
}
SERVER_END_REQ;
return retvalue;
}
/* now we have a valid wndPtr */
if (offset >= 0)
{
if (offset > (int)(wndPtr->cbWndExtra - size))
{
WARN("Invalid offset %d\n", offset );
WIN_ReleasePtr( wndPtr );
SetLastError( ERROR_INVALID_INDEX );
return 0;
}
retvalue = get_win_data( (char *)wndPtr->wExtra + offset, size );
/* Special case for dialog window procedure */
if ((offset == DWLP_DLGPROC) && (size == sizeof(LONG_PTR)) && wndPtr->dlgInfo)
retvalue = (LONG_PTR)WINPROC_GetProc( (WNDPROC)retvalue, unicode );
WIN_ReleasePtr( wndPtr );
return retvalue;
}
switch(offset)
{
case GWLP_USERDATA: retvalue = wndPtr->userdata; break;
case GWL_STYLE: retvalue = wndPtr->dwStyle; break;
case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle; break;
case GWLP_ID: retvalue = wndPtr->wIDmenu; break;
case GWLP_HINSTANCE: retvalue = (ULONG_PTR)wndPtr->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
* that the hack is in GetWindowLongPtr[AW], not in winprocs.
*/
if (wndPtr->winproc == BUILTIN_WINPROC(WINPROC_EDIT) && (!unicode != !(wndPtr->flags & WIN_ISUNICODE)))
retvalue = (ULONG_PTR)wndPtr->winproc;
else
retvalue = (ULONG_PTR)WINPROC_GetProc( wndPtr->winproc, unicode );
break;
default:
WARN("Unknown offset %d\n", offset );
SetLastError( ERROR_INVALID_INDEX );
break;
}
WIN_ReleasePtr(wndPtr);
return retvalue;
}
/**********************************************************************
* WIN_SetWindowLong
*
@ -2539,7 +2414,7 @@ LONG_PTR WIN_SetWindowLong( HWND hwnd, INT offset, UINT size, LONG_PTR newval, B
{
WNDPROC proc;
UINT old_flags = wndPtr->flags;
retval = WIN_GetWindowLong( hwnd, offset, size, unicode );
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;
@ -2680,27 +2555,22 @@ LONG_PTR WIN_SetWindowLong( HWND hwnd, INT offset, UINT size, LONG_PTR newval, B
}
/* FIXME: move to win32u */
static ULONG_PTR get_hwnd_parent( HWND hwnd )
{
HWND parent = GetAncestor( hwnd, GA_PARENT );
if (parent == GetDesktopWindow()) parent = GetWindow( hwnd, GW_OWNER );
return (ULONG_PTR)parent;
}
/**********************************************************************
* GetWindowWord (USER32.@)
*/
WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
{
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_GetWindowLong( hwnd, offset, sizeof(WORD), FALSE );
if (offset == GWLP_HWNDPARENT) return get_hwnd_parent( hwnd );
return NtUserCallHwndParam( hwnd, offset, NtUserGetWindowWord );
}
@ -2720,7 +2590,8 @@ LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
return 0;
#endif
default:
return WIN_GetWindowLong( hwnd, offset, sizeof(LONG), FALSE );
if (offset == GWLP_HWNDPARENT) return get_hwnd_parent( hwnd );
return NtUserCallHwndParam( hwnd, offset, NtUserGetWindowLongA );
}
}
@ -2741,7 +2612,8 @@ LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
return 0;
#endif
default:
return WIN_GetWindowLong( hwnd, offset, sizeof(LONG), TRUE );
if (offset == GWLP_HWNDPARENT) return get_hwnd_parent( hwnd );
return NtUserCallHwndParam( hwnd, offset, NtUserGetWindowLongW );
}
}
@ -4075,7 +3947,8 @@ BOOL WINAPI SetProcessDefaultLayout( DWORD layout )
*/
LONG_PTR WINAPI GetWindowLongPtrW( HWND hwnd, INT offset )
{
return WIN_GetWindowLong( hwnd, offset, sizeof(LONG_PTR), TRUE );
if (offset == GWLP_HWNDPARENT) return get_hwnd_parent( hwnd );
return NtUserCallHwndParam( hwnd, offset, NtUserGetWindowLongPtrW );
}
/*****************************************************************************
@ -4083,7 +3956,8 @@ LONG_PTR WINAPI GetWindowLongPtrW( HWND hwnd, INT offset )
*/
LONG_PTR WINAPI GetWindowLongPtrA( HWND hwnd, INT offset )
{
return WIN_GetWindowLong( hwnd, offset, sizeof(LONG_PTR), FALSE );
if (offset == GWLP_HWNDPARENT) return get_hwnd_parent( hwnd );
return NtUserCallHwndParam( hwnd, offset, NtUserGetWindowLongPtrA );
}
/*****************************************************************************

View File

@ -33,16 +33,6 @@
struct tagCLASS;
struct tagDIALOGINFO;
/* WND flags values */
#define WIN_RESTORE_MAX 0x0001 /* Maximize when restoring */
#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 */
/* Window functions */
extern HWND get_hwnd_message_parent(void) DECLSPEC_HIDDEN;
extern BOOL is_desktop_window( HWND hwnd ) DECLSPEC_HIDDEN;

View File

@ -135,7 +135,7 @@ WNDPROC alloc_winproc( WNDPROC func, BOOL ansi )
}
/* Get a window procedure pointer that can be passed to the Windows program. */
static WNDPROC get_winproc( WNDPROC proc, BOOL ansi )
WNDPROC get_winproc( WNDPROC proc, BOOL ansi )
{
WINDOWPROC *ptr = get_winproc_ptr( proc );

View File

@ -91,6 +91,16 @@ typedef struct tagWND
DWORD wExtra[1]; /* Window extra bytes */
} WND;
/* WND flags values */
#define WIN_RESTORE_MAX 0x0001 /* Maximize when restoring */
#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 */
#define WND_OTHER_PROCESS ((WND *)1) /* returned by WIN_GetPtr on unknown window handles */
#define WND_DESKTOP ((WND *)2) /* returned by WIN_GetPtr on the desktop window */
@ -207,6 +217,7 @@ WINDOWPROC *get_winproc_ptr( WNDPROC handle ) 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;
WNDPROC get_winproc( WNDPROC proc, BOOL ansi ) DECLSPEC_HIDDEN;
/* cursoricon.c */
HICON alloc_cursoricon_handle( BOOL is_icon ) DECLSPEC_HIDDEN;

View File

@ -154,6 +154,60 @@ WND *next_thread_window_ptr( HWND *hwnd )
return NULL;
}
/*******************************************************************
* get_hwnd_message_parent
*
* Return the parent for HWND_MESSAGE windows.
*/
static HWND get_hwnd_message_parent(void)
{
struct user_thread_info *thread_info = get_user_thread_info();
if (!thread_info->msg_window && user_callbacks)
user_callbacks->pGetDesktopWindow(); /* trigger creation */
return thread_info->msg_window;
}
/***********************************************************************
* get_full_window_handle
*
* Convert a possibly truncated window handle to a full 32-bit handle.
*/
static HWND get_full_window_handle( HWND hwnd )
{
WND *win;
if (!hwnd || (ULONG_PTR)hwnd >> 16) return hwnd;
if (LOWORD(hwnd) <= 1 || LOWORD(hwnd) == 0xffff) return hwnd;
/* do sign extension for -2 and -3 */
if (LOWORD(hwnd) >= (WORD)-3) return (HWND)(LONG_PTR)(INT16)LOWORD(hwnd);
if (!(win = get_win_ptr( hwnd ))) return hwnd;
if (win == WND_DESKTOP)
{
if (user_callbacks && LOWORD(hwnd) == LOWORD(user_callbacks->pGetDesktopWindow()))
return user_callbacks->pGetDesktopWindow();
else return get_hwnd_message_parent();
}
if (win != WND_OTHER_PROCESS)
{
hwnd = win->obj.handle;
release_win_ptr( win );
}
else /* may belong to another process */
{
SERVER_START_REQ( get_window_info )
{
req->handle = wine_server_user_handle( hwnd );
if (!wine_server_call_err( req )) hwnd = wine_server_ptr_handle( reply->full_handle );
}
SERVER_END_REQ;
}
return hwnd;
}
/*******************************************************************
* register_window_surface
*
@ -307,6 +361,179 @@ static DWORD get_window_thread( HWND hwnd, DWORD *process )
return tid;
}
static 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;
}
}
static LONG_PTR get_window_long_size( HWND hwnd, INT offset, UINT size, BOOL ansi )
{
LONG_PTR retval = 0;
WND *win;
if (offset == GWLP_HWNDPARENT)
{
FIXME( "GWLP_HWNDPARENT not supported\n" );
return 0;
}
if (!(win = get_win_ptr( hwnd )))
{
SetLastError( ERROR_INVALID_WINDOW_HANDLE );
return 0;
}
if (win == WND_DESKTOP)
{
switch (offset)
{
case GWL_STYLE:
retval = WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN; /* message parent is not visible */
if (user_callbacks && get_full_window_handle( hwnd ) == user_callbacks->pGetDesktopWindow())
retval |= WS_VISIBLE;
return retval;
case GWL_EXSTYLE:
case GWLP_USERDATA:
case GWLP_ID:
case GWLP_HINSTANCE:
return 0;
case GWLP_WNDPROC:
SetLastError( ERROR_ACCESS_DENIED );
return 0;
}
SetLastError( ERROR_INVALID_INDEX );
return 0;
}
if (win == WND_OTHER_PROCESS)
{
if (offset == GWLP_WNDPROC)
{
SetLastError( ERROR_ACCESS_DENIED );
return 0;
}
SERVER_START_REQ( set_window_info )
{
req->handle = wine_server_user_handle( hwnd );
req->flags = 0; /* don't set anything, just retrieve */
req->extra_offset = (offset >= 0) ? offset : -1;
req->extra_size = (offset >= 0) ? size : 0;
if (!wine_server_call_err( req ))
{
switch(offset)
{
case GWL_STYLE: retval = reply->old_style; break;
case GWL_EXSTYLE: retval = reply->old_ex_style; break;
case GWLP_ID: retval = reply->old_id; break;
case GWLP_HINSTANCE: retval = (ULONG_PTR)wine_server_get_ptr( reply->old_instance ); break;
case GWLP_USERDATA: retval = reply->old_user_data; break;
default:
if (offset >= 0) retval = get_win_data( &reply->old_extra_value, size );
else SetLastError( ERROR_INVALID_INDEX );
break;
}
}
}
SERVER_END_REQ;
return retval;
}
/* now we have a valid win */
if (offset >= 0)
{
if (offset > (int)(win->cbWndExtra - size))
{
WARN("Invalid offset %d\n", offset );
release_win_ptr( win );
SetLastError( ERROR_INVALID_INDEX );
return 0;
}
retval = get_win_data( (char *)win->wExtra + offset, size );
/* Special case for dialog window procedure */
if ((offset == DWLP_DLGPROC) && (size == sizeof(LONG_PTR)) && win->dlgInfo)
retval = (LONG_PTR)get_winproc( (WNDPROC)retval, ansi );
release_win_ptr( win );
return retval;
}
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_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
* 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 == BUILTIN_WINPROC(WINPROC_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 );
SetLastError( ERROR_INVALID_INDEX );
break;
}
release_win_ptr( win );
return retval;
}
/* see GetWindowLongW */
static DWORD get_window_long( HWND hwnd, INT offset )
{
return get_window_long_size( hwnd, offset, sizeof(LONG), FALSE );
}
/* see GetWindowLongPtr */
static ULONG_PTR get_window_long_ptr( HWND hwnd, INT offset, BOOL ansi )
{
return get_window_long_size( hwnd, offset, sizeof(LONG_PTR), ansi );
}
/* see GetWindowWord */
static WORD get_window_word( HWND hwnd, INT offset )
{
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 get_window_long_size( hwnd, offset, sizeof(WORD), TRUE );
}
/***********************************************************************
* NtUserGetProp (win32u.@)
*
@ -502,8 +729,18 @@ ULONG_PTR WINAPI NtUserCallHwndParam( HWND hwnd, DWORD_PTR param, DWORD code )
return get_class_long_ptr( hwnd, param, FALSE );
case NtUserGetClassWord:
return get_class_word( hwnd, param );
case NtUserGetWindowLongA:
return get_window_long_size( hwnd, param, sizeof(LONG), TRUE );
case NtUserGetWindowLongW:
return get_window_long( hwnd, param );
case NtUserGetWindowLongPtrA:
return get_window_long_ptr( hwnd, param, TRUE );
case NtUserGetWindowLongPtrW:
return get_window_long_ptr( hwnd, param, FALSE );
case NtUserGetWindowThread:
return get_window_thread( hwnd, (DWORD *)param );
case NtUserGetWindowWord:
return get_window_word( hwnd, param );
default:
FIXME( "invalid code %u\n", code );
return 0;

View File

@ -151,7 +151,12 @@ enum
NtUserGetClassLongPtrA,
NtUserGetClassLongPtrW,
NtUserGetClassWord,
NtUserGetWindowLongA,
NtUserGetWindowLongW,
NtUserGetWindowLongPtrA,
NtUserGetWindowLongPtrW,
NtUserGetWindowThread,
NtUserGetWindowWord,
};
/* color index used to retrieve system 55aa brush */