user32: CallWindowProc[AW] for mismatched built-in winprocs should
take into account if the window is Unicode (with testcase,
fixes bug #9198, 2nd try)
Mikołaj Zalewski
mikolaj at zalewski.pl
Wed Aug 8 23:47:00 CDT 2007
Contains all the suggestions of Dimtry and Alexandre except for
unistring which was chosen on purpose.
-------------- next part --------------
>From 3e8fdcb421281d3e9fcf35de761336069b64294e Mon Sep 17 00:00:00 2001
From: =?utf-8?q?Miko=C5=82aj_Zalewski?= <mikolaj at zalewski.pl>
Date: Wed, 8 Aug 2007 21:35:28 -0700
Subject: [PATCH] user32: CallWindowProc[AW] for mismatched built-in winprocs should take into account if the window is Unicode (with testcase, fixes bug #9198)
---
dlls/user32/tests/class.c | 119 +++++++++++++++++++++++++++++++++++++++++++-
dlls/user32/winproc.c | 48 +++++++++++++++++--
2 files changed, 160 insertions(+), 7 deletions(-)
diff --git a/dlls/user32/tests/class.c b/dlls/user32/tests/class.c
index 9878ac1..7a52e7c 100644
--- a/dlls/user32/tests/class.c
+++ b/dlls/user32/tests/class.c
@@ -33,6 +33,10 @@
#include "wingdi.h"
#include "winuser.h"
+/* we don't want to include commctrl.h: */
+static const CHAR WC_EDITA[] = "Edit";
+static const WCHAR WC_EDITW[] = {'E','d','i','t',0};
+
#define NUMCLASSWORDS 4
static LRESULT WINAPI ClassTest_WndProc (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
@@ -40,6 +44,11 @@ static LRESULT WINAPI ClassTest_WndProc (HWND hWnd, UINT msg, WPARAM wParam, LPA
return DefWindowProcW (hWnd, msg, wParam, lParam);
}
+static LRESULT WINAPI ClassTest_WndProc2 (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ return DefWindowProcA (hWnd, msg, wParam, lParam);
+}
+
/***********************************************************************
*/
static void ClassTest(HINSTANCE hInstance, BOOL global)
@@ -560,7 +569,12 @@ static void test_defwndproc()
{
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;
+ WNDCLASSEXA cls; /* the memory layout of WNDCLASSEXA and WNDCLASSEXW is the same */
+ WCHAR buf[128];
+ ATOM atom;
+ HWND hwnd;
int i;
pDefWindowProcA = (void *)GetProcAddress(GetModuleHandle("user32.dll"), "DefWindowProcA");
@@ -568,9 +582,6 @@ static void test_defwndproc()
for (i = 0; i < 4; i++)
{
- WNDCLASSEXA cls; /* the memory layout of WNDCLASSEXA and WNDCLASSEXW is the same */
- ATOM atom;
- HWND hwnd;
ZeroMemory(&cls, sizeof(cls));
cls.cbSize = sizeof(cls);
cls.hInstance = GetModuleHandle(NULL);
@@ -608,8 +619,110 @@ static void test_defwndproc()
DestroyWindow(hwnd);
UnregisterClass((LPSTR)(DWORD_PTR)atom, GetModuleHandle(NULL));
}
+
+ /* built-in winproc - window A/W type automatically detected */
+ ZeroMemory(&cls, sizeof(cls));
+ cls.cbSize = sizeof(cls);
+ cls.hInstance = GetModuleHandle(NULL);
+ cls.hbrBackground = GetStockObject (WHITE_BRUSH);
+ cls.lpszClassName = classA;
+ cls.lpfnWndProc = pDefWindowProcW;
+ atom = RegisterClassExA(&cls);
+
+ hwnd = CreateWindowExW(0, classW, NULL, WS_OVERLAPPEDWINDOW,
+ CW_USEDEFAULT, CW_USEDEFAULT, 680, 260, NULL, NULL, GetModuleHandleA(NULL), 0);
+ ok(IsWindowUnicode(hwnd), "Windows should be Unicode\n");
+ SetWindowLongPtrW(hwnd, GWLP_WNDPROC, (LONG_PTR)pDefWindowProcA);
+ ok(IsWindowUnicode(hwnd), "Windows should have remained Unicode\n");
+ ok(GetWindowLongPtrW(hwnd, GWLP_WNDPROC) == (LONG_PTR)pDefWindowProcW, "Invalid ANSI winproc\n");
+ ok(GetWindowLongPtrA(hwnd, GWLP_WNDPROC) == (LONG_PTR)pDefWindowProcA, "Invalid Unicode winproc\n");
+ SetWindowLongPtrA(hwnd, GWL_WNDPROC, (LONG_PTR)ClassTest_WndProc);
+ ok(IsWindowUnicode(hwnd) == FALSE, "SetWindowLongPtrA should have switched window to ANSI\n");
+
+ DestroyWindow(hwnd);
+ UnregisterClass((LPSTR)(DWORD_PTR)atom, GetModuleHandle(NULL));
+
+ /* custom winproc - the same function can be used as both A and W*/
+ ZeroMemory(&cls, sizeof(cls));
+ cls.cbSize = sizeof(cls);
+ cls.hInstance = GetModuleHandle(NULL);
+ cls.hbrBackground = GetStockObject (WHITE_BRUSH);
+ cls.lpszClassName = classA;
+ cls.lpfnWndProc = ClassTest_WndProc2;
+ atom = RegisterClassExA(&cls);
+
+ hwnd = CreateWindowExW(0, classW, NULL, WS_OVERLAPPEDWINDOW,
+ CW_USEDEFAULT, CW_USEDEFAULT, 680, 260, NULL, NULL, GetModuleHandleA(NULL), 0);
+ ok(IsWindowUnicode(hwnd) == FALSE, "Window should be ANSI\n");
+ SetWindowLongPtrW(hwnd, GWL_WNDPROC, (LONG_PTR)ClassTest_WndProc);
+ ok(IsWindowUnicode(hwnd), "SetWindowLongPtrW should have changed window to Unicode\n");
+ SetWindowLongPtrA(hwnd, GWL_WNDPROC, (LONG_PTR)ClassTest_WndProc);
+ ok(IsWindowUnicode(hwnd) == FALSE, "SetWindowLongPtrA should have changed window to ANSI\n");
+
+ 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 */
+ hwnd = CreateWindowW(WC_EDITW, unistring, WS_OVERLAPPEDWINDOW,
+ CW_USEDEFAULT, CW_USEDEFAULT, 680, 260, NULL, NULL, NULL, 0);
+ 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);
+ ok(memcmp(buf, unistring, sizeof(unistring)) == 0, "WM_GETTEXT invalid return\n");
+ CallWindowProcW((WNDPROC)GetWindowLongPtrA(hwnd, GWLP_WNDPROC), hwnd, WM_GETTEXT, 120, (LPARAM)buf);
+ ok(memcmp(buf, unistring, sizeof(unistring)) == 0, "WM_GETTEXT invalid return\n");
+
+ SetWindowTextW(hwnd, classW);
+ 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);
+ 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));
+ 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);
+ ok(memcmp(buf, classA, sizeof(classA)) == 0, "WM_GETTEXT invalid return\n");
+ CallWindowProcW((WNDPROC)GetWindowLongPtrA(hwnd, GWLP_WNDPROC), hwnd, WM_GETTEXT, 120, (LPARAM)buf);
+ ok(memcmp(buf, classA, sizeof(classA)) == 0, "WM_GETTEXT invalid return\n");
+
+ CallWindowProcW((WNDPROC)GetWindowLongPtrW(hwnd, GWLP_WNDPROC), hwnd, WM_GETTEXT, 120, (LPARAM)buf);
+ ok(memcmp(buf, classW, sizeof(classW)) == 0, "WM_GETTEXT invalid return\n");
+
+ DestroyWindow(hwnd);
+
+ hwnd = CreateWindowA(WC_EDITA, classA, WS_OVERLAPPEDWINDOW,
+ CW_USEDEFAULT, CW_USEDEFAULT, 680, 260, NULL, NULL, NULL, 0);
+
+ 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);
+ ok(memcmp(buf, classA, sizeof(classA)) == 0, "WM_GETTEXT invalid return\n");
+ CallWindowProcW((WNDPROC)GetWindowLongPtrA(hwnd, GWLP_WNDPROC), hwnd, WM_GETTEXT, 120, (LPARAM)buf);
+ ok(memcmp(buf, classA, sizeof(classA)) == 0, "WM_GETTEXT invalid return\n");
+
+ CallWindowProcW((WNDPROC)GetWindowLongPtrW(hwnd, GWLP_WNDPROC), hwnd, WM_GETTEXT, 120, (LPARAM)buf);
+ ok(memcmp(buf, classW, sizeof(classW)) == 0, "WM_GETTEXT invalid return\n");
+
+ SetWindowLongPtrW(hwnd, GWLP_WNDPROC, (LONG_PTR)ClassTest_WndProc);
+ SetWindowTextW(hwnd, unistring);
+ 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);
+ ok(memcmp(buf, unistring, sizeof(unistring)) == 0, "WM_GETTEXT invalid return\n");
+ CallWindowProcW((WNDPROC)GetWindowLongPtrA(hwnd, GWLP_WNDPROC), hwnd, WM_GETTEXT, 120, (LPARAM)buf);
+ ok(memcmp(buf, unistring, sizeof(unistring)) == 0, "WM_GETTEXT invalid return\n");
+
+ SetWindowTextW(hwnd, classW);
+ CallWindowProcA((WNDPROC)GetWindowLongPtrA(hwnd, GWLP_WNDPROC), hwnd, WM_GETTEXT, 120, (LPARAM)buf);
+ ok(memcmp(buf, classA, sizeof(classA)) == 0, "WM_GETTEXT invalid return\n");
+
+ DestroyWindow(hwnd);
}
+
static LRESULT WINAPI TestDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
return DefWindowProc(hWnd, uMsg, wParam, lParam);
diff --git a/dlls/user32/winproc.c b/dlls/user32/winproc.c
index 27b31a1..6369c2e 100644
--- a/dlls/user32/winproc.c
+++ b/dlls/user32/winproc.c
@@ -2257,7 +2257,17 @@ LRESULT WINAPI CallWindowProcA(
if (!func) return 0;
- if (!(proc = handle_to_proc( func )) && !(proc = find_builtin_proc( func )))
+ /* for built-in procs we do as if the second item was a thunk */
+ if ((proc = find_builtin_proc( func )) != NULL)
+ {
+ if (func == proc->procA || !IsWindowUnicode( hwnd ))
+ call_window_proc( hwnd, msg, wParam, lParam, &result, proc->procA );
+ else
+ call_window_proc( hwnd, msg, wParam, lParam, &result, proc->procW );
+ return result;
+ }
+
+ if (!(proc = handle_to_proc( func )))
call_window_proc( hwnd, msg, wParam, lParam, &result, func );
else if (proc->procA)
call_window_proc( hwnd, msg, wParam, lParam, &result, proc->procA );
@@ -2281,8 +2291,18 @@ LRESULT WINAPI CallWindowProcW( WNDPROC func, HWND hwnd, UINT msg,
LRESULT result;
if (!func) return 0;
+
+ /* for built-in procs we do as if the second item was a thunk */
+ if ((proc = find_builtin_proc( func )) != NULL)
+ {
+ if (func == proc->procW || IsWindowUnicode( hwnd ))
+ call_window_proc( hwnd, msg, wParam, lParam, &result, proc->procW );
+ else
+ call_window_proc( hwnd, msg, wParam, lParam, &result, proc->procA );
+ return result;
+ }
- if (!(proc = handle_to_proc( func )) && !(proc = find_builtin_proc( func )))
+ if (!(proc = handle_to_proc( func )))
call_window_proc( hwnd, msg, wParam, lParam, &result, func );
else if (proc->procW)
call_window_proc( hwnd, msg, wParam, lParam, &result, proc->procW );
@@ -2340,7 +2360,17 @@ INT_PTR WINPROC_CallDlgProcA( DLGPROC func, HWND hwnd, UINT msg, WPARAM wParam,
if (!func) return 0;
- if (!(proc = handle_to_proc( func )) && !(proc = find_builtin_proc( func )))
+ /* for built-in procs we do as if the second item was a thunk */
+ if ((proc = find_builtin_proc( func )) != NULL)
+ {
+ if (func == proc->procA || !IsWindowUnicode( hwnd ))
+ call_dialog_proc( hwnd, msg, wParam, lParam, &result, proc->procA );
+ else
+ call_dialog_proc( hwnd, msg, wParam, lParam, &result, proc->procW );
+ return result;
+ }
+
+ if (!(proc = handle_to_proc( 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 );
@@ -2368,8 +2398,18 @@ INT_PTR WINPROC_CallDlgProcW( DLGPROC func, HWND hwnd, UINT msg, WPARAM wParam,
INT_PTR ret;
if (!func) return 0;
+
+ /* for built-in procs we do as if the second item was a thunk */
+ if ((proc = find_builtin_proc( func )) != NULL)
+ {
+ if (func == proc->procW || IsWindowUnicode( hwnd ))
+ call_dialog_proc( hwnd, msg, wParam, lParam, &result, proc->procW );
+ else
+ call_dialog_proc( hwnd, msg, wParam, lParam, &result, proc->procA );
+ return result;
+ }
- if (!(proc = handle_to_proc( func )) && !(proc = find_builtin_proc( func )))
+ if (!(proc = handle_to_proc( 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 );
--
1.4.4.2
More information about the wine-patches
mailing list