2 * Copyright 2015 Mark Jansen
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 #define WIN32_NO_STATUS
28 #include "wine/test.h"
30 typedef struct tagHOOKAPI
{
33 PVOID ReplacementFunction
;
34 PVOID OriginalFunction
;
39 static BOOL (WINAPI
* pSdbGetAppPatchDir
)(PVOID
,LPWSTR
,DWORD
);
40 static PHOOKAPI (WINAPI
* pGetHookAPIs
)(LPCSTR
,LPCWSTR
,PDWORD
);
43 static DWORD g_WinVersion
;
44 #define WINVER_WINXP 0x0501
47 typedef struct VersionLieInfo
54 WORD wServicePackMajor
;
55 WORD wServicePackMinor
;
58 typedef BOOL(WINAPI
* GETVERSIONEXAPROC
)(LPOSVERSIONINFOEXA
);
59 typedef BOOL(WINAPI
* GETVERSIONEXWPROC
)(LPOSVERSIONINFOEXW
);
60 typedef DWORD(WINAPI
* GETVERSIONPROC
)(void);
62 static void expect_shim_imp(PHOOKAPI hook
, PCSTR library
, PCSTR function
, PCSTR shim
, int* same
)
64 int lib
= lstrcmpA(library
, hook
->LibraryName
);
65 int fn
= lstrcmpA(function
, hook
->FunctionName
);
66 winetest_ok(lib
== 0, "Expected LibrarayName to be %s, was: %s for %s\n", library
, hook
->LibraryName
, shim
);
67 winetest_ok(fn
== 0, "Expected FunctionName to be %s, was: %s for %s\n", function
, hook
->FunctionName
, shim
);
68 *same
= (lib
== 0 && fn
== 0);
71 static void verify_shima_imp(PHOOKAPI hook
, const VersionLieInfo
* info
, PCSTR shim
, int same
)
73 OSVERSIONINFOEXA v1
= { sizeof(v1
), 0 }, v2
= { sizeof(v2
), 0 };
78 skip("Skipping implementation tests for %s\n", shim
);
82 while (v1
.dwOSVersionInfoSize
)
84 ok1
= GetVersionExA((LPOSVERSIONINFOA
)&v1
), ok2
;
85 hook
->OriginalFunction
= GetVersionExA
;
87 ok2
= ((GETVERSIONEXAPROC
)hook
->ReplacementFunction
)(&v2
);
89 winetest_ok(ok1
== ok2
, "Expected ok1 to equal ok2, was: %i, %i for %s\n", ok1
, ok2
, shim
);
92 char szCSDVersion
[128] = "";
93 winetest_ok(v1
.dwOSVersionInfoSize
== v2
.dwOSVersionInfoSize
, "Expected dwOSVersionInfoSize to be equal, was: %u, %u for %s\n", v1
.dwOSVersionInfoSize
, v2
.dwOSVersionInfoSize
, shim
);
94 winetest_ok(info
->dwMajorVersion
== v2
.dwMajorVersion
, "Expected dwMajorVersion to be equal, was: %u, %u for %s\n", info
->dwMajorVersion
, v2
.dwMajorVersion
, shim
);
95 winetest_ok(info
->dwMinorVersion
== v2
.dwMinorVersion
, "Expected dwMinorVersion to be equal, was: %u, %u for %s\n", info
->dwMinorVersion
, v2
.dwMinorVersion
, shim
);
96 winetest_ok(info
->dwBuildNumber
== v2
.dwBuildNumber
, "Expected dwBuildNumber to be equal, was: %u, %u for %s\n", info
->dwBuildNumber
, v2
.dwBuildNumber
, shim
);
97 winetest_ok(info
->dwPlatformId
== v2
.dwPlatformId
, "Expected dwPlatformId to be equal, was: %u, %u for %s\n", info
->dwPlatformId
, v2
.dwPlatformId
, shim
);
99 if (info
->wServicePackMajor
)
100 sprintf(szCSDVersion
, "Service Pack %u", info
->wServicePackMajor
);
101 winetest_ok(lstrcmpA(szCSDVersion
, v2
.szCSDVersion
) == 0, "Expected szCSDVersion to be equal, was: %s, %s for %s\n", szCSDVersion
, v2
.szCSDVersion
, shim
);
103 if (v1
.dwOSVersionInfoSize
== sizeof(OSVERSIONINFOEXA
))
105 if (info
->dwPlatformId
!= VER_PLATFORM_WIN32_WINDOWS
)
107 winetest_ok(info
->wServicePackMajor
== v2
.wServicePackMajor
, "Expected wServicePackMajor to be equal, was: %i, %i for %s\n", info
->wServicePackMajor
, v2
.wServicePackMajor
, shim
);
108 winetest_ok(info
->wServicePackMinor
== v2
.wServicePackMinor
, "Expected wServicePackMinor to be equal, was: %i, %i for %s\n", info
->wServicePackMinor
, v2
.wServicePackMinor
, shim
);
112 winetest_ok(v1
.wServicePackMajor
== v2
.wServicePackMajor
, "Expected wServicePackMajor to be equal, was: %i, %i for %s\n", v1
.wServicePackMajor
, v2
.wServicePackMajor
, shim
);
113 winetest_ok(v1
.wServicePackMinor
== v2
.wServicePackMinor
, "Expected wServicePackMinor to be equal, was: %i, %i for %s\n", v1
.wServicePackMinor
, v2
.wServicePackMinor
, shim
);
115 winetest_ok(v1
.wSuiteMask
== v2
.wSuiteMask
, "Expected wSuiteMask to be equal, was: %i, %i for %s\n", v1
.wSuiteMask
, v2
.wSuiteMask
, shim
);
116 winetest_ok(v1
.wProductType
== v2
.wProductType
, "Expected wProductType to be equal, was: %i, %i for %s\n", v1
.wProductType
, v2
.wProductType
, shim
);
117 winetest_ok(v1
.wReserved
== v2
.wReserved
, "Expected wReserved to be equal, was: %i, %i for %s\n", v1
.wReserved
, v2
.wReserved
, shim
);
121 winetest_ok(v1
.wServicePackMajor
== 0 && v2
.wServicePackMajor
== 0, "Expected wServicePackMajor to be 0, was: %i, %i for %s\n", v1
.wServicePackMajor
, v2
.wServicePackMajor
, shim
);
122 winetest_ok(v1
.wServicePackMinor
== 0 && v2
.wServicePackMinor
== 0, "Expected wServicePackMinor to be 0, was: %i, %i for %s\n", v1
.wServicePackMinor
, v2
.wServicePackMinor
, shim
);
123 winetest_ok(v1
.wSuiteMask
== 0 && v2
.wSuiteMask
== 0, "Expected wSuiteMask to be 0, was: %i, %i for %s\n", v1
.wSuiteMask
, v2
.wSuiteMask
, shim
);
124 winetest_ok(v1
.wProductType
== 0 && v2
.wProductType
== 0, "Expected wProductType to be 0, was: %i, %i for %s\n", v1
.wProductType
, v2
.wProductType
, shim
);
125 winetest_ok(v1
.wReserved
== 0 && v2
.wReserved
== 0, "Expected wReserved to be 0, was: %i, %i for %s\n", v1
.wReserved
, v2
.wReserved
, shim
);
129 ZeroMemory(&v1
, sizeof(v1
));
130 ZeroMemory(&v2
, sizeof(v2
));
131 if (v1
.dwOSVersionInfoSize
== sizeof(OSVERSIONINFOEXA
))
132 v1
.dwOSVersionInfoSize
= v2
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFOA
);
136 static void verify_shimw_imp(PHOOKAPI hook
, const VersionLieInfo
* info
, PCSTR shim
, int same
, int first_might_be_broken
)
138 OSVERSIONINFOEXW v1
= { sizeof(v1
), 0 }, v2
= { sizeof(v2
), 0 };
139 BOOL ok1
, ok2
, first
= TRUE
;
143 skip("Skipping implementation tests for %s\n", shim
);
147 while (v1
.dwOSVersionInfoSize
)
149 ok1
= GetVersionExW((LPOSVERSIONINFOW
)&v1
), ok2
;
150 hook
->OriginalFunction
= GetVersionExW
;
152 ok2
= ((GETVERSIONEXWPROC
)hook
->ReplacementFunction
)(&v2
);
154 if (first_might_be_broken
&& first
&& ok1
== TRUE
&& ok2
== FALSE
)
156 skip("Skipping first check because 0x%x is (falsely) not accepted by the shim %s\n", sizeof(v1
), shim
);
160 winetest_ok(ok1
== ok2
, "Expected ok1 to equal ok2, was: %i, %i for %s(first:%d)\n", ok1
, ok2
, shim
, first
);
164 static const WCHAR szCSDFMT
[] = {'S','e','r','v','i','c','e',' ','P','a','c','k',' ','%','u',0};
165 WCHAR szCSDVersion
[128] = { 0 };
166 winetest_ok(v1
.dwOSVersionInfoSize
== v2
.dwOSVersionInfoSize
, "Expected dwOSVersionInfoSize to be equal, was: %u, %u for %s\n", v1
.dwOSVersionInfoSize
, v2
.dwOSVersionInfoSize
, shim
);
167 winetest_ok(info
->dwMajorVersion
== v2
.dwMajorVersion
, "Expected dwMajorVersion to be equal, was: %u, %u for %s\n", info
->dwMajorVersion
, v2
.dwMajorVersion
, shim
);
168 winetest_ok(info
->dwMinorVersion
== v2
.dwMinorVersion
, "Expected dwMinorVersion to be equal, was: %u, %u for %s\n", info
->dwMinorVersion
, v2
.dwMinorVersion
, shim
);
169 winetest_ok(info
->dwBuildNumber
== v2
.dwBuildNumber
, "Expected dwBuildNumber to be equal, was: %u, %u for %s\n", info
->dwBuildNumber
, v2
.dwBuildNumber
, shim
);
170 winetest_ok(info
->dwPlatformId
== v2
.dwPlatformId
, "Expected dwPlatformId to be equal, was: %u, %u for %s\n", info
->dwPlatformId
, v2
.dwPlatformId
, shim
);
172 if (info
->wServicePackMajor
)
173 swprintf(szCSDVersion
, szCSDFMT
, info
->wServicePackMajor
);
174 winetest_ok(lstrcmpW(szCSDVersion
, v2
.szCSDVersion
) == 0, "Expected szCSDVersion to be equal, was: %s, %s for %s\n", wine_dbgstr_w(szCSDVersion
), wine_dbgstr_w(v2
.szCSDVersion
), shim
);
176 if (v1
.dwOSVersionInfoSize
== sizeof(OSVERSIONINFOEXW
))
178 if (info
->dwPlatformId
!= VER_PLATFORM_WIN32_WINDOWS
)
180 winetest_ok(info
->wServicePackMajor
== v2
.wServicePackMajor
, "Expected wServicePackMajor to be equal, was: %i, %i for %s\n", info
->wServicePackMajor
, v2
.wServicePackMajor
, shim
);
181 winetest_ok(info
->wServicePackMinor
== v2
.wServicePackMinor
, "Expected wServicePackMinor to be equal, was: %i, %i for %s\n", info
->wServicePackMinor
, v2
.wServicePackMinor
, shim
);
185 winetest_ok(v1
.wServicePackMajor
== v2
.wServicePackMajor
, "Expected wServicePackMajor to be equal, was: %i, %i for %s\n", v1
.wServicePackMajor
, v2
.wServicePackMajor
, shim
);
186 winetest_ok(v1
.wServicePackMinor
== v2
.wServicePackMinor
, "Expected wServicePackMinor to be equal, was: %i, %i for %s\n", v1
.wServicePackMinor
, v2
.wServicePackMinor
, shim
);
188 winetest_ok(v1
.wSuiteMask
== v2
.wSuiteMask
, "Expected wSuiteMask to be equal, was: %i, %i for %s\n", v1
.wSuiteMask
, v2
.wSuiteMask
, shim
);
189 winetest_ok(v1
.wProductType
== v2
.wProductType
, "Expected wProductType to be equal, was: %i, %i for %s\n", v1
.wProductType
, v2
.wProductType
, shim
);
190 winetest_ok(v1
.wReserved
== v2
.wReserved
, "Expected wReserved to be equal, was: %i, %i for %s\n", v1
.wReserved
, v2
.wReserved
, shim
);
194 winetest_ok(v1
.wServicePackMajor
== 0 && v2
.wServicePackMajor
== 0, "Expected wServicePackMajor to be 0, was: %i, %i for %s\n", v1
.wServicePackMajor
, v2
.wServicePackMajor
, shim
);
195 winetest_ok(v1
.wServicePackMinor
== 0 && v2
.wServicePackMinor
== 0, "Expected wServicePackMinor to be 0, was: %i, %i for %s\n", v1
.wServicePackMinor
, v2
.wServicePackMinor
, shim
);
196 winetest_ok(v1
.wSuiteMask
== 0 && v2
.wSuiteMask
== 0, "Expected wSuiteMask to be 0, was: %i, %i for %s\n", v1
.wSuiteMask
, v2
.wSuiteMask
, shim
);
197 winetest_ok(v1
.wProductType
== 0 && v2
.wProductType
== 0, "Expected wProductType to be 0, was: %i, %i for %s\n", v1
.wProductType
, v2
.wProductType
, shim
);
198 winetest_ok(v1
.wReserved
== 0 && v2
.wReserved
== 0, "Expected wReserved to be 0, was: %i, %i for %s\n", v1
.wReserved
, v2
.wReserved
, shim
);
202 ZeroMemory(&v1
, sizeof(v1
));
203 ZeroMemory(&v2
, sizeof(v2
));
204 if (v1
.dwOSVersionInfoSize
== sizeof(OSVERSIONINFOEXW
))
205 v1
.dwOSVersionInfoSize
= v2
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFOW
);
210 static void verify_shim_imp(PHOOKAPI hook
, const VersionLieInfo
* info
, PCSTR shim
, int same
)
215 skip("Skipping implementation tests for %s\n", shim
);
218 ver
= ((GETVERSIONPROC
)hook
->ReplacementFunction
)();
219 winetest_ok(info
->FullVersion
== ver
, "Expected GetVersion to return %u, was: %u for %s\n", info
->FullVersion
, ver
, shim
);
223 #define expect_shim (winetest_set_location(__FILE__, __LINE__), 0) ? (void)0 : expect_shim_imp
224 #define verify_shima (winetest_set_location(__FILE__, __LINE__), 0) ? (void)0 : verify_shima_imp
225 #define verify_shimw (winetest_set_location(__FILE__, __LINE__), 0) ? (void)0 : verify_shimw_imp
226 #define verify_shim (winetest_set_location(__FILE__, __LINE__), 0) ? (void)0 : verify_shim_imp
231 static void run_test(LPCSTR shim
, const VersionLieInfo
* info
)
234 WCHAR wide_shim
[50] = { 0 };
237 MultiByteToWideChar(CP_ACP
, 0, shim
, -1, wide_shim
, 50);
238 hook
= pGetHookAPIs("", wide_shim
, &num_shims
);
239 ver
= (info
->dwMajorVersion
<< 8) | info
->dwMinorVersion
;
242 skip("Skipping tests for layers (%s) not present in this os (0x%x)\n", shim
, g_WinVersion
);
245 ok(hook
!= NULL
, "Expected hook to be a valid pointer for %s\n", shim
);
246 if (info
->dwPlatformId
== VER_PLATFORM_WIN32_WINDOWS
)
248 ok(num_shims
== 3, "Expected num_shims to be 3, was: %u for %s\n", num_shims
, shim
);
249 if (hook
&& num_shims
== 3)
251 int off
= info
->dwBuildNumber
== 0x040A08AE ? 0 : 1, same
= 0;
252 expect_shim(hook
+ ((0+off
)%3), "KERNEL32.DLL", "GetVersionExA", shim
, &same
);
253 verify_shima(hook
+ ((0+off
)%3), info
, shim
, same
);
254 expect_shim(hook
+ ((1+off
)%3), "KERNEL32.DLL", "GetVersionExW", shim
, &same
);
255 verify_shimw(hook
+ ((1+off
)%3), info
, shim
, same
, 0);
256 expect_shim(hook
+ ((2+off
)%3), "KERNEL32.DLL", "GetVersion", shim
, &same
);
257 verify_shim(hook
+ ((2+off
)%3), info
, shim
, same
);
262 int shimnum_ok
= num_shims
== 4 || ((ver
< WINVER_WINXP
) && (num_shims
== 3));
263 ok(shimnum_ok
, "Expected num_shims to be 4%s, was: %u for %s\n", ((ver
< WINVER_WINXP
) ? " or 3":""), num_shims
, shim
);
264 if (hook
&& shimnum_ok
)
267 expect_shim(hook
+ 0, "KERNEL32.DLL", "GetVersionExA", shim
, &same
);
268 verify_shima(hook
+ 0, info
, shim
, same
);
269 expect_shim(hook
+ 1, "KERNEL32.DLL", "GetVersionExW", shim
, &same
);
270 verify_shimw(hook
+ 1, info
, shim
, same
, 0);
271 expect_shim(hook
+ 2, "KERNEL32.DLL", "GetVersion", shim
, &same
);
272 verify_shim(hook
+ 2, info
, shim
, same
);
275 expect_shim(hook
+ 3, "NTDLL.DLL", "RtlGetVersion", shim
, &same
);
276 verify_shimw(hook
+ 3, info
, shim
, same
, 1);
282 static void hookless_shim(LPCSTR shim
)
285 WCHAR wide_shim
[50] = { 0 };
287 MultiByteToWideChar(CP_ACP
, 0, shim
, -1, wide_shim
, 50);
288 hook
= pGetHookAPIs("", wide_shim
, &num_shims
);
291 skip("Skipping tests for layers (%s) not present in this os (0x%x)\n", shim
, g_WinVersion
);
294 ok(hook
!= NULL
, "Expected hook to be a valid pointer for %s\n", shim
);
295 ok(num_shims
== 0, "Expected not to find any apihooks, got: %u for %s\n", num_shims
, shim
);
298 VersionLieInfo g_Win95
= { 0xC3B60004, 4, 0, 950, VER_PLATFORM_WIN32_WINDOWS
, 0, 0 };
299 VersionLieInfo g_WinNT4SP5
= { 0x05650004, 4, 0, 1381, VER_PLATFORM_WIN32_NT
, 5, 0 };
300 VersionLieInfo g_Win98
= { 0xC0000A04, 4, 10, 0x040A08AE, VER_PLATFORM_WIN32_WINDOWS
, 0, 0 };
302 VersionLieInfo g_Win2000
= { 0x08930005, 5, 0, 2195, VER_PLATFORM_WIN32_NT
, 0, 0 };
303 VersionLieInfo g_Win2000SP1
= { 0x08930005, 5, 0, 2195, VER_PLATFORM_WIN32_NT
, 1, 0 };
304 VersionLieInfo g_Win2000SP2
= { 0x08930005, 5, 0, 2195, VER_PLATFORM_WIN32_NT
, 2, 0 };
305 VersionLieInfo g_Win2000SP3
= { 0x08930005, 5, 0, 2195, VER_PLATFORM_WIN32_NT
, 3, 0 };
307 VersionLieInfo g_WinXP
= { 0x0a280105, 5, 1, 2600, VER_PLATFORM_WIN32_NT
, 0, 0 };
308 VersionLieInfo g_WinXPSP1
= { 0x0a280105, 5, 1, 2600, VER_PLATFORM_WIN32_NT
, 1, 0 };
309 VersionLieInfo g_WinXPSP2
= { 0x0a280105, 5, 1, 2600, VER_PLATFORM_WIN32_NT
, 2, 0 };
310 VersionLieInfo g_WinXPSP3
= { 0x0a280105, 5, 1, 2600, VER_PLATFORM_WIN32_NT
, 3, 0 };
312 VersionLieInfo g_Win2k3RTM
= { 0x0ece0205, 5, 2, 3790, VER_PLATFORM_WIN32_NT
, 0, 0 };
313 VersionLieInfo g_Win2k3SP1
= { 0x0ece0205, 5, 2, 3790, VER_PLATFORM_WIN32_NT
, 1, 0 };
315 VersionLieInfo g_WinVistaRTM
= { 0x17700006, 6, 0, 6000, VER_PLATFORM_WIN32_NT
, 0, 0 };
316 VersionLieInfo g_WinVistaSP1
= { 0x17710006, 6, 0, 6001, VER_PLATFORM_WIN32_NT
, 1, 0 };
317 VersionLieInfo g_WinVistaSP2
= { 0x17720006, 6, 0, 6002, VER_PLATFORM_WIN32_NT
, 2, 0 };
319 VersionLieInfo g_Win7RTM
= { 0x1db00106, 6, 1, 7600, VER_PLATFORM_WIN32_NT
, 0, 0 };
321 DWORD
get_host_winver(void)
323 RTL_OSVERSIONINFOEXW rtlinfo
= {0};
324 void (__stdcall
* pRtlGetVersion
)(RTL_OSVERSIONINFOEXW
*);
325 pRtlGetVersion
= (void (__stdcall
*)(RTL_OSVERSIONINFOEXW
*))GetProcAddress(GetModuleHandleA("ntdll"), "RtlGetVersion");
327 rtlinfo
.dwOSVersionInfoSize
= sizeof(rtlinfo
);
328 pRtlGetVersion(&rtlinfo
);
329 return (rtlinfo
.dwMajorVersion
<< 8) | rtlinfo
.dwMinorVersion
;
332 START_TEST(versionlie
)
334 HMODULE dll
= LoadLibraryA("apphelp.dll");
336 WCHAR aclayers
[] = {'\\','a','c','l','a','y','e','r','s','.','d','l','l',0};
337 pSdbGetAppPatchDir
= (void*)GetProcAddress(dll
, "SdbGetAppPatchDir");
338 if (!pSdbGetAppPatchDir
)
340 skip("apphelp.dll not loaded, or does not export SdbGetAppPatchDir\n");
344 pSdbGetAppPatchDir(NULL
, buf
, MAX_PATH
);
345 lstrcatW(buf
, aclayers
);
346 dll
= LoadLibraryW(buf
);
347 pGetHookAPIs
= (void*)GetProcAddress(dll
, "GetHookAPIs");
351 skip("aclayers.dll not loaded, or does not export GetHookAPIs\n");
354 g_WinVersion
= get_host_winver();
356 run_test("Win95VersionLie", &g_Win95
);
357 run_test("WinNT4SP5VersionLie", &g_WinNT4SP5
);
358 run_test("Win98VersionLie", &g_Win98
);
359 run_test("Win2000VersionLie", &g_Win2000
);
360 run_test("Win2000SP1VersionLie", &g_Win2000SP1
);
361 run_test("Win2000SP2VersionLie", &g_Win2000SP2
);
362 run_test("Win2000SP3VersionLie", &g_Win2000SP3
);
363 run_test("WinXPVersionLie", &g_WinXP
);
364 run_test("WinXPSP1VersionLie", &g_WinXPSP1
);
365 run_test("WinXPSP2VersionLie", &g_WinXPSP2
);
366 run_test("WinXPSP3VersionLie", &g_WinXPSP3
);
367 run_test("Win2k3RTMVersionLie", &g_Win2k3RTM
);
368 run_test("Win2k3SP1VersionLie", &g_Win2k3SP1
);
369 run_test("VistaRTMVersionLie", &g_WinVistaRTM
);
370 run_test("VistaSP1VersionLie", &g_WinVistaSP1
);
371 run_test("VistaSP2VersionLie", &g_WinVistaSP2
);
372 run_test("Win7RTMVersionLie", &g_Win7RTM
);
374 hookless_shim("Force8BitColor");
375 hookless_shim("Force640x480");
376 hookless_shim("DisableThemes");