[SHELL32_APITEST] -Add some tests for SHParseDisplayName for CORE-12882.
[reactos.git] / rostests / apitests / appshim / versionlie.c
1 /*
2 * Copyright 2015 Mark Jansen
3 *
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.
8 *
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.
13 *
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
17 */
18
19 #include <ntstatus.h>
20 #define WIN32_NO_STATUS
21 #include <windows.h>
22 #ifdef __REACTOS__
23 #include <ntndk.h>
24 #else
25 #include <winternl.h>
26 #endif
27 #include <stdio.h>
28 #include "wine/test.h"
29
30 typedef struct tagHOOKAPI {
31 PCSTR LibraryName;
32 PCSTR FunctionName;
33 PVOID ReplacementFunction;
34 PVOID OriginalFunction;
35 PVOID Unk1;
36 PVOID Unk2;
37 } HOOKAPI, *PHOOKAPI;
38
39 static BOOL (WINAPI* pSdbGetAppPatchDir)(PVOID,LPWSTR,DWORD);
40 static PHOOKAPI (WINAPI* pGetHookAPIs)(LPCSTR,LPCWSTR,PDWORD);
41
42
43 static DWORD g_WinVersion;
44 #define WINVER_WINXP 0x0501
45
46
47 typedef struct VersionLieInfo
48 {
49 DWORD FullVersion;
50 DWORD dwMajorVersion;
51 DWORD dwMinorVersion;
52 DWORD dwBuildNumber;
53 DWORD dwPlatformId;
54 WORD wServicePackMajor;
55 WORD wServicePackMinor;
56 } VersionLieInfo;
57
58 typedef BOOL(WINAPI* GETVERSIONEXAPROC)(LPOSVERSIONINFOEXA);
59 typedef BOOL(WINAPI* GETVERSIONEXWPROC)(LPOSVERSIONINFOEXW);
60 typedef DWORD(WINAPI* GETVERSIONPROC)(void);
61
62 static void expect_shim_imp(PHOOKAPI hook, PCSTR library, PCSTR function, PCSTR shim, int* same)
63 {
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);
69 }
70
71 static void verify_shima_imp(PHOOKAPI hook, const VersionLieInfo* info, PCSTR shim, int same)
72 {
73 OSVERSIONINFOEXA v1 = { sizeof(v1), 0 }, v2 = { sizeof(v2), 0 };
74 BOOL ok1, ok2;
75
76 if (!same)
77 {
78 skip("Skipping implementation tests for %s\n", shim);
79 return;
80 }
81
82 while (v1.dwOSVersionInfoSize)
83 {
84 ok1 = GetVersionExA((LPOSVERSIONINFOA)&v1), ok2;
85 hook->OriginalFunction = GetVersionExA;
86
87 ok2 = ((GETVERSIONEXAPROC)hook->ReplacementFunction)(&v2);
88
89 winetest_ok(ok1 == ok2, "Expected ok1 to equal ok2, was: %i, %i for %s\n", ok1, ok2, shim);
90 if (ok1 && ok2)
91 {
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);
98
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);
102
103 if (v1.dwOSVersionInfoSize == sizeof(OSVERSIONINFOEXA))
104 {
105 if (info->dwPlatformId != VER_PLATFORM_WIN32_WINDOWS)
106 {
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);
109 }
110 else
111 {
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);
114 }
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);
118 }
119 else
120 {
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);
126 }
127 }
128
129 ZeroMemory(&v1, sizeof(v1));
130 ZeroMemory(&v2, sizeof(v2));
131 if (v1.dwOSVersionInfoSize == sizeof(OSVERSIONINFOEXA))
132 v1.dwOSVersionInfoSize = v2.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
133 }
134 }
135
136 static void verify_shimw_imp(PHOOKAPI hook, const VersionLieInfo* info, PCSTR shim, int same, int first_might_be_broken)
137 {
138 OSVERSIONINFOEXW v1 = { sizeof(v1), 0 }, v2 = { sizeof(v2), 0 };
139 BOOL ok1, ok2, first = TRUE;
140
141 if (!same)
142 {
143 skip("Skipping implementation tests for %s\n", shim);
144 return;
145 }
146
147 while (v1.dwOSVersionInfoSize)
148 {
149 ok1 = GetVersionExW((LPOSVERSIONINFOW)&v1), ok2;
150 hook->OriginalFunction = GetVersionExW;
151
152 ok2 = ((GETVERSIONEXWPROC)hook->ReplacementFunction)(&v2);
153
154 if (first_might_be_broken && first && ok1 == TRUE && ok2 == FALSE)
155 {
156 skip("Skipping first check because 0x%x is (falsely) not accepted by the shim %s\n", sizeof(v1), shim);
157 }
158 else
159 {
160 winetest_ok(ok1 == ok2, "Expected ok1 to equal ok2, was: %i, %i for %s(first:%d)\n", ok1, ok2, shim, first);
161 }
162 if (ok1 && ok2)
163 {
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);
171
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);
175
176 if (v1.dwOSVersionInfoSize == sizeof(OSVERSIONINFOEXW))
177 {
178 if (info->dwPlatformId != VER_PLATFORM_WIN32_WINDOWS)
179 {
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);
182 }
183 else
184 {
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);
187 }
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);
191 }
192 else
193 {
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);
199 }
200 }
201
202 ZeroMemory(&v1, sizeof(v1));
203 ZeroMemory(&v2, sizeof(v2));
204 if (v1.dwOSVersionInfoSize == sizeof(OSVERSIONINFOEXW))
205 v1.dwOSVersionInfoSize = v2.dwOSVersionInfoSize = sizeof(OSVERSIONINFOW);
206 first = FALSE;
207 }
208 }
209
210 static void verify_shim_imp(PHOOKAPI hook, const VersionLieInfo* info, PCSTR shim, int same)
211 {
212 DWORD ver;
213 if (!same)
214 {
215 skip("Skipping implementation tests for %s\n", shim);
216 return;
217 }
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);
220 }
221
222
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
227
228
229
230
231 static void run_test(LPCSTR shim, const VersionLieInfo* info)
232 {
233 DWORD num_shims = 0;
234 WCHAR wide_shim[50] = { 0 };
235 PHOOKAPI hook;
236 DWORD ver;
237 MultiByteToWideChar(CP_ACP, 0, shim, -1, wide_shim, 50);
238 hook = pGetHookAPIs("", wide_shim, &num_shims);
239 ver = (info->dwMajorVersion << 8) | info->dwMinorVersion;
240 if (hook == NULL)
241 {
242 skip("Skipping tests for layers (%s) not present in this os (0x%x)\n", shim, g_WinVersion);
243 return;
244 }
245 ok(hook != NULL, "Expected hook to be a valid pointer for %s\n", shim);
246 if (info->dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
247 {
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)
250 {
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);
258 }
259 }
260 else
261 {
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)
265 {
266 int same = 0;
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);
273 if (num_shims == 4)
274 {
275 expect_shim(hook + 3, "NTDLL.DLL", "RtlGetVersion", shim, &same);
276 verify_shimw(hook + 3, info, shim, same, 1);
277 }
278 }
279 }
280 }
281
282
283 VersionLieInfo g_Win95 = { 0xC3B60004, 4, 0, 950, VER_PLATFORM_WIN32_WINDOWS, 0, 0 };
284 VersionLieInfo g_WinNT4SP5 = { 0x05650004, 4, 0, 1381, VER_PLATFORM_WIN32_NT, 5, 0 };
285 VersionLieInfo g_Win98 = { 0xC0000A04, 4, 10, 0x040A08AE, VER_PLATFORM_WIN32_WINDOWS, 0, 0 };
286
287 VersionLieInfo g_Win2000 = { 0x08930005, 5, 0, 2195, VER_PLATFORM_WIN32_NT, 0, 0 };
288 VersionLieInfo g_Win2000SP1 = { 0x08930005, 5, 0, 2195, VER_PLATFORM_WIN32_NT, 1, 0 };
289 VersionLieInfo g_Win2000SP2 = { 0x08930005, 5, 0, 2195, VER_PLATFORM_WIN32_NT, 2, 0 };
290 VersionLieInfo g_Win2000SP3 = { 0x08930005, 5, 0, 2195, VER_PLATFORM_WIN32_NT, 3, 0 };
291
292 VersionLieInfo g_WinXP = { 0x0a280105, 5, 1, 2600, VER_PLATFORM_WIN32_NT, 0, 0 };
293 VersionLieInfo g_WinXPSP1 = { 0x0a280105, 5, 1, 2600, VER_PLATFORM_WIN32_NT, 1, 0 };
294 VersionLieInfo g_WinXPSP2 = { 0x0a280105, 5, 1, 2600, VER_PLATFORM_WIN32_NT, 2, 0 };
295 VersionLieInfo g_WinXPSP3 = { 0x0a280105, 5, 1, 2600, VER_PLATFORM_WIN32_NT, 3, 0 };
296
297 VersionLieInfo g_Win2k3RTM = { 0x0ece0205, 5, 2, 3790, VER_PLATFORM_WIN32_NT, 0, 0 };
298 VersionLieInfo g_Win2k3SP1 = { 0x0ece0205, 5, 2, 3790, VER_PLATFORM_WIN32_NT, 1, 0 };
299
300 VersionLieInfo g_WinVistaRTM = { 0x17700006, 6, 0, 6000, VER_PLATFORM_WIN32_NT, 0, 0 };
301 VersionLieInfo g_WinVistaSP1 = { 0x17710006, 6, 0, 6001, VER_PLATFORM_WIN32_NT, 1, 0 };
302 VersionLieInfo g_WinVistaSP2 = { 0x17720006, 6, 0, 6002, VER_PLATFORM_WIN32_NT, 2, 0 };
303
304 VersionLieInfo g_Win7RTM = { 0x1db00106, 6, 1, 7600, VER_PLATFORM_WIN32_NT, 0, 0 };
305
306 DWORD get_host_winver(void)
307 {
308 RTL_OSVERSIONINFOEXW rtlinfo = {0};
309 void (__stdcall* pRtlGetVersion)(RTL_OSVERSIONINFOEXW*);
310 pRtlGetVersion = (void (__stdcall*)(RTL_OSVERSIONINFOEXW*))GetProcAddress(GetModuleHandleA("ntdll"), "RtlGetVersion");
311
312 rtlinfo.dwOSVersionInfoSize = sizeof(rtlinfo);
313 pRtlGetVersion(&rtlinfo);
314 return (rtlinfo.dwMajorVersion << 8) | rtlinfo.dwMinorVersion;
315 }
316
317 START_TEST(versionlie)
318 {
319 HMODULE dll = LoadLibraryA("apphelp.dll");
320 WCHAR buf[MAX_PATH];
321 WCHAR aclayers[] = {'\\','a','c','l','a','y','e','r','s','.','d','l','l',0};
322 pSdbGetAppPatchDir = (void*)GetProcAddress(dll, "SdbGetAppPatchDir");
323 if (!pSdbGetAppPatchDir)
324 {
325 skip("apphelp.dll not loaded, or does not export SdbGetAppPatchDir\n");
326 return;
327 }
328
329 pSdbGetAppPatchDir(NULL, buf, MAX_PATH);
330 lstrcatW(buf, aclayers);
331 dll = LoadLibraryW(buf);
332 pGetHookAPIs = (void*)GetProcAddress(dll, "GetHookAPIs");
333
334 if (!pGetHookAPIs)
335 {
336 skip("aclayers.dll not loaded, or does not export GetHookAPIs\n");
337 return;
338 }
339 g_WinVersion = get_host_winver();
340
341 run_test("Win95VersionLie", &g_Win95);
342 run_test("WinNT4SP5VersionLie", &g_WinNT4SP5);
343 run_test("Win98VersionLie", &g_Win98);
344 run_test("Win2000VersionLie", &g_Win2000);
345 run_test("Win2000SP1VersionLie", &g_Win2000SP1);
346 run_test("Win2000SP2VersionLie", &g_Win2000SP2);
347 run_test("Win2000SP3VersionLie", &g_Win2000SP3);
348 run_test("WinXPVersionLie", &g_WinXP);
349 run_test("WinXPSP1VersionLie", &g_WinXPSP1);
350 run_test("WinXPSP2VersionLie", &g_WinXPSP2);
351 run_test("WinXPSP3VersionLie", &g_WinXPSP3);
352 run_test("Win2k3RTMVersionLie", &g_Win2k3RTM);
353 run_test("Win2k3SP1VersionLie", &g_Win2k3SP1);
354 run_test("VistaRTMVersionLie", &g_WinVistaRTM);
355 run_test("VistaSP1VersionLie", &g_WinVistaSP1);
356 run_test("VistaSP2VersionLie", &g_WinVistaSP2);
357 run_test("Win7RTMVersionLie", &g_Win7RTM);
358 }