[CRT] Remove useless #undef abort from process.h
[reactos.git] / modules / rostests / apitests / apphelp / env.c
1 /*
2 * PROJECT: apphelp_apitest
3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4 * PURPOSE: Tests showing shim artifacts in the environment
5 * COPYRIGHT: Copyright 2016,2017 Mark Jansen (mark.jansen@reactos.org)
6 */
7
8 #include <ntstatus.h>
9 #define WIN32_NO_STATUS
10 #include <windows.h>
11 #include <shlwapi.h>
12 #include <winnt.h>
13 #include <userenv.h>
14 #ifdef __REACTOS__
15 #include <ntndk.h>
16 #else
17 #include <winternl.h>
18 #endif
19 #include <winerror.h>
20 #include <stdio.h>
21
22 #include "wine/test.h"
23
24 #include <pseh/pseh2.h>
25
26 #include "apphelp_apitest.h"
27
28 typedef void* HSDB;
29 typedef void* PDB;
30 typedef DWORD TAGREF;
31 typedef WORD TAG;
32
33
34
35 static HMODULE hdll;
36
37 BOOL(WINAPI *pSdbGetMatchingExe)(HSDB hsdb, LPCWSTR szPath, LPCWSTR szModuleName, LPCWSTR pszEnvironment, DWORD dwFlags, PSDBQUERYRESULT_VISTA pQueryResult);
38 HSDB (WINAPI *pSdbInitDatabase)(DWORD dwFlags, LPCWSTR pszDatabasePath);
39 void (WINAPI *pSdbReleaseDatabase)(HSDB hsdb);
40 BOOL (WINAPI *pSdbTagRefToTagID)(HSDB hsdb, TAGREF trWhich, PDB* ppdb, TAGID* ptiWhich);
41 TAG (WINAPI *pSdbGetTagFromTagID)(PDB pdb, TAGID tiWhich);
42 TAGREF (WINAPI *pSdbGetLayerTagRef)(HSDB hsdb, LPCWSTR layerName);
43
44
45 /* TODO: Investigate ApphelpCheckRunApp, for some reason there is not AppCompatData generated... */
46
47 BOOL (WINAPI *pApphelpCheckRunAppEx_w7)(HANDLE FileHandle, PVOID Unk1, PVOID Unk2, PWCHAR ApplicationName, PVOID Environment, USHORT ExeType, PULONG Reason,
48 PVOID* SdbQueryAppCompatData, PULONG SdbQueryAppCompatDataSize, PVOID* SxsData, PULONG SxsDataSize,
49 PULONG FusionFlags, PULONG64 SomeFlag1, PULONG SomeFlag2);
50
51 BOOL (WINAPI *pApphelpCheckRunAppEx_w10)(HANDLE FileHandle, PVOID Unk1, PVOID Unk2, PWCHAR ApplicationName, PVOID Environment, PVOID Unk3, USHORT ExeType, PULONG Reason,
52 PVOID* SdbQueryAppCompatData, PULONG SdbQueryAppCompatDataSize, PVOID* SxsData, PULONG SxsDataSize,
53 PULONG FusionFlags, PULONG64 SomeFlag1, PULONG SomeFlag2);
54
55
56 BOOL (WINAPI *pSdbPackAppCompatData)(HSDB hsdb, PSDBQUERYRESULT_VISTA pQueryResult, PVOID* ppData, DWORD *dwSize);
57 BOOL (WINAPI *pSdbUnpackAppCompatData)(HSDB hsdb, LPCWSTR pszImageName, PVOID pData, PSDBQUERYRESULT_VISTA pQueryResult);
58 DWORD (WINAPI *pSdbGetAppCompatDataSize)(PVOID pData);
59
60
61 static HSDB g_LayerDB;
62 static DWORD g_ShimDataSize;
63 static DWORD g_ModuleVersion;
64 static const SDBQUERYRESULT_VISTA empty_result = { { 0 } };
65 static const SDBQUERYRESULT_VISTA almost_empty = { { 0 }, { 0 }, { 0 }, 0, 0, 0, 0, { 0 }, SHIMREG_DISABLE_LAYER, 0 };
66
67
68 #define SHIMDATA_MAGIC 0xAC0DEDAB
69 #define MAX_LAYER_LENGTH 256
70
71
72 typedef struct ShimData_Win2k3
73 {
74 WCHAR szModule[34];
75 DWORD dwSize;
76 DWORD dwMagic;
77
78 TAGREF atrExes[SDB_MAX_EXES_2k3];
79 TAGREF atrLayers[SDB_MAX_LAYERS];
80 DWORD dwUnk0;
81 DWORD dwUnk1;
82 DWORD dwCustomSDBMap;
83 GUID rgGuidDB[SDB_MAX_SDBS];
84 } ShimData_Win2k3;
85
86
87
88 typedef struct ShimData_Win7
89 {
90 WCHAR szModule[260];
91 DWORD dwSize;
92 DWORD dwMagic;
93 SDBQUERYRESULT_VISTA Query;
94 WCHAR szLayer[MAX_LAYER_LENGTH];
95 DWORD unknown; // 0x14c
96 } ShimData_Win7;
97
98 typedef struct ShimData_Win10_v1
99 {
100 WCHAR szModule[260];
101 DWORD dwSize;
102 DWORD dwMagic;
103 DWORD unk1;
104 SDBQUERYRESULT_VISTA Query;
105 WCHAR szLayer[MAX_LAYER_LENGTH];
106 char padding1[0x200];
107 char padding2[0x404]; // Contains some data at the start
108 DWORD unk2;
109 DWORD unk3;
110 WCHAR processname[MAX_PATH];
111 WCHAR szLayerEnv[MAX_LAYER_LENGTH];
112 WCHAR unk4[MAX_LAYER_LENGTH];
113 char padding4[120];
114 } ShimData_Win10_v1;
115
116 typedef struct ShimData_Win10_v2
117 {
118 DWORD dwSize;
119 DWORD dwMagic;
120 DWORD unk1;
121 DWORD unk2;
122 SDBQUERYRESULT_VISTA Query;
123 WCHAR szLayer[MAX_LAYER_LENGTH];
124 char padding1[0x200];
125 char padding2[0x2ae + 0x54 + 0x2a + 0x16 + 0x16];
126 DWORD unk3;
127 DWORD unk4;
128 WCHAR processname[MAX_PATH-2];
129 WCHAR szLayerEnv[MAX_LAYER_LENGTH];
130 WCHAR unk5[MAX_LAYER_LENGTH];
131 char padding4[76];
132 } ShimData_Win10_v2;
133
134 typedef struct ShimData_QueryOffset
135 {
136 DWORD dwSize_10_v2;
137 DWORD dwMagic_10_v2;
138
139 char spacing1[60];
140
141 DWORD dwSize_2k3;
142 DWORD dwMagic_2k3;
143
144 char spacing2[444];
145
146 DWORD dwSize_7_10;
147 DWORD dwMagic_7_10;
148 } ShimData_QueryOffset;
149
150
151 C_ASSERT(sizeof(ShimData_Win2k3) == 392);
152 C_ASSERT(sizeof(ShimData_Win7) == 1500);
153 C_ASSERT(sizeof(ShimData_Win10_v1) == 4712);
154 C_ASSERT(sizeof(ShimData_Win10_v2) == 3976);
155
156 C_ASSERT(offsetof(ShimData_Win10_v2, dwSize) == 0);
157 C_ASSERT(offsetof(ShimData_Win2k3, dwSize) == 68);
158 C_ASSERT(offsetof(ShimData_Win7, dwSize) == 520);
159 C_ASSERT(offsetof(ShimData_Win10_v1, dwSize) == 520);
160
161 C_ASSERT(offsetof(ShimData_Win10_v2, dwMagic) == 4);
162 C_ASSERT(offsetof(ShimData_Win2k3, dwMagic) == 72);
163 C_ASSERT(offsetof(ShimData_Win7, dwMagic) == 524);
164 C_ASSERT(offsetof(ShimData_Win10_v1, dwMagic) == 524);
165
166 C_ASSERT(offsetof(ShimData_QueryOffset, dwSize_10_v2) == 0);
167 C_ASSERT(offsetof(ShimData_QueryOffset, dwSize_2k3) == 68);
168 C_ASSERT(offsetof(ShimData_QueryOffset, dwSize_7_10) == 520);
169
170 C_ASSERT(offsetof(ShimData_QueryOffset, dwMagic_10_v2) == 4);
171 C_ASSERT(offsetof(ShimData_QueryOffset, dwMagic_2k3) == 72);
172 C_ASSERT(offsetof(ShimData_QueryOffset, dwMagic_7_10) == 524);
173
174
175
176 #define SDB_DATABASE_MAIN_SHIM 0x80030000
177
178 #define SDBGMEF_IGNORE_ENVIRONMENT 0x1
179
180
181 typedef struct test_RemoteShimInfo
182 {
183 ULARGE_INTEGER AppCompatFlags;
184 ULARGE_INTEGER AppCompatFlagsUser;
185 PVOID pShimData;
186 DWORD ShimDataSize;
187 PVOID AppCompatInfo;
188 } test_RemoteShimInfo;
189
190
191 static BOOL readproc(HANDLE proc, LPVOID address, PVOID target, DWORD size)
192 {
193 SIZE_T dwRead;
194 if (ReadProcessMemory(proc, address, target, size, &dwRead))
195 {
196 ok(dwRead == size, "Expected to read %u bytes, got %lu\n", size, dwRead);
197 return dwRead == size;
198 }
199 ok(0, "RPM failed with %u\n", GetLastError());
200 return FALSE;
201 }
202
203 static BOOL get_shiminfo(HANDLE proc, test_RemoteShimInfo* info)
204 {
205 PROCESS_BASIC_INFORMATION pbi = { 0 };
206 ULONG sizeOut = 0;
207 NTSTATUS status = NtQueryInformationProcess(proc, ProcessBasicInformation, &pbi, sizeof(pbi), &sizeOut);
208 ok(NT_SUCCESS(status), "Expected NtQI to succeed, but failed with: %x\n", status);
209 memset(info, 0, sizeof(*info));
210 if (NT_SUCCESS(status))
211 {
212 PEB peb = { 0 };
213 if (readproc(proc, pbi.PebBaseAddress, &peb, sizeof(peb)))
214 {
215 MEMORY_BASIC_INFORMATION mbi = { 0 };
216 SIZE_T dwRead;
217
218 info->AppCompatFlags = peb.AppCompatFlags;
219 info->AppCompatFlagsUser = peb.AppCompatFlagsUser;
220 info->AppCompatInfo = peb.AppCompatInfo;
221 if (peb.pShimData == NULL)
222 return TRUE;
223
224 dwRead = VirtualQueryEx(proc, (LPCVOID)peb.pShimData, &mbi, sizeof(mbi));
225 ok(dwRead == sizeof(mbi), "Expected VQE to return %u, got %lu\n", sizeof(mbi), dwRead);
226 if (dwRead == sizeof(mbi) || peb.pShimData == NULL)
227 {
228 info->ShimDataSize = mbi.RegionSize;
229 info->pShimData = malloc(mbi.RegionSize);
230 if (readproc(proc, peb.pShimData, info->pShimData, mbi.RegionSize))
231 return TRUE;
232 free(info->pShimData);
233 info->pShimData = NULL;
234 }
235 }
236 }
237 return FALSE;
238 }
239
240 static HANDLE create_proc(BOOL suspended)
241 {
242 static char proc_name[MAX_PATH] = { 0 };
243 STARTUPINFOA si = {sizeof(si)};
244 PROCESS_INFORMATION pi;
245 BOOL res;
246 if (!proc_name[0])
247 {
248 GetModuleFileNameA(NULL, proc_name, MAX_PATH);
249 }
250
251 res = CreateProcessA(NULL, proc_name, NULL, NULL, TRUE, suspended ? CREATE_SUSPENDED : 0, NULL, NULL, &si, &pi);
252 if (!res)
253 return NULL;
254 CloseHandle(pi.hThread);
255 return pi.hProcess;
256 }
257
258 static void create_environ(const char* layers[], size_t num)
259 {
260 char buf[256] = { 0 };
261 size_t n;
262 for (n = 0; n < num; ++n)
263 {
264 if (n)
265 strcat(buf, " ");
266 strcat(buf, layers[n]);
267 }
268 SetEnvironmentVariableA("__COMPAT_LAYER", buf);
269 }
270
271 static void ValidateShim(TAGREF trLayer, const char* name)
272 {
273 HSDB hsdb = pSdbInitDatabase(SDB_DATABASE_MAIN_SHIM, NULL);
274 ok(hsdb != NULL, "Expected a valid handle\n");
275 if (hsdb)
276 {
277 PDB pdb = NULL;
278 TAGID tagid = 0xdeadbeef;
279 WCHAR nameW[256] = { 0 };
280 BOOL ret;
281
282 mbstowcs(nameW, name, strlen(name));
283
284 ret = pSdbTagRefToTagID(hsdb, trLayer, &pdb, &tagid);
285 ok(ret == TRUE, "Expected pSdbTagRefToTagID to succeed\n");
286 if (ret)
287 {
288 TAG tag;
289 ok(pdb != NULL, "Expected pdb to be a valid pointer\n");
290 ok(tagid != 0 && tagid != 0xdeadbeef, "Expected tagid to be a valid tag id, was: 0x%x\n", tagid);
291 tag = pSdbGetTagFromTagID(pdb, tagid);
292 ok(tag == 0x700b, "Expected tag to be 0x700b, was 0x%x\n", (DWORD)tag);
293 }
294
295 pSdbReleaseDatabase(hsdb);
296 }
297 }
298
299
300 static void Validate_ShimData_Win2k3(PVOID data, size_t count, const char* layers[])
301 {
302 //size_t n;
303 ShimData_Win2k3* pShimData = (ShimData_Win2k3*)data;
304
305 ok(!lstrcmpW(pShimData->szModule, L"ShimEng.dll"), "Expected pShimData->Module to be %s, was %s\n", wine_dbgstr_w(L"ShimEng.dll"), wine_dbgstr_w(pShimData->szModule));
306 ok(pShimData->dwMagic == SHIMDATA_MAGIC, "Expected pShimData->dwMagic to be 0x%x, was 0x%x\n", SHIMDATA_MAGIC, pShimData->dwMagic);
307 ok(pShimData->dwSize == sizeof(ShimData_Win2k3), "Expected pShimData->dwSize to be %u, was %u\n", sizeof(ShimData_Win2k3), pShimData->dwSize);
308 ok(pShimData->dwCustomSDBMap == 1, "Expected pShimData->dwCustomSDBMap to be 1, was %u\n", pShimData->dwCustomSDBMap);
309 }
310
311 static void Validate_ShimData_Win7(PVOID data, WCHAR szApphelp[256], size_t count, const char* layers[])
312 {
313 size_t n;
314 ShimData_Win7* pShimData = (ShimData_Win7*)data;
315
316 ok(!lstrcmpW(pShimData->szModule, szApphelp), "Expected pShimData->Module to be %s, was %s\n",
317 wine_dbgstr_w(szApphelp), wine_dbgstr_w(pShimData->szModule));
318 ok(pShimData->dwMagic == SHIMDATA_MAGIC, "Expected pShimData->dwMagic to be 0x%x, was 0x%x\n",
319 SHIMDATA_MAGIC, pShimData->dwMagic);
320 ok(pShimData->dwSize == sizeof(ShimData_Win7), "Expected pShimData->dwSize to be %u, was %u\n",
321 sizeof(ShimData_Win7), pShimData->dwSize);
322 if (pShimData->Query.dwLayerCount != min(count, SDB_MAX_LAYERS))
323 {
324 char buf[250] = {0};
325 GetEnvironmentVariableA("__COMPAT_LAYER", buf, _countof(buf));
326 trace("At test: %s\n", buf);
327 }
328 ok(pShimData->Query.dwLayerCount == min(count, SDB_MAX_LAYERS),
329 "Expected LayerCount to be %u, was %u\n", min(count, SDB_MAX_LAYERS), pShimData->Query.dwLayerCount);
330 for (n = 0; n < SDB_MAX_LAYERS; ++n)
331 {
332 if (n < count)
333 {
334 ok(pShimData->Query.atrLayers[n] != 0, "Expected to find a valid layer in index %u / %u\n", n, count);
335 ValidateShim(pShimData->Query.atrLayers[n], layers[n]);
336 }
337 else
338 ok(pShimData->Query.atrLayers[n] == 0, "Expected to find an empty layer in index %u / %u\n", n, count);
339 }
340 ok(pShimData->unknown == 0x14c, "Expected pShimData->unknown to be 0x14c, was 0x%x\n", pShimData->unknown);
341 }
342
343 static void Validate_ShimData_Win10_v2(PVOID data, WCHAR szApphelp[256], size_t count, const char* layers[])
344 {
345 size_t n;
346 ShimData_Win10_v2* pShimData = (ShimData_Win10_v2*)data;
347
348 if (pShimData->dwMagic != SHIMDATA_MAGIC)
349 {
350 skip("Yet another unknown shimdata variant...\n");
351 return;
352 }
353
354 ok(pShimData->dwSize == sizeof(ShimData_Win10_v2), "Expected pShimData->dwSize to be %u, was %u\n",
355 sizeof(ShimData_Win10_v2), pShimData->dwSize);
356 if (pShimData->Query.dwLayerCount != min(count, SDB_MAX_LAYERS))
357 {
358 char buf[250] = {0};
359 GetEnvironmentVariableA("__COMPAT_LAYER", buf, _countof(buf));
360 trace("At test: %s\n", buf);
361 }
362 ok(pShimData->Query.dwLayerCount == min(count, SDB_MAX_LAYERS),
363 "Expected LayerCount to be %u, was %u\n", min(count, SDB_MAX_LAYERS), pShimData->Query.dwLayerCount);
364 for (n = 0; n < SDB_MAX_LAYERS; ++n)
365 {
366 if (n < count)
367 {
368 ok(pShimData->Query.atrLayers[n] != 0, "Expected to find a valid layer in index %u / %u\n", n, count);
369 ValidateShim(pShimData->Query.atrLayers[n], layers[n]);
370 }
371 else
372 ok(pShimData->Query.atrLayers[n] == 0, "Expected to find an empty layer in index %u / %u\n", n, count);
373 }
374
375 }
376
377 static void Validate_ShimData_Win10(PVOID data, WCHAR szApphelp[256], size_t count, const char* layers[])
378 {
379 size_t n;
380 ShimData_Win10_v1* pShimData = (ShimData_Win10_v1*)data;
381
382 if (pShimData->dwMagic != SHIMDATA_MAGIC)
383 {
384 Validate_ShimData_Win10_v2(data, szApphelp, count, layers);
385 return;
386 }
387
388
389 ok(!lstrcmpiW(pShimData->szModule, szApphelp), "Expected pShimData->Module to be %s, was %s\n",
390 wine_dbgstr_w(szApphelp), wine_dbgstr_w(pShimData->szModule));
391 ok(pShimData->dwSize == sizeof(ShimData_Win10_v1), "Expected pShimData->dwSize to be %u, was %u\n",
392 sizeof(ShimData_Win10_v1), pShimData->dwSize);
393 if (pShimData->Query.dwLayerCount != min(count, SDB_MAX_LAYERS))
394 {
395 char buf[250] = {0};
396 GetEnvironmentVariableA("__COMPAT_LAYER", buf, _countof(buf));
397 trace("At test: %s\n", buf);
398 }
399 ok(pShimData->Query.dwLayerCount == min(count, SDB_MAX_LAYERS),
400 "Expected LayerCount to be %u, was %u\n", min(count, SDB_MAX_LAYERS), pShimData->Query.dwLayerCount);
401 for (n = 0; n < SDB_MAX_LAYERS; ++n)
402 {
403 if (n < count)
404 {
405 ok(pShimData->Query.atrLayers[n] != 0, "Expected to find a valid layer in index %u / %u\n", n, count);
406 ValidateShim(pShimData->Query.atrLayers[n], layers[n]);
407 }
408 else
409 ok(pShimData->Query.atrLayers[n] == 0, "Expected to find an empty layer in index %u / %u\n", n, count);
410 }
411 }
412
413 static void Validate_EmptyShimData_Win10(PVOID data)
414 {
415 ShimData_Win10_v1* pShimData = (ShimData_Win10_v1*)data;
416 ok(pShimData != NULL, "Expected pShimData\n");
417 if (!pShimData)
418 return;
419
420 if (pShimData->dwMagic != SHIMDATA_MAGIC)
421 {
422 ShimData_Win10_v2* pShimData2 = (ShimData_Win10_v2*)data;
423 if (pShimData2->dwMagic != SHIMDATA_MAGIC)
424 {
425 skip("Unknown shimdata (win10)\n");
426 return;
427 }
428
429 ok(!lstrcmpiW(pShimData2->szLayer, L""), "Expected pShimData->szLayer to be '', was %s\n", wine_dbgstr_w(pShimData2->szLayer));
430 ok(pShimData2->dwSize == sizeof(ShimData_Win10_v2), "Expected pShimData->dwSize to be %u, was %u\n", sizeof(ShimData_Win10_v2), pShimData2->dwSize);
431 ok(!memcmp(&pShimData2->Query, &empty_result, sizeof(empty_result)), "Expected result to be empty\n");
432 }
433 else
434 {
435 ok(!lstrcmpiW(pShimData->szModule, L""), "Expected pShimData->Module to be '', was %s\n", wine_dbgstr_w(pShimData->szModule));
436 ok(!lstrcmpiW(pShimData->szLayer, L""), "Expected pShimData->szLayer to be '', was %s\n", wine_dbgstr_w(pShimData->szLayer));
437 ok(pShimData->dwSize == sizeof(ShimData_Win10_v1), "Expected pShimData->dwSize to be %u, was %u\n", sizeof(ShimData_Win10_v1), pShimData->dwSize);
438 ok(!memcmp(&pShimData->Query, &empty_result, sizeof(empty_result)), "Expected result to be empty\n");
439 }
440 }
441
442 static void Test_layers(WCHAR szApphelp[256])
443 {
444 static const char* layers[] = {
445 "256Color", "NT4SP5", "DisableNXHideUI", "DisableNXShowUI",
446 "WIN2000SP3", "640X480", /*"DISABLEDWM",*/ "HIGHDPIAWARE",
447 /*"RUNASADMIN",*/ "DISABLETHEMES" /*, "Layer_Win95VersionLie"*/ };
448
449 size_t n;
450 HANDLE proc;
451 test_RemoteShimInfo info;
452 BOOL res;
453
454 for (n = 0; n <= (sizeof(layers) / sizeof(layers[0])); ++n)
455 {
456 create_environ(layers, n);
457
458 proc = create_proc(TRUE);
459 res = get_shiminfo(proc, &info);
460 TerminateProcess(proc, 0);
461 CloseHandle(proc);
462
463 if (!res)
464 {
465 ok(0, "Unable to get process info (%u)!\n", n);
466 continue;
467 }
468
469 if (n == 0)
470 {
471 ok(info.AppCompatFlags.QuadPart == 0, "Expected AppCompatFlags to be 0, was: %s\n", wine_dbgstr_longlong(info.AppCompatFlags.QuadPart));
472 ok(info.AppCompatFlagsUser.QuadPart == 0, "Expected AppCompatFlagsUser to be 0, was: %s\n", wine_dbgstr_longlong(info.AppCompatFlagsUser.QuadPart));
473 ok(info.AppCompatInfo == NULL, "Expected AppCompatInfo to be NULL, was: %p\n", info.AppCompatInfo);
474 if (g_WinVersion < WINVER_WIN10)
475 {
476 ok(info.pShimData == NULL, "Expected pShimData to be NULL, was: %p\n", info.pShimData);
477 }
478 else
479 {
480 Validate_EmptyShimData_Win10(info.pShimData);
481 }
482 }
483 else
484 {
485 ok(info.AppCompatFlags.QuadPart == 0, "Expected AppCompatFlags to be 0, was: %s\n", wine_dbgstr_longlong(info.AppCompatFlags.QuadPart));
486 ok(info.AppCompatFlagsUser.QuadPart == 0, "Expected AppCompatFlagsUser to be 0, was: %s\n", wine_dbgstr_longlong(info.AppCompatFlagsUser.QuadPart));
487 ok(info.AppCompatInfo == NULL, "Expected AppCompatInfo to be NULL, was: %p\n", info.AppCompatInfo);
488 ok(info.pShimData != NULL, "Expected pShimData to be valid, was NULL\n");
489 ok(info.ShimDataSize == g_ShimDataSize, "Expected ShimDataSize to be %u, was: %u\n", g_ShimDataSize, info.ShimDataSize);
490 if (info.pShimData)
491 {
492 if (g_WinVersion < WINVER_VISTA)
493 Validate_ShimData_Win2k3(info.pShimData, n, layers);
494 else if (g_WinVersion < WINVER_WIN10)
495 Validate_ShimData_Win7(info.pShimData, szApphelp, n, layers);
496 else
497 Validate_ShimData_Win10(info.pShimData, szApphelp, n, layers);
498 }
499 }
500 free(info.pShimData);
501 }
502 }
503
504
505 /*
506 [Warn][SdbGetMatchingExe ] __COMPAT_LAYER name cannot exceed 256 characters.
507 [Info][SdbpGetPermLayersInternal] Failed to read value info from Key "\Registry\Machine\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers" Status 0xc0000034
508 [Info][SdbpGetPermLayersInternal] Failed to read value info from Key "\REGISTRY\USER\S-1-5-21-4051718696-421402927-393408651-2638\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers" Status 0xc0000034
509 [Warn][SdbpEnumUserSdb ] Failed to open key "\Registry\Machine\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Custom\NotepadReplacer.exe" Status 0xc0000034
510 */
511 static void Test_repeatlayer(WCHAR szApphelp[256])
512 {
513 static const char* layers[] = {
514 "256Color", "256Color", "256Color", "256Color",
515 "256Color", "256Color", "256Color", "256Color" };
516
517 HANDLE proc;
518 test_RemoteShimInfo info;
519 BOOL res;
520
521 SetEnvironmentVariableA("__COMPAT_LAYER", "256Color 256Color 256Color 256Color 256Color 256Color 256Color 256Color");
522
523
524 proc = create_proc(TRUE);
525 res = get_shiminfo(proc, &info);
526 TerminateProcess(proc, 0);
527 CloseHandle(proc);
528
529 if (res)
530 {
531 ok(info.AppCompatFlags.QuadPart == 0, "Expected AppCompatFlags to be 0, was: %s\n", wine_dbgstr_longlong(info.AppCompatFlags.QuadPart));
532 ok(info.AppCompatFlagsUser.QuadPart == 0, "Expected AppCompatFlagsUser to be 0, was: %s\n", wine_dbgstr_longlong(info.AppCompatFlagsUser.QuadPart));
533 ok(info.AppCompatInfo == 0, "Expected AppCompatInfo to be 0, was: %p\n", info.AppCompatInfo);
534 ok(info.pShimData != NULL, "Expected pShimData to be valid, was NULL\n");
535 ok(info.ShimDataSize == g_ShimDataSize, "Expected ShimDataSize to be %u, was: %u\n", g_ShimDataSize, info.ShimDataSize);
536 if (info.pShimData)
537 {
538 /* Win10 only 'loads' one layer */
539 if (g_WinVersion < WINVER_VISTA)
540 Validate_ShimData_Win2k3(info.pShimData, SDB_MAX_LAYERS, layers);
541 else if (g_WinVersion < WINVER_WIN10)
542 Validate_ShimData_Win7(info.pShimData, szApphelp, SDB_MAX_LAYERS, layers);
543 else
544 Validate_ShimData_Win10(info.pShimData, szApphelp, 1, layers);
545 }
546 }
547 else
548 {
549 ok(0, "Unable to get process info!\n");
550 }
551
552 }
553
554
555 TAGREF find_layer(const char* szLayerStart, const char* szLayerEnd)
556 {
557 char layer[100] = { 0 };
558 WCHAR layerW[100] = { 0 };
559 strncpy(layer, szLayerStart, szLayerEnd - szLayerStart);
560
561 if (!g_LayerDB)
562 {
563 g_LayerDB = pSdbInitDatabase(SDB_DATABASE_MAIN_SHIM, 0);
564 }
565
566 mbstowcs(layerW, layer, strlen(layer));
567 return pSdbGetLayerTagRef(g_LayerDB, layerW);
568 }
569
570 static void expect_layeronly_imp(SDBQUERYRESULT_VISTA* result, const char* layers, DWORD flags)
571 {
572 DWORD dwLayerCount = 0, n;
573 TAGREF atrLayers[SDB_MAX_LAYERS] = { 0 };
574
575 const char* layer = layers, *nextlayer;
576 while (layer && *layer)
577 {
578 nextlayer = strchr(layer, ' ');
579 atrLayers[dwLayerCount++] = find_layer(layer, nextlayer ? nextlayer : (layer + strlen(layer)));
580 layer = nextlayer ? (nextlayer+1) : NULL;
581 }
582
583 if (g_ModuleVersion < WINVER_VISTA)
584 {
585 SDBQUERYRESULT_2k3* result2 = (SDBQUERYRESULT_2k3*)result;
586 result = NULL;
587
588 winetest_ok(!memcmp(&result2->atrExes, &empty_result.atrExes, sizeof(result2->atrExes)), "Expected atrExes to be empty\n");
589 winetest_ok(!memcmp(&result2->atrLayers[dwLayerCount], &empty_result.atrLayers[dwLayerCount], sizeof(result2->atrLayers) - dwLayerCount * sizeof(result2->atrLayers[0])), "Expected atrLayers[+1] to be empty\n");
590 for (n = 0; n < dwLayerCount; ++n)
591 {
592 winetest_ok(result2->atrLayers[n] == atrLayers[n], "Expected atrLayers[%u] to be %x, was %x\n",
593 n, atrLayers[n], result2->atrLayers[n]);
594 }
595 winetest_ok(result2->dwLayerFlags == 0, "Expected dwLayerFlags to be 0, was %u\n", result2->dwLayerFlags);
596 winetest_ok(result2->trApphelp == 0, "Expected trApphelp to be 0, was %u\n", result2->trApphelp);
597 winetest_ok(result2->dwExeCount == 0, "Expected dwExeCount to be 0, was %u\n", result2->dwExeCount);
598 winetest_ok(result2->dwLayerCount == dwLayerCount, "Expected dwLayerCount to be %u, was %u\n", dwLayerCount, result2->dwLayerCount);
599 winetest_ok(!memcmp(&result2->guidID, &empty_result.guidID, sizeof(result2->guidID)), "Expected guidID to be empty\n");
600 winetest_ok(result2->dwFlags == flags, "Expected dwFlags to be 0x%x, was 0x%x\n", flags, result2->dwFlags);
601 winetest_ok(result2->dwCustomSDBMap == 1, "Expected dwCustomSDBMap to be 1, was %u\n", result2->dwCustomSDBMap);
602 winetest_ok(!memcmp(&result2->rgGuidDB[1], &empty_result.rgGuidDB[1], sizeof(result2->rgGuidDB) - sizeof(result2->rgGuidDB[0])), "Expected rgGuidDB[+1] to be empty\n");
603 }
604 else
605 {
606 winetest_ok(!memcmp(&result->atrExes, &empty_result.atrExes, sizeof(empty_result.atrExes)), "Expected atrExes to be empty\n");
607 winetest_ok(!memcmp(&result->adwExeFlags, &empty_result.adwExeFlags, sizeof(empty_result.adwExeFlags)), "Expected adwExeFlags to be empty\n");
608 winetest_ok(!memcmp(&result->atrLayers[dwLayerCount], &empty_result.atrLayers[dwLayerCount], sizeof(empty_result.atrLayers) - dwLayerCount * sizeof(empty_result.atrLayers[0])), "Expected atrLayers[+1] to be empty\n");
609 for (n = 0; n < dwLayerCount; ++n)
610 {
611 winetest_ok(result->atrLayers[n] == atrLayers[n], "Expected atrLayers[%u] to be %x, was %x\n",
612 n, atrLayers[n], result->atrLayers[n]);
613 }
614 winetest_ok(result->dwLayerFlags == 0, "Expected dwLayerFlags to be 0, was %u\n", result->dwLayerFlags);
615 winetest_ok(result->trApphelp == 0, "Expected trApphelp to be 0, was %u\n", result->trApphelp);
616 winetest_ok(result->dwExeCount == 0, "Expected dwExeCount to be 0, was %u\n", result->dwExeCount);
617 winetest_ok(result->dwLayerCount == dwLayerCount, "Expected dwLayerCount to be %u, was %u\n", dwLayerCount, result->dwLayerCount);
618 winetest_ok(!memcmp(&result->guidID, &empty_result.guidID, sizeof(empty_result.guidID)), "Expected guidID to be empty\n");
619 winetest_ok(result->dwFlags == flags, "Expected dwFlags to be 0x%x, was 0x%x\n", flags, result->dwFlags);
620 winetest_ok(result->dwCustomSDBMap == 1, "Expected dwCustomSDBMap to be 1, was %u\n", result->dwCustomSDBMap);
621 winetest_ok(!memcmp(&result->rgGuidDB[1], &empty_result.rgGuidDB[1], sizeof(empty_result.rgGuidDB) - sizeof(empty_result.rgGuidDB[0])), "Expected rgGuidDB[+1] to be empty\n");
622 }
623 }
624
625 static void Test_Shimdata(SDBQUERYRESULT_VISTA* result, const WCHAR* szLayer)
626 {
627 BOOL ret;
628 PVOID pData;
629 DWORD dwSize;
630
631 pData = NULL;
632 dwSize = 0;
633 ret = pSdbPackAppCompatData(g_LayerDB, result, &pData, &dwSize);
634 ok(ret == TRUE, "Expected ret to be TRUE\n");
635
636 if (pData)
637 {
638 ShimData_Win2k3* pWin2k3;
639 ShimData_Win7* pWin7;
640 ShimData_Win10_v1* pWin10;
641 ShimData_Win10_v2* pWin10_v2;
642 SDBQUERYRESULT_VISTA result2 = { { 0 } };
643
644 DWORD res = pSdbGetAppCompatDataSize(pData);
645 ok_int(dwSize, res);
646 switch(dwSize)
647 {
648 case sizeof(ShimData_Win2k3):
649 pWin2k3 = (ShimData_Win2k3*)pData;
650 ok_hex(pWin2k3->dwMagic, SHIMDATA_MAGIC);
651 ok_int(pWin2k3->dwSize, dwSize);
652 ok(pWin2k3->dwCustomSDBMap == 1, "Expected pWin2k3->dwCustomSDBMap to equal 1, was %u for %s\n", pWin2k3->dwCustomSDBMap, wine_dbgstr_w(szLayer));
653 //ok(!memcmp(&pWin2k3->Query, result, sizeof(SDBQUERYRESULT_2k3)), "Expected pWin2k3->Query to equal result\n");
654 //ok_wstr(pWin7->szLayer, szLayer);
655 break;
656 case sizeof(ShimData_Win7):
657 pWin7 = (ShimData_Win7*)pData;
658 ok_hex(pWin7->dwMagic, SHIMDATA_MAGIC);
659 ok_int(pWin7->dwSize, dwSize);
660 ok(!memcmp(&pWin7->Query, result, sizeof(*result)), "Expected pWin7->Query to equal result\n");
661 ok_wstr(pWin7->szLayer, szLayer);
662 break;
663 case sizeof(ShimData_Win10_v1):
664 pWin10 = (ShimData_Win10_v1*)pData;
665 ok_hex(pWin10->dwMagic, SHIMDATA_MAGIC);
666 ok_int(pWin10->dwSize, dwSize);
667 ok(!memcmp(&pWin10->Query, result, sizeof(*result)), "Expected pWin10->Query to equal result\n");
668 ok_wstr(pWin10->szLayerEnv, szLayer);
669 ok_wstr(pWin10->szLayer, L"");
670 break;
671 case sizeof(ShimData_Win10_v2):
672 pWin10_v2 = (ShimData_Win10_v2*)pData;
673 ok_hex(pWin10_v2->dwMagic, SHIMDATA_MAGIC);
674 ok_int(pWin10_v2->dwSize, dwSize);
675 ok(!memcmp(&pWin10_v2->Query, result, sizeof(*result)), "Expected pWin10->Query to equal result\n");
676 ok_wstr(pWin10_v2->szLayerEnv, szLayer);
677 ok_wstr(pWin10_v2->szLayer, L"");
678 break;
679 default:
680 skip("Unknown size %d\n", dwSize);
681 break;
682 }
683
684 ret = pSdbUnpackAppCompatData(g_LayerDB, NULL, pData, &result2);
685 ok(ret == TRUE, "Expected ret to be TRUE\n");
686 /* TODO: For some reason 2k3 does not seem to output the database GUIDs,
687 investigate when we have support for multible db's! */
688 if (dwSize == sizeof(ShimData_Win2k3))
689 {
690 SDBQUERYRESULT_2k3* input = (SDBQUERYRESULT_2k3*)result;
691 SDBQUERYRESULT_2k3* output = (SDBQUERYRESULT_2k3*)&result2;
692 const GUID rgGuidDB0 = {0x11111111, 0x1111, 0x1111, {0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11}};
693
694 // Check expected data.
695 ok(input->dwLayerCount == 1,
696 "Expected input->dwLayerCount to be 1, was %u for %s\n",
697 input->dwLayerCount, wine_dbgstr_w(szLayer));
698 ok(input->dwCustomSDBMap == 1,
699 "Expected input->dwCustomSDBMap to be 1, was %u for %s\n",
700 input->dwCustomSDBMap, wine_dbgstr_w(szLayer));
701 ok(IsEqualGUID(&input->rgGuidDB[0], &rgGuidDB0),
702 "Expected input->rgGuidDB[0] to be %s, was %s for %s\n",
703 wine_dbgstr_guid(&rgGuidDB0), wine_dbgstr_guid(&input->rgGuidDB[0]), wine_dbgstr_w(szLayer));
704
705 // Check missing data.
706 ok(output->dwLayerCount == 0,
707 "Expected output->dwLayerCount to be 0, was %u for %s\n",
708 output->dwLayerCount, wine_dbgstr_w(szLayer));
709 ok(output->dwCustomSDBMap == 0,
710 "Expected output->dwCustomSDBMap to be 0, was %u for %s\n",
711 output->dwCustomSDBMap, wine_dbgstr_w(szLayer));
712 ok(IsEqualGUID(&output->rgGuidDB[0], &empty_result.rgGuidDB[0]),
713 "Expected output->rgGuidDB[0] to be empty, was %s for %s\n",
714 wine_dbgstr_guid(&output->rgGuidDB[0]), wine_dbgstr_w(szLayer));
715
716 // Fake it for now, so the memcmp works.
717 output->dwLayerCount = input->dwLayerCount;
718 output->dwCustomSDBMap = input->dwCustomSDBMap;
719 output->rgGuidDB[0] = input->rgGuidDB[0];
720 }
721 ok(!memcmp(&result2, result, sizeof(*result)), "Expected result2 to equal result for %s\n", wine_dbgstr_w(szLayer));
722
723 RtlFreeHeap(GetProcessHeap(), 0, pData);
724 }
725 }
726
727
728 #define expect_layeronly (winetest_set_location(__FILE__, __LINE__), 0) ? (void)0 : expect_layeronly_imp
729
730
731 static void Test_GetMatchingExe(void)
732 {
733 BOOL ret;
734 SDBQUERYRESULT_VISTA result = { { 0 } };
735 WCHAR self[MAX_PATH];
736 DWORD flags = (g_WinVersion < WINVER_VISTA) ? 0 : ((g_WinVersion < WINVER_WIN10) ? 1 : 0x21);
737
738 GetModuleFileNameW(NULL, self, MAX_PATH);
739 SetEnvironmentVariableA("__COMPAT_LAYER", NULL);
740
741 /* szPath cannot be NULL! */
742 ret = pSdbGetMatchingExe(NULL, L"", NULL, NULL, 0, &result);
743 ok(ret == FALSE, "Expected ret to be FALSE\n");
744 ok(!memcmp(&result, &empty_result, sizeof(empty_result)), "Expected result to be empty\n");
745
746 result = empty_result;
747
748 ret = pSdbGetMatchingExe(NULL, self, NULL, NULL, 0, &result);
749 ok(ret == FALSE, "Expected ret to be FALSE\n");
750 ok(!memcmp(&result, &empty_result, sizeof(empty_result)), "Expected result to be empty\n");
751
752 result = empty_result;
753 SetEnvironmentVariableA("__COMPAT_LAYER", "Some_invalid_layer_name");
754
755 ret = pSdbGetMatchingExe(NULL, self, NULL, NULL, 0, &result);
756 ok(ret == FALSE, "Expected ret to be FALSE\n");
757 if (g_WinVersion < WINVER_WIN10)
758 ok(!memcmp(&result, &empty_result, sizeof(empty_result)), "Expected result to be empty\n");
759 else
760 ok(!memcmp(&result, &almost_empty, sizeof(almost_empty)), "Expected result to be almost empty\n");
761
762 result = empty_result;
763 SetEnvironmentVariableA("__COMPAT_LAYER", "256Color");
764
765 ret = pSdbGetMatchingExe(NULL, self, NULL, NULL, 0, &result);
766 ok(ret == TRUE, "Expected ret to be TRUE\n");
767 expect_layeronly(&result, "256Color", flags);
768
769 Test_Shimdata(&result, L"256Color");
770
771 result = empty_result;
772 SetEnvironmentVariableA("__COMPAT_LAYER", "640X480");
773
774 ret = pSdbGetMatchingExe(NULL, self, NULL, NULL, 0, &result);
775 ok(ret == TRUE, "Expected ret to be TRUE\n");
776 expect_layeronly(&result, "640X480", flags);
777
778 Test_Shimdata(&result, L"640X480");
779
780 /* HIGHDPIAWARE does not exist in 2k3 */
781 if (g_WinVersion > WINVER_2003)
782 {
783 result = empty_result;
784 SetEnvironmentVariableA("__COMPAT_LAYER", "HIGHDPIAWARE");
785
786 ret = pSdbGetMatchingExe(NULL, self, NULL, NULL, 0, &result);
787 ok(ret == TRUE, "Expected ret to be TRUE\n");
788 expect_layeronly(&result, "HIGHDPIAWARE", flags);
789
790 Test_Shimdata(&result, L"HIGHDPIAWARE");
791
792 result = empty_result;
793 SetEnvironmentVariableA("__COMPAT_LAYER", "256Color HIGHDPIAWARE 640X480");
794
795 ret = pSdbGetMatchingExe(NULL, self, NULL, NULL, 0, &result);
796 ok(ret == TRUE, "Expected ret to be TRUE\n");
797 expect_layeronly(&result, "256Color HIGHDPIAWARE 640X480", flags);
798
799 Test_Shimdata(&result, L"256Color HIGHDPIAWARE 640X480");
800 }
801 }
802
803
804 HANDLE xOpenFile(WCHAR* ApplicationName)
805 {
806 UNICODE_STRING FileName;
807 OBJECT_ATTRIBUTES ObjectAttributes;
808 IO_STATUS_BLOCK IoStatusBlock;
809 NTSTATUS Status;
810 HANDLE FileHandle;
811
812 if (!RtlDosPathNameToNtPathName_U(ApplicationName, &FileName, NULL, NULL))
813 {
814 skip("Unable to translate %s to Nt path\n", wine_dbgstr_w(ApplicationName));
815 return NULL;
816 }
817
818
819 InitializeObjectAttributes(&ObjectAttributes, &FileName, OBJ_CASE_INSENSITIVE, NULL, NULL);
820 Status = NtOpenFile(&FileHandle,
821 SYNCHRONIZE |
822 FILE_READ_ATTRIBUTES |
823 FILE_READ_DATA |
824 FILE_EXECUTE,
825 &ObjectAttributes,
826 &IoStatusBlock,
827 FILE_SHARE_READ | FILE_SHARE_DELETE,
828 FILE_SYNCHRONOUS_IO_NONALERT |
829 FILE_NON_DIRECTORY_FILE);
830
831 RtlFreeUnicodeString(&FileName);
832
833 if (!NT_SUCCESS(Status))
834 return NULL;
835
836 return FileHandle;
837 }
838
839
840 #define RESET_CHECKRUNAPP_VARS()\
841 do { \
842 if (AppCompatData && AppCompatData != &Query) { RtlFreeHeap(RtlGetProcessHeap(), 0, AppCompatData); } \
843 ExeType = IMAGE_FILE_MACHINE_I386; \
844 SxsDataSize = FusionFlags = Reason = 0; \
845 SxsData = NULL; \
846 memset(&Query, 0, sizeof(Query)); \
847 AppCompatData = &Query; \
848 AppCompatDataSize = 123456; \
849 } while (0)
850
851 #define CHECK_BASICS()\
852 do { \
853 ok_hex(ret, TRUE); \
854 ok(AppCompatData != NULL && AppCompatData != &Query, "Expected the pointer to be valid\n"); \
855 ok_hex(AppCompatDataSize, sizeof(SDBQUERYRESULT_VISTA)); \
856 ok(SxsData == NULL, "Expected the pointer to be NULL\n"); \
857 ok_hex(SxsDataSize, 0); \
858 ok_hex(FusionFlags, 0); \
859 } while (0)
860
861 /* W10 does not seem to use the flags at all, so with this macro we can still test it below 10. */
862 #define CHECKREASON(value, w10dum) (g_ModuleVersion < WINVER_WIN10 ? value : w10dum)
863
864
865 static BOOL call_ApphelpCheckRunApp(HANDLE FileHandle, PWCHAR ApplicationName, PVOID Environment, USHORT ExeType,
866 PULONG Reason, PVOID* SdbQueryAppCompatData, PULONG SdbQueryAppCompatDataSize,
867 PVOID* SxsData, PULONG SxsDataSize, PULONG FusionFlags)
868 {
869 ULONG64 SomeFlag1 = 0;
870 ULONG SomeFlag2 = 0;
871
872 if (pApphelpCheckRunAppEx_w7)
873 {
874 return pApphelpCheckRunAppEx_w7(FileHandle, NULL, NULL, ApplicationName, Environment, ExeType, Reason,
875 SdbQueryAppCompatData, SdbQueryAppCompatDataSize, SxsData, SxsDataSize,
876 FusionFlags, &SomeFlag1, &SomeFlag2);
877 }
878
879 if (pApphelpCheckRunAppEx_w10)
880 {
881 return pApphelpCheckRunAppEx_w10(FileHandle, NULL, NULL, ApplicationName, Environment, NULL, ExeType, Reason,
882 SdbQueryAppCompatData, SdbQueryAppCompatDataSize, SxsData, SxsDataSize,
883 FusionFlags, &SomeFlag1, &SomeFlag2);
884 }
885
886 return FALSE;
887 }
888
889
890
891
892
893 static void Test_ApphelpCheckRunApp(WCHAR szApphelp[256])
894 {
895 BOOL ret;
896 HANDLE FileHandle = NULL;
897 WCHAR ApplicationName[MAX_PATH], EmptyName[1] = { 0 };
898 DWORD expect_flags = (g_WinVersion < WINVER_WIN10) ? 1 : 0x21;
899
900 USHORT ExeType;
901 PVOID AppCompatData = NULL, SxsData, DuplicatedEnv, Environment;
902 ULONG AppCompatDataSize, SxsDataSize, FusionFlags;
903 ULONG Reason;
904 SDBQUERYRESULT_VISTA Query;
905 int n;
906 /* this are the only interesting bits (with the exception of '1', which is there to invoke the 'default' case) */
907 const int kTestBits = 0x70503;
908
909 if (!pApphelpCheckRunAppEx_w7 && !pApphelpCheckRunAppEx_w10)
910 {
911 skip("No usable ApphelpCheckRunAppEx\n");
912 return;
913 }
914
915 GetModuleFileNameW(NULL, ApplicationName, MAX_PATH);
916
917 FileHandle = xOpenFile(ApplicationName);
918 SetEnvironmentVariableA("__COMPAT_LAYER", NULL);
919 if (!CreateEnvironmentBlock(&DuplicatedEnv, NULL, TRUE))
920 DuplicatedEnv = NULL;
921 ok(DuplicatedEnv != NULL, "Invalid env (%u)\n", GetLastError());
922
923 /* First with the environment without __COMPAT_LAYER */
924 RESET_CHECKRUNAPP_VARS();
925
926 ret = call_ApphelpCheckRunApp(FileHandle, ApplicationName, DuplicatedEnv, ExeType, &Reason,
927 &AppCompatData, &AppCompatDataSize, &SxsData, &SxsDataSize, &FusionFlags);
928
929 CHECK_BASICS();
930 ok_hex(Reason, CHECKREASON(0x30000, 0));
931 ok(!memcmp(AppCompatData, &empty_result, sizeof(empty_result)), "Expected result to be empty\n");
932
933 /* We need this to be set for tests later on. */
934 SetEnvironmentVariableA("__COMPAT_LAYER", "256Color");
935
936 if (g_ModuleVersion < WINVER_WIN10)
937 {
938 /* Showing that when an environment is passed in, that is used instead of the current.
939 In Win10 this behavior is no longer observed */
940
941 RESET_CHECKRUNAPP_VARS();
942
943 ret = call_ApphelpCheckRunApp(FileHandle, ApplicationName, DuplicatedEnv, ExeType, &Reason,
944 &AppCompatData, &AppCompatDataSize, &SxsData, &SxsDataSize, &FusionFlags);
945
946 CHECK_BASICS();
947 ok_hex(Reason, CHECKREASON(0x30000, 0));
948 ok(!memcmp(AppCompatData, &empty_result, sizeof(empty_result)), "Expected result to be empty\n");
949 }
950
951 for (n = 0; n < 32; ++n)
952 {
953 ULONG ExpectedReason;
954 if (!(kTestBits & (1<<n)))
955 continue;
956 RESET_CHECKRUNAPP_VARS();
957 ExpectedReason = Reason = (1 << n);
958 ret = call_ApphelpCheckRunApp(FileHandle, ApplicationName, DuplicatedEnv, ExeType, &Reason,
959 &AppCompatData, &AppCompatDataSize, &SxsData, &SxsDataSize, &FusionFlags);
960
961 CHECK_BASICS();
962 if (ExpectedReason == 2)
963 ExpectedReason = 2;
964 else if (ExpectedReason == 0x100)
965 ExpectedReason = 0x30000;
966 else
967 ExpectedReason |= 0x30000;
968 ok_hex(Reason, CHECKREASON(ExpectedReason, (1 << n)));
969 ok(!memcmp(AppCompatData, &empty_result, sizeof(empty_result)), "Expected result to be empty\n");
970 }
971
972 if (g_ModuleVersion < WINVER_WIN10)
973 {
974 /* Now, using a NULL env, showing that the current environment is used.
975 W10 does no longer do this, so we skip this test here. */
976 Environment = NULL;
977
978 RESET_CHECKRUNAPP_VARS();
979
980 ret = call_ApphelpCheckRunApp(FileHandle, ApplicationName, Environment, ExeType, &Reason,
981 &AppCompatData, &AppCompatDataSize, &SxsData, &SxsDataSize, &FusionFlags);
982
983 CHECK_BASICS();
984 ok_hex(Reason, CHECKREASON(0x50000, 0));
985 if (AppCompatData && AppCompatDataSize == sizeof(SDBQUERYRESULT_VISTA))
986 expect_layeronly(AppCompatData, "256Color", expect_flags);
987
988 for (n = 0; n < 32; ++n)
989 {
990 ULONG ExpectedReason;
991 RESET_CHECKRUNAPP_VARS();
992 if (!(kTestBits & (1<<n)))
993 continue;
994 ExpectedReason = Reason = (1 << n);
995 ret = call_ApphelpCheckRunApp(FileHandle, ApplicationName, Environment, ExeType, &Reason,
996 &AppCompatData, &AppCompatDataSize, &SxsData, &SxsDataSize, &FusionFlags);
997
998 CHECK_BASICS();
999 if (ExpectedReason == 2)
1000 ExpectedReason = 2;
1001 else if (ExpectedReason == 0x100)
1002 ExpectedReason = 0x50000;
1003 else if (ExpectedReason == 0x400)
1004 ExpectedReason = 0x30400;
1005 else
1006 ExpectedReason |= 0x50000;
1007 ok_hex(Reason, CHECKREASON(ExpectedReason, (1 << n)));
1008 if (AppCompatData && AppCompatDataSize == sizeof(SDBQUERYRESULT_VISTA))
1009 {
1010 if (ExpectedReason != 0x30400)
1011 expect_layeronly(AppCompatData, "256Color", expect_flags);
1012 else
1013 ok(!memcmp(AppCompatData, &empty_result, sizeof(empty_result)), "Expected result to be empty\n");
1014 }
1015 }
1016 }
1017
1018 /* Passing in an environment with __COMPAT_LAYER set */
1019 Environment = GetEnvironmentStringsW();
1020
1021 RESET_CHECKRUNAPP_VARS();
1022
1023 ret = call_ApphelpCheckRunApp(FileHandle, ApplicationName, Environment, ExeType, &Reason,
1024 &AppCompatData, &AppCompatDataSize, &SxsData, &SxsDataSize, &FusionFlags);
1025
1026 CHECK_BASICS();
1027 ok_hex(Reason, CHECKREASON(0x50000, 0));
1028 if (AppCompatData && AppCompatDataSize == sizeof(SDBQUERYRESULT_VISTA))
1029 expect_layeronly(AppCompatData, "256Color", expect_flags);
1030
1031 for (n = 0; n < 32; ++n)
1032 {
1033 ULONG ExpectedReason;
1034 if (!(kTestBits & (1<<n)))
1035 continue;
1036 RESET_CHECKRUNAPP_VARS();
1037 ExpectedReason = Reason = (1 << n);
1038 ret = call_ApphelpCheckRunApp(FileHandle, ApplicationName, Environment, ExeType, &Reason,
1039 &AppCompatData, &AppCompatDataSize, &SxsData, &SxsDataSize, &FusionFlags);
1040
1041 CHECK_BASICS();
1042 if (ExpectedReason == 2)
1043 ExpectedReason = 2;
1044 else if (ExpectedReason == 0x100)
1045 ExpectedReason = 0x50000;
1046 else if (ExpectedReason == 0x400)
1047 ExpectedReason = 0x30400;
1048 else
1049 ExpectedReason |= 0x50000;
1050 ok_hex(Reason, CHECKREASON(ExpectedReason, (1 << n)));
1051 if (AppCompatData && AppCompatDataSize == sizeof(SDBQUERYRESULT_VISTA))
1052 {
1053 if (ExpectedReason != 0x30400 || g_ModuleVersion >= WINVER_WIN10)
1054 expect_layeronly(AppCompatData, "256Color", expect_flags);
1055 else
1056 ok(!memcmp(AppCompatData, &empty_result, sizeof(empty_result)), "Expected result to be empty\n");
1057 }
1058 }
1059
1060 /* NULL file handle still works */
1061 RESET_CHECKRUNAPP_VARS();
1062
1063 ret = call_ApphelpCheckRunApp(NULL, ApplicationName, Environment, ExeType, &Reason,
1064 &AppCompatData, &AppCompatDataSize, &SxsData, &SxsDataSize, &FusionFlags);
1065
1066 CHECK_BASICS();
1067 ok_hex(Reason, CHECKREASON(0x50000, 0));
1068 if (AppCompatData && AppCompatDataSize == sizeof(SDBQUERYRESULT_VISTA))
1069 expect_layeronly(AppCompatData, "256Color", expect_flags);
1070
1071 for (n = 0; n < 32; ++n)
1072 {
1073 ULONG ExpectedReason;
1074 RESET_CHECKRUNAPP_VARS();
1075 if (!(kTestBits & (1<<n)))
1076 continue;
1077 ExpectedReason = Reason = (1 << n);
1078 ret = call_ApphelpCheckRunApp(NULL, ApplicationName, Environment, ExeType, &Reason,
1079 &AppCompatData, &AppCompatDataSize, &SxsData, &SxsDataSize, &FusionFlags);
1080
1081 CHECK_BASICS();
1082 if (ExpectedReason == 2)
1083 ExpectedReason = 2;
1084 else if (ExpectedReason == 0x100)
1085 ExpectedReason = 0x50000;
1086 else if (ExpectedReason == 0x400)
1087 ExpectedReason = 0x30400;
1088 else
1089 ExpectedReason |= 0x50000;
1090 ok_hex(Reason, CHECKREASON(ExpectedReason, (1 << n)));
1091 if (AppCompatData && AppCompatDataSize == sizeof(SDBQUERYRESULT_VISTA))
1092 {
1093 /* W10 does not use the flags anymore? */
1094 if (ExpectedReason != 0x30400 || g_ModuleVersion >= WINVER_WIN10)
1095 expect_layeronly(AppCompatData, "256Color", expect_flags);
1096 else
1097 ok(!memcmp(AppCompatData, &empty_result, sizeof(empty_result)), "Expected result to be empty\n");
1098 }
1099 }
1100
1101
1102 /* INVALID_HANDLE_VALUE file handle results in failure (according to flags!), but still results in AppCompatData */
1103 RESET_CHECKRUNAPP_VARS();
1104
1105 ret = call_ApphelpCheckRunApp(INVALID_HANDLE_VALUE, ApplicationName, Environment, ExeType, &Reason,
1106 &AppCompatData, &AppCompatDataSize, &SxsData, &SxsDataSize, &FusionFlags);
1107
1108 CHECK_BASICS();
1109 ok_hex(Reason, 0);
1110 if (AppCompatData && AppCompatDataSize == sizeof(SDBQUERYRESULT_VISTA))
1111 expect_layeronly(AppCompatData, "256Color", expect_flags);
1112
1113 for (n = 0; n < 32; ++n)
1114 {
1115 ULONG ExpectedReason;
1116 if (!(kTestBits & (1<<n)))
1117 continue;
1118 RESET_CHECKRUNAPP_VARS();
1119 ExpectedReason = Reason = (1 << n);
1120 ret = call_ApphelpCheckRunApp(INVALID_HANDLE_VALUE, NULL, Environment, ExeType, &Reason,
1121 &AppCompatData, &AppCompatDataSize, &SxsData, &SxsDataSize, &FusionFlags);
1122
1123 CHECK_BASICS();
1124 if (ExpectedReason == 0x100)
1125 ExpectedReason = 0;
1126 ok_hex(Reason, CHECKREASON(ExpectedReason, (1 << n)));
1127 if (AppCompatData && AppCompatDataSize == sizeof(SDBQUERYRESULT_VISTA))
1128 {
1129 if (ExpectedReason != 0x400 && g_ModuleVersion < WINVER_WIN7)
1130 expect_layeronly(AppCompatData, "256Color", expect_flags);
1131 else
1132 ok(!memcmp(AppCompatData, &empty_result, sizeof(empty_result)), "Expected result to be empty\n");
1133 }
1134 }
1135
1136 /* NULL filename crashes, showing this in the log before going down:
1137 [Err ][SdbpGetLongFileName ] Failed to get NT path name for ""
1138 [Err ][SdbpCreateSearchDBContext] Unable to parse executable path for "".
1139 [Err ][SdbGetMatchingExe ] Failed to create search DB context.
1140 */
1141 RESET_CHECKRUNAPP_VARS();
1142
1143 ret = call_ApphelpCheckRunApp(FileHandle, EmptyName, Environment, ExeType, &Reason,
1144 &AppCompatData, &AppCompatDataSize, &SxsData, &SxsDataSize, &FusionFlags);
1145
1146 CHECK_BASICS();
1147 ok_hex(Reason, CHECKREASON(0x30000, 0));
1148 if (AppCompatData && AppCompatDataSize == sizeof(SDBQUERYRESULT_VISTA))
1149 ok(!memcmp(AppCompatData, &empty_result, sizeof(empty_result)), "Expected result to be empty\n");
1150
1151 /* 0 ExeType = don't care? */
1152 RESET_CHECKRUNAPP_VARS();
1153 ExeType = 0;
1154
1155 ret = call_ApphelpCheckRunApp(FileHandle, ApplicationName, Environment, ExeType, &Reason,
1156 &AppCompatData, &AppCompatDataSize, &SxsData, &SxsDataSize, &FusionFlags);
1157
1158 CHECK_BASICS();
1159 ok_hex(Reason, CHECKREASON(0x50000, 0));
1160 if (AppCompatData && AppCompatDataSize == sizeof(SDBQUERYRESULT_VISTA))
1161 expect_layeronly(AppCompatData, "256Color", expect_flags);
1162
1163 for (n = 0; n < 32; ++n)
1164 {
1165 ULONG ExpectedReason;
1166 if (!(kTestBits & (1<<n)))
1167 continue;
1168 RESET_CHECKRUNAPP_VARS();
1169 ExeType = 0;
1170 ExpectedReason = Reason = (1 << n);
1171 ret = call_ApphelpCheckRunApp(FileHandle, ApplicationName, Environment, ExeType, &Reason,
1172 &AppCompatData, &AppCompatDataSize, &SxsData, &SxsDataSize, &FusionFlags);
1173
1174 CHECK_BASICS();
1175 if (ExpectedReason == 2)
1176 ExpectedReason = 2;
1177 else if (ExpectedReason == 0x100)
1178 ExpectedReason = 0x50000;
1179 else if (ExpectedReason == 0x400)
1180 ExpectedReason = 0x30400;
1181 else
1182 ExpectedReason |= 0x50000;
1183 ok_hex(Reason, CHECKREASON(ExpectedReason, (1 << n)));
1184 if (AppCompatData && AppCompatDataSize == sizeof(SDBQUERYRESULT_VISTA))
1185 {
1186 if (ExpectedReason != 0x30400 || g_ModuleVersion >= WINVER_WIN10)
1187 expect_layeronly(AppCompatData, "256Color", expect_flags);
1188 else
1189 ok(!memcmp(AppCompatData, &empty_result, sizeof(empty_result)), "Expected result to be empty\n");
1190 }
1191 }
1192
1193
1194 RESET_CHECKRUNAPP_VARS();
1195 ExeType = IMAGE_FILE_MACHINE_POWERPCFP;
1196
1197 ret = call_ApphelpCheckRunApp(FileHandle, ApplicationName, Environment, ExeType, &Reason,
1198 &AppCompatData, &AppCompatDataSize, &SxsData, &SxsDataSize, &FusionFlags);
1199
1200 CHECK_BASICS();
1201 ok_hex(Reason, CHECKREASON(0x50000, 0));
1202 if (AppCompatData && AppCompatDataSize == sizeof(SDBQUERYRESULT_VISTA))
1203 expect_layeronly(AppCompatData, "256Color", expect_flags);
1204
1205 for (n = 0; n < 32; ++n)
1206 {
1207 ULONG ExpectedReason;
1208 if (!(kTestBits & (1<<n)))
1209 continue;
1210 RESET_CHECKRUNAPP_VARS();
1211 ExeType = IMAGE_FILE_MACHINE_POWERPCFP;
1212 ExpectedReason = Reason = (1 << n);
1213 ret = call_ApphelpCheckRunApp(FileHandle, ApplicationName, Environment, ExeType, &Reason,
1214 &AppCompatData, &AppCompatDataSize, &SxsData, &SxsDataSize, &FusionFlags);
1215
1216 CHECK_BASICS();
1217 if (ExpectedReason == 2)
1218 ExpectedReason = 2;
1219 else if (ExpectedReason == 0x100)
1220 ExpectedReason = 0x50000;
1221 else if (ExpectedReason == 0x400)
1222 ExpectedReason = 0x30400;
1223 else
1224 ExpectedReason |= 0x50000;
1225 ok_hex(Reason, CHECKREASON(ExpectedReason, (1 << n)));
1226 if (AppCompatData && AppCompatDataSize == sizeof(SDBQUERYRESULT_VISTA))
1227 {
1228 if (ExpectedReason != 0x30400 || g_ModuleVersion >= WINVER_WIN10)
1229 expect_layeronly(AppCompatData, "256Color", expect_flags);
1230 else
1231 ok(!memcmp(AppCompatData, &empty_result, sizeof(empty_result)), "Expected result to be empty\n");
1232 }
1233 }
1234
1235
1236 if (AppCompatData && AppCompatData != &Query)
1237 RtlFreeHeap(RtlGetProcessHeap(), 0, AppCompatData);
1238
1239 FreeEnvironmentStringsW(Environment);
1240 DestroyEnvironmentBlock(DuplicatedEnv);
1241 NtClose(FileHandle);
1242 }
1243
1244
1245 START_TEST(env)
1246 {
1247 WCHAR szApphelp[MAX_PATH];
1248 ShimData_QueryOffset QueryOffset;
1249 DWORD ShimDataType;
1250 NTSTATUS ExceptionStatus = STATUS_SUCCESS;
1251
1252 //SetEnvironmentVariable("SHIM_DEBUG_LEVEL", "127");
1253 //SetEnvironmentVariable("SHIMENG_DEBUG_LEVEL", "127");
1254
1255 silence_debug_output();
1256
1257 hdll = LoadLibraryA("apphelp.dll");
1258
1259
1260
1261 g_WinVersion = get_host_winver();
1262 g_ModuleVersion = get_module_version(hdll);
1263 trace("Detected host: 0x%x, module: 0x%x\n", g_WinVersion, g_ModuleVersion);
1264
1265 GetModuleFileNameW(hdll, szApphelp, _countof(szApphelp));
1266
1267
1268 pSdbGetMatchingExe = (void*)GetProcAddress(hdll, "SdbGetMatchingExe");
1269 pSdbInitDatabase = (void*)GetProcAddress(hdll, "SdbInitDatabase");
1270 pSdbReleaseDatabase = (void*)GetProcAddress(hdll, "SdbReleaseDatabase");
1271 pSdbTagRefToTagID = (void*)GetProcAddress(hdll, "SdbTagRefToTagID");
1272 pSdbGetTagFromTagID = (void*)GetProcAddress(hdll, "SdbGetTagFromTagID");
1273 pSdbGetLayerTagRef = (void*)GetProcAddress(hdll, "SdbGetLayerTagRef");
1274
1275 switch (g_ModuleVersion)
1276 {
1277 case WINVER_WIN7:
1278 pApphelpCheckRunAppEx_w7 = (void*)GetProcAddress(hdll, "ApphelpCheckRunAppEx");
1279 break;
1280 case WINVER_WIN10:
1281 pApphelpCheckRunAppEx_w10 = (void*)GetProcAddress(hdll, "ApphelpCheckRunAppEx");
1282 break;
1283 default:
1284 skip("Unknown apphelp.dll version %x, cannot determine which ApphelpCheckRunApp(Ex) function to use\n", g_ModuleVersion);
1285 break;
1286 }
1287
1288 pSdbPackAppCompatData = (void*)GetProcAddress(hdll, "SdbPackAppCompatData");
1289 pSdbUnpackAppCompatData = (void*)GetProcAddress(hdll, "SdbUnpackAppCompatData");
1290 pSdbGetAppCompatDataSize = (void*)GetProcAddress(hdll, "SdbGetAppCompatDataSize");
1291
1292
1293 memset(&QueryOffset, 0, sizeof(QueryOffset));
1294 QueryOffset.dwMagic_2k3 = QueryOffset.dwMagic_7_10 = QueryOffset.dwMagic_10_v2 = SHIMDATA_MAGIC;
1295 QueryOffset.dwSize_2k3 = 1;
1296 QueryOffset.dwSize_7_10 = 2;
1297 QueryOffset.dwSize_10_v2 = 3;
1298
1299 g_ShimDataSize = g_WinVersion < WINVER_WIN10 ? 4096 : 8192;
1300 _SEH2_TRY
1301 {
1302 ShimDataType = pSdbGetAppCompatDataSize(&QueryOffset);
1303 }
1304 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1305 {
1306 ExceptionStatus = _SEH2_GetExceptionCode();
1307 }
1308 _SEH2_END;
1309
1310 ok(ExceptionStatus == STATUS_SUCCESS, "Exception 0x%08x, expected 0x%08x\n", ExceptionStatus, STATUS_SUCCESS);
1311 if (ExceptionStatus != STATUS_SUCCESS)
1312 {
1313 skip("SdbGetAppCompatDataSize not functional\n");
1314 return;
1315 }
1316
1317 /* New version of Win10.. */
1318 if (g_WinVersion == WINVER_WIN10 && ShimDataType == 3)
1319 g_ShimDataSize = 4096;
1320
1321 if (g_WinVersion == g_ModuleVersion)
1322 {
1323 Test_layers(szApphelp);
1324 Test_repeatlayer(szApphelp);
1325 }
1326 else
1327 {
1328 skip("Tests requiring process launch, reported OS version (0x%x) does not match apphelp version (0x%x)\n", g_WinVersion, g_ModuleVersion);
1329 }
1330
1331 {
1332 Test_GetMatchingExe();
1333 }
1334
1335 Test_ApphelpCheckRunApp(szApphelp);
1336 if (g_LayerDB)
1337 pSdbReleaseDatabase(g_LayerDB);
1338 }
1339