comctl32: initial theming tests (try 2)

André Hentschel nerv at dawncrow.de
Thu Sep 24 13:36:29 CDT 2009


tests class redirection and "load"-order _atm_
try 2: fixed hints by Nikolay Sivov (http://www.winehq.org/pipermail/wine-devel/2009-September/078756.html)
---
 dlls/comctl32/tests/Makefile.in |    3 +-
 dlls/comctl32/tests/theming.c   |  219 +++++++++++++++++++++++++++++++++++++++
 dlls/comctl32/tests/v6util.h    |   28 +++++
 3 files changed, 249 insertions(+), 1 deletions(-)
 create mode 100644 dlls/comctl32/tests/theming.c

diff --git a/dlls/comctl32/tests/Makefile.in b/dlls/comctl32/tests/Makefile.in
index 386780d..cb38abe 100644
--- a/dlls/comctl32/tests/Makefile.in
+++ b/dlls/comctl32/tests/Makefile.in
@@ -3,7 +3,7 @@ TOPOBJDIR = ../../..
 SRCDIR    = @srcdir@
 VPATH     = @srcdir@
 TESTDLL   = comctl32.dll
-IMPORTS   = comctl32 ole32 user32 gdi32 advapi32 kernel32
+IMPORTS   = comctl32 ole32 user32 gdi32 advapi32 kernel32 psapi
 
 CTESTS = \
 	comboex.c \
@@ -22,6 +22,7 @@ CTESTS = \
 	status.c \
 	subclass.c \
 	tab.c \
+	theming.c \
 	toolbar.c \
 	tooltips.c \
 	trackbar.c \
diff --git a/dlls/comctl32/tests/theming.c b/dlls/comctl32/tests/theming.c
new file mode 100644
index 0000000..04b7353
--- /dev/null
+++ b/dlls/comctl32/tests/theming.c
@@ -0,0 +1,219 @@
+/* Unit test suite for window classes.
+ *
+ * Copyright 2009 André Hentschel
+ * Copyright 2009 Roderick Colenbrander
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "wine/test.h"
+#include <wingdi.h>
+#include <winuser.h>
+#include <winnls.h>
+#include <commctrl.h>
+#include <stdio.h>
+#include <psapi.h>
+#include "v6util.h"
+
+static struct addrspace{LPVOID pBegin, pEnd;} comctl32_addr, user32_addr;
+
+static BOOL isindll(const struct addrspace *module, LPVOID addr)
+{
+    if (addr >= module->pBegin && addr < module->pEnd) return TRUE;
+    return FALSE;
+}
+
+static void test_redirection(HINSTANCE hInstance, LPCWSTR clsname, BOOL todo)
+{
+    WNDCLASSEXW wc;
+
+    GetClassInfoExW(hInstance, clsname, &wc);
+    if (!todo)
+    {
+        ok(isindll(&comctl32_addr, wc.lpfnWndProc), "%s: should be in comctl32\n", wine_dbgstr_w(clsname));
+        ok(!isindll(&user32_addr, wc.lpfnWndProc), "%s: should not be in user32\n", wine_dbgstr_w(clsname));
+    }
+    else todo_wine
+    {
+        ok(isindll(&comctl32_addr, wc.lpfnWndProc), "%s: should be in comctl32\n", wine_dbgstr_w(clsname));
+        ok(!isindll(&user32_addr, wc.lpfnWndProc), "%s: should not be in user32\n", wine_dbgstr_w(clsname));
+    }
+}
+
+static LRESULT WINAPI ClassTest_WndProc (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+    if (msg == WM_NCCREATE) return 1;
+    return DefWindowProcW (hWnd, msg, wParam, lParam);
+}
+
+#define NUMCLASSWORDS 4
+
+static void test_order(HINSTANCE hInstance, LPCWSTR clsname, BOOL global)
+{
+    WNDCLASSEXW wc;
+    WNDCLASSW cls;
+    ATOM classatom;
+    HWND hTestWnd;
+
+    cls.style         = CS_HREDRAW | CS_VREDRAW | (global?CS_GLOBALCLASS:0);
+    cls.lpfnWndProc   = ClassTest_WndProc;
+    cls.cbClsExtra    = NUMCLASSWORDS*sizeof(DWORD);
+    cls.cbWndExtra    = 12;
+    cls.hInstance     = hInstance;
+    cls.hIcon         = LoadIconW (0, (LPWSTR)IDI_APPLICATION);
+    cls.hCursor       = LoadCursorW (0, (LPWSTR)IDC_ARROW);
+    cls.hbrBackground = GetStockObject (WHITE_BRUSH);
+    cls.lpszMenuName  = 0;
+    cls.lpszClassName = clsname;
+    classatom=RegisterClassW(&cls);
+
+    if (!classatom && GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
+        return;
+    if (global)
+        ok(!classatom, "success registering class\n");
+    else
+        ok(classatom, "failed to register class\n");
+
+    ok(!RegisterClassW (&cls),
+        "RegisterClass of the same class should fail for the second time\n");
+    /* Setup class window */
+    hTestWnd = CreateWindowW (clsname, clsname,
+                              WS_OVERLAPPEDWINDOW, 0, 0, 10, 10, 0, 0, hInstance, 0);
+
+    GetClassInfoExW(hInstance, clsname, &wc);
+    if (global)
+    {
+        ok(wc.lpfnWndProc!=cls.lpfnWndProc,"Adresses should be different\n");
+        ok(!UnregisterClassW(clsname, hInstance),
+           "Unregister class succeeded with window existing\n");
+        return;
+    }
+
+    ok(wc.lpfnWndProc==cls.lpfnWndProc,"Adresses should be the same\n");
+    ok(!(wc.style & CS_GLOBALCLASS),"Should not be a global class by style\n");
+
+    ok(!UnregisterClassW(clsname, hInstance),
+       "Unregister class succeeded with window existing\n");
+    ok(DestroyWindow(hTestWnd),
+       "DestroyWindow() failed!\n");
+    ok(UnregisterClassW(clsname, hInstance),
+       "UnregisterClass() failed\n");
+}
+
+static void run_child_process(void)
+{
+    char cmdline[MAX_PATH];
+    char path[MAX_PATH];
+    char **argv;
+    PROCESS_INFORMATION pi;
+    STARTUPINFO si = { 0 };
+    HANDLE file;
+    FILETIME now;
+
+    GetModuleFileNameA(NULL, path, MAX_PATH);
+    strcat(path, ".manifest");
+    if(!create_v6_manifest_file(path, manifest, -1))
+    {
+        skip("Could not create manifest file\n");
+        return;
+    }
+
+    si.cb = sizeof(si);
+    winetest_get_mainargs( &argv );
+    /* Vista+ seems to cache presence of .manifest files. Change last modified
+       date to defeat the cache */
+    file = CreateFileA(argv[0], FILE_WRITE_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE,
+                       NULL, OPEN_EXISTING, 0, NULL);
+    if (file != INVALID_HANDLE_VALUE)
+    {
+        GetSystemTimeAsFileTime(&now);
+        SetFileTime(file, NULL, NULL, &now);
+        CloseHandle(file);
+    }
+    sprintf(cmdline, "\"%s\" %s manifest", argv[0], argv[1]);
+    ok(CreateProcess(argv[0], cmdline, NULL, NULL, FALSE, 0, NULL, NULL,
+                     &si, &pi) != 0, "Could not create process: %u\n", GetLastError());
+    winetest_wait_child_process( pi.hProcess );
+    CloseHandle(pi.hThread);
+    CloseHandle(pi.hProcess);
+    delete_v6_manifest_file(path);
+}
+
+static BOOL init_addr(void)
+{
+    HMODULE hComctl32 = GetModuleHandle("comctl32");
+    HMODULE hUser32 = GetModuleHandle("user32");
+    MODULEINFO  mi;
+
+    /* get the adress space of the dlls */
+    if (!GetModuleInformation(GetCurrentProcess(  ), hComctl32, &mi, sizeof(mi)))
+        return FALSE;
+    comctl32_addr.pBegin=mi.lpBaseOfDll;
+    comctl32_addr.pEnd=(LPBYTE)mi.lpBaseOfDll + mi.SizeOfImage;
+    if (!GetModuleInformation(GetCurrentProcess(  ), hUser32, &mi, sizeof(mi)))
+        return FALSE;
+    user32_addr.pBegin=mi.lpBaseOfDll;
+    user32_addr.pEnd=(LPBYTE)mi.lpBaseOfDll + mi.SizeOfImage;
+    return TRUE;
+}
+
+START_TEST(theming)
+{
+    HANDLE hInstance = GetModuleHandleA( NULL );
+    HMODULE hUxtheme;
+    BOOL (WINAPI * pIsThemeActive)(VOID);
+    INT i;
+    int argc;
+    char **argv;
+    struct classlist {const WCHAR *class; BOOL todo;} listW[] = {
+        {WC_BUTTONW, TRUE},
+        {WC_COMBOBOXW, TRUE},
+        {WC_EDITW, TRUE},
+        {WC_LISTBOXW, TRUE},
+        {WC_SCROLLBARW, TRUE},
+        {WC_STATICW, TRUE},
+    };
+
+    hUxtheme = LoadLibraryA("uxtheme.dll");
+    if (hUxtheme)
+        FreeLibrary(hUxtheme);
+    else
+    {
+        win_skip("Theming not available\n");
+        return;
+    }
+
+    if (!init_addr())
+    {
+        win_skip("Could not retrieve needed addresses\n");
+        return;
+    }
+
+    /* run tests in child process */
+    argc = winetest_get_mainargs(&argv);
+    if(argc > 2 && !strcmp(argv[2], "manifest"))
+    {
+        InitCommonControls();
+        for(i=0;i<sizeof(listW)/sizeof(listW[0]);i++)
+        {
+            test_redirection(hInstance, listW[i].class, listW[i].todo);
+            test_order(hInstance, listW[i].class, FALSE);
+            test_order(hInstance, listW[i].class, TRUE);
+        }
+        return;
+    }
+
+    run_child_process();
+}
diff --git a/dlls/comctl32/tests/v6util.h b/dlls/comctl32/tests/v6util.h
index 21a8e4f..a6d68a7 100644
--- a/dlls/comctl32/tests/v6util.h
+++ b/dlls/comctl32/tests/v6util.h
@@ -136,5 +136,33 @@ static BOOL load_v6_module(ULONG_PTR *pcookie)
     return ret;
 }
 
+static BOOL create_v6_manifest_file(const char *filename, const char *manifest, int manifest_len)
+{
+    DWORD size;
+    HANDLE file;
+    WCHAR path[MAX_PATH], manifest_path[MAX_PATH];
+
+    MultiByteToWideChar( CP_ACP, 0, filename, -1, path, MAX_PATH );
+    GetFullPathNameW(path, sizeof(manifest_path)/sizeof(WCHAR), manifest_path, NULL);
+
+    if (manifest_len == -1)
+        manifest_len = strlen(manifest);
+
+    file = CreateFileW(path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
+                       FILE_ATTRIBUTE_NORMAL, NULL);
+    ok(file != INVALID_HANDLE_VALUE, "CreateFile failed: %u\n", GetLastError());
+    if(file == INVALID_HANDLE_VALUE)
+        return FALSE;
+    WriteFile(file, manifest, manifest_len, &size, NULL);
+    CloseHandle(file);
+
+    return TRUE;
+}
+
+static BOOL delete_v6_manifest_file(const char *filename)
+{
+    return DeleteFileA(filename);
+}
+
 #undef expect
 #undef ARCH
-- 

Best Regards, André Hentschel



More information about the wine-patches mailing list