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