diff --git a/rostests/apitests/appshim/CMakeLists.txt b/rostests/apitests/appshim/CMakeLists.txt index efb6594406e..ae219599f65 100644 --- a/rostests/apitests/appshim/CMakeLists.txt +++ b/rostests/apitests/appshim/CMakeLists.txt @@ -8,5 +8,5 @@ list(APPEND SOURCE add_executable(appshim_apitest ${SOURCE}) set_module_type(appshim_apitest win32cui) -add_importlibs(appshim_apitest msvcrt kernel32 ntdll) +add_importlibs(appshim_apitest version msvcrt kernel32 ntdll) add_cd_file(TARGET appshim_apitest DESTINATION reactos/bin FOR all) diff --git a/rostests/apitests/appshim/dispmode.c b/rostests/apitests/appshim/dispmode.c index 00107f273d8..d904e92a769 100644 --- a/rostests/apitests/appshim/dispmode.c +++ b/rostests/apitests/appshim/dispmode.c @@ -28,34 +28,100 @@ #include #include "wine/test.h" -extern DWORD get_host_winver(void); -static DWORD g_WinVersion; +static DWORD g_Version; #define WINVER_ANY 0 -#define WINVER_VISTA 0x0600 /* apphelp.dll */ static BOOL(WINAPI* pSdbGetAppPatchDir)(PVOID, LPWSTR, DWORD); -/* aclayers.dll */ +/* aclayers.dll / acgenral.dll */ static PVOID(WINAPI* pGetHookAPIs)(LPCSTR, LPCWSTR, PDWORD); static BOOL(WINAPI* pNotifyShims)(DWORD fdwReason, PVOID ptr); +DWORD get_module_version(HMODULE mod) +{ + DWORD dwVersion = 0; + HRSRC hResInfo = FindResource(mod, MAKEINTRESOURCE(VS_VERSION_INFO), RT_VERSION); + DWORD dwSize = SizeofResource(mod, hResInfo); + if (hResInfo && dwSize) + { + VS_FIXEDFILEINFO *lpFfi; + UINT uLen; -static LONG g_Count; + HGLOBAL hResData = LoadResource(mod, hResInfo); + LPVOID pRes = LockResource(hResData); + HLOCAL pResCopy = LocalAlloc(LMEM_FIXED, dwSize); + + CopyMemory(pResCopy, pRes, dwSize); + FreeResource(hResData); + + if (VerQueryValueW(pResCopy, L"\\", (LPVOID*)&lpFfi, &uLen)) + { + dwVersion = (HIWORD(lpFfi->dwProductVersionMS) << 8) | LOWORD(lpFfi->dwProductVersionMS); + if (!dwVersion) + dwVersion = (HIWORD(lpFfi->dwFileVersionMS) << 8) | LOWORD(lpFfi->dwFileVersionMS); + } + + LocalFree(pResCopy); + } + + return dwVersion; +} + +static LONG g_ChangeCount; static DEVMODEA g_LastDevmode; static DWORD g_LastFlags; static LONG (WINAPI *pChangeDisplaySettingsA)(_In_opt_ PDEVMODEA lpDevMode, _In_ DWORD dwflags); LONG WINAPI mChangeDisplaySettingsA(_In_opt_ PDEVMODEA lpDevMode, _In_ DWORD dwflags) { - g_Count++; + g_ChangeCount++; g_LastDevmode = *lpDevMode; g_LastFlags = dwflags; return DISP_CHANGE_FAILED; } +static LONG g_EnumCount; +static BOOL bFix = TRUE; + +static BOOL (WINAPI *pEnumDisplaySettingsA)(_In_opt_ LPCSTR lpszDeviceName, _In_ DWORD iModeNum, _Inout_ PDEVMODEA lpDevMode); +BOOL WINAPI mEnumDisplaySettingsA(_In_opt_ LPCSTR lpszDeviceName, _In_ DWORD iModeNum, _Inout_ PDEVMODEA lpDevMode) +{ + g_EnumCount++; + if (pEnumDisplaySettingsA(lpszDeviceName, iModeNum, lpDevMode)) + { + if (bFix) + { + if (lpDevMode && lpDevMode->dmBitsPerPel == 8) + { + trace("Running at 8bpp, faking 16\n"); + lpDevMode->dmBitsPerPel = 16; + } + if (lpDevMode && lpDevMode->dmPelsWidth == 640 && lpDevMode->dmPelsHeight == 480) + { + trace("Running at 640x480, faking 800x600\n"); + lpDevMode->dmPelsWidth = 800; + lpDevMode->dmPelsHeight = 600; + } + } + else + { + if (lpDevMode) + { + lpDevMode->dmBitsPerPel = 8; + lpDevMode->dmPelsWidth = 640; + lpDevMode->dmPelsHeight = 480; + } + } + return TRUE; + } + return FALSE; +} + + + static LONG g_ThemeCount; static DWORD g_LastThemeFlags; @@ -77,33 +143,146 @@ static const WCHAR* shim_dll(const WCHAR* name) static void pre_8bit(void) { - g_Count = 0; + g_ChangeCount = 0; memset(&g_LastDevmode, 0, sizeof(g_LastDevmode)); g_LastFlags = 0xffffffff; + g_EnumCount = 0; +} + +static void pre_8bit_2(void) +{ + bFix = FALSE; + + pre_8bit(); } static void post_8bit(void) { - ok_int(g_Count, 1); + ok_int(g_ChangeCount, 1); ok_hex(g_LastDevmode.dmFields & DM_BITSPERPEL, DM_BITSPERPEL); ok_int(g_LastDevmode.dmBitsPerPel, 8); ok_hex(g_LastFlags, CDS_FULLSCREEN); + ok_int(g_EnumCount, 1); +} + +static void post_8bit_2(void) +{ + ok_int(g_ChangeCount, 0); + ok_hex(g_LastFlags, 0xffffffff); + ok_int(g_EnumCount, 1); + + bFix = TRUE; +} + +static void post_8bit_no(void) +{ + if (g_Version == _WIN32_WINNT_WS03) + { + ok_int(g_ChangeCount, 1); + ok_hex(g_LastDevmode.dmFields & DM_BITSPERPEL, DM_BITSPERPEL); + ok_int(g_LastDevmode.dmBitsPerPel, 8); + ok_hex(g_LastFlags, CDS_FULLSCREEN); + ok_int(g_EnumCount, 1); + } + else + { + ok_int(g_ChangeCount, 0); + ok_hex(g_LastFlags, 0xffffffff); + ok_int(g_EnumCount, 0); + } + + bFix = TRUE; +} + +static void post_8bit_2_no(void) +{ + if (g_Version == _WIN32_WINNT_WS03) + { + ok_int(g_ChangeCount, 0); + ok_hex(g_LastFlags, 0xffffffff); + ok_int(g_EnumCount, 1); + } + else + { + ok_int(g_ChangeCount, 0); + ok_hex(g_LastFlags, 0xffffffff); + ok_int(g_EnumCount, 0); + } + + bFix = TRUE; } static void pre_640(void) { - g_Count = 0; + g_ChangeCount = 0; memset(&g_LastDevmode, 0, sizeof(g_LastDevmode)); g_LastFlags = 0xffffffff; + g_EnumCount = 0; +} + +static void pre_640_2(void) +{ + bFix = FALSE; + + pre_640(); } static void post_640(void) { - ok_int(g_Count, 1); + ok_int(g_ChangeCount, 1); ok_hex(g_LastDevmode.dmFields & (DM_PELSWIDTH | DM_PELSHEIGHT), (DM_PELSWIDTH | DM_PELSHEIGHT)); ok_int(g_LastDevmode.dmPelsWidth, 640); ok_int(g_LastDevmode.dmPelsHeight, 480); ok_hex(g_LastFlags, CDS_FULLSCREEN); + ok_int(g_EnumCount, 1); +} + +static void post_640_2(void) +{ + ok_int(g_ChangeCount, 0); + ok_hex(g_LastFlags, 0xffffffff); + ok_int(g_EnumCount, 1); + + bFix = TRUE; +} + +static void post_640_no(void) +{ + if (g_Version == _WIN32_WINNT_WS03) + { + ok_int(g_ChangeCount, 1); + ok_hex(g_LastDevmode.dmFields & (DM_PELSWIDTH | DM_PELSHEIGHT), (DM_PELSWIDTH | DM_PELSHEIGHT)); + ok_int(g_LastDevmode.dmPelsWidth, 640); + ok_int(g_LastDevmode.dmPelsHeight, 480); + ok_hex(g_LastFlags, CDS_FULLSCREEN); + ok_int(g_EnumCount, 1); + } + else + { + ok_int(g_ChangeCount, 0); + ok_hex(g_LastFlags, 0xffffffff); + ok_int(g_EnumCount, 0); + } + + bFix = TRUE; +} + +static void post_640_2_no(void) +{ + if (g_Version == _WIN32_WINNT_WS03) + { + ok_int(g_ChangeCount, 0); + ok_hex(g_LastFlags, 0xffffffff); + ok_int(g_EnumCount, 1); + } + else + { + ok_int(g_ChangeCount, 0); + ok_hex(g_LastFlags, 0xffffffff); + ok_int(g_EnumCount, 0); + } + + bFix = TRUE; } static void pre_theme(void) @@ -118,6 +297,20 @@ static void post_theme(void) ok_hex(g_LastThemeFlags, 0); } +static void post_theme_no(void) +{ + if (g_Version == _WIN32_WINNT_WS03) + { + ok_int(g_ThemeCount, 1); + ok_hex(g_LastThemeFlags, 0); + } + else + { + ok_int(g_ThemeCount, 0); + ok_hex(g_LastThemeFlags, 0xffffffff); + } +} + static PIMAGE_IMPORT_DESCRIPTOR FindImportDescriptor(PBYTE DllBase, PCSTR DllName) { ULONG Size; @@ -173,7 +366,8 @@ static BOOL RedirectIat(HMODULE TargetDll, PCSTR DllName, PCSTR FunctionName, UL static BOOL hook_disp(HMODULE dll) { - return RedirectIat(dll, "user32.dll", "ChangeDisplaySettingsA", (ULONG_PTR)mChangeDisplaySettingsA, (ULONG_PTR*)&pChangeDisplaySettingsA); + return RedirectIat(dll, "user32.dll", "ChangeDisplaySettingsA", (ULONG_PTR)mChangeDisplaySettingsA, (ULONG_PTR*)&pChangeDisplaySettingsA) && + RedirectIat(dll, "user32.dll", "EnumDisplaySettingsA", (ULONG_PTR)mEnumDisplaySettingsA, (ULONG_PTR*)&pEnumDisplaySettingsA); } static BOOL hook_theme(HMODULE dll) @@ -182,7 +376,7 @@ static BOOL hook_theme(HMODULE dll) } -static void test_one(LPCSTR shim, DWORD dwReason, void(*pre)(), void(*post)()) +static void test_one(LPCSTR shim, DWORD dwReason, void(*pre)(), void(*post)(), void(*second)(void)) { DWORD num_shims = 0; WCHAR wide_shim[50] = { 0 }; @@ -196,7 +390,7 @@ static void test_one(LPCSTR shim, DWORD dwReason, void(*pre)(), void(*post)()) hook = pGetHookAPIs("", wide_shim, &num_shims); if (hook == NULL) { - skip("Skipping tests for layers (%s) not present in this os (0x%x)\n", shim, g_WinVersion); + skip("Skipping tests for layers (%s) not present in this os (0x%x)\n", shim, g_Version); return; } ok(hook != NULL, "Expected hook to be a valid pointer for %s\n", shim); @@ -209,8 +403,20 @@ static void test_one(LPCSTR shim, DWORD dwReason, void(*pre)(), void(*post)()) if (post) post(); + + /* Invoking it a second time does not call the init functions again! */ + if (pre && second) + { + pre(); + + ret = pNotifyShims(dwReason, NULL); + ok(ret != 0, "Expected pNotifyShims to succeed (%i)\n", ret); + + second(); + } } +/* In 2k3 0, 2, 4, 6, 8 are not guarded against re-initializations! */ static struct test_info { const char* name; @@ -220,14 +426,22 @@ static struct test_info BOOL(*hook)(HMODULE); void(*pre)(void); void(*post)(void); + void(*second)(void); } tests[] = { - { "Force8BitColor", L"\\aclayers.dll", WINVER_ANY, 1, hook_disp, pre_8bit, post_8bit }, - { "Force8BitColor", L"\\aclayers.dll", WINVER_VISTA, 100, hook_disp, pre_8bit, post_8bit }, - { "Force640x480", L"\\aclayers.dll", WINVER_ANY, 1, hook_disp, pre_640, post_640 }, - { "Force640x480", L"\\aclayers.dll", WINVER_VISTA, 100, hook_disp, pre_640, post_640 }, - { "DisableThemes", L"\\acgenral.dll", WINVER_ANY, 1, hook_theme, pre_theme, post_theme }, - { "DisableThemes", L"\\acgenral.dll", WINVER_VISTA, 100, hook_theme, pre_theme, post_theme }, + /* Success */ + { "Force8BitColor", L"\\aclayers.dll", WINVER_ANY, 1, hook_disp, pre_8bit, post_8bit, post_8bit_no }, + { "Force8BitColor", L"\\aclayers.dll", _WIN32_WINNT_VISTA, 100, hook_disp, pre_8bit, post_8bit, post_8bit_no }, + { "Force640x480", L"\\aclayers.dll", WINVER_ANY, 1, hook_disp, pre_640, post_640, post_640_no }, + { "Force640x480", L"\\aclayers.dll", _WIN32_WINNT_VISTA, 100, hook_disp, pre_640, post_640, post_640_no }, + { "DisableThemes", L"\\acgenral.dll", WINVER_ANY, 1, hook_theme, pre_theme, post_theme, post_theme_no }, + { "DisableThemes", L"\\acgenral.dll", _WIN32_WINNT_VISTA, 100, hook_theme, pre_theme, post_theme, post_theme_no }, + + /* No need to change anything */ + { "Force8BitColor", L"\\aclayers.dll", WINVER_ANY, 1, hook_disp, pre_8bit_2, post_8bit_2, post_8bit_2_no }, + { "Force8BitColor", L"\\aclayers.dll", _WIN32_WINNT_VISTA, 100, hook_disp, pre_8bit_2, post_8bit_2, post_8bit_2_no }, + { "Force640x480", L"\\aclayers.dll", WINVER_ANY, 1, hook_disp, pre_640_2, post_640_2, post_640_2_no }, + { "Force640x480", L"\\aclayers.dll", _WIN32_WINNT_VISTA, 100, hook_disp, pre_640_2, post_640_2, post_640_2_no }, }; @@ -248,14 +462,25 @@ static void run_test(size_t n, BOOL unload) return; } - ret = tests[n].hook(dll); - if (ret) + g_Version = get_module_version(dll); + + if (!g_Version) { - test_one(tests[n].name, tests[n].reason, tests[n].pre, tests[n].post); + g_Version = _WIN32_WINNT_WS03; + trace("Module %s has no version, faking 2k3\n", wine_dbgstr_w(tests[n].dll)); } - else + + if (g_Version >= tests[n].winver) { - ok(0, "Unable to redirect functions!\n"); + ret = tests[n].hook(dll); + if (ret) + { + test_one(tests[n].name, tests[n].reason, tests[n].pre, tests[n].post, tests[n].second); + } + else + { + ok(0, "Unable to redirect functions!\n"); + } } FreeLibrary(dll); if (unload) @@ -280,8 +505,6 @@ START_TEST(dispmode) return; } - g_WinVersion = get_host_winver(); - argc = winetest_get_mainargs(&argv); if (argc < 3) { @@ -297,9 +520,6 @@ START_TEST(dispmode) { LONG failures = winetest_get_failures(); - if (g_WinVersion < tests[n].winver) - continue; - if (dll == NULL) { run_test(n, TRUE); @@ -322,10 +542,8 @@ START_TEST(dispmode) } } - if (failures != winetest_get_failures()) - { - trace("Failures from %d (%s)\n", n, tests[n].name); - } + ok(failures == winetest_get_failures(), "Last %u failures are from %d (%s)\n", + winetest_get_failures() - failures, n, tests[n].name); } } else