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