ReactOS 0.4.16-dev-334-g4d9f67c
dispmode.c
Go to the documentation of this file.
1/*
2 * PROJECT: appshim_apitest
3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4 * PURPOSE: Tests for display mode shims
5 * COPYRIGHT: Copyright 2016-2018 Mark Jansen (mark.jansen@reactos.org)
6 */
7
8#include <ntstatus.h>
9#define WIN32_NO_STATUS
10#include <windows.h>
11#ifdef __REACTOS__
12#include <ntndk.h>
13#else
14#include <winternl.h>
15#endif
16#include <stdio.h>
17#include <strsafe.h>
18#include "wine/test.h"
19#include "apitest_iathook.h"
20#include "appshim_apitest.h"
21
23#define WINVER_ANY 0
24
25/* aclayers.dll / acgenral.dll */
27static BOOL(WINAPI* pNotifyShims)(DWORD fdwReason, PVOID ptr);
28
29
31{
32 DWORD dwVersion = 0;
34 DWORD dwSize = SizeofResource(mod, hResInfo);
35 if (hResInfo && dwSize)
36 {
37 VS_FIXEDFILEINFO *lpFfi;
38 UINT uLen;
39
40 HGLOBAL hResData = LoadResource(mod, hResInfo);
41 LPVOID pRes = LockResource(hResData);
43
44 CopyMemory(pResCopy, pRes, dwSize);
45 FreeResource(hResData);
46
47 if (VerQueryValueW(pResCopy, L"\\", (LPVOID*)&lpFfi, &uLen))
48 {
50 if (!dwVersion)
51 dwVersion = (HIWORD(lpFfi->dwFileVersionMS) << 8) | LOWORD(lpFfi->dwFileVersionMS);
52 }
53
54 LocalFree(pResCopy);
55 }
56
57 return dwVersion;
58}
59
63
64static LONG (WINAPI *pChangeDisplaySettingsA)(_In_opt_ PDEVMODEA lpDevMode, _In_ DWORD dwflags);
66{
70
71 return DISP_CHANGE_FAILED;
72}
73
75static BOOL bFix = TRUE;
76
77static BOOL (WINAPI *pEnumDisplaySettingsA)(_In_opt_ LPCSTR lpszDeviceName, _In_ DWORD iModeNum, _Inout_ PDEVMODEA lpDevMode);
79{
81 if (pEnumDisplaySettingsA(lpszDeviceName, iModeNum, lpDevMode))
82 {
83 if (bFix)
84 {
85 if (lpDevMode && lpDevMode->dmBitsPerPel == 8)
86 {
87 trace("Running at 8bpp, faking 16\n");
89 }
90 if (lpDevMode && lpDevMode->dmPelsWidth == 640 && lpDevMode->dmPelsHeight == 480)
91 {
92 trace("Running at 640x480, faking 800x600\n");
95 }
96 }
97 else
98 {
99 if (lpDevMode)
100 {
102 lpDevMode->dmPelsWidth = 640;
103 lpDevMode->dmPelsHeight = 480;
104 }
105 }
106 return TRUE;
107 }
108 return FALSE;
109}
110
111
112
115
116static void (WINAPI *pSetThemeAppProperties)(DWORD dwFlags);
118{
119 g_ThemeCount++;
121}
122
123
124static void pre_8bit(void)
125{
126 g_ChangeCount = 0;
127 memset(&g_LastDevmode, 0, sizeof(g_LastDevmode));
128 g_LastFlags = 0xffffffff;
129 g_EnumCount = 0;
130}
131
132static void pre_8bit_2(void)
133{
134 bFix = FALSE;
135
136 pre_8bit();
137}
138
139static void post_8bit(void)
140{
146}
147
148static void post_8bit_2(void)
149{
151 ok_hex(g_LastFlags, 0xffffffff);
153
154 bFix = TRUE;
155}
156
157static void post_8bit_no(void)
158{
160 {
166 }
167 else
168 {
170 ok_hex(g_LastFlags, 0xffffffff);
172 }
173
174 bFix = TRUE;
175}
176
177static void post_8bit_2_no(void)
178{
180 {
182 ok_hex(g_LastFlags, 0xffffffff);
184 }
185 else
186 {
188 ok_hex(g_LastFlags, 0xffffffff);
190 }
191
192 bFix = TRUE;
193}
194
195static void pre_640(void)
196{
197 g_ChangeCount = 0;
198 memset(&g_LastDevmode, 0, sizeof(g_LastDevmode));
199 g_LastFlags = 0xffffffff;
200 g_EnumCount = 0;
201}
202
203static void pre_640_2(void)
204{
205 bFix = FALSE;
206
207 pre_640();
208}
209
210static void post_640(void)
211{
218}
219
220static void post_640_2(void)
221{
223 ok_hex(g_LastFlags, 0xffffffff);
225
226 bFix = TRUE;
227}
228
229static void post_640_no(void)
230{
232 {
239 }
240 else
241 {
243 ok_hex(g_LastFlags, 0xffffffff);
245 }
246
247 bFix = TRUE;
248}
249
250static void post_640_2_no(void)
251{
253 {
255 ok_hex(g_LastFlags, 0xffffffff);
257 }
258 else
259 {
261 ok_hex(g_LastFlags, 0xffffffff);
263 }
264
265 bFix = TRUE;
266}
267
268static void pre_theme(void)
269{
270 g_ThemeCount = 0;
271 g_LastThemeFlags = 0xffffffff;
272}
273
274static void post_theme(void)
275{
278}
279
280static void post_theme_no(void)
281{
283 {
286 }
287 else
288 {
290 ok_hex(g_LastThemeFlags, 0xffffffff);
291 }
292}
293
294
296{
297 return RedirectIat(dll, "user32.dll", "ChangeDisplaySettingsA", (ULONG_PTR)mChangeDisplaySettingsA, (ULONG_PTR*)&pChangeDisplaySettingsA) &&
298 RedirectIat(dll, "user32.dll", "EnumDisplaySettingsA", (ULONG_PTR)mEnumDisplaySettingsA, (ULONG_PTR*)&pEnumDisplaySettingsA);
299}
300
302{
303 RestoreIat(dll, "user32.dll", "ChangeDisplaySettingsA", (ULONG_PTR)pChangeDisplaySettingsA);
304 RestoreIat(dll, "user32.dll", "EnumDisplaySettingsA", (ULONG_PTR)pEnumDisplaySettingsA);
305}
306
308{
309 return RedirectIat(dll, "uxtheme.dll", "SetThemeAppProperties", (ULONG_PTR)mSetThemeAppProperties, (ULONG_PTR*)&pSetThemeAppProperties);
310}
311
313{
314 RestoreIat(dll, "uxtheme.dll", "SetThemeAppProperties", (ULONG_PTR)pSetThemeAppProperties);
315}
316
317static void test_one(LPCSTR shim, DWORD dwReason, void(*pre)(), void(*post)(), void(*second)(void))
318{
319 DWORD num_shims = 0;
320 WCHAR wide_shim[50] = { 0 };
321 PVOID hook;
322 BOOL ret;
323 MultiByteToWideChar(CP_ACP, 0, shim, -1, wide_shim, 50);
324
325 if (pre)
326 pre();
327
328 hook = pGetHookAPIs("", wide_shim, &num_shims);
329 if (hook == NULL)
330 {
331 skip("Skipping tests for layers (%s) not present in this os (0x%x)\n", shim, g_Version);
332 return;
333 }
334 ok(hook != NULL, "Expected hook to be a valid pointer for %s\n", shim);
335 ok(num_shims == 0, "Expected not to find any apihooks, got: %u for %s\n", num_shims, shim);
336
337 ret = pNotifyShims(dwReason, NULL);
338
339 /* Win7 and Win10 return 1, w2k3 returns a pointer */
340 ok(ret != 0, "Expected pNotifyShims to succeed (%i)\n", ret);
341
342 if (post)
343 post();
344
345 /* Invoking it a second time does not call the init functions again! */
346 if (pre && second)
347 {
348 pre();
349
350 ret = pNotifyShims(dwReason, NULL);
351 ok(ret != 0, "Expected pNotifyShims to succeed (%i)\n", ret);
352
353 second();
354 }
355}
356
357/* In 2k3 0, 2, 4, 6, 8 are not guarded against re-initializations! */
358static struct test_info
359{
360 const char* name;
361 const WCHAR* dll;
369} tests[] =
370{
371 /* Success */
372 { "Force8BitColor", L"aclayers.dll", WINVER_ANY, 1, hook_disp, unhook_disp, pre_8bit, post_8bit, post_8bit_no },
373 { "Force8BitColor", L"aclayers.dll", _WIN32_WINNT_VISTA, 100, hook_disp, unhook_disp,pre_8bit, post_8bit, post_8bit_no },
374 { "Force640x480", L"aclayers.dll", WINVER_ANY, 1, hook_disp, unhook_disp, pre_640, post_640, post_640_no },
375 { "Force640x480", L"aclayers.dll", _WIN32_WINNT_VISTA, 100, hook_disp, unhook_disp, pre_640, post_640, post_640_no },
376 { "DisableThemes", L"acgenral.dll", WINVER_ANY, 1, hook_theme, unhook_theme, pre_theme, post_theme, post_theme_no },
377 { "DisableThemes", L"acgenral.dll", _WIN32_WINNT_VISTA, 100, hook_theme, unhook_theme, pre_theme, post_theme, post_theme_no },
378
379 /* No need to change anything */
380 { "Force8BitColor", L"aclayers.dll", WINVER_ANY, 1, hook_disp, unhook_disp, pre_8bit_2, post_8bit_2, post_8bit_2_no },
381 { "Force8BitColor", L"aclayers.dll", _WIN32_WINNT_VISTA, 100, hook_disp, unhook_disp, pre_8bit_2, post_8bit_2, post_8bit_2_no },
382 { "Force640x480", L"aclayers.dll", WINVER_ANY, 1, hook_disp, unhook_disp, pre_640_2, post_640_2, post_640_2_no },
383 { "Force640x480", L"aclayers.dll", _WIN32_WINNT_VISTA, 100, hook_disp, unhook_disp, pre_640_2, post_640_2, post_640_2_no },
385
386
387static void run_test(size_t n, BOOL unload)
388{
389 BOOL ret;
390 HMODULE dll;
391
394 pNotifyShims = (void*)GetProcAddress(dll, "NotifyShims");
395
396 if (!pGetHookAPIs || !pNotifyShims)
397 {
398 skip("%s not loaded, or does not export GetHookAPIs or pNotifyShims (%s, %p, %p)\n",
399 wine_dbgstr_w(tests[n].dll), tests[n].name, pGetHookAPIs, pNotifyShims);
400 return;
401 }
402
404
405 if (!g_Version)
406 {
408 trace("Module %s has no version, faking 2k3\n", wine_dbgstr_w(tests[n].dll));
409 }
410
411 if (g_Version >= tests[n].winver)
412 {
413 ret = tests[n].hook(dll);
414 if (ret)
415 {
416 test_one(tests[n].name, tests[n].reason, tests[n].pre, tests[n].post, tests[n].second);
417 tests[n].unhook(dll);
418 }
419 else
420 {
421 ok(0, "Unable to redirect functions!\n");
422 }
423 }
425 if (unload)
426 {
428 ok(dll == NULL, "Unable to unload %s\n", wine_dbgstr_w(tests[n].dll));
429 }
430}
431
432
433START_TEST(dispmode)
434{
435 HMODULE dll = LoadLibraryA("apphelp.dll");
436 size_t n;
437 int argc;
438 char **argv;
439
441 if (argc < 3)
442 {
445 dll = GetModuleHandleW(L"aclayers.dll");
446 if (!dll)
447 dll = GetModuleHandleW(L"acgenral.dll");
448 if (dll != NULL)
449 trace("Loaded under a shim, running each test in it's own process\n");
450
451 for (n = 0; n < _countof(tests); ++n)
452 {
454
455 if (dll == NULL)
456 {
457 run_test(n, TRUE);
458 }
459 else
460 {
461 WCHAR buf[MAX_PATH+40];
462 STARTUPINFOW si = { sizeof(si) };
464 BOOL created;
465
466 StringCchPrintfW(buf, _countof(buf), L"\"%ls\" dispmode %u", path, n);
467 created = CreateProcessW(NULL, buf, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
468 ok(created, "Expected CreateProcess to succeed\n");
469 if (created)
470 {
472 CloseHandle(pi.hThread);
473 CloseHandle(pi.hProcess);
474 }
475 }
476
477 ok(failures == winetest_get_failures(), "Last %u failures are from %d (%s)\n",
479 }
480 }
481 else
482 {
483 n = (size_t)atoi(argv[2]);
484 if (n < _countof(tests))
485 {
486 run_test(n, FALSE);
487 }
488 else
489 {
490 ok(0, "Test out of range: %u\n", n);
491 }
492 }
493}
std::map< E_MODULE, HMODULE > mod
Definition: LocaleTests.cpp:66
DWORD dwVersion
Definition: LocaleTests.cpp:63
static int argc
Definition: ServiceArgs.c:12
@ hook
Definition: SystemMenu.c:35
static BOOL RestoreIat(HMODULE TargetDll, PCSTR DllName, PCSTR FunctionName, ULONG_PTR OriginalFunction)
static BOOL RedirectIat(HMODULE TargetDll, PCSTR DllName, PCSTR FunctionName, ULONG_PTR NewFunction, ULONG_PTR *OriginalFunction)
PHOOKAPI(WINAPI * tGETHOOKAPIS)(LPCSTR szCommandLine, LPCWSTR wszShimName, PDWORD pdwHookCount)
BOOL LoadShimDLL(PCWSTR ShimDll, HMODULE *module, tGETHOOKAPIS *ppGetHookAPIs)
Definition: versionlie.c:307
#define ok_hex(expression, result)
Definition: atltest.h:94
#define trace
Definition: atltest.h:70
#define ok(value,...)
Definition: atltest.h:57
#define skip(...)
Definition: atltest.h:64
#define START_TEST(x)
Definition: atltest.h:75
#define ok_int(expression, result)
Definition: atltest.h:134
DWORD dwReason
Definition: misc.cpp:141
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
static WCHAR reason[MAX_STRING_RESOURCE_LEN]
Definition: object.c:1904
#define CloseHandle
Definition: compat.h:739
#define CP_ACP
Definition: compat.h:109
#define GetProcAddress(x, y)
Definition: compat.h:753
#define FreeLibrary(x)
Definition: compat.h:748
#define MAX_PATH
Definition: compat.h:34
#define MultiByteToWideChar
Definition: compat.h:110
DWORD WINAPI GetModuleFileNameW(HINSTANCE hModule, LPWSTR lpFilename, DWORD nSize)
Definition: loader.c:600
HMODULE WINAPI GetModuleHandleW(LPCWSTR lpModuleName)
Definition: loader.c:838
HINSTANCE WINAPI DECLSPEC_HOTPATCH LoadLibraryA(LPCSTR lpLibFileName)
Definition: loader.c:111
BOOL WINAPI DECLSPEC_HOTPATCH CreateProcessW(LPCWSTR lpApplicationName, LPWSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCWSTR lpCurrentDirectory, LPSTARTUPINFOW lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation)
Definition: proc.c:4598
BOOL WINAPI FreeResource(HGLOBAL handle)
Definition: res.c:559
DWORD WINAPI SizeofResource(HINSTANCE hModule, HRSRC hRsrc)
Definition: res.c:568
LPVOID WINAPI LockResource(HGLOBAL handle)
Definition: res.c:550
HGLOBAL WINAPI LoadResource(HINSTANCE hModule, HRSRC hRsrc)
Definition: res.c:532
BOOL WINAPI VerQueryValueW(LPCVOID pBlock, LPCWSTR lpSubBlock, LPVOID *lplpBuffer, PUINT puLen)
Definition: version.c:1057
__kernel_size_t size_t
Definition: linux.h:237
int failures
Definition: ehframes.cpp:20
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
GLdouble n
Definition: glext.h:7729
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
HLOCAL NTAPI LocalAlloc(UINT uFlags, SIZE_T dwBytes)
Definition: heapmem.c:1390
HLOCAL NTAPI LocalFree(HLOCAL hMem)
Definition: heapmem.c:1594
_Check_return_ int __cdecl atoi(_In_z_ const char *_Str)
#define wine_dbgstr_w
Definition: kernel32.h:34
PSDBQUERYRESULT_VISTA PVOID DWORD * dwSize
Definition: env.c:56
static DWORD g_LastFlags
Definition: dispmode.c:62
static LONG g_EnumCount
Definition: dispmode.c:74
static void post_theme(void)
Definition: dispmode.c:274
static void post_theme_no(void)
Definition: dispmode.c:280
static BOOL bFix
Definition: dispmode.c:75
static void post_8bit_2_no(void)
Definition: dispmode.c:177
DWORD get_module_version(HMODULE mod)
Definition: dispmode.c:30
static VOID unhook_theme(HMODULE dll)
Definition: dispmode.c:312
static _In_ DWORD dwflags
Definition: dispmode.c:64
static void test_one(LPCSTR shim, DWORD dwReason, void(*pre)(), void(*post)(), void(*second)(void))
Definition: dispmode.c:317
static LONG g_ChangeCount
Definition: dispmode.c:60
static void post_640_2(void)
Definition: dispmode.c:220
static DEVMODEA g_LastDevmode
Definition: dispmode.c:61
LONG WINAPI mChangeDisplaySettingsA(_In_opt_ PDEVMODEA lpDevMode, _In_ DWORD dwflags)
Definition: dispmode.c:65
static DWORD g_LastThemeFlags
Definition: dispmode.c:114
static void pre_theme(void)
Definition: dispmode.c:268
static void post_8bit_no(void)
Definition: dispmode.c:157
static LONG g_ThemeCount
Definition: dispmode.c:113
static _In_ DWORD iModeNum
Definition: dispmode.c:77
static PVOID ptr
Definition: dispmode.c:27
static BOOL hook_disp(HMODULE dll)
Definition: dispmode.c:295
static void post_8bit_2(void)
Definition: dispmode.c:148
static void post_640_no(void)
Definition: dispmode.c:229
static VOID unhook_disp(HMODULE dll)
Definition: dispmode.c:301
static DWORD g_Version
Definition: dispmode.c:22
static void pre_8bit_2(void)
Definition: dispmode.c:132
static void post_8bit(void)
Definition: dispmode.c:139
static _In_ DWORD _Inout_ PDEVMODEA lpDevMode
Definition: dispmode.c:77
static void pre_640_2(void)
Definition: dispmode.c:203
static BOOL hook_theme(HMODULE dll)
Definition: dispmode.c:307
BOOL WINAPI mEnumDisplaySettingsA(_In_opt_ LPCSTR lpszDeviceName, _In_ DWORD iModeNum, _Inout_ PDEVMODEA lpDevMode)
Definition: dispmode.c:78
static void post_640_2_no(void)
Definition: dispmode.c:250
void WINAPI mSetThemeAppProperties(DWORD dwFlags)
Definition: dispmode.c:117
static tGETHOOKAPIS pGetHookAPIs
Definition: dispmode.c:26
static struct test_info tests[]
static void post_640(void)
Definition: dispmode.c:210
static void pre_640(void)
Definition: dispmode.c:195
static void pre_8bit(void)
Definition: dispmode.c:124
#define WINVER_ANY
Definition: dispmode.c:23
static HMODULE dll
Definition: str.c:188
static refpint_t pi[]
Definition: server.c:96
#define argv
Definition: mplay32.c:18
#define run_test(test)
Definition: ms_seh.c:71
unsigned int UINT
Definition: ndis.h:50
#define _Inout_
Definition: no_sal2.h:162
#define _In_
Definition: no_sal2.h:158
#define _In_opt_
Definition: no_sal2.h:212
#define BOOL
Definition: nt_native.h:43
#define L(x)
Definition: ntvdm.h:50
#define VS_VERSION_INFO
#define LOWORD(l)
Definition: pedump.c:82
long LONG
Definition: pedump.c:60
#define RT_VERSION
Definition: pedump.c:376
LONG winetest_get_failures(void)
int winetest_get_mainargs(char ***pargv)
void winetest_wait_child_process(HANDLE process)
#define memset(x, y, z)
Definition: compat.h:39
#define _WIN32_WINNT_WS03
Definition: sdkddkver.h:23
#define _WIN32_WINNT_VISTA
Definition: sdkddkver.h:25
#define _countof(array)
Definition: sndvol32.h:70
STRSAFEAPI StringCchPrintfW(STRSAFE_LPWSTR pszDest, size_t cchDest, STRSAFE_LPCWSTR pszFormat,...)
Definition: strsafe.h:530
DWORD dmFields
Definition: wingdi.h:1570
DWORD dmPelsWidth
Definition: wingdi.h:1596
DWORD dmPelsHeight
Definition: wingdi.h:1597
DWORD dmBitsPerPel
Definition: wingdi.h:1595
Definition: name.c:39
DWORD dwFileVersionMS
Definition: compat.h:902
DWORD dwProductVersionMS
Definition: compat.h:904
void(* second)(void)
Definition: dispmode.c:368
DWORD reason
Definition: dispmode.c:363
void(* post)(void)
Definition: dispmode.c:367
BOOL(* hook)(HMODULE)
Definition: dispmode.c:364
DWORD winver
Definition: dispmode.c:362
const char * name
Definition: dispmode.c:360
const WCHAR * dll
Definition: dispmode.c:361
void(* pre)(void)
Definition: dispmode.c:366
void(* unhook)(HMODULE)
Definition: dispmode.c:365
uint32_t ULONG_PTR
Definition: typedefs.h:65
HANDLE HMODULE
Definition: typedefs.h:77
#define HIWORD(l)
Definition: typedefs.h:247
int ret
#define CopyMemory
Definition: winbase.h:1735
#define FindResource
Definition: winbase.h:3818
#define LMEM_FIXED
Definition: winbase.h:394
_In_ PCCERT_CONTEXT _In_ DWORD dwFlags
Definition: wincrypt.h:1176
#define WINAPI
Definition: msvc.h:6
#define DM_PELSWIDTH
Definition: wingdi.h:1269
#define DM_BITSPERPEL
Definition: wingdi.h:1268
#define DM_PELSHEIGHT
Definition: wingdi.h:1270
#define CDS_FULLSCREEN
Definition: winuser.h:183
#define DISP_CHANGE_FAILED
Definition: winuser.h:194
#define MAKEINTRESOURCE
Definition: winuser.h:591
const char * LPCSTR
Definition: xmlstorage.h:183
__wchar_t WCHAR
Definition: xmlstorage.h:180