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