[TRY3]user32/tests: add tests for creating subclassed builtin-class windows

Hongbo Ni hongbo at njstar.com
Thu Aug 7 21:48:57 CDT 2008


Changes since TRY2 - thanks to Dmitry Timoshkov for advice.

1. adds extra bulitin classes: ScrollBar,Message,DDEMLEvent & all #327xx;
2. make sure created hwnd is valid;
3. more tests for unicodeness of built-in-class window before subclassing;
4. add more todo_wine for those extra classes without subclassing.

Tested on Windows Vista SP1, XP SP3.

---
 dlls/user32/tests/class.c |  276 +++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 276 insertions(+), 0 deletions(-)

diff --git a/dlls/user32/tests/class.c b/dlls/user32/tests/class.c
index 8412e8b..ede8dc8 100644
--- a/dlls/user32/tests/class.c
+++ b/dlls/user32/tests/class.c
@@ -2,6 +2,7 @@
  *
  * Copyright 2002 Mike McCormack
  * Copyright 2003 Alexandre Julliard
+ * Copyright 2008 Hongbo Ni
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -32,6 +33,7 @@
 #include "winreg.h"
 #include "wingdi.h"
 #include "winuser.h"
+#include "windows.h"
 
 /* we don't want to include commctrl.h: */
 static const CHAR WC_EDITA[] = "Edit";
@@ -778,6 +780,279 @@ static void test_builtinproc(void)
     DestroyWindow(hwnd);
 }
 
