From 2c2299685fc5e8300ae307e4e15a0b297a42bd4d Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Wed, 2 Aug 2006 21:59:00 +0200 Subject: [PATCH] user: Implementation of Get/SetWindowLongPtr for 64-bit platforms. Also use the same code for Get/SetWindowWord. Based on a patch by Ge van Geldorp. --- dlls/user/message.c | 2 +- dlls/user/win.c | 286 ++++++++++++++------------------- include/win.h | 1 + include/wine/server_protocol.h | 6 +- server/protocol.def | 4 +- server/trace.c | 4 +- 6 files changed, 132 insertions(+), 171 deletions(-) diff --git a/dlls/user/message.c b/dlls/user/message.c index c7a9a6c46dc..44f296e1554 100644 --- a/dlls/user/message.c +++ b/dlls/user/message.c @@ -1183,7 +1183,7 @@ static LRESULT handle_internal_message( HWND hwnd, UINT msg, WPARAM wparam, LPAR if (hwnd == GetDesktopWindow()) return 0; return (LRESULT)SetParent( hwnd, (HWND)wparam ); case WM_WINE_SETWINDOWLONG: - return (LRESULT)SetWindowLongW( hwnd, wparam, lparam ); + return WIN_SetWindowLong( hwnd, (short)LOWORD(wparam), HIWORD(wparam), lparam, TRUE ); case WM_WINE_ENABLEWINDOW: if (hwnd == GetDesktopWindow()) return 0; return EnableWindow( hwnd, wparam ); diff --git a/dlls/user/win.c b/dlls/user/win.c index 16690b0ac7b..68d6bb0d8d5 100644 --- a/dlls/user/win.c +++ b/dlls/user/win.c @@ -46,6 +46,48 @@ WINE_DEFAULT_DEBUG_CHANNEL(win); /**********************************************************************/ +/* 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) ); + } +} + static void *user_handles[NB_USER_HANDLES]; @@ -1691,139 +1733,12 @@ BOOL WINAPI IsWindowUnicode( HWND hwnd ) } -/********************************************************************** - * GetWindowWord (USER32.@) - */ -WORD WINAPI GetWindowWord( HWND hwnd, INT offset ) -{ - if (offset >= 0) - { - WORD retvalue = 0; - WND *wndPtr = WIN_GetPtr( hwnd ); - if (!wndPtr) - { - SetLastError( ERROR_INVALID_WINDOW_HANDLE ); - return 0; - } - if (wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) - { - SERVER_START_REQ( set_window_info ) - { - req->handle = hwnd; - req->flags = 0; /* don't set anything, just retrieve */ - req->extra_offset = offset; - req->extra_size = sizeof(retvalue); - if (!wine_server_call_err( req )) - memcpy( &retvalue, &reply->old_extra_value, sizeof(retvalue) ); - } - SERVER_END_REQ; - return retvalue; - } - if (offset > (int)(wndPtr->cbWndExtra - sizeof(WORD))) - { - WARN("Invalid offset %d\n", offset ); - SetLastError( ERROR_INVALID_INDEX ); - } - else memcpy( &retvalue, (char *)wndPtr->wExtra + offset, sizeof(retvalue) ); - WIN_ReleasePtr( wndPtr ); - return retvalue; - } - - switch(offset) - { - case GWLP_HWNDPARENT: - return GetWindowLongPtrW( hwnd, offset ); - case GWLP_ID: - case GWLP_HINSTANCE: - { - LONG_PTR ret = GetWindowLongPtrW( hwnd, offset ); - if (HIWORD(ret)) - WARN("%d: discards high bits of 0x%08lx!\n", offset, ret ); - return LOWORD(ret); - } - default: - WARN("Invalid offset %d\n", offset ); - return 0; - } -} - - -/********************************************************************** - * SetWindowWord (USER32.@) - */ -WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval ) -{ - WORD retval = 0; - WND * wndPtr; - - switch(offset) - { - case GWLP_ID: - case GWLP_HINSTANCE: - case GWLP_HWNDPARENT: - return SetWindowLongPtrW( hwnd, offset, (ULONG_PTR)newval ); - default: - if (offset < 0) - { - WARN("Invalid offset %d\n", offset ); - SetLastError( ERROR_INVALID_INDEX ); - return 0; - } - } - - wndPtr = WIN_GetPtr( hwnd ); - if (wndPtr == WND_DESKTOP) - { - SetLastError( ERROR_ACCESS_DENIED ); - return 0; - } - if (wndPtr == WND_OTHER_PROCESS) - { - if (IsWindow(hwnd)) - FIXME( "set %d <- %x not supported yet on other process window %p\n", - offset, newval, hwnd ); - wndPtr = NULL; - } - if (!wndPtr) - { - SetLastError( ERROR_INVALID_WINDOW_HANDLE ); - return 0; - } - - if (offset > (int)(wndPtr->cbWndExtra - sizeof(WORD))) - { - WARN("Invalid offset %d\n", offset ); - WIN_ReleasePtr(wndPtr); - SetLastError( ERROR_INVALID_INDEX ); - return 0; - } - - SERVER_START_REQ( set_window_info ) - { - req->handle = hwnd; - req->flags = SET_WIN_EXTRA; - req->extra_offset = offset; - req->extra_size = sizeof(newval); - memcpy( &req->extra_value, &newval, sizeof(newval) ); - if (!wine_server_call_err( req )) - { - void *ptr = (char *)wndPtr->wExtra + offset; - memcpy( &retval, ptr, sizeof(retval) ); - memcpy( ptr, &newval, sizeof(newval) ); - } - } - SERVER_END_REQ; - WIN_ReleasePtr( wndPtr ); - return retval; -} - - /********************************************************************** * WIN_GetWindowLong * * Helper function for GetWindowLong(). */ -static LONG_PTR WIN_GetWindowLong( HWND hwnd, INT offset, BOOL unicode ) +static LONG_PTR WIN_GetWindowLong( HWND hwnd, INT offset, UINT size, BOOL unicode ) { LONG_PTR retvalue = 0; WND *wndPtr; @@ -1853,7 +1768,7 @@ static LONG_PTR WIN_GetWindowLong( HWND hwnd, INT offset, BOOL unicode ) req->handle = hwnd; req->flags = 0; /* don't set anything, just retrieve */ req->extra_offset = (offset >= 0) ? offset : -1; - req->extra_size = (offset >= 0) ? sizeof(retvalue) : 0; + req->extra_size = (offset >= 0) ? size : 0; if (!wine_server_call_err( req )) { switch(offset) @@ -1864,7 +1779,7 @@ static LONG_PTR WIN_GetWindowLong( HWND hwnd, INT offset, BOOL unicode ) case GWLP_HINSTANCE: retvalue = (ULONG_PTR)reply->old_instance; break; case GWLP_USERDATA: retvalue = (ULONG_PTR)reply->old_user_data; break; default: - if (offset >= 0) retvalue = reply->old_extra_value; + if (offset >= 0) retvalue = get_win_data( &reply->old_extra_value, size ); else SetLastError( ERROR_INVALID_INDEX ); break; } @@ -1878,16 +1793,17 @@ static LONG_PTR WIN_GetWindowLong( HWND hwnd, INT offset, BOOL unicode ) if (offset >= 0) { - if (offset > (int)(wndPtr->cbWndExtra - sizeof(LONG))) + if (offset > (int)(wndPtr->cbWndExtra - size)) { WARN("Invalid offset %d\n", offset ); WIN_ReleasePtr( wndPtr ); SetLastError( ERROR_INVALID_INDEX ); return 0; } - retvalue = *(LONG_PTR *)(((char *)wndPtr->wExtra) + offset); + retvalue = get_win_data( (char *)wndPtr->wExtra + offset, size ); + /* Special case for dialog window procedure */ - if ((offset == DWLP_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG)) + if ((offset == DWLP_DLGPROC) && (size == sizeof(LONG_PTR)) && (wndPtr->flags & WIN_ISDIALOG)) retvalue = (LONG_PTR)WINPROC_GetProc( (WNDPROC)retvalue, unicode ); WIN_ReleasePtr( wndPtr ); return retvalue; @@ -1919,7 +1835,7 @@ static LONG_PTR WIN_GetWindowLong( HWND hwnd, INT offset, BOOL unicode ) * 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. */ -static LONG_PTR WIN_SetWindowLong( HWND hwnd, INT offset, LONG_PTR newval, BOOL unicode ) +LONG_PTR WIN_SetWindowLong( HWND hwnd, INT offset, UINT size, LONG_PTR newval, BOOL unicode ) { STYLESTRUCT style; BOOL ok; @@ -1952,7 +1868,12 @@ static LONG_PTR WIN_SetWindowLong( HWND hwnd, INT offset, LONG_PTR newval, BOOL SetLastError( ERROR_ACCESS_DENIED ); return 0; } - return SendMessageW( hwnd, WM_WINE_SETWINDOWLONG, offset, newval ); + 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 */ @@ -2002,7 +1923,8 @@ static LONG_PTR WIN_SetWindowLong( HWND hwnd, INT offset, LONG_PTR newval, BOOL case GWLP_USERDATA: break; case DWLP_DLGPROC: - if ((wndPtr->cbWndExtra - sizeof(LONG_PTR) >= DWLP_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG)) + if ((wndPtr->cbWndExtra - sizeof(LONG_PTR) >= DWLP_DLGPROC) && + (size == sizeof(LONG_PTR)) && (wndPtr->flags & WIN_ISDIALOG)) { WNDPROC *ptr = (WNDPROC *)((char *)wndPtr->wExtra + DWLP_DLGPROC); retval = (ULONG_PTR)WINPROC_GetProc( *ptr, unicode ); @@ -2013,21 +1935,18 @@ static LONG_PTR WIN_SetWindowLong( HWND hwnd, INT offset, LONG_PTR newval, BOOL } /* fall through */ default: - if (offset < 0 || offset > (int)(wndPtr->cbWndExtra - sizeof(LONG_PTR))) + if (offset < 0 || offset > (int)(wndPtr->cbWndExtra - size)) { WARN("Invalid offset %d\n", offset ); WIN_ReleasePtr( wndPtr ); SetLastError( ERROR_INVALID_INDEX ); return 0; } - else + else if (get_win_data( (char *)wndPtr->wExtra + offset, size ) == newval) { - LONG_PTR *ptr = (LONG_PTR *)((char *)wndPtr->wExtra + offset); - if (*ptr == newval) /* already set to the same value */ - { - WIN_ReleasePtr( wndPtr ); - return newval; - } + /* already set to the same value */ + WIN_ReleasePtr( wndPtr ); + return newval; } break; } @@ -2065,8 +1984,8 @@ static LONG_PTR WIN_SetWindowLong( HWND hwnd, INT offset, LONG_PTR newval, BOOL default: req->flags = SET_WIN_EXTRA; req->extra_offset = offset; - req->extra_size = sizeof(newval); - memcpy( &req->extra_value, &newval, sizeof(newval) ); + req->extra_size = size; + set_win_data( &req->extra_value, newval, size ); } if ((ok = !wine_server_call_err( req ))) { @@ -2095,11 +2014,8 @@ static LONG_PTR WIN_SetWindowLong( HWND hwnd, INT offset, LONG_PTR newval, BOOL retval = (ULONG_PTR)reply->old_user_data; break; default: - { - void *ptr = (char *)wndPtr->wExtra + offset; - memcpy( &retval, ptr, sizeof(retval) ); - memcpy( ptr, &newval, sizeof(newval) ); - } + retval = get_win_data( (char *)wndPtr->wExtra + offset, size ); + set_win_data( (char *)wndPtr->wExtra + offset, newval, size ); break; } } @@ -2167,12 +2083,36 @@ LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset ) } +/********************************************************************** + * 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 ); +} + + /********************************************************************** * GetWindowLongA (USER32.@) */ LONG WINAPI GetWindowLongA( HWND hwnd, INT offset ) { - return WIN_GetWindowLong( hwnd, offset, FALSE ); + return WIN_GetWindowLong( hwnd, offset, sizeof(LONG), FALSE ); } @@ -2181,7 +2121,7 @@ LONG WINAPI GetWindowLongA( HWND hwnd, INT offset ) */ LONG WINAPI GetWindowLongW( HWND hwnd, INT offset ) { - return WIN_GetWindowLong( hwnd, offset, TRUE ); + return WIN_GetWindowLong( hwnd, offset, sizeof(LONG), TRUE ); } @@ -2218,6 +2158,30 @@ LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval ) } +/********************************************************************** + * 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.@) * @@ -2225,7 +2189,7 @@ LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval ) */ LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval ) { - return WIN_SetWindowLong( hwnd, offset, newval, FALSE ); + return WIN_SetWindowLong( hwnd, offset, sizeof(LONG), newval, FALSE ); } @@ -2300,7 +2264,7 @@ LONG WINAPI SetWindowLongW( INT offset, /* [in] offset, in bytes, of location to alter */ LONG newval /* [in] new value of location */ ) { - return WIN_SetWindowLong( hwnd, offset, newval, TRUE ); + return WIN_SetWindowLong( hwnd, offset, sizeof(LONG), newval, TRUE ); } @@ -3198,8 +3162,7 @@ BOOL WINAPI UpdateLayeredWindow( HWND hwnd, HDC hdcDst, POINT *pptDst, SIZE *psi */ LONG_PTR WINAPI GetWindowLongPtrW( HWND hwnd, INT offset ) { - FIXME("\n"); - return 0; + return WIN_GetWindowLong( hwnd, offset, sizeof(LONG_PTR), TRUE ); } /***************************************************************************** @@ -3207,8 +3170,7 @@ LONG_PTR WINAPI GetWindowLongPtrW( HWND hwnd, INT offset ) */ LONG_PTR WINAPI GetWindowLongPtrA( HWND hwnd, INT offset ) { - FIXME("\n"); - return 0; + return WIN_GetWindowLong( hwnd, offset, sizeof(LONG_PTR), FALSE ); } /***************************************************************************** @@ -3216,8 +3178,7 @@ LONG_PTR WINAPI GetWindowLongPtrA( HWND hwnd, INT offset ) */ LONG_PTR WINAPI SetWindowLongPtrW( HWND hwnd, INT offset, LONG_PTR newval ) { - FIXME("\n"); - return 0; + return WIN_SetWindowLong( hwnd, offset, sizeof(LONG_PTR), newval, TRUE ); } /***************************************************************************** @@ -3225,6 +3186,5 @@ LONG_PTR WINAPI SetWindowLongPtrW( HWND hwnd, INT offset, LONG_PTR newval ) */ LONG_PTR WINAPI SetWindowLongPtrA( HWND hwnd, INT offset, LONG_PTR newval ) { - FIXME("\n"); - return 0; + return WIN_SetWindowLong( hwnd, offset, sizeof(LONG_PTR), newval, FALSE ); } diff --git a/include/win.h b/include/win.h index bc7a4cb717c..d6268cf8b6f 100644 --- a/include/win.h +++ b/include/win.h @@ -83,6 +83,7 @@ extern LRESULT WIN_DestroyWindow( HWND hwnd ); extern void WIN_DestroyThreadWindows( HWND hwnd ); extern BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL ); extern HWND *WIN_ListChildren( HWND hwnd ); +extern LONG_PTR WIN_SetWindowLong( HWND hwnd, INT offset, UINT size, LONG_PTR newval, BOOL unicode ); extern void MDI_CalcDefaultChildPos( HWND hwndClient, INT total, LPPOINT lpPos, INT delta, UINT *id ); /* user lock */ diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h index 15b18cdc6e6..a7c9b9894b4 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h @@ -2608,7 +2608,7 @@ struct set_window_info_request void* user_data; int extra_offset; data_size_t extra_size; - unsigned int extra_value; + unsigned long extra_value; }; struct set_window_info_reply { @@ -2618,7 +2618,7 @@ struct set_window_info_reply unsigned int old_id; void* old_instance; void* old_user_data; - unsigned int old_extra_value; + unsigned long old_extra_value; }; #define SET_WIN_STYLE 0x01 #define SET_WIN_EXSTYLE 0x02 @@ -4385,6 +4385,6 @@ union generic_reply struct query_symlink_reply query_symlink_reply; }; -#define SERVER_PROTOCOL_VERSION 243 +#define SERVER_PROTOCOL_VERSION 244 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */ diff --git a/server/protocol.def b/server/protocol.def index e64cf437f01..25e93e976bd 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -1854,14 +1854,14 @@ enum message_type void* user_data; /* user-specific data */ int extra_offset; /* offset to set in extra bytes */ data_size_t extra_size; /* size to set in extra bytes */ - unsigned int extra_value; /* value to set in extra bytes */ + unsigned long extra_value; /* value to set in extra bytes */ @REPLY unsigned int old_style; /* old window style */ unsigned int old_ex_style; /* old window extended style */ unsigned int old_id; /* old window id */ void* old_instance; /* old creator instance */ void* old_user_data; /* old user-specific data */ - unsigned int old_extra_value; /* old value in extra bytes */ + unsigned long old_extra_value; /* old value in extra bytes */ @END #define SET_WIN_STYLE 0x01 #define SET_WIN_EXSTYLE 0x02 diff --git a/server/trace.c b/server/trace.c index 574943a9b89..c5248fea3e1 100644 --- a/server/trace.c +++ b/server/trace.c @@ -2372,7 +2372,7 @@ static void dump_set_window_info_request( const struct set_window_info_request * fprintf( stderr, " user_data=%p,", req->user_data ); fprintf( stderr, " extra_offset=%d,", req->extra_offset ); fprintf( stderr, " extra_size=%u,", req->extra_size ); - fprintf( stderr, " extra_value=%08x", req->extra_value ); + fprintf( stderr, " extra_value=%lx", req->extra_value ); } static void dump_set_window_info_reply( const struct set_window_info_reply *req ) @@ -2382,7 +2382,7 @@ static void dump_set_window_info_reply( const struct set_window_info_reply *req fprintf( stderr, " old_id=%08x,", req->old_id ); fprintf( stderr, " old_instance=%p,", req->old_instance ); fprintf( stderr, " old_user_data=%p,", req->old_user_data ); - fprintf( stderr, " old_extra_value=%08x", req->old_extra_value ); + fprintf( stderr, " old_extra_value=%lx", req->old_extra_value ); } static void dump_set_parent_request( const struct set_parent_request *req )