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