[WIN32NT_APITEST] Add some NtUserCreateWindowEx tests by Sylvain Deverre. ROSTESTS-237
[reactos.git] / rostests / apitests / win32nt / ntuser / NtUserCreateWindowEx.c
diff --git a/rostests/apitests/win32nt/ntuser/NtUserCreateWindowEx.c b/rostests/apitests/win32nt/ntuser/NtUserCreateWindowEx.c
new file mode 100644 (file)
index 0000000..a90d19d
--- /dev/null
@@ -0,0 +1,228 @@
+/*
+ * PROJECT:         ReactOS api tests
+ * LICENSE:         GPL - See COPYING in the top level directory
+ * PURPOSE:         Test for NtUserCreateWindowEx
+ */
+
+#include <win32nt.h>
+
+static
+inline
+HWND
+CreateWnd(HINSTANCE hinst,
+          PLARGE_STRING clsName,
+          PLARGE_STRING clsVer,
+          PLARGE_STRING wndName)
+{
+    return NtUserCreateWindowEx(WS_EX_OVERLAPPEDWINDOW,
+                                clsName,
+                                clsVer,
+                                wndName,
+                                WS_CAPTION,
+                                CW_USEDEFAULT,
+                                CW_USEDEFAULT,
+                                100,
+                                100,
+                                NULL,
+                                NULL,
+                                hinst,
+                                0,
+                                0,
+                                NULL);
+}
+
+/* WndProc for class1 */
+
+LRESULT CALLBACK wndProc1(HWND hwnd, UINT msg, WPARAM wPrm, LPARAM lPrm)
+{
+    return DefWindowProc(hwnd, msg, wPrm, lPrm);
+}
+
+/* WndProc for class2 */
+LRESULT CALLBACK wndProc2(HWND hwnd, UINT msg, WPARAM wPrm, LPARAM lPrm)
+{
+    return DefWindowProc(hwnd, msg, wPrm, lPrm);
+}
+
+
+START_TEST(NtUserCreateWindowEx)
+{
+    HINSTANCE hinst = GetModuleHandle(NULL);
+    WNDCLASSEXW wclex = {0};
+    WNDCLASSEXW wclex2 = {0};
+    WNDCLASSEXW res = {0};
+
+    /* Unicode strings for NtRegisterClassExWOW */
+    UNICODE_STRING cls = {14, 32, L"MyClass"};
+    UNICODE_STRING ver_cls = {12, 32, L"v2test"};
+    UNICODE_STRING another_cls = {10, 32, L"Dummy"};
+    UNICODE_STRING menu = {10, 10, L"MuMnu"};
+
+    /* LARGE_STRING for NtUserCreateWindowEx */
+    LARGE_STRING l_dummy = {14, 32, 0, L"DummyMe"};
+    LARGE_STRING l_wndName = {32, 32, 0, L""};
+    LARGE_STRING l_cls = {cls.Length, 32, 0, cls.Buffer};
+    LARGE_STRING l_ver_cls = {ver_cls.Length, 32, 0, ver_cls.Buffer};
+    WCHAR bufMe[255] = {0};
+    UNICODE_STRING capture = {255, 255, bufMe};
+    PWSTR pwstr = NULL;
+    CLSMENUNAME clsMenuName, outClsMnu = {0};
+    ATOM atom, atom2, atom3;
+    HWND hwnd;
+
+    clsMenuName.pszClientAnsiMenuName = "MuMnu";
+    clsMenuName.pwszClientUnicodeMenuName = menu.Buffer;
+    clsMenuName.pusMenuName = &menu;
+
+    wclex.cbSize = sizeof(WNDCLASSEXW);
+    wclex.style = 0;
+    wclex.lpfnWndProc = wndProc1;
+    wclex.cbClsExtra = 2;
+    wclex.cbWndExtra = 4;
+    wclex.hInstance = hinst;
+    wclex.hIcon = NULL;
+    wclex.hCursor = NULL;
+    wclex.hbrBackground = CreateSolidBrush(RGB(4,7,5));
+    wclex.lpszMenuName = menu.Buffer;
+    wclex.lpszClassName = cls.Buffer;
+    wclex.hIconSm = NULL;
+    memcpy(&wclex2, &wclex, sizeof(wclex));
+    wclex2.lpfnWndProc = wndProc2;
+
+    /* Register our first version */
+    atom = NtUserRegisterClassExWOW(&wclex,       /* wndClass */
+                                    &cls,         /* ClassName */
+                                    &cls,         /* Version */
+                                    &clsMenuName, /* MenuName */
+                                    0,
+                                    0,
+                                    NULL);
+    TEST(atom != 0);
+
+    /* Register second version */
+    atom2 = NtUserRegisterClassExWOW(&wclex2,      /* wndClass */
+                                     &cls,         /* ClassName */
+                                     &ver_cls,     /* Version */
+                                     &clsMenuName, /* MenuName */
+                                     0,
+                                     0,
+                                     NULL);
+
+    atom3 = NtUserRegisterClassExWOW(&wclex2,      /* wndClass */
+                                    &another_cls, /* ClassName */
+                                    &another_cls, /* Version */
+                                    &clsMenuName, /* MenuName */
+                                    0,
+                                    0,
+                                    NULL);
+
+    TEST(NtUserGetWOWClass(hinst, &ver_cls) != 0);
+
+    TEST(atom2 != 0);
+    TEST(atom == atom2 && (atom | atom2) != 0);
+
+    /* Now, create our first window */
+    hwnd = CreateWnd(hinst, &l_cls, &l_cls, &l_wndName);
+    TEST(hwnd != 0);
+    if(hwnd)
+    {
+        /* Test some settings about the window */
+        TEST((WNDPROC)GetWindowLongPtrW(hwnd, GWLP_WNDPROC) == wndProc1);
+
+        /* Check class name isn't versioned */
+        TEST(NtUserGetClassName(hwnd, TRUE, &capture) != 0);
+        TEST(wcscmp(capture.Buffer, cls.Buffer) == 0);
+        TEST(wcscmp(capture.Buffer, ver_cls.Buffer) != 0);
+        ZeroMemory(capture.Buffer, 255);
+
+        /* Check what return GetClassLong */
+        TEST(GetClassLong(hwnd, GCW_ATOM) == atom);
+        TEST(NtUserSetClassLong(hwnd, GCW_ATOM, atom3, FALSE) == atom);
+        NtUserGetClassName(hwnd, TRUE, &capture);
+        TEST(wcscmp(capture.Buffer, another_cls.Buffer) == 0);
+
+        /* Finally destroy it */
+        DestroyWindow(hwnd);
+    }
+
+    /* Create our second version */
+    hwnd = CreateWnd(hinst, &l_cls, &l_ver_cls, &l_wndName);
+    TEST(hwnd != 0);
+    if (hwnd)
+    {
+        /* Test settings about window */
+        TEST((WNDPROC)GetWindowLongPtrW(hwnd, GWLP_WNDPROC) == wndProc2);
+
+        /* Check class name isn't versioned */
+        TEST(NtUserGetClassName(hwnd, TRUE, &capture) != 0);
+        TEST(wcscmp(capture.Buffer, cls.Buffer) == 0);
+        TEST(wcscmp(capture.Buffer, ver_cls.Buffer) != 0);
+        ZeroMemory(capture.Buffer, 255);
+
+        /* Check what return GetClassLong */
+        TEST(GetClassLong(hwnd, GCW_ATOM) == atom);
+
+        /* Finally destroy it */
+        DestroyWindow(hwnd);
+    }
+
+    /* Create a nonexistent window */
+    hwnd = CreateWnd(hinst, &l_cls, &l_dummy, &l_wndName);
+    TEST(hwnd == 0);
+    if (hwnd) DestroyWindow(hwnd);
+
+    /* Get non-versioned class info */
+    res.cbSize = sizeof(res);
+    SetLastError(0);
+    TEST(NtUserGetClassInfo(hinst, &cls, &res, &pwstr, 0) != 0);
+    TEST(GetLastError() == 0);
+    TEST(res.cbSize == wclex.cbSize);
+    TEST(res.style == wclex.style);
+    TEST(res.lpfnWndProc == wclex.lpfnWndProc);
+    TEST(res.cbClsExtra == wclex.cbClsExtra);
+    TEST(res.cbWndExtra == wclex.cbWndExtra);
+    TEST(res.hInstance == wclex.hInstance);
+    TEST(res.hIcon == wclex.hIcon);
+    TEST(res.hCursor == wclex.hCursor);
+    TEST(res.hbrBackground == wclex.hbrBackground);
+    TEST(res.lpszMenuName == 0);
+    TEST(res.lpszClassName == 0);
+    TEST(res.hIconSm == wclex.hIconSm);
+
+    /* Get versioned class info */
+    TEST(NtUserGetClassInfo(hinst, &ver_cls, &res, &pwstr, 0) != 0);
+    TEST(GetLastError() == 0);
+    TEST(res.cbSize == wclex2.cbSize);
+    TEST(res.style == wclex2.style);
+    TEST(res.lpfnWndProc == wclex2.lpfnWndProc);
+    TEST(res.cbClsExtra == wclex2.cbClsExtra);
+    TEST(res.cbWndExtra == wclex2.cbWndExtra);
+    TEST(res.hInstance == wclex2.hInstance);
+    TEST(res.hIcon == wclex2.hIcon);
+    TEST(res.hCursor == wclex2.hCursor);
+    TEST(res.hbrBackground == wclex2.hbrBackground);
+    TEST(res.lpszMenuName == 0);
+    TEST(res.lpszClassName == 0);
+    TEST(res.hIconSm == wclex2.hIconSm);
+
+    /* Create a new window from our old class. Since we set a new class atom,
+     * it should be set to our new atom
+     */
+    hwnd = NULL;
+    hwnd = CreateWnd(hinst, &l_cls, &l_cls, &l_wndName);
+    TEST(hwnd != NULL);
+    if (hwnd)
+    {
+        TEST(GetClassLong(hwnd, GCW_ATOM) == atom3);
+        TEST(NtUserGetClassName(hwnd, TRUE, &capture) != 0);
+        TEST(wcscmp(capture.Buffer, another_cls.Buffer) == 0);
+        DestroyWindow(hwnd);
+    }
+
+    /* Test class destruction */
+    TEST(NtUserUnregisterClass(&cls, hinst, (PCLSMENUNAME)0xbad) != 0);
+    TEST(NtUserUnregisterClass(&ver_cls, hinst, &outClsMnu) != 0);
+    TEST(NtUserUnregisterClass(&another_cls, hinst, &outClsMnu) != 0);
+    TEST(NtUserUnregisterClass(&menu, hinst, &outClsMnu) == 0);
+
+}