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