+#define MAX_CLASSNAME_LEN 11
+static void test_builtin_class_subclassed(const char *classA, BOOL has_text)
+{
+    HWND hwnd, hwnd2;
+    WNDPROC oldproc;
+    WCHAR classW[MAX_CLASSNAME_LEN];
+    int len;
+    
+    /* convert to Unicode name, return len includes null terminating char */
+    if((int)strlen(classA)+1 > MAX_CLASSNAME_LEN)
+    {
+        trace("MAX_CLASSNAME_LEN is too short for class %s, require %d\n", classA, strlen(classA)+1);
+        return;
+    }
+    len = MultiByteToWideChar( CP_ACP, 0, classA, -1, classW, MAX_CLASSNAME_LEN );
+    if(len == 0)
+    {
+        trace("MultiByteToWideChar failed to convert class %s to Unicode\n", classA);
+        return;
+    }
+
+    /* create a unicode builtin-class window without subclass */
+    hwnd = CreateWindowExW(0, classW, NULL, WS_POPUP, 0, 0, 100, 100, NULL, 0, 0, NULL);
+    ok((hwnd != NULL), "%s - CreateWindowExW failed to create a Window\n", classA);
+    if(hwnd == NULL) return;
+
+    ok(IsWindowUnicode(hwnd), 
+       "%s - CreateWindowExW should create a Unicode window (not subclassed)\n", classA);
+    ok(!IS_WNDPROC_HANDLE(GetWindowLongPtrW(hwnd, GWLP_WNDPROC)),
+       "%s - GetWindowLongPtrW should return a Unicode wndproc, got %p\n", 
+       classA, (void *)GetWindowLongPtrW(hwnd, GWLP_WNDPROC));
+
+    if(strcmp(classA, "Edit") == 0 ) /* Edit is special */
+    {
+        ok(IS_WNDPROC_HANDLE(GetWindowLongPtrA(hwnd, GWLP_WNDPROC)),
+           "%s - GetWindowLongPtrA should return a wndproc handle, got %p\n", 
+           classA, (void *)GetWindowLongPtrA(hwnd, GWLP_WNDPROC));
+    }
+    else
+    {
+        if(!has_text && strcmp(classA, "ScrollBar") != 0)
+        {
+            /* this block is the same as next block, but wine fails on some classes */
+            todo_wine
+            { 
+            ok(!IS_WNDPROC_HANDLE(GetWindowLongPtrA(hwnd, GWLP_WNDPROC)),
+               "%s - GetWindowLongPtrA should return an Ansi wndproc, got %p\n", 
+               classA, (void *)GetWindowLongPtrA(hwnd, GWLP_WNDPROC));
+            }
+        }
+        else
+        {
+            ok(!IS_WNDPROC_HANDLE(GetWindowLongPtrA(hwnd, GWLP_WNDPROC)),
+               "%s - GetWindowLongPtrA should return an Ansi wndproc, got %p\n", 
+               classA, (void *)GetWindowLongPtrA(hwnd, GWLP_WNDPROC));
+        }
+    }
+    DestroyWindow(hwnd);
+
+    /* create an ansi builtin-class window without subclass */
+    hwnd = CreateWindowExA(0, classA, NULL, WS_POPUP, 0, 0, 100, 100, NULL, 0, 0, NULL);
+    ok((hwnd != NULL), "%s - CreateWindowExA failed to create a Window\n", classA);
+    if(hwnd == NULL) return;
+
+    if(has_text)
+    {
+        ok(!IsWindowUnicode(hwnd), 
+           "%s - CreateWindowExA should create an Ansi window (not subclassed)\n", classA);
+    }
+    else 
+    { 
+        if(strcmp(classA, "ScrollBar") == 0 )
+        {
+            /* this block is the same as next block, but wine fails on ScrollBar */
+            todo_wine
+            {
+            ok(IsWindowUnicode(hwnd), 
+               "%s - CreateWindowExA should create a Unicode window (not subclassed)\n", classA);
+            }
+        }
+        else
+        {
+            ok(IsWindowUnicode(hwnd), 
+               "%s - CreateWindowExA should create a Unicode window (not subclassed)\n", classA);
+        }
+    }
+
+    if(!has_text && strcmp(classA, "ScrollBar") != 0)
+    {
+        /* this block is the same as next block, but wine fails on some classes */
+        todo_wine
+        { 
+        ok(!IS_WNDPROC_HANDLE(GetWindowLongPtrA(hwnd, GWLP_WNDPROC)),
+           "%s - GetWindowLongPtrA should return an Ansi wndproc, got %p\n", 
+           classA, (void *)GetWindowLongPtrA(hwnd, GWLP_WNDPROC));
+        }
+    }
+    else
+    {
+        ok(!IS_WNDPROC_HANDLE(GetWindowLongPtrA(hwnd, GWLP_WNDPROC)),
+           "%s - GetWindowLongPtrA should return an Ansi wndproc, got %p\n", 
+           classA, (void *)GetWindowLongPtrA(hwnd, GWLP_WNDPROC));
+    }
+
+    if(strcmp(classA, "Edit") == 0 )  /* Edit is special */
+    {
+        ok(IS_WNDPROC_HANDLE(GetWindowLongPtrW(hwnd, GWLP_WNDPROC)),
+           "%s - GetWindowLongPtrW should return a wndproc handle, got %p\n", 
+           classA, (void *)GetWindowLongPtrW(hwnd, GWLP_WNDPROC));
+    }
+    else
+    {
+        ok(!IS_WNDPROC_HANDLE(GetWindowLongPtrW(hwnd, GWLP_WNDPROC)),
+           "%s - GetWindowLongPtrW should return a Unicode wndproc, got %p\n", 
+           classA, (void *)GetWindowLongPtrW(hwnd, GWLP_WNDPROC));
+    }
+    /* DestroyWindow(hwnd) at end - need to use hwnd for subclass */
+
+    /** subclass builtin class globally using SetClassLongPtrA with ClassTest_WndProc2(A) **/
+    oldproc = (WNDPROC)SetClassLongPtrA( hwnd, GCLP_WNDPROC, (ULONG_PTR)ClassTest_WndProc2);
+    if(!has_text && strcmp(classA, "ScrollBar") != 0)
+    {
+        /* this block is the same as next block, but wine fails on some classes */
+        todo_wine
+        { 
+        ok(!IS_WNDPROC_HANDLE(oldproc),
+           "%s - SetClassLongPtrA should not return a wndproc handle, got %p\n", classA, (void *)oldproc);
+        }
+    }
+    else
+    {
+        ok(!IS_WNDPROC_HANDLE(oldproc),
+           "%s - SetClassLongPtrA should not return a wndproc handle, got %p\n", classA, (void *)oldproc);
+    }
+    ok(!IS_WNDPROC_HANDLE(GetClassLongPtrA(hwnd, GCLP_WNDPROC)),
+       "%s - GetClassLongPtrA should return an Ansi wndproc, got %p\n", 
+       classA, (void *)GetClassLongPtrA(hwnd, GCLP_WNDPROC));
+    ok(IS_WNDPROC_HANDLE(GetClassLongPtrW(hwnd, GCLP_WNDPROC)),
+       "%s - GetClassLongPtrW should return a wndproc handle, got %p\n", 
+       classA, (void *)GetClassLongPtrW(hwnd, GCLP_WNDPROC));
+
+    /* create a unicode builtin-class window after subclassed with SetClassLongPtrA*/
+    hwnd2 = CreateWindowExW(0, classW, NULL, WS_POPUP, 0, 0, 100, 100, NULL, 0, 0, NULL);
+    ok((hwnd2 != NULL), "%s - CreateWindowExW failed to create a Window\n", classA);
+    if(hwnd2 == NULL) return;
+
+    ok(!IsWindowUnicode(hwnd2), 
+       "%s - CreateWindowExW should create an Ansi window (subclassed by SetClassLongPtrA)\n", classA);
+    ok(!IS_WNDPROC_HANDLE(GetWindowLongPtrA(hwnd2, GWLP_WNDPROC)),
+       "%s - GetWindowLongPtrA should return an Ansi wndproc, got %p\n", 
+       classA, (void *)GetWindowLongPtrA(hwnd2, GWLP_WNDPROC));
+    ok(IS_WNDPROC_HANDLE(GetWindowLongPtrW(hwnd2, GWLP_WNDPROC)),
+       "%s - GetWindowLongPtrW should return a wndproc handle, got %p\n", 
+       classA, (void *)GetWindowLongPtrW(hwnd2, GWLP_WNDPROC));
+    DestroyWindow(hwnd2);
+
+    /* create a ansi builtin-class window after subclassed with SetClassLongPtrA */
+    hwnd2 = CreateWindowExA(0, classA, NULL, WS_POPUP, 0, 0, 100, 100, NULL, 0, 0, NULL);
+    ok((hwnd2 != NULL), "%s - CreateWindowExA failed to create a Window\n", classA);
+    if(hwnd2 == NULL) return;
+
+    ok(!IsWindowUnicode(hwnd2), 
+       "%s - CreateWindowExA should create an Ansi window (subclassed by SetClassLongPtrA)\n", classA);
+    ok(!IS_WNDPROC_HANDLE(GetWindowLongPtrA(hwnd2, GWLP_WNDPROC)),
+       "%s - GetWindowLongPtrA should return an Ansi wndproc, got %p\n", 
+       classA, (void *)GetWindowLongPtrA(hwnd2, GWLP_WNDPROC));
+    ok(IS_WNDPROC_HANDLE(GetWindowLongPtrW(hwnd2, GWLP_WNDPROC)),
+       "%s - GetWindowLongPtrW should return a wndproc handle, got %p\n", 
+       classA, (void *)GetWindowLongPtrW(hwnd2, GWLP_WNDPROC));
+    DestroyWindow(hwnd2);
+
+    SetWindowLongPtrA( hwnd, GCLP_WNDPROC, (ULONG_PTR)oldproc); /* restore procA */
+
+    /** subclass builtin class globally using SetClassLongPtrW with ClassTest_WndProc(W) **/
+    oldproc = (WNDPROC)SetClassLongPtrW( hwnd, GCLP_WNDPROC, (ULONG_PTR)ClassTest_WndProc);
+    ok(IS_WNDPROC_HANDLE(oldproc),
+       "%s - SetClassLongPtrW should not return a wndproc handle, got %p\n", 
+       classA, (void *)oldproc);
+    ok(IS_WNDPROC_HANDLE(GetClassLongPtrA(hwnd, GCLP_WNDPROC)),
+       "%s - GetClassLongPtrA should return a wndproc handle, got %p\n", 
+       classA, (void *)GetClassLongPtrA(hwnd, GCLP_WNDPROC));
+    ok(!IS_WNDPROC_HANDLE(GetClassLongPtrW(hwnd, GCLP_WNDPROC)),
+       "%s - GetClassLongPtrW should return a Unicode wndproc, got %p\n", 
+       classA, (void *)GetClassLongPtrW(hwnd, GCLP_WNDPROC));
+
+    /* create a unicode builtin-class window after subclassed with SetClassLongPtrW */
+    hwnd2 = CreateWindowExW(0, classW, NULL, WS_POPUP, 0, 0, 100, 100, NULL, 0, 0, NULL);
+    ok((hwnd2 != NULL), "%s - CreateWindowExW failed to create a Window\n", classA);
+    if(hwnd2 == NULL) return;
+
+    ok(IsWindowUnicode(hwnd2), 
+       "%s - CreateWindowExW should create a Unicode window (subclassed by SetClassLongPtrW)\n", classA);
+    ok(IS_WNDPROC_HANDLE(GetWindowLongPtrA(hwnd2, GWLP_WNDPROC)),
+       "%s - GetWindowLongPtrA should return a wndproc handle, got %p\n", 
+       classA, (void *)GetWindowLongPtrA(hwnd2, GWLP_WNDPROC));
+    ok(!IS_WNDPROC_HANDLE(GetWindowLongPtrW(hwnd2, GWLP_WNDPROC)),
+       "%s - GetWindowLongPtrW should return a Unicode wndproc, got %p\n", 
+       classA, (void *)GetWindowLongPtrW(hwnd2, GWLP_WNDPROC));
+    /* ClassTest_WndProc handles Unciode message - expected */
+    ok(((WNDPROC)GetWindowLongPtrW(hwnd2, GWLP_WNDPROC) == ClassTest_WndProc),
+       "%s - GetWindowLongPtrW should return ClassTest_WndProc, %p vs %p\n",
+        classA, (void *)GetWindowLongPtrW(hwnd2, GWLP_WNDPROC), ClassTest_WndProc);
+    DestroyWindow(hwnd2);
+
+    /* create an ansi builtin-class window after subclassed with SetClassLongPtrW */
+    hwnd2 = CreateWindowExA(0, classA, NULL, WS_POPUP, 0, 0, 100, 100, NULL, 0, 0, NULL);
+    ok((hwnd2 != NULL), "%s - CreateWindowExA failed to create a Window\n", classA);
+    if(hwnd2 == NULL) return;
+
+    if(has_text)
+    {
+        todo_wine
+        {
+        ok(!IsWindowUnicode(hwnd2), 
+           "%s - CreateWindowExA should create an Ansi window (subclassed by SetClassLongPtrW)\n", classA);
+        ok(!IS_WNDPROC_HANDLE(GetWindowLongPtrA(hwnd2, GWLP_WNDPROC)),
+           "%s - GetWindowLongPtrA should return an Ansi wndproc, got %p\n", 
+           classA, (void *)GetWindowLongPtrA(hwnd2, GWLP_WNDPROC));
+        ok(IS_WNDPROC_HANDLE(GetWindowLongPtrW(hwnd2, GWLP_WNDPROC)),
+           "%s - GetWindowLongPtrW should return a wndproc handle, got %p\n", 
+           classA, (void *)GetWindowLongPtrW(hwnd2, GWLP_WNDPROC));
+
+        /* ClassTest_WndProc(W) should also handle Ansi message - a window Hack */
+        ok(((WNDPROC)GetWindowLongPtrA(hwnd2, GWLP_WNDPROC) == ClassTest_WndProc),
+           "%s - GetWindowLongPtrA should return ClassTest_WndProc, %p vs %p\n", classA,
+           (void *)GetWindowLongPtrA(hwnd2, GWLP_WNDPROC), ClassTest_WndProc);
+        } /* todo_wine */
+    }
+    else
+    {
+        ok(IsWindowUnicode(hwnd2), 
+           "%s - CreateWindowExA should create a Unicode window (subclassed by SetClassLongPtrW)\n", classA);
+        ok(!IS_WNDPROC_HANDLE(GetWindowLongPtrW(hwnd2, GWLP_WNDPROC)),
+           "%s - GetWindowLongPtrW should return a Unicode wndproc, got %p\n", 
+           classA, (void *)GetWindowLongPtrW(hwnd2, GWLP_WNDPROC));
+        ok(IS_WNDPROC_HANDLE(GetWindowLongPtrA(hwnd2, GWLP_WNDPROC)),
+           "%s - GetWindowLongPtrA should return a wndproc handle, got %p\n", 
+           classA, (void *)GetWindowLongPtrA(hwnd2, GWLP_WNDPROC));
+    
+        /* ClassTest_WndProc(W) should handle Unicode message - It's normal */
+        ok(((WNDPROC)GetWindowLongPtrW(hwnd2, GWLP_WNDPROC) == ClassTest_WndProc),
+           "%s - GetWindowLongPtrW should return ClassTest_WndProc, %p vs %p\n", classA,
+           (void *)GetWindowLongPtrW(hwnd2, GWLP_WNDPROC), ClassTest_WndProc);
+    }
+    DestroyWindow(hwnd2);
+
+    SetWindowLongPtrW( hwnd, GCLP_WNDPROC, (ULONG_PTR)oldproc);
+    DestroyWindow(hwnd);   
+}
+
+static void test_all_builtin_classes_subclassed(void)
+{
+    /* test builtin classes that deals with Ansi/Unicode text */
+    test_builtin_class_subclassed("Edit", 1);
+    test_builtin_class_subclassed("Button", 1);
+    test_builtin_class_subclassed("Static", 1);
+    test_builtin_class_subclassed("ComboBox", 1);
+    test_builtin_class_subclassed("ComboLBox", 1);
+    test_builtin_class_subclassed("ListBox", 1);
+    test_builtin_class_subclassed("#32770", 1);  /* dialog */
+
+    /* test builtin classes that does not deal with Ansi/Unicode text */
+    test_builtin_class_subclassed("ScrollBar", 0);
+    test_builtin_class_subclassed("Message", 0);
+    test_builtin_class_subclassed("#32768", 0);  /* menu */
+    test_builtin_class_subclassed("#32769", 0);  /* desktop */
+    test_builtin_class_subclassed("#32772", 0);  /* icon title */
+    todo_wine 
+    { /* those 2 classes fail on the first call to CreateWindowExW */
+    test_builtin_class_subclassed("DDEMLEvent", 0);
+    test_builtin_class_subclassed("#32771", 0);  /* task switch */
+    }
+}
 
 static LRESULT WINAPI TestDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
 {
@@ -842,6 +1117,7 @@ START_TEST(class)
     CreateDialogParamTest(hInstance);
     test_styles();
     test_builtinproc();
+    test_all_builtin_classes_subclassed();
 
     /* this test unregisters the Button class so it should be executed at the end */
     test_instances();
-- 
1.5.6.1.1071.g76fb





More information about the wine-patches mailing list