Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-cw
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-cw
Commits
585329ed
Commit
585329ed
authored
Oct 17, 2007
by
Mikolaj Zalewski
Committed by
Alexandre Julliard
Oct 30, 2007
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
user32: Better fix how to handle GetWindowLongPtr[AW](..., GWLP_WNDPROC) for builtin winprocs.
parent
55d274d1
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
83 additions
and
47 deletions
+83
-47
class.c
dlls/user32/class.c
+3
-3
controls.h
dlls/user32/controls.h
+2
-0
class.c
dlls/user32/tests/class.c
+61
-5
win.c
dlls/user32/win.c
+11
-2
winproc.c
dlls/user32/winproc.c
+6
-37
No files found.
dlls/user32/class.c
View file @
585329ed
...
...
@@ -366,7 +366,7 @@ static CLASS *CLASS_RegisterClass( ATOM atom, HINSTANCE hInstance, BOOL local,
* Register a builtin control class.
* This allows having both ASCII and Unicode winprocs for the same class.
*/
static
CLASS
*
register_builtin
(
const
struct
builtin_class_descr
*
descr
)
static
WNDPROC
register_builtin
(
const
struct
builtin_class_descr
*
descr
)
{
ATOM
atom
;
CLASS
*
classPtr
;
...
...
@@ -380,7 +380,7 @@ static CLASS *register_builtin( const struct builtin_class_descr *descr )
classPtr
->
hbrBackground
=
descr
->
brush
;
classPtr
->
winproc
=
WINPROC_AllocProc
(
descr
->
procA
,
descr
->
procW
);
release_class_ptr
(
classPtr
);
return
classPtr
;
return
classPtr
->
winproc
;
}
...
...
@@ -407,7 +407,7 @@ void CLASS_RegisterBuiltinClasses(void)
register_builtin
(
&
COMBO_builtin_class
);
register_builtin
(
&
COMBOLBOX_builtin_class
);
register_builtin
(
&
DIALOG_builtin_class
);
register_builtin
(
&
EDIT_builtin_class
);
EDIT_winproc_handle
=
register_builtin
(
&
EDIT_builtin_class
);
register_builtin
(
&
ICONTITLE_builtin_class
);
register_builtin
(
&
LISTBOX_builtin_class
);
register_builtin
(
&
MDICLIENT_builtin_class
);
...
...
dlls/user32/controls.h
View file @
585329ed
...
...
@@ -43,6 +43,8 @@ struct builtin_class_descr
HBRUSH
brush
;
/* brush or system color */
};
extern
WNDPROC
EDIT_winproc_handle
;
/* Class functions */
struct
tagCLASS
;
/* opaque structure */
struct
tagWND
;
...
...
dlls/user32/tests/class.c
View file @
585329ed
...
...
@@ -39,6 +39,8 @@ static const WCHAR WC_EDITW[] = {'E','d','i','t',0};
#define NUMCLASSWORDS 4
#define IS_WNDPROC_HANDLE(x) (((ULONG_PTR)(x) >> 16) == (~((ULONG_PTR)0) >> 16))
static
LRESULT
WINAPI
ClassTest_WndProc
(
HWND
hWnd
,
UINT
msg
,
WPARAM
wParam
,
LPARAM
lParam
)
{
return
DefWindowProcW
(
hWnd
,
msg
,
wParam
,
lParam
);
...
...
@@ -565,12 +567,23 @@ static void test_instances(void)
check_thread_instance
(
"EDIT"
,
(
HINSTANCE
)
0x12345678
,
(
HINSTANCE
)
0x12345678
,
(
HINSTANCE
)
0xdeadbeef
);
}
static
void
test_
defwnd
proc
(
void
)
static
void
test_
builtin
proc
(
void
)
{
/* Edit behaves differently. ScrollBar have currently only a Unicode winproc */
static
const
CHAR
NORMAL_CLASSES
[][
10
]
=
{
"Button"
,
"Static"
,
"ComboBox"
,
"ComboLBox"
,
"ListBox"
,
"#32770"
,
/* dialog */
};
static
const
int
NUM_NORMAL_CLASSES
=
(
sizeof
(
NORMAL_CLASSES
)
/
sizeof
(
NORMAL_CLASSES
[
0
]));
static
const
char
classA
[]
=
"deftest"
;
static
const
WCHAR
classW
[]
=
{
'd'
,
'e'
,
'f'
,
't'
,
'e'
,
's'
,
't'
,
0
};
WCHAR
unistring
[]
=
{
0x142
,
0x40e
,
0x3b4
,
0
};
/* a string that would be destoryed by a W->A->W conversion */
WNDPROC
pDefWindowProcA
,
pDefWindowProcW
;
WNDPROC
oldproc
;
WNDCLASSEXA
cls
;
/* the memory layout of WNDCLASSEXA and WNDCLASSEXW is the same */
WCHAR
buf
[
128
];
ATOM
atom
;
...
...
@@ -662,10 +675,43 @@ static void test_defwndproc(void)
DestroyWindow
(
hwnd
);
UnregisterClass
((
LPSTR
)(
DWORD_PTR
)
atom
,
GetModuleHandle
(
NULL
));
/* calling built-in and custom winprocs with CallWindowProc[AW]. Despite
* a slightly different nature the end result is the same */
/* For most of the builtin controls both GetWindowLongPtrA and W returns a pointer that is executed directly
* by CallWindowProcA/W */
for
(
i
=
0
;
i
<
NUM_NORMAL_CLASSES
;
i
++
)
{
WNDPROC
procA
,
procW
;
hwnd
=
CreateWindowExA
(
0
,
NORMAL_CLASSES
[
i
],
classA
,
WS_OVERLAPPEDWINDOW
,
CW_USEDEFAULT
,
CW_USEDEFAULT
,
680
,
260
,
NULL
,
NULL
,
NULL
,
0
);
ok
(
hwnd
!=
NULL
,
"Couldn't create window of class %s
\n
"
,
NORMAL_CLASSES
[
i
]);
SetWindowText
(
hwnd
,
classA
);
/* ComboBox needs this */
procA
=
(
WNDPROC
)
GetWindowLongPtrA
(
hwnd
,
GWLP_WNDPROC
);
procW
=
(
WNDPROC
)
GetWindowLongPtrW
(
hwnd
,
GWLP_WNDPROC
);
ok
(
!
IS_WNDPROC_HANDLE
(
procA
),
"procA should not be a handle for %s (%p)
\n
"
,
NORMAL_CLASSES
[
i
],
procA
);
ok
(
!
IS_WNDPROC_HANDLE
(
procW
),
"procW should not be a handle for %s (%p)
\n
"
,
NORMAL_CLASSES
[
i
],
procW
);
CallWindowProcA
(
procA
,
hwnd
,
WM_GETTEXT
,
120
,
(
LPARAM
)
buf
);
ok
(
memcmp
(
buf
,
classA
,
sizeof
(
classA
))
==
0
,
"WM_GETTEXT A/A invalid return for class %s
\n
"
,
NORMAL_CLASSES
[
i
]);
CallWindowProcA
(
procW
,
hwnd
,
WM_GETTEXT
,
120
,
(
LPARAM
)
buf
);
ok
(
memcmp
(
buf
,
classW
,
sizeof
(
classW
))
==
0
,
"WM_GETTEXT A/W invalid return for class %s
\n
"
,
NORMAL_CLASSES
[
i
]);
CallWindowProcW
(
procA
,
hwnd
,
WM_GETTEXT
,
120
,
(
LPARAM
)
buf
);
ok
(
memcmp
(
buf
,
classA
,
sizeof
(
classA
))
==
0
,
"WM_GETTEXT W/A invalid return for class %s
\n
"
,
NORMAL_CLASSES
[
i
]);
CallWindowProcW
(
procW
,
hwnd
,
WM_GETTEXT
,
120
,
(
LPARAM
)
buf
);
ok
(
memcmp
(
buf
,
classW
,
sizeof
(
classW
))
==
0
,
"WM_GETTEXT W/W invalid return for class %s
\n
"
,
NORMAL_CLASSES
[
i
]);
oldproc
=
(
WNDPROC
)
SetWindowLongPtrW
(
hwnd
,
GWLP_WNDPROC
,
(
LONG_PTR
)
ClassTest_WndProc
);
ok
(
IS_WNDPROC_HANDLE
(
oldproc
)
==
FALSE
,
"Class %s shouldn't return a handle
\n
"
,
NORMAL_CLASSES
[
i
]);
DestroyWindow
(
hwnd
);
}
/* Edit controls are special - they return a wndproc handle when GetWindowLongPtr is called with a different A/W.
* On the other hand there is no W->A->W conversion so this control is treated specially. */
hwnd
=
CreateWindowW
(
WC_EDITW
,
unistring
,
WS_OVERLAPPEDWINDOW
,
CW_USEDEFAULT
,
CW_USEDEFAULT
,
680
,
260
,
NULL
,
NULL
,
NULL
,
0
);
/* GetClassLongPtr returns that both the Unicode and ANSI wndproc */
ok
(
IS_WNDPROC_HANDLE
(
GetClassLongPtrA
(
hwnd
,
GCLP_WNDPROC
))
==
FALSE
,
"Edit control class should have a Unicode wndproc
\n
"
);
ok
(
IS_WNDPROC_HANDLE
(
GetClassLongPtrW
(
hwnd
,
GCLP_WNDPROC
))
==
FALSE
,
"Edit control class should have a ANSI wndproc
\n
"
);
/* But GetWindowLongPtr returns only a handle for the ANSI one */
ok
(
IS_WNDPROC_HANDLE
(
GetWindowLongPtrA
(
hwnd
,
GWLP_WNDPROC
)),
"Edit control should return a wndproc handle
\n
"
);
ok
(
!
IS_WNDPROC_HANDLE
(
GetWindowLongPtrW
(
hwnd
,
GWLP_WNDPROC
)),
"Edit control shouldn't return a W wndproc handle
\n
"
);
CallWindowProcW
((
WNDPROC
)
GetWindowLongPtrW
(
hwnd
,
GWLP_WNDPROC
),
hwnd
,
WM_GETTEXT
,
120
,
(
LPARAM
)
buf
);
ok
(
memcmp
(
buf
,
unistring
,
sizeof
(
unistring
))
==
0
,
"WM_GETTEXT invalid return
\n
"
);
CallWindowProcA
((
WNDPROC
)
GetWindowLongPtrW
(
hwnd
,
GWLP_WNDPROC
),
hwnd
,
WM_GETTEXT
,
120
,
(
LPARAM
)
buf
);
...
...
@@ -677,7 +723,9 @@ static void test_defwndproc(void)
CallWindowProcA
((
WNDPROC
)
GetWindowLongPtrA
(
hwnd
,
GWLP_WNDPROC
),
hwnd
,
WM_GETTEXT
,
120
,
(
LPARAM
)
buf
);
ok
(
memcmp
(
buf
,
classA
,
sizeof
(
classA
))
==
0
,
"WM_GETTEXT invalid return
\n
"
);
SetWindowLongPtrA
(
hwnd
,
GWLP_WNDPROC
,
(
LONG_PTR
)
ClassTest_WndProc2
);
oldproc
=
(
WNDPROC
)
SetWindowLongPtrA
(
hwnd
,
GWLP_WNDPROC
,
(
LONG_PTR
)
ClassTest_WndProc2
);
/* SetWindowLongPtr returns a wndproc handle - like GetWindowLongPtr */
ok
(
IS_WNDPROC_HANDLE
(
oldproc
),
"Edit control should return a wndproc handle
\n
"
);
ok
(
IsWindowUnicode
(
hwnd
)
==
FALSE
,
"SetWindowLongPtrA should have changed window to ANSI
\n
"
);
SetWindowTextA
(
hwnd
,
classA
);
/* Windows resets the title to WideStringToMultiByte(unistring) */
memset
(
buf
,
0
,
sizeof
(
buf
));
...
...
@@ -696,6 +744,12 @@ static void test_defwndproc(void)
hwnd
=
CreateWindowA
(
WC_EDITA
,
classA
,
WS_OVERLAPPEDWINDOW
,
CW_USEDEFAULT
,
CW_USEDEFAULT
,
680
,
260
,
NULL
,
NULL
,
NULL
,
0
);
/* GetClassLongPtr returns that both the Unicode and ANSI wndproc */
ok
(
!
IS_WNDPROC_HANDLE
(
GetClassLongPtrA
(
hwnd
,
GCLP_WNDPROC
)),
"Edit control class should have a Unicode wndproc
\n
"
);
ok
(
!
IS_WNDPROC_HANDLE
(
GetClassLongPtrW
(
hwnd
,
GCLP_WNDPROC
)),
"Edit control class should have a ANSI wndproc
\n
"
);
/* But GetWindowLongPtr returns only a handle for the Unicode one */
ok
(
!
IS_WNDPROC_HANDLE
(
GetWindowLongPtrA
(
hwnd
,
GWLP_WNDPROC
)),
"Edit control shouldn't return an A wndproc handle
\n
"
);
ok
(
IS_WNDPROC_HANDLE
(
GetWindowLongPtrW
(
hwnd
,
GWLP_WNDPROC
)),
"Edit control should return a wndproc handle
\n
"
);
CallWindowProcA
((
WNDPROC
)
GetWindowLongPtrA
(
hwnd
,
GWLP_WNDPROC
),
hwnd
,
WM_GETTEXT
,
120
,
(
LPARAM
)
buf
);
ok
(
memcmp
(
buf
,
classA
,
sizeof
(
classA
))
==
0
,
"WM_GETTEXT invalid return
\n
"
);
CallWindowProcA
((
WNDPROC
)
GetWindowLongPtrW
(
hwnd
,
GWLP_WNDPROC
),
hwnd
,
WM_GETTEXT
,
120
,
(
LPARAM
)
buf
);
...
...
@@ -785,6 +839,8 @@ START_TEST(class)
ClassTest
(
hInstance
,
TRUE
);
CreateDialogParamTest
(
hInstance
);
test_styles
();
test_builtinproc
();
/* this test unregisters the Button class so it should be executed at the end */
test_instances
();
test_defwndproc
();
}
dlls/user32/win.c
View file @
585329ed
...
...
@@ -1788,8 +1788,17 @@ static LONG_PTR WIN_GetWindowLong( HWND hwnd, INT offset, UINT size, BOOL unicod
case
GWL_STYLE
:
retvalue
=
wndPtr
->
dwStyle
;
break
;
case
GWL_EXSTYLE
:
retvalue
=
wndPtr
->
dwExStyle
;
break
;
case
GWLP_ID
:
retvalue
=
(
ULONG_PTR
)
wndPtr
->
wIDmenu
;
break
;
case
GWLP_WNDPROC
:
retvalue
=
(
ULONG_PTR
)
WINPROC_GetProc
(
wndPtr
->
winproc
,
unicode
);
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
==
EDIT_winproc_handle
&&
(
!
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
);
...
...
@@ -1877,7 +1886,7 @@ LONG_PTR WIN_SetWindowLong( HWND hwnd, INT offset, UINT size, LONG_PTR newval, B
{
WNDPROC
proc
;
UINT
old_flags
=
wndPtr
->
flags
;
retval
=
(
ULONG_PTR
)
WINPROC_GetProc
(
wndPtr
->
winproc
,
unicode
);
retval
=
WIN_GetWindowLong
(
hwnd
,
offset
,
size
,
unicode
);
if
(
unicode
)
proc
=
WINPROC_AllocProc
(
NULL
,
(
WNDPROC
)
newval
);
else
proc
=
WINPROC_AllocProc
(
(
WNDPROC
)
newval
,
NULL
);
if
(
proc
)
wndPtr
->
winproc
=
proc
;
...
...
dlls/user32/winproc.c
View file @
585329ed
...
...
@@ -54,6 +54,8 @@ typedef struct tagWINDOWPROC
#define MAX_WINPROCS 8192
#define BUILTIN_WINPROCS 8
/* first BUILTIN_WINPROCS entries are reserved for builtin procs */
WNDPROC
EDIT_winproc_handle
=
0
;
static
WINDOWPROC
winproc_array
[
MAX_WINPROCS
];
static
UINT
builtin_used
;
static
UINT
winproc_used
=
BUILTIN_WINPROCS
;
...
...
@@ -113,19 +115,6 @@ static inline WINDOWPROC *find_winproc( WNDPROC funcA, WNDPROC funcW )
return
NULL
;
}
/* find an existing builtin winproc */
static
inline
WINDOWPROC
*
find_builtin_proc
(
WNDPROC
func
)
{
unsigned
int
i
;
for
(
i
=
0
;
i
<
builtin_used
;
i
++
)
{
if
(
winproc_array
[
i
].
procA
==
func
||
winproc_array
[
i
].
procW
==
func
)
return
&
winproc_array
[
i
];
}
return
NULL
;
}
/* return the window proc for a given handle, or NULL for an invalid handle */
static
inline
WINDOWPROC
*
handle_to_proc
(
WNDPROC
handle
)
{
...
...
@@ -2288,12 +2277,7 @@ LRESULT WINAPI CallWindowProcA(
if
(
!
func
)
return
0
;
if
(
!
(
proc
=
handle_to_proc
(
func
)))
{
if
((
proc
=
find_builtin_proc
(
func
))
&&
!
IsWindowUnicode
(
hwnd
))
call_window_proc
(
hwnd
,
msg
,
wParam
,
lParam
,
&
result
,
proc
->
procA
);
else
call_window_proc
(
hwnd
,
msg
,
wParam
,
lParam
,
&
result
,
func
);
}
call_window_proc
(
hwnd
,
msg
,
wParam
,
lParam
,
&
result
,
func
);
else
if
(
proc
->
procA
)
call_window_proc
(
hwnd
,
msg
,
wParam
,
lParam
,
&
result
,
proc
->
procA
);
else
if
(
proc
->
procW
)
...
...
@@ -2319,12 +2303,7 @@ LRESULT WINAPI CallWindowProcW( WNDPROC func, HWND hwnd, UINT msg,
if
(
!
func
)
return
0
;
if
(
!
(
proc
=
handle_to_proc
(
func
)))
{
if
((
proc
=
find_builtin_proc
(
func
))
&&
IsWindowUnicode
(
hwnd
))
call_window_proc
(
hwnd
,
msg
,
wParam
,
lParam
,
&
result
,
proc
->
procW
);
else
call_window_proc
(
hwnd
,
msg
,
wParam
,
lParam
,
&
result
,
func
);
}
call_window_proc
(
hwnd
,
msg
,
wParam
,
lParam
,
&
result
,
func
);
else
if
(
proc
->
procW
)
call_window_proc
(
hwnd
,
msg
,
wParam
,
lParam
,
&
result
,
proc
->
procW
);
else
if
(
proc
->
procA
)
...
...
@@ -2382,12 +2361,7 @@ INT_PTR WINPROC_CallDlgProcA( DLGPROC func, HWND hwnd, UINT msg, WPARAM wParam,
if
(
!
func
)
return
0
;
if
(
!
(
proc
=
handle_to_proc
(
func
)))
{
if
((
proc
=
find_builtin_proc
(
func
))
&&
!
IsWindowUnicode
(
hwnd
))
ret
=
call_dialog_proc
(
hwnd
,
msg
,
wParam
,
lParam
,
&
result
,
proc
->
procA
);
else
ret
=
call_dialog_proc
(
hwnd
,
msg
,
wParam
,
lParam
,
&
result
,
func
);
}
ret
=
call_dialog_proc
(
hwnd
,
msg
,
wParam
,
lParam
,
&
result
,
func
);
else
if
(
proc
->
procA
)
ret
=
call_dialog_proc
(
hwnd
,
msg
,
wParam
,
lParam
,
&
result
,
proc
->
procA
);
else
if
(
proc
->
procW
)
...
...
@@ -2417,12 +2391,7 @@ INT_PTR WINPROC_CallDlgProcW( DLGPROC func, HWND hwnd, UINT msg, WPARAM wParam,
if
(
!
func
)
return
0
;
if
(
!
(
proc
=
handle_to_proc
(
func
)))
{
if
((
proc
=
find_builtin_proc
(
func
))
&&
IsWindowUnicode
(
hwnd
))
ret
=
call_dialog_proc
(
hwnd
,
msg
,
wParam
,
lParam
,
&
result
,
proc
->
procW
);
else
ret
=
call_dialog_proc
(
hwnd
,
msg
,
wParam
,
lParam
,
&
result
,
func
);
}
ret
=
call_dialog_proc
(
hwnd
,
msg
,
wParam
,
lParam
,
&
result
,
func
);
else
if
(
proc
->
procW
)
ret
=
call_dialog_proc
(
hwnd
,
msg
,
wParam
,
lParam
,
&
result
,
proc
->
procW
);
else
if
(
proc
->
procA
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment