[PATCH2+TEST] RE: user32: Problem using SetClassLongW to subclass built-in control (Edit)

Hongbo Ni hongbo_ni at hotmail.com
Mon Jul 14 02:50:14 CDT 2008


Hello,

Now I have fixed the problem, or corrected to window behaviour. Included is
the Patch, Test and Debug (play with windows). Can anyone please test or comment ?

Regards
Hongbo Ni

==============================================================================
# Patch 
==============================================================================
--- wine-1.1.1-orig/dlls/user32/win.c   2008-07-12 01:55:55.000000000 +1000
+++ wine-1.1.1/dlls/user32/win.c        2008-07-14 16:49:21.000000000 +1000
@@ -173,6 +173,13 @@ static WND *create_window_handle( HWND p
     win->owner      = full_owner;
     win->class      = class;
     win->winproc    = get_class_winproc( class );
+    /* This is a window hack - When builtin Edit class has been subclassed by SetClassLong(Ptr)W   */
+    /* If creating ansi Edit window & the class does not have a ansi proc, use unicode proc as ansi */
+    if(!unicode && !IS_INTRESOURCE(name) && !strcmpiW( name, EDIT_builtin_class.name )
+       && WINPROC_IsUnicode( win->winproc, 0 ) &&  WINPROC_IsUnicode( win->winproc, 1 ))
+    {
+        win->winproc = WINPROC_AllocProc((WNDPROC)WINPROC_GetProc( win->winproc, 1 ), NULL);
+    }
     win->dwMagic    = WND_MAGIC;
     win->cbWndExtra = extra_bytes;
     if (WINPROC_IsUnicode( win->winproc, unicode )) win->flags |= WIN_ISUNICODE;

==============================================================================
# Debug - following debug shows the window hack 
#        >>show var: is value show by the MSVC debuger
==============================================================================
	WNDPROC EditWndProcA=NULL, EditClassProcA=NULL;
	WNDPROC EditWndProcW=NULL, EditClassProcW=NULL;
	HWND hEditWnd1,hEditWnd2;
	static const CHAR classNameA[] = "Edit";
	static const WCHAR classNameW[] = {'E','d','i','t',0};
	int i=0;
	HWND hEditWnd0 = CreateWindowExA(0,classNameA, NULL,WS_POPUP,0, 0, 1, 1,NULL,NULL,hInst,NULL);
	EditClassProcA =(WNDPROC)GetClassLongPtrA(hEditWnd0, GCLP_WNDPROC);
	EditClassProcW =(WNDPROC)GetClassLongPtrW(hEditWnd0, GCLP_WNDPROC);
	>>show var: EditClassProcA=0x77246feb  EditClassProcW=0x7726f52f

	EditWndProcA =(WNDPROC)GetWindowLongPtrA(hEditWnd0, GWLP_WNDPROC);
	EditWndProcW =(WNDPROC)GetWindowLongPtrW(hEditWnd0, GWLP_WNDPROC);
	>>show var: EditWndProcA  =0x77246feb  EditWndProcW=0xffff0597(handle)

	if(IsWindowUnicode(hEditWnd0)) i++;
	>>show var: i = 0 -- not a unciode windows

	OldEditWndProcW =(WNDPROC)SetClassLongPtrW(hEditWnd0, GCLP_WNDPROC , (DWORD)EditWndProc );
	>>show var: OldEditWndProcW=0x7726f52f

	EditClassProcA =(WNDPROC)GetClassLongPtrA(hEditWnd1, GCLP_WNDPROC);
	EditClassProcW =(WNDPROC)GetClassLongPtrW(hEditWnd1, GCLP_WNDPROC);
	>>show var: EditClassProcA=0xffff05bf  EditClassProcW=0x00401014

	hEditWnd1 = CreateWindowA(classNameA, NULL,WS_POPUP,0, 16, 100, 16,hWnd,NULL,hInst,NULL);
	EditWndProcA =(WNDPROC)GetWindowLongPtrA(hEditWnd1, GWLP_WNDPROC);
	EditWndProcW =(WNDPROC)GetWindowLongPtrW(hEditWnd1, GWLP_WNDPROC);
	>>show var: EditWndProcA  =0x00401014  EditWndProcW=0xffff0637

	if(IsWindowUnicode(hEditWnd1)) i++;
	>>show var: i = 0 -- not a unicode windows

Now you can see EditWndProcA==EditClassProcW and it's not a Unicode Window

I have got a screenshot showing the same debug result on MSVC 6.0
http://www.njstar.com/devimg/SetClassLongW-debug.png

==============================================================================
# Test -  Following tests are added to dlls/user32/tests/class.c
#         Latest 4 added tests fails on current wine 1.1.1
==============================================================================
--- wine-1.1.1-orig/dlls/user32/tests/class.c   2008-07-12 01:55:55.000000000 +1000
+++ wine-1.1.1/dlls/user32/tests/class.c        2008-07-14 16:44:34.000000000 +1000
@@ -590,6 +590,7 @@ static void test_builtinproc(void)
     WCHAR buf[128];
     ATOM atom;
     HWND hwnd;
+    HWND hwnd2;
     int i;

     pDefWindowProcA = (void *)GetProcAddress(GetModuleHandle("user32.dll"), "DefWindowProcA");
@@ -775,6 +776,72 @@ static void test_builtinproc(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");

+    /** subclass Edit class using SetClassLongPtrA with ClassTest_WndProc2 **/
+    oldproc = (WNDPROC)SetClassLongPtrA( hwnd, GCLP_WNDPROC, (ULONG_PTR)ClassTest_WndProc2);
+    ok(!IS_WNDPROC_HANDLE(GetClassLongPtrA(hwnd, GCLP_WNDPROC)),
+       "GetClassLongPtrA expect to return a Ansi wndproc, got %p\n",(void *)GetClassLongPtrA(hwnd, GCLP_WNDPROC));
+    ok(IS_WNDPROC_HANDLE(GetClassLongPtrW(hwnd, GCLP_WNDPROC)),
+       "GetClassLongPtrW expect to return a wndproc handle, got %p\n", (void *)GetClassLongPtrW(hwnd, GCLP_WNDPROC));
+
+    /* create a unicode edit window */
+    hwnd2 = CreateWindowExW(0, WC_EDITW, NULL, WS_POPUP,
+                           0, 0, 100, 100, GetDesktopWindow(), 0, 0, NULL);
+    ok(!IsWindowUnicode(hwnd2), "CreateWindowExW should create a Ansi Edit window (subclassed by SetClassLongPtrA)\n");
+    ok(!IS_WNDPROC_HANDLE(GetWindowLongPtrA(hwnd2, GWLP_WNDPROC)),
+       "GetWindowLongPtrA expect to return a Ansi wndproc, got %p\n",(void *)GetWindowLongPtrA(hwnd2, GWLP_WNDPROC));
+    ok(IS_WNDPROC_HANDLE(GetWindowLongPtrW(hwnd2, GWLP_WNDPROC)),
+       "GetWindowLongPtrW expect to return a wndproc handle, got %p\n",(void *)GetWindowLongPtrW(hwnd2, GWLP_WNDPROC));
+    DestroyWindow(hwnd2);
+
+    /* create a ansi edit window */
+    hwnd2 = CreateWindowExA(0, WC_EDITA, NULL, WS_POPUP,
+                           0, 0, 100, 100, GetDesktopWindow(), 0, 0, NULL);
+    ok(!IsWindowUnicode(hwnd2), "CreateWindowExA should create a Ansi Edit window (subclassed by SetClassLongPtrA)\n");
+    ok(!IS_WNDPROC_HANDLE(GetWindowLongPtrA(hwnd2, GWLP_WNDPROC)),
+       "GetWindowLongPtrA expect to return a Ansi wndproc, got %p\n",(void *)GetWindowLongPtrA(hwnd2, GWLP_WNDPROC));
+    ok(IS_WNDPROC_HANDLE(GetWindowLongPtrW(hwnd2, GWLP_WNDPROC)),
+       "GetWindowLongPtrW expect to return a wndproc handle, got %p\n",(void *)GetWindowLongPtrW(hwnd2, GWLP_WNDPROC));
+    DestroyWindow(hwnd2);
+
+    SetWindowLongPtrA( hwnd, GCLP_WNDPROC, (ULONG_PTR)oldproc); /* restore procA */
+
+    /** subclass Edit class using SetClassLongPtrW with ClassTest_WndProc **/
+    oldproc = (WNDPROC)SetClassLongPtrW( hwnd, GCLP_WNDPROC, (ULONG_PTR)ClassTest_WndProc);
+    ok(IS_WNDPROC_HANDLE(GetClassLongPtrA(hwnd, GCLP_WNDPROC)),
+       "GetClassLongPtrA expect to return a wndproc handle, got %p\n",(void *)GetClassLongPtrA(hwnd, GCLP_WNDPROC));
+    ok(!IS_WNDPROC_HANDLE(GetClassLongPtrW(hwnd, GCLP_WNDPROC)),
+       "GetClassLongPtrW expect to return a Unicode wndproc, got %p\n",(void *)GetClassLongPtrW(hwnd, GCLP_WNDPROC));
+
+    /* create a unicode edit window */
+    hwnd2 = CreateWindowExW(0, WC_EDITW, NULL, WS_POPUP,
+                           0, 0, 100, 100, GetDesktopWindow(), 0, 0, NULL);
+    ok(IsWindowUnicode(hwnd2), "CreateWindowExW should create a Unicode Edit window (subclassed by SetClassLongPtrW)\n");
+    ok(IS_WNDPROC_HANDLE(GetWindowLongPtrA(hwnd2, GWLP_WNDPROC)),
+       "GetWindowLongPtrA expect to return a wndproc handle, got %p\n",(void *)GetWindowLongPtrA(hwnd2, GWLP_WNDPROC));
+    ok(!IS_WNDPROC_HANDLE(GetWindowLongPtrW(hwnd2, GWLP_WNDPROC)),
+       "GetWindowLongPtrW expect to return a Unicode wndproc, got %p\n",(void *)GetWindowLongPtrW(hwnd2, GWLP_WNDPROC));
+    /* ClassTest_WndProc handles Unciode message - expected */
+    ok(((WNDPROC)GetWindowLongPtrW(hwnd2, GWLP_WNDPROC)==ClassTest_WndProc),
+       "GetWindowLongPtrW expect to be ClassTest_WndProc, %p vs %p\n",
+       (void *)GetWindowLongPtrW(hwnd2, GWLP_WNDPROC),ClassTest_WndProc);
+    DestroyWindow(hwnd2);
+
+    /* create a ansi edit window */
+    hwnd2 = CreateWindowExA(0, WC_EDITA, NULL, WS_POPUP,
+                           0, 0, 100, 100, GetDesktopWindow(), 0, 0, NULL);
+    ok(!IsWindowUnicode(hwnd2), "CreateWindowExA should create a Ansi Edit window (subclassed by SetClassLongPtrW)\n");
+    ok(!IS_WNDPROC_HANDLE(GetWindowLongPtrA(hwnd2, GWLP_WNDPROC)),
+       "GetWindowLongPtrA expect to return a Ansi wndproc, got %p\n",(void *)GetWindowLongPtrA(hwnd2, GWLP_WNDPROC));
+    ok(IS_WNDPROC_HANDLE(GetWindowLongPtrW(hwnd2, GWLP_WNDPROC)),
+       "GetWindowLongPtrW expect to return a wndproc handle, got %p\n",(void *)GetWindowLongPtrW(hwnd2, GWLP_WNDPROC));
+    /* ClassTest_WndProc should also handle Ansi message - a window Hack */
+    ok(((WNDPROC)GetWindowLongPtrA(hwnd2, GWLP_WNDPROC)==ClassTest_WndProc),
+       "GetWindowLongPtrA expect to be ClassTest_WndProc, %p vs %p\n",
+       (void *)GetWindowLongPtrA(hwnd2, GWLP_WNDPROC),ClassTest_WndProc);
+    DestroyWindow(hwnd2);
+
+    SetWindowLongPtrW( hwnd, GCLP_WNDPROC, (ULONG_PTR)oldproc); /* restore procW */
+
     DestroyWindow(hwnd);
 }
==============================================================================

                                

_________________________________________________________________
Meet singles near you. Try ninemsn dating now!
http://a.ninemsn.com.au/b.aspx?URL=http%3A%2F%2Fdating%2Eninemsn%2Ecom%2Eau%2Fchannel%2Findex%2Easpx%3Ftrackingid%3D1046247&_t=773166080&_r=WL_TAGLINE&_m=EXT


More information about the wine-devel mailing list