Something went wrong. Try again.
Reactos
Something went wrong. Try again.
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477/* * PROJECT: apphelp_apitest * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) * PURPOSE: Tests showing shim artifacts in the environment * COPYRIGHT: Copyright 2016,2017 Mark Jansen (mark.jansen@reactos.org) */
#include <ntstatus.h>#define WIN32_NO_STATUS#include <windows.h>#include <shlwapi.h>#include <winnt.h>#include <userenv.h>#ifdef __REACTOS__#include <ntndk.h>#else#include <winternl.h>#endif#include <winerror.h>#include <stdio.h>
#include "wine/test.h"
#include <pseh/pseh2.h>
#include "apphelp_apitest.h"
typedef void* HSDB;typedef void* PDB;typedef DWORD TAGREF;typedef WORD TAG;
static HMODULE hdll;
BOOL(WINAPI *pSdbGetMatchingExe)(HSDB hsdb, LPCWSTR szPath, LPCWSTR szModuleName, LPCWSTR pszEnvironment, DWORD dwFlags, PSDBQUERYRESULT_VISTA pQueryResult);HSDB (WINAPI *pSdbInitDatabase)(DWORD dwFlags, LPCWSTR pszDatabasePath);void (WINAPI *pSdbReleaseDatabase)(HSDB hsdb);BOOL (WINAPI *pSdbTagRefToTagID)(HSDB hsdb, TAGREF trWhich, PDB* ppdb, TAGID* ptiWhich);TAG (WINAPI *pSdbGetTagFromTagID)(PDB pdb, TAGID tiWhich);TAGREF (WINAPI *pSdbGetLayerTagRef)(HSDB hsdb, LPCWSTR layerName);
/* TODO: Investigate ApphelpCheckRunApp, for some reason there is not AppCompatData generated... */
BOOL (WINAPI *pApphelpCheckRunAppEx_w7)(HANDLE FileHandle, PVOID Unk1, PVOID Unk2, PWCHAR ApplicationName, PVOID Environment, USHORT ExeType, PULONG Reason, PVOID* SdbQueryAppCompatData, PULONG SdbQueryAppCompatDataSize, PVOID* SxsData, PULONG SxsDataSize, PULONG FusionFlags, PULONG64 SomeFlag1, PULONG SomeFlag2);
BOOL (WINAPI *pApphelpCheckRunAppEx_w10)(HANDLE FileHandle, PVOID Unk1, PVOID Unk2, PWCHAR ApplicationName, PVOID Environment, PVOID Unk3, USHORT ExeType, PULONG Reason, PVOID* SdbQueryAppCompatData, PULONG SdbQueryAppCompatDataSize, PVOID* SxsData, PULONG SxsDataSize, PULONG FusionFlags, PULONG64 SomeFlag1, PULONG SomeFlag2);
BOOL (WINAPI *pSdbPackAppCompatData)(HSDB hsdb, PSDBQUERYRESULT_VISTA pQueryResult, PVOID* ppData, DWORD *dwSize);BOOL (WINAPI *pSdbUnpackAppCompatData)(HSDB hsdb, LPCWSTR pszImageName, PVOID pData, PSDBQUERYRESULT_VISTA pQueryResult);DWORD (WINAPI *pSdbGetAppCompatDataSize)(PVOID pData);
static HSDB g_LayerDB;static DWORD g_ShimDataSize;static DWORD g_ModuleVersion;static const SDBQUERYRESULT_VISTA empty_result = { { 0 } };static const SDBQUERYRESULT_VISTA almost_empty = { { 0 }, { 0 }, { 0 }, 0, 0, 0, 0, { 0 }, SHIMREG_DISABLE_LAYER, 0 };
#define SHIMDATA_MAGIC 0xAC0DEDAB#define MAX_LAYER_LENGTH 256
typedef struct ShimData_Win2k3{ WCHAR szModule[34]; DWORD dwSize; DWORD dwMagic;
TAGREF atrExes[SDB_MAX_EXES_2k3]; TAGREF atrLayers[SDB_MAX_LAYERS]; DWORD dwUnk0; DWORD dwUnk1; DWORD dwCustomSDBMap; GUID rgGuidDB[SDB_MAX_SDBS];} ShimData_Win2k3;
typedef struct ShimData_WinVista{ WCHAR szModule[260]; DWORD dwSize; DWORD dwMagic; SDBQUERYRESULT_VISTA Query;} ShimData_WinVista;
typedef struct ShimData_Win7{ WCHAR szModule[260]; DWORD dwSize; DWORD dwMagic; SDBQUERYRESULT_VISTA Query; WCHAR szLayer[MAX_LAYER_LENGTH]; DWORD unknown; // 0x14c} ShimData_Win7;
typedef struct ShimData_Win8{ WCHAR szModule[260]; DWORD dwSize; DWORD dwMagic; DWORD unk1; SDBQUERYRESULT_VISTA Query; WCHAR szLayer[MAX_LAYER_LENGTH]; char padding1[0x200]; char padding2[0x404]; DWORD unk2; DWORD unk3; WCHAR processname[MAX_PATH]; WCHAR szLayerEnv[MAX_LAYER_LENGTH]; WCHAR unk4[MAX_LAYER_LENGTH]; char padding4[112];} ShimData_Win8;
typedef struct ShimData_Win10_v1{ WCHAR szModule[260]; DWORD dwSize; DWORD dwMagic; DWORD unk1; SDBQUERYRESULT_VISTA Query; WCHAR szLayer[MAX_LAYER_LENGTH]; char padding1[0x200]; char padding2[0x404]; // Contains some data at the start DWORD unk2; DWORD unk3; WCHAR processname[MAX_PATH]; WCHAR szLayerEnv[MAX_LAYER_LENGTH]; WCHAR unk4[MAX_LAYER_LENGTH]; char padding4[120];} ShimData_Win10_v1;
typedef struct ShimData_Win10_v2{ DWORD dwSize; DWORD dwMagic; DWORD unk1; DWORD unk2; SDBQUERYRESULT_VISTA Query; WCHAR szLayer[MAX_LAYER_LENGTH]; char padding1[0x200]; char padding2[0x2ae + 0x54 + 0x2a + 0x16 + 0x16]; DWORD unk3; DWORD unk4; WCHAR processname[MAX_PATH-2]; WCHAR szLayerEnv[MAX_LAYER_LENGTH]; WCHAR unk5[MAX_LAYER_LENGTH]; char padding4[76];} ShimData_Win10_v2;
typedef struct ShimData_QueryOffset{ DWORD dwSize_10_v2; DWORD dwMagic_10_v2;
char spacing1[60];
DWORD dwSize_2k3; DWORD dwMagic_2k3;
char spacing2[444];
DWORD dwSize_7_10; DWORD dwMagic_7_10;} ShimData_QueryOffset;
C_ASSERT(sizeof(ShimData_Win2k3) == 392);C_ASSERT(sizeof(ShimData_WinVista) == 984);C_ASSERT(sizeof(ShimData_Win7) == 1500);C_ASSERT(sizeof(ShimData_Win8) == 4704);C_ASSERT(sizeof(ShimData_Win10_v1) == 4712);C_ASSERT(sizeof(ShimData_Win10_v2) == 3976);
C_ASSERT(offsetof(ShimData_Win10_v2, dwSize) == 0);C_ASSERT(offsetof(ShimData_Win2k3, dwSize) == 68);C_ASSERT(offsetof(ShimData_Win7, dwSize) == 520);C_ASSERT(offsetof(ShimData_Win10_v1, dwSize) == 520);
C_ASSERT(offsetof(ShimData_Win10_v2, dwMagic) == 4);C_ASSERT(offsetof(ShimData_Win2k3, dwMagic) == 72);C_ASSERT(offsetof(ShimData_Win7, dwMagic) == 524);C_ASSERT(offsetof(ShimData_Win10_v1, dwMagic) == 524);
C_ASSERT(offsetof(ShimData_QueryOffset, dwSize_10_v2) == 0);C_ASSERT(offsetof(ShimData_QueryOffset, dwSize_2k3) == 68);C_ASSERT(offsetof(ShimData_QueryOffset, dwSize_7_10) == 520);
C_ASSERT(offsetof(ShimData_QueryOffset, dwMagic_10_v2) == 4);C_ASSERT(offsetof(ShimData_QueryOffset, dwMagic_2k3) == 72);C_ASSERT(offsetof(ShimData_QueryOffset, dwMagic_7_10) == 524);
#define SDB_DATABASE_MAIN_SHIM 0x80030000
#define SDBGMEF_IGNORE_ENVIRONMENT 0x1
typedef struct test_RemoteShimInfo{ ULARGE_INTEGER AppCompatFlags; ULARGE_INTEGER AppCompatFlagsUser; PVOID pShimData; DWORD ShimDataSize; PVOID AppCompatInfo;} test_RemoteShimInfo;
static BOOL readproc(HANDLE proc, LPVOID address, PVOID target, DWORD size){ SIZE_T dwRead; if (ReadProcessMemory(proc, address, target, size, &dwRead)) { ok(dwRead == size, "Expected to read %lu bytes, got %Iu\n", size, dwRead); return dwRead == size; } ok(0, "RPM failed with %lu\n", GetLastError()); return FALSE;}
static BOOL get_shiminfo(HANDLE proc, test_RemoteShimInfo* info){ PROCESS_BASIC_INFORMATION pbi = { 0 }; ULONG sizeOut = 0; NTSTATUS status = NtQueryInformationProcess(proc, ProcessBasicInformation, &pbi, sizeof(pbi), &sizeOut); ok(NT_SUCCESS(status), "Expected NtQI to succeed, but failed with: %lx\n", status); memset(info, 0, sizeof(*info)); if (NT_SUCCESS(status)) { PEB peb = { 0 }; if (readproc(proc, pbi.PebBaseAddress, &peb, sizeof(peb))) { MEMORY_BASIC_INFORMATION mbi = { 0 }; SIZE_T dwRead;
info->AppCompatFlags = peb.AppCompatFlags; info->AppCompatFlagsUser = peb.AppCompatFlagsUser; info->AppCompatInfo = peb.AppCompatInfo; if (peb.pShimData == NULL) return TRUE;
dwRead = VirtualQueryEx(proc, (LPCVOID)peb.pShimData, &mbi, sizeof(mbi)); ok(dwRead == sizeof(mbi), "Expected VQE to return %u, got %Iu\n", sizeof(mbi), dwRead); if (dwRead == sizeof(mbi) || peb.pShimData == NULL) { info->ShimDataSize = mbi.RegionSize; info->pShimData = malloc(mbi.RegionSize); if (readproc(proc, peb.pShimData, info->pShimData, mbi.RegionSize)) return TRUE; free(info->pShimData); info->pShimData = NULL; } } } return FALSE;}
static HANDLE create_proc(BOOL suspended){ static char proc_name[MAX_PATH] = { 0 }; STARTUPINFOA si = {sizeof(si)}; PROCESS_INFORMATION pi; BOOL res; if (!proc_name[0]) { GetModuleFileNameA(NULL, proc_name, MAX_PATH); }
res = CreateProcessA(NULL, proc_name, NULL, NULL, TRUE, suspended ? CREATE_SUSPENDED : 0, NULL, NULL, &si, &pi); if (!res) return NULL; CloseHandle(pi.hThread); return pi.hProcess;}
static void create_environ(const char* layers[], size_t num){ char buf[256] = { 0 }; size_t n; for (n = 0; n < num; ++n) { if (n) strcat(buf, " "); strcat(buf, layers[n]); } SetEnvironmentVariableA("__COMPAT_LAYER", buf);}
static void ValidateShim(TAGREF trLayer, const char* name){ HSDB hsdb = pSdbInitDatabase(SDB_DATABASE_MAIN_SHIM, NULL); ok(hsdb != NULL, "Expected a valid handle\n"); if (hsdb) { PDB pdb = NULL; TAGID tagid = 0xdeadbeef; WCHAR nameW[256] = { 0 }; BOOL ret;
mbstowcs(nameW, name, strlen(name));
ret = pSdbTagRefToTagID(hsdb, trLayer, &pdb, &tagid); ok(ret == TRUE, "Expected pSdbTagRefToTagID to succeed\n"); if (ret) { TAG tag; ok(pdb != NULL, "Expected pdb to be a valid pointer\n"); ok(tagid != 0 && tagid != 0xdeadbeef, "Expected tagid to be a valid tag id, was: 0x%lx\n", tagid); tag = pSdbGetTagFromTagID(pdb, tagid); ok(tag == 0x700b, "Expected tag to be 0x700b, was 0x%lx\n", (DWORD)tag); }
pSdbReleaseDatabase(hsdb); }}
static void Validate_ShimData_Win2k3(PVOID data, size_t count, const char* layers[]){ //size_t n; ShimData_Win2k3* pShimData = (ShimData_Win2k3*)data;
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)); ok(pShimData->dwMagic == SHIMDATA_MAGIC, "Expected pShimData->dwMagic to be 0x%x, was 0x%lx\n", SHIMDATA_MAGIC, pShimData->dwMagic); ok(pShimData->dwSize == sizeof(ShimData_Win2k3), "Expected pShimData->dwSize to be %u, was %lu\n", sizeof(ShimData_Win2k3), pShimData->dwSize); ok(pShimData->dwCustomSDBMap == 1, "Expected pShimData->dwCustomSDBMap to be 1, was %lu\n", pShimData->dwCustomSDBMap);}
static void Validate_ShimData_WinVista(PVOID data, size_t count, const char* layers[]){ size_t n; ShimData_WinVista* pShimData = (ShimData_WinVista*)data; WCHAR szShimEng[MAX_PATH]; HMODULE hShimEngDll = LoadLibraryA("ShimEng.dll");
GetModuleFileNameW(hShimEngDll, szShimEng, _countof(szShimEng));
ok(!lstrcmpW(pShimData->szModule, szShimEng), "Expected pShimData->Module to be %s, was %s\n", wine_dbgstr_w(szShimEng), wine_dbgstr_w(pShimData->szModule)); ok(pShimData->dwMagic == SHIMDATA_MAGIC, "Expected pShimData->dwMagic to be 0x%x, was 0x%lx\n", SHIMDATA_MAGIC, pShimData->dwMagic); ok(pShimData->dwSize == sizeof(ShimData_WinVista), "Expected pShimData->dwSize to be %u, was %lu\n", sizeof(ShimData_WinVista), pShimData->dwSize); if (pShimData->Query.dwLayerCount != min(count, SDB_MAX_LAYERS)) { char buf[250] = {0}; GetEnvironmentVariableA("__COMPAT_LAYER", buf, _countof(buf)); trace("At test: %s\n", buf); } ok(pShimData->Query.dwLayerCount == min(count, SDB_MAX_LAYERS), "Expected LayerCount to be %u, was %lu\n", min(count, SDB_MAX_LAYERS), pShimData->Query.dwLayerCount); for (n = 0; n < SDB_MAX_LAYERS; ++n) { if (n < count) { ok(pShimData->Query.atrLayers[n] != 0, "Expected to find a valid layer in index %Iu / %Iu\n", n, count); ValidateShim(pShimData->Query.atrLayers[n], layers[n]); } else ok(pShimData->Query.atrLayers[n] == 0, "Expected to find an empty layer in index %Iu / %Iu\n", n, count); }}
static void Validate_ShimData_Win7(PVOID data, WCHAR szApphelp[256], size_t count, const char* layers[]){ size_t n; ShimData_Win7* pShimData = (ShimData_Win7*)data;
ok(!lstrcmpW(pShimData->szModule, szApphelp), "Expected pShimData->Module to be %s, was %s\n", wine_dbgstr_w(szApphelp), wine_dbgstr_w(pShimData->szModule)); ok(pShimData->dwMagic == SHIMDATA_MAGIC, "Expected pShimData->dwMagic to be 0x%x, was 0x%lx\n", SHIMDATA_MAGIC, pShimData->dwMagic); ok(pShimData->dwSize == sizeof(ShimData_Win7), "Expected pShimData->dwSize to be %u, was %lu\n", sizeof(ShimData_Win7), pShimData->dwSize); if (pShimData->Query.dwLayerCount != min(count, SDB_MAX_LAYERS)) { char buf[250] = {0}; GetEnvironmentVariableA("__COMPAT_LAYER", buf, _countof(buf)); trace("At test: %s\n", buf); } ok(pShimData->Query.dwLayerCount == min(count, SDB_MAX_LAYERS), "Expected LayerCount to be %u, was %lu\n", min(count, SDB_MAX_LAYERS), pShimData->Query.dwLayerCount); for (n = 0; n < SDB_MAX_LAYERS; ++n) { if (n < count) { ok(pShimData->Query.atrLayers[n] != 0, "Expected to find a valid layer in index %Iu / %Iu\n", n, count); ValidateShim(pShimData->Query.atrLayers[n], layers[n]); } else ok(pShimData->Query.atrLayers[n] == 0, "Expected to find an empty layer in index %Iu / %Iu\n", n, count); } ok(pShimData->unknown == 0x14c, "Expected pShimData->unknown to be 0x14c, was 0x%lx\n", pShimData->unknown);}
static void Validate_ShimData_Win8(PVOID data, WCHAR szApphelp[256], size_t count, const char* layers[]){ size_t n; ShimData_Win8* pShimData = (ShimData_Win8*)data;
ok(!lstrcmpiW(pShimData->szModule, szApphelp), "Expected pShimData->Module to be %s, was %s\n", wine_dbgstr_w(szApphelp), wine_dbgstr_w(pShimData->szModule)); ok(pShimData->dwSize == sizeof(ShimData_Win8), "Expected pShimData->dwSize to be %u, was %lu\n", sizeof(ShimData_Win8), pShimData->dwSize); if (pShimData->Query.dwLayerCount != min(count, SDB_MAX_LAYERS)) { char buf[250] = {0}; GetEnvironmentVariableA("__COMPAT_LAYER", buf, _countof(buf)); trace("At test: %s\n", buf); } ok(pShimData->Query.dwLayerCount == min(count, SDB_MAX_LAYERS), "Expected LayerCount to be %Iu, was %lu\n", min(count, SDB_MAX_LAYERS), pShimData->Query.dwLayerCount); for (n = 0; n < SDB_MAX_LAYERS; ++n) { if (n < count) { ok(pShimData->Query.atrLayers[n] != 0, "Expected to find a valid layer in index %Iu / %Iu\n", n, count); ValidateShim(pShimData->Query.atrLayers[n], layers[n]); } else ok(pShimData->Query.atrLayers[n] == 0, "Expected to find an empty layer in index %Iu / %Iu\n", n, count); }}
static void Validate_ShimData_Win10_v2(PVOID data, WCHAR szApphelp[256], size_t count, const char* layers[]){ size_t n; ShimData_Win10_v2* pShimData = (ShimData_Win10_v2*)data;
if (pShimData->dwMagic != SHIMDATA_MAGIC) { skip("Yet another unknown shimdata variant...\n"); return; }
ok(pShimData->dwSize == sizeof(ShimData_Win10_v2), "Expected pShimData->dwSize to be %u, was %Iu\n", sizeof(ShimData_Win10_v2), pShimData->dwSize); if (pShimData->Query.dwLayerCount != min(count, SDB_MAX_LAYERS)) { char buf[250] = {0}; GetEnvironmentVariableA("__COMPAT_LAYER", buf, _countof(buf)); trace("At test: %s\n", buf); } ok(pShimData->Query.dwLayerCount == min(count, SDB_MAX_LAYERS), "Expected LayerCount to be %u, was %Iu\n", min(count, SDB_MAX_LAYERS), pShimData->Query.dwLayerCount); for (n = 0; n < SDB_MAX_LAYERS; ++n) { if (n < count) { ok(pShimData->Query.atrLayers[n] != 0, "Expected to find a valid layer in index %Iu / %Iu\n", n, count); ValidateShim(pShimData->Query.atrLayers[n], layers[n]); } else ok(pShimData->Query.atrLayers[n] == 0, "Expected to find an empty layer in index %Iu / %Iu\n", n, count); }
}
static void Validate_ShimData_Win10(PVOID data, WCHAR szApphelp[256], size_t count, const char* layers[]){ size_t n; ShimData_Win10_v1* pShimData = (ShimData_Win10_v1*)data;
if (pShimData->dwMagic != SHIMDATA_MAGIC) { Validate_ShimData_Win10_v2(data, szApphelp, count, layers); return; }
ok(!lstrcmpiW(pShimData->szModule, szApphelp), "Expected pShimData->Module to be %s, was %s\n", wine_dbgstr_w(szApphelp), wine_dbgstr_w(pShimData->szModule)); ok(pShimData->dwSize == sizeof(ShimData_Win10_v1), "Expected pShimData->dwSize to be %u, was %lu\n", sizeof(ShimData_Win10_v1), pShimData->dwSize); if (pShimData->Query.dwLayerCount != min(count, SDB_MAX_LAYERS)) { char buf[250] = {0}; GetEnvironmentVariableA("__COMPAT_LAYER", buf, _countof(buf)); trace("At test: %s\n", buf); } ok(pShimData->Query.dwLayerCount == min(count, SDB_MAX_LAYERS), "Expected LayerCount to be %u, was %lu\n", min(count, SDB_MAX_LAYERS), pShimData->Query.dwLayerCount); for (n = 0; n < SDB_MAX_LAYERS; ++n) { if (n < count) { ok(pShimData->Query.atrLayers[n] != 0, "Expected to find a valid layer in index %Iu / %Iu\n", n, count); ValidateShim(pShimData->Query.atrLayers[n], layers[n]); } else ok(pShimData->Query.atrLayers[n] == 0, "Expected to find an empty layer in index %Iu / %Iu\n", n, count); }}
static void Validate_EmptyShimData_Win8(PVOID data){ ShimData_Win8* pShimData = (ShimData_Win8*)data; ok(pShimData != NULL, "Expected pShimData\n"); if (!pShimData) return;
ok(!lstrcmpiW(pShimData->szModule, L""), "Expected pShimData->Module to be '', was %s\n", wine_dbgstr_w(pShimData->szModule)); ok(!lstrcmpiW(pShimData->szLayer, L""), "Expected pShimData->szLayer to be '', was %s\n", wine_dbgstr_w(pShimData->szLayer)); ok(pShimData->dwSize == sizeof(ShimData_Win8), "Expected pShimData->dwSize to be %u, was %lu\n", sizeof(ShimData_Win8), pShimData->dwSize); ok(!memcmp(&pShimData->Query, &empty_result, sizeof(empty_result)), "Expected result to be empty\n");}
static void Validate_EmptyShimData_Win10(PVOID data){ ShimData_Win10_v1* pShimData = (ShimData_Win10_v1*)data; ok(pShimData != NULL, "Expected pShimData\n"); if (!pShimData) return;
if (pShimData->dwMagic != SHIMDATA_MAGIC) { ShimData_Win10_v2* pShimData2 = (ShimData_Win10_v2*)data; if (pShimData2->dwMagic != SHIMDATA_MAGIC) { skip("Unknown shimdata (win10)\n"); return; }
ok(!lstrcmpiW(pShimData2->szLayer, L""), "Expected pShimData->szLayer to be '', was %s\n", wine_dbgstr_w(pShimData2->szLayer)); ok(pShimData2->dwSize == sizeof(ShimData_Win10_v2), "Expected pShimData->dwSize to be %u, was %lu\n", sizeof(ShimData_Win10_v2), pShimData2->dwSize); ok(!memcmp(&pShimData2->Query, &empty_result, sizeof(empty_result)), "Expected result to be empty\n"); } else { ok(!lstrcmpiW(pShimData->szModule, L""), "Expected pShimData->Module to be '', was %s\n", wine_dbgstr_w(pShimData->szModule)); ok(!lstrcmpiW(pShimData->szLayer, L""), "Expected pShimData->szLayer to be '', was %s\n", wine_dbgstr_w(pShimData->szLayer)); ok(pShimData->dwSize == sizeof(ShimData_Win10_v1), "Expected pShimData->dwSize to be %u, was %lu\n", sizeof(ShimData_Win10_v1), pShimData->dwSize); ok(!memcmp(&pShimData->Query, &empty_result, sizeof(empty_result)), "Expected result to be empty\n"); }}
static void Test_layers(WCHAR szApphelp[256]){ static const char* layers[] = { "256Color", "NT4SP5", "DisableNXHideUI", "DisableNXShowUI", "WIN2000SP3", "640X480", /*"DISABLEDWM",*/ "HIGHDPIAWARE", /*"RUNASADMIN",*/ "DISABLETHEMES" /*, "Layer_Win95VersionLie"*/ };
size_t n; HANDLE proc; test_RemoteShimInfo info; BOOL res;
for (n = 0; n <= (sizeof(layers) / sizeof(layers[0])); ++n) { create_environ(layers, n);
proc = create_proc(TRUE); res = get_shiminfo(proc, &info); TerminateProcess(proc, 0); CloseHandle(proc);
if (!res) { ok(0, "Unable to get process info (%u)!\n", n); continue; }
if (n == 0) { ok(info.AppCompatFlags.QuadPart == 0, "Expected AppCompatFlags to be 0, was: %s\n", wine_dbgstr_longlong(info.AppCompatFlags.QuadPart)); ok(info.AppCompatFlagsUser.QuadPart == 0, "Expected AppCompatFlagsUser to be 0, was: %s\n", wine_dbgstr_longlong(info.AppCompatFlagsUser.QuadPart)); ok(info.AppCompatInfo == NULL, "Expected AppCompatInfo to be NULL, was: %p\n", info.AppCompatInfo); if (g_WinVersion < WINVER_WIN8) { ok(info.pShimData == NULL, "Expected pShimData to be NULL, was: %p\n", info.pShimData); } else if (g_WinVersion < WINVER_WIN10) { Validate_EmptyShimData_Win8(info.pShimData); } else { Validate_EmptyShimData_Win10(info.pShimData); } } else { ok(info.AppCompatFlags.QuadPart == 0, "Expected AppCompatFlags to be 0, was: %s\n", wine_dbgstr_longlong(info.AppCompatFlags.QuadPart)); ok(info.AppCompatFlagsUser.QuadPart == 0, "Expected AppCompatFlagsUser to be 0, was: %s\n", wine_dbgstr_longlong(info.AppCompatFlagsUser.QuadPart)); ok(info.AppCompatInfo == NULL, "Expected AppCompatInfo to be NULL, was: %p\n", info.AppCompatInfo); ok(info.pShimData != NULL, "Expected pShimData to be valid, was NULL\n"); ok(info.ShimDataSize == g_ShimDataSize, "Expected ShimDataSize to be %lu, was: %lu\n", g_ShimDataSize, info.ShimDataSize); if (info.pShimData) { if (g_WinVersion < WINVER_VISTA) Validate_ShimData_Win2k3(info.pShimData, n, layers); else if (g_WinVersion == WINVER_VISTA) Validate_ShimData_WinVista(info.pShimData, n, layers); else if (g_WinVersion < WINVER_WIN8) Validate_ShimData_Win7(info.pShimData, szApphelp, n, layers); else if (g_WinVersion < WINVER_WIN10) Validate_ShimData_Win8(info.pShimData, szApphelp, n, layers); else Validate_ShimData_Win10(info.pShimData, szApphelp, n, layers); } } free(info.pShimData); }}
/*[Warn][SdbGetMatchingExe ] __COMPAT_LAYER name cannot exceed 256 characters.[Info][SdbpGetPermLayersInternal] Failed to read value info from Key "\Registry\Machine\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers" Status 0xc0000034[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[Warn][SdbpEnumUserSdb ] Failed to open key "\Registry\Machine\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Custom\NotepadReplacer.exe" Status 0xc0000034*/static void Test_repeatlayer(WCHAR szApphelp[256]){ static const char* layers[] = { "256Color", "256Color", "256Color", "256Color", "256Color", "256Color", "256Color", "256Color" };
HANDLE proc; test_RemoteShimInfo info; BOOL res;
SetEnvironmentVariableA("__COMPAT_LAYER", "256Color 256Color 256Color 256Color 256Color 256Color 256Color 256Color");
proc = create_proc(TRUE); res = get_shiminfo(proc, &info); TerminateProcess(proc, 0); CloseHandle(proc);
if (res) { ok(info.AppCompatFlags.QuadPart == 0, "Expected AppCompatFlags to be 0, was: %s\n", wine_dbgstr_longlong(info.AppCompatFlags.QuadPart)); ok(info.AppCompatFlagsUser.QuadPart == 0, "Expected AppCompatFlagsUser to be 0, was: %s\n", wine_dbgstr_longlong(info.AppCompatFlagsUser.QuadPart)); ok(info.AppCompatInfo == 0, "Expected AppCompatInfo to be 0, was: %p\n", info.AppCompatInfo); ok(info.pShimData != NULL, "Expected pShimData to be valid, was NULL\n"); ok(info.ShimDataSize == g_ShimDataSize, "Expected ShimDataSize to be %lu, was: %lu\n", g_ShimDataSize, info.ShimDataSize); if (info.pShimData) { /* Win10 only 'loads' one layer */ if (g_WinVersion < WINVER_VISTA) Validate_ShimData_Win2k3(info.pShimData, SDB_MAX_LAYERS, layers); else if (g_WinVersion == WINVER_VISTA) Validate_ShimData_WinVista(info.pShimData, SDB_MAX_LAYERS, layers); else if (g_WinVersion < WINVER_WIN8) Validate_ShimData_Win7(info.pShimData, szApphelp, SDB_MAX_LAYERS, layers); else if (g_WinVersion < WINVER_WIN10) Validate_ShimData_Win8(info.pShimData, szApphelp, SDB_MAX_LAYERS, layers); else Validate_ShimData_Win10(info.pShimData, szApphelp, 1, layers); } } else { ok(0, "Unable to get process info!\n"); }
}
TAGREF find_layer(const char* szLayerStart, const char* szLayerEnd){ char layer[100] = { 0 }; WCHAR layerW[100] = { 0 }; strncpy(layer, szLayerStart, szLayerEnd - szLayerStart);
if (!g_LayerDB) { g_LayerDB = pSdbInitDatabase(SDB_DATABASE_MAIN_SHIM, 0); }
mbstowcs(layerW, layer, strlen(layer)); return pSdbGetLayerTagRef(g_LayerDB, layerW);}
static void expect_layeronly_imp(SDBQUERYRESULT_VISTA* result, const char* layers, DWORD flags){ DWORD dwLayerCount = 0, n; TAGREF atrLayers[SDB_MAX_LAYERS] = { 0 };
const char* layer = layers, *nextlayer; while (layer && *layer) { nextlayer = strchr(layer, ' '); atrLayers[dwLayerCount++] = find_layer(layer, nextlayer ? nextlayer : (layer + strlen(layer))); layer = nextlayer ? (nextlayer+1) : NULL; }
if (g_ModuleVersion < WINVER_VISTA) { SDBQUERYRESULT_2k3* result2 = (SDBQUERYRESULT_2k3*)result; result = NULL;
winetest_ok(!memcmp(&result2->atrExes, &empty_result.atrExes, sizeof(result2->atrExes)), "Expected atrExes to be empty\n"); 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"); for (n = 0; n < dwLayerCount; ++n) { winetest_ok(result2->atrLayers[n] == atrLayers[n], "Expected atrLayers[%lu] to be %lx, was %lx\n", n, atrLayers[n], result2->atrLayers[n]); } winetest_ok(result2->dwLayerFlags == 0, "Expected dwLayerFlags to be 0, was %lu\n", result2->dwLayerFlags); winetest_ok(result2->trApphelp == 0, "Expected trApphelp to be 0, was %lu\n", result2->trApphelp); winetest_ok(result2->dwExeCount == 0, "Expected dwExeCount to be 0, was %lu\n", result2->dwExeCount); winetest_ok(result2->dwLayerCount == dwLayerCount, "Expected dwLayerCount to be %lu, was %lu\n", dwLayerCount, result2->dwLayerCount); winetest_ok(!memcmp(&result2->guidID, &empty_result.guidID, sizeof(result2->guidID)), "Expected guidID to be empty\n"); winetest_ok(result2->dwFlags == flags, "Expected dwFlags to be 0x%lx, was 0x%lx\n", flags, result2->dwFlags); winetest_ok(result2->dwCustomSDBMap == 1, "Expected dwCustomSDBMap to be 1, was %lu\n", result2->dwCustomSDBMap); winetest_ok(!memcmp(&result2->rgGuidDB[1], &empty_result.rgGuidDB[1], sizeof(result2->rgGuidDB) - sizeof(result2->rgGuidDB[0])), "Expected rgGuidDB[+1] to be empty\n"); } else { winetest_ok(!memcmp(&result->atrExes, &empty_result.atrExes, sizeof(empty_result.atrExes)), "Expected atrExes to be empty\n"); winetest_ok(!memcmp(&result->adwExeFlags, &empty_result.adwExeFlags, sizeof(empty_result.adwExeFlags)), "Expected adwExeFlags to be empty\n"); 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"); for (n = 0; n < dwLayerCount; ++n) { winetest_ok(result->atrLayers[n] == atrLayers[n], "Expected atrLayers[%lu] to be %lx, was %lx\n", n, atrLayers[n], result->atrLayers[n]); } winetest_ok(result->dwLayerFlags == 0, "Expected dwLayerFlags to be 0, was %lu\n", result->dwLayerFlags); winetest_ok(result->trApphelp == 0, "Expected trApphelp to be 0, was %lu\n", result->trApphelp); winetest_ok(result->dwExeCount == 0, "Expected dwExeCount to be 0, was %lu\n", result->dwExeCount); winetest_ok(result->dwLayerCount == dwLayerCount, "Expected dwLayerCount to be %lu, was %lu\n", dwLayerCount, result->dwLayerCount); winetest_ok(!memcmp(&result->guidID, &empty_result.guidID, sizeof(empty_result.guidID)), "Expected guidID to be empty\n"); winetest_ok(result->dwFlags == flags, "Expected dwFlags to be 0x%lx, was 0x%lx\n", flags, result->dwFlags); winetest_ok(result->dwCustomSDBMap == 1, "Expected dwCustomSDBMap to be 1, was %lu\n", result->dwCustomSDBMap); 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"); }}
static void Test_Shimdata(SDBQUERYRESULT_VISTA* result, const WCHAR* szLayer){ BOOL ret; PVOID pData; DWORD dwSize;
pData = NULL; dwSize = 0; ret = pSdbPackAppCompatData(g_LayerDB, result, &pData, &dwSize); ok(ret == TRUE, "Expected ret to be TRUE\n");
if (pData) { ShimData_Win2k3* pWin2k3; ShimData_WinVista* pWinVista; ShimData_Win7* pWin7; ShimData_Win8* pWin8; ShimData_Win10_v1* pWin10; ShimData_Win10_v2* pWin10_v2; SDBQUERYRESULT_VISTA result2 = { { 0 } };
DWORD res = pSdbGetAppCompatDataSize(pData); ok_int(dwSize, res); switch(dwSize) { case sizeof(ShimData_Win2k3): pWin2k3 = (ShimData_Win2k3*)pData; ok_hex(pWin2k3->dwMagic, SHIMDATA_MAGIC); ok_int(pWin2k3->dwSize, dwSize); ok(pWin2k3->dwCustomSDBMap == 1, "Expected pWin2k3->dwCustomSDBMap to equal 1, was %lu for %s\n", pWin2k3->dwCustomSDBMap, wine_dbgstr_w(szLayer)); //ok(!memcmp(&pWin2k3->Query, result, sizeof(SDBQUERYRESULT_2k3)), "Expected pWin2k3->Query to equal result\n"); //ok_wstr(pWin7->szLayer, szLayer); break; case sizeof(ShimData_WinVista): pWinVista = (ShimData_WinVista*)pData; ok_hex(pWinVista->dwMagic, SHIMDATA_MAGIC); ok_int(pWinVista->dwSize, dwSize); ok(!memcmp(&pWinVista->Query, result, sizeof(*result)), "Expected pWinVista->Query to equal result\n"); break; case sizeof(ShimData_Win7): pWin7 = (ShimData_Win7*)pData; ok_hex(pWin7->dwMagic, SHIMDATA_MAGIC); ok_int(pWin7->dwSize, dwSize); ok(!memcmp(&pWin7->Query, result, sizeof(*result)), "Expected pWin7->Query to equal result\n"); ok_wstr(pWin7->szLayer, szLayer); break; case sizeof(ShimData_Win8): pWin8 = (ShimData_Win8*)pData; ok_hex(pWin8->dwMagic, SHIMDATA_MAGIC); ok_int(pWin8->dwSize, dwSize); ok(!memcmp(&pWin8->Query, result, sizeof(*result)), "Expected pWin8->Query to equal result\n"); ok_wstr(pWin8->szLayerEnv, szLayer); ok_wstr(pWin8->szLayer, L""); break; case sizeof(ShimData_Win10_v1): pWin10 = (ShimData_Win10_v1*)pData; ok_hex(pWin10->dwMagic, SHIMDATA_MAGIC); ok_int(pWin10->dwSize, dwSize); ok(!memcmp(&pWin10->Query, result, sizeof(*result)), "Expected pWin10->Query to equal result\n"); ok_wstr(pWin10->szLayerEnv, szLayer); ok_wstr(pWin10->szLayer, L""); break; case sizeof(ShimData_Win10_v2): pWin10_v2 = (ShimData_Win10_v2*)pData; ok_hex(pWin10_v2->dwMagic, SHIMDATA_MAGIC); ok_int(pWin10_v2->dwSize, dwSize); ok(!memcmp(&pWin10_v2->Query, result, sizeof(*result)), "Expected pWin10->Query to equal result\n"); ok_wstr(pWin10_v2->szLayerEnv, szLayer); ok_wstr(pWin10_v2->szLayer, L""); break; default: skip("Unknown size %ld\n", dwSize); break; }
ret = pSdbUnpackAppCompatData(g_LayerDB, NULL, pData, &result2); ok(ret == TRUE, "Expected ret to be TRUE\n"); /* TODO: For some reason 2k3 does not seem to output the database GUIDs, investigate when we have support for multible db's! */ if (dwSize == sizeof(ShimData_Win2k3)) { SDBQUERYRESULT_2k3* input = (SDBQUERYRESULT_2k3*)result; SDBQUERYRESULT_2k3* output = (SDBQUERYRESULT_2k3*)&result2; const GUID rgGuidDB0 = {0x11111111, 0x1111, 0x1111, {0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11}};
// Check expected data. ok(input->dwLayerCount == 1, "Expected input->dwLayerCount to be 1, was %lu for %s\n", input->dwLayerCount, wine_dbgstr_w(szLayer)); ok(input->dwCustomSDBMap == 1, "Expected input->dwCustomSDBMap to be 1, was %lu for %s\n", input->dwCustomSDBMap, wine_dbgstr_w(szLayer)); ok(IsEqualGUID(&input->rgGuidDB[0], &rgGuidDB0), "Expected input->rgGuidDB[0] to be %s, was %s for %s\n", wine_dbgstr_guid(&rgGuidDB0), wine_dbgstr_guid(&input->rgGuidDB[0]), wine_dbgstr_w(szLayer));
// Check missing data. ok(output->dwLayerCount == 0, "Expected output->dwLayerCount to be 0, was %lu for %s\n", output->dwLayerCount, wine_dbgstr_w(szLayer)); ok(output->dwCustomSDBMap == 0, "Expected output->dwCustomSDBMap to be 0, was %lu for %s\n", output->dwCustomSDBMap, wine_dbgstr_w(szLayer)); ok(IsEqualGUID(&output->rgGuidDB[0], &empty_result.rgGuidDB[0]), "Expected output->rgGuidDB[0] to be empty, was %s for %s\n", wine_dbgstr_guid(&output->rgGuidDB[0]), wine_dbgstr_w(szLayer));
// Fake it for now, so the memcmp works. output->dwLayerCount = input->dwLayerCount; output->dwCustomSDBMap = input->dwCustomSDBMap; output->rgGuidDB[0] = input->rgGuidDB[0]; } ok(!memcmp(&result2, result, sizeof(*result)), "Expected result2 to equal result for %s\n", wine_dbgstr_w(szLayer));
RtlFreeHeap(GetProcessHeap(), 0, pData); }}
#define expect_layeronly (winetest_set_location(__FILE__, __LINE__), 0) ? (void)0 : expect_layeronly_imp
static void Test_GetMatchingExe(void){ BOOL ret; SDBQUERYRESULT_VISTA result = { { 0 } }; WCHAR self[MAX_PATH]; DWORD flags = (g_WinVersion <= WINVER_VISTA) ? 0 : ((g_WinVersion < WINVER_WIN10) ? 1 : 0x21);
GetModuleFileNameW(NULL, self, MAX_PATH); SetEnvironmentVariableA("__COMPAT_LAYER", NULL);
/* szPath cannot be NULL! */ ret = pSdbGetMatchingExe(NULL, L"", NULL, NULL, 0, &result); ok(ret == FALSE, "Expected ret to be FALSE\n"); ok(!memcmp(&result, &empty_result, sizeof(empty_result)), "Expected result to be empty\n");
result = empty_result;
ret = pSdbGetMatchingExe(NULL, self, NULL, NULL, 0, &result); ok(ret == FALSE, "Expected ret to be FALSE\n"); ok(!memcmp(&result, &empty_result, sizeof(empty_result)), "Expected result to be empty\n");
result = empty_result; SetEnvironmentVariableA("__COMPAT_LAYER", "Some_invalid_layer_name");
ret = pSdbGetMatchingExe(NULL, self, NULL, NULL, 0, &result); ok(ret == FALSE, "Expected ret to be FALSE\n"); if (g_WinVersion < WINVER_WIN10) ok(!memcmp(&result, &empty_result, sizeof(empty_result)), "Expected result to be empty\n"); else ok(!memcmp(&result, &almost_empty, sizeof(almost_empty)), "Expected result to be almost empty\n");
result = empty_result; SetEnvironmentVariableA("__COMPAT_LAYER", "256Color");
ret = pSdbGetMatchingExe(NULL, self, NULL, NULL, 0, &result); ok(ret == TRUE, "Expected ret to be TRUE\n"); expect_layeronly(&result, "256Color", flags);
Test_Shimdata(&result, L"256Color");
result = empty_result; SetEnvironmentVariableA("__COMPAT_LAYER", "640X480");
ret = pSdbGetMatchingExe(NULL, self, NULL, NULL, 0, &result); ok(ret == TRUE, "Expected ret to be TRUE\n"); expect_layeronly(&result, "640X480", flags);
Test_Shimdata(&result, L"640X480");
/* HIGHDPIAWARE does not exist in 2k3 */ if (g_WinVersion > WINVER_2003) { result = empty_result; SetEnvironmentVariableA("__COMPAT_LAYER", "HIGHDPIAWARE");
ret = pSdbGetMatchingExe(NULL, self, NULL, NULL, 0, &result); ok(ret == TRUE, "Expected ret to be TRUE\n"); expect_layeronly(&result, "HIGHDPIAWARE", flags);
Test_Shimdata(&result, L"HIGHDPIAWARE");
result = empty_result; SetEnvironmentVariableA("__COMPAT_LAYER", "256Color HIGHDPIAWARE 640X480");
ret = pSdbGetMatchingExe(NULL, self, NULL, NULL, 0, &result); ok(ret == TRUE, "Expected ret to be TRUE\n"); expect_layeronly(&result, "256Color HIGHDPIAWARE 640X480", flags);
Test_Shimdata(&result, L"256Color HIGHDPIAWARE 640X480"); }}
HANDLE xOpenFile(WCHAR* ApplicationName){ UNICODE_STRING FileName; OBJECT_ATTRIBUTES ObjectAttributes; IO_STATUS_BLOCK IoStatusBlock; NTSTATUS Status; HANDLE FileHandle;
if (!RtlDosPathNameToNtPathName_U(ApplicationName, &FileName, NULL, NULL)) { skip("Unable to translate %s to Nt path\n", wine_dbgstr_w(ApplicationName)); return NULL; }
InitializeObjectAttributes(&ObjectAttributes, &FileName, OBJ_CASE_INSENSITIVE, NULL, NULL); Status = NtOpenFile(&FileHandle, SYNCHRONIZE | FILE_READ_ATTRIBUTES | FILE_READ_DATA | FILE_EXECUTE, &ObjectAttributes, &IoStatusBlock, FILE_SHARE_READ | FILE_SHARE_DELETE, FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE);
RtlFreeUnicodeString(&FileName);
if (!NT_SUCCESS(Status)) return NULL;
return FileHandle;}
#define RESET_CHECKRUNAPP_VARS()\ do { \ if (AppCompatData && AppCompatData != &Query) { RtlFreeHeap(RtlGetProcessHeap(), 0, AppCompatData); } \ ExeType = IMAGE_FILE_MACHINE_I386; \ SxsDataSize = FusionFlags = Reason = 0; \ SxsData = NULL; \ memset(&Query, 0, sizeof(Query)); \ AppCompatData = &Query; \ AppCompatDataSize = 123456; \ } while (0)
#define CHECK_BASICS()\ do { \ ok_hex(ret, TRUE); \ ok(AppCompatData != NULL && AppCompatData != &Query, "Expected the pointer to be valid\n"); \ ok_hex(AppCompatDataSize, sizeof(SDBQUERYRESULT_VISTA)); \ ok(SxsData == NULL, "Expected the pointer to be NULL\n"); \ ok_hex(SxsDataSize, 0); \ ok_hex(FusionFlags, 0); \ } while (0)
/* W10 does not seem to use the flags at all, so with this macro we can still test it below 10. */#define CHECKREASON(value, w10dum) (g_ModuleVersion < WINVER_WIN10 ? value : w10dum)
static BOOL call_ApphelpCheckRunApp(HANDLE FileHandle, PWCHAR ApplicationName, PVOID Environment, USHORT ExeType, PULONG Reason, PVOID* SdbQueryAppCompatData, PULONG SdbQueryAppCompatDataSize, PVOID* SxsData, PULONG SxsDataSize, PULONG FusionFlags){ ULONG64 SomeFlag1 = 0; ULONG SomeFlag2 = 0;
if (pApphelpCheckRunAppEx_w7) { return pApphelpCheckRunAppEx_w7(FileHandle, NULL, NULL, ApplicationName, Environment, ExeType, Reason, SdbQueryAppCompatData, SdbQueryAppCompatDataSize, SxsData, SxsDataSize, FusionFlags, &SomeFlag1, &SomeFlag2); }
if (pApphelpCheckRunAppEx_w10) { return pApphelpCheckRunAppEx_w10(FileHandle, NULL, NULL, ApplicationName, Environment, NULL, ExeType, Reason, SdbQueryAppCompatData, SdbQueryAppCompatDataSize, SxsData, SxsDataSize, FusionFlags, &SomeFlag1, &SomeFlag2); }
return FALSE;}
static void Test_ApphelpCheckRunApp(WCHAR szApphelp[256]){ BOOL ret; HANDLE FileHandle = NULL; WCHAR ApplicationName[MAX_PATH], EmptyName[1] = { 0 }; DWORD expect_flags = (g_WinVersion < WINVER_WIN10) ? 1 : 0x21;
USHORT ExeType; PVOID AppCompatData = NULL, SxsData, DuplicatedEnv, Environment; ULONG AppCompatDataSize, SxsDataSize, FusionFlags; ULONG Reason; SDBQUERYRESULT_VISTA Query; int n; /* this are the only interesting bits (with the exception of '1', which is there to invoke the 'default' case) */ const int kTestBits = 0x70503;
if (!pApphelpCheckRunAppEx_w7 && !pApphelpCheckRunAppEx_w10) { skip("No usable ApphelpCheckRunAppEx\n"); return; }
GetModuleFileNameW(NULL, ApplicationName, MAX_PATH);
FileHandle = xOpenFile(ApplicationName); SetEnvironmentVariableA("__COMPAT_LAYER", NULL); if (!CreateEnvironmentBlock(&DuplicatedEnv, NULL, TRUE)) DuplicatedEnv = NULL; ok(DuplicatedEnv != NULL, "Invalid env (%lu)\n", GetLastError());
/* First with the environment without __COMPAT_LAYER */ RESET_CHECKRUNAPP_VARS();
ret = call_ApphelpCheckRunApp(FileHandle, ApplicationName, DuplicatedEnv, ExeType, &Reason, &AppCompatData, &AppCompatDataSize, &SxsData, &SxsDataSize, &FusionFlags);
CHECK_BASICS(); ok_hex(Reason, CHECKREASON(0x30000, 0)); ok(!memcmp(AppCompatData, &empty_result, sizeof(empty_result)), "Expected result to be empty\n");
/* We need this to be set for tests later on. */ SetEnvironmentVariableA("__COMPAT_LAYER", "256Color");
if (g_ModuleVersion < WINVER_WIN10) { /* Showing that when an environment is passed in, that is used instead of the current. In Win10 this behavior is no longer observed */
RESET_CHECKRUNAPP_VARS();
ret = call_ApphelpCheckRunApp(FileHandle, ApplicationName, DuplicatedEnv, ExeType, &Reason, &AppCompatData, &AppCompatDataSize, &SxsData, &SxsDataSize, &FusionFlags);
CHECK_BASICS(); ok_hex(Reason, CHECKREASON(0x30000, 0)); ok(!memcmp(AppCompatData, &empty_result, sizeof(empty_result)), "Expected result to be empty\n"); }
for (n = 0; n < 32; ++n) { ULONG ExpectedReason; if (!(kTestBits & (1<<n))) continue; RESET_CHECKRUNAPP_VARS(); ExpectedReason = Reason = (1 << n); ret = call_ApphelpCheckRunApp(FileHandle, ApplicationName, DuplicatedEnv, ExeType, &Reason, &AppCompatData, &AppCompatDataSize, &SxsData, &SxsDataSize, &FusionFlags);
CHECK_BASICS(); if (ExpectedReason == 2) ExpectedReason = 2; else if (ExpectedReason == 0x100) ExpectedReason = 0x30000; else ExpectedReason |= 0x30000; ok_hex(Reason, CHECKREASON(ExpectedReason, (1 << n))); ok(!memcmp(AppCompatData, &empty_result, sizeof(empty_result)), "Expected result to be empty\n"); }
if (g_ModuleVersion < WINVER_WIN10) { /* Now, using a NULL env, showing that the current environment is used. W10 does no longer do this, so we skip this test here. */ Environment = NULL;
RESET_CHECKRUNAPP_VARS();
ret = call_ApphelpCheckRunApp(FileHandle, ApplicationName, Environment, ExeType, &Reason, &AppCompatData, &AppCompatDataSize, &SxsData, &SxsDataSize, &FusionFlags);
CHECK_BASICS(); ok_hex(Reason, CHECKREASON(0x50000, 0)); if (AppCompatData && AppCompatDataSize == sizeof(SDBQUERYRESULT_VISTA)) expect_layeronly(AppCompatData, "256Color", expect_flags);
for (n = 0; n < 32; ++n) { ULONG ExpectedReason; RESET_CHECKRUNAPP_VARS(); if (!(kTestBits & (1<<n))) continue; ExpectedReason = Reason = (1 << n); ret = call_ApphelpCheckRunApp(FileHandle, ApplicationName, Environment, ExeType, &Reason, &AppCompatData, &AppCompatDataSize, &SxsData, &SxsDataSize, &FusionFlags);
CHECK_BASICS(); if (ExpectedReason == 2) ExpectedReason = 2; else if (ExpectedReason == 0x100) ExpectedReason = 0x50000; else if (ExpectedReason == 0x400) ExpectedReason = 0x30400; else ExpectedReason |= 0x50000; ok_hex(Reason, CHECKREASON(ExpectedReason, (1 << n))); if (AppCompatData && AppCompatDataSize == sizeof(SDBQUERYRESULT_VISTA)) { if (ExpectedReason != 0x30400) expect_layeronly(AppCompatData, "256Color", expect_flags); else ok(!memcmp(AppCompatData, &empty_result, sizeof(empty_result)), "Expected result to be empty\n"); } } }
/* Passing in an environment with __COMPAT_LAYER set */ Environment = GetEnvironmentStringsW();
RESET_CHECKRUNAPP_VARS();
ret = call_ApphelpCheckRunApp(FileHandle, ApplicationName, Environment, ExeType, &Reason, &AppCompatData, &AppCompatDataSize, &SxsData, &SxsDataSize, &FusionFlags);
CHECK_BASICS(); ok_hex(Reason, CHECKREASON(0x50000, 0)); if (AppCompatData && AppCompatDataSize == sizeof(SDBQUERYRESULT_VISTA)) expect_layeronly(AppCompatData, "256Color", expect_flags);
for (n = 0; n < 32; ++n) { ULONG ExpectedReason; if (!(kTestBits & (1<<n))) continue; RESET_CHECKRUNAPP_VARS(); ExpectedReason = Reason = (1 << n); ret = call_ApphelpCheckRunApp(FileHandle, ApplicationName, Environment, ExeType, &Reason, &AppCompatData, &AppCompatDataSize, &SxsData, &SxsDataSize, &FusionFlags);
CHECK_BASICS(); if (ExpectedReason == 2) ExpectedReason = 2; else if (ExpectedReason == 0x100) ExpectedReason = 0x50000; else if (ExpectedReason == 0x400) ExpectedReason = 0x30400; else ExpectedReason |= 0x50000; ok_hex(Reason, CHECKREASON(ExpectedReason, (1 << n))); if (AppCompatData && AppCompatDataSize == sizeof(SDBQUERYRESULT_VISTA)) { if (ExpectedReason != 0x30400 || g_ModuleVersion >= WINVER_WIN10) expect_layeronly(AppCompatData, "256Color", expect_flags); else ok(!memcmp(AppCompatData, &empty_result, sizeof(empty_result)), "Expected result to be empty\n"); } }
/* NULL file handle still works */ RESET_CHECKRUNAPP_VARS();
ret = call_ApphelpCheckRunApp(NULL, ApplicationName, Environment, ExeType, &Reason, &AppCompatData, &AppCompatDataSize, &SxsData, &SxsDataSize, &FusionFlags);
CHECK_BASICS(); ok_hex(Reason, CHECKREASON(0x50000, 0)); if (AppCompatData && AppCompatDataSize == sizeof(SDBQUERYRESULT_VISTA)) expect_layeronly(AppCompatData, "256Color", expect_flags);
for (n = 0; n < 32; ++n) { ULONG ExpectedReason; RESET_CHECKRUNAPP_VARS(); if (!(kTestBits & (1<<n))) continue; ExpectedReason = Reason = (1 << n); ret = call_ApphelpCheckRunApp(NULL, ApplicationName, Environment, ExeType, &Reason, &AppCompatData, &AppCompatDataSize, &SxsData, &SxsDataSize, &FusionFlags);
CHECK_BASICS(); if (ExpectedReason == 2) ExpectedReason = 2; else if (ExpectedReason == 0x100) ExpectedReason = 0x50000; else if (ExpectedReason == 0x400) ExpectedReason = 0x30400; else ExpectedReason |= 0x50000; ok_hex(Reason, CHECKREASON(ExpectedReason, (1 << n))); if (AppCompatData && AppCompatDataSize == sizeof(SDBQUERYRESULT_VISTA)) { /* W10 does not use the flags anymore? */ if (ExpectedReason != 0x30400 || g_ModuleVersion >= WINVER_WIN10) expect_layeronly(AppCompatData, "256Color", expect_flags); else ok(!memcmp(AppCompatData, &empty_result, sizeof(empty_result)), "Expected result to be empty\n"); } }
/* INVALID_HANDLE_VALUE file handle results in failure (according to flags!), but still results in AppCompatData */ RESET_CHECKRUNAPP_VARS();
ret = call_ApphelpCheckRunApp(INVALID_HANDLE_VALUE, ApplicationName, Environment, ExeType, &Reason, &AppCompatData, &AppCompatDataSize, &SxsData, &SxsDataSize, &FusionFlags);
CHECK_BASICS(); ok_hex(Reason, 0); if (AppCompatData && AppCompatDataSize == sizeof(SDBQUERYRESULT_VISTA)) expect_layeronly(AppCompatData, "256Color", expect_flags);
for (n = 0; n < 32; ++n) { ULONG ExpectedReason; if (!(kTestBits & (1<<n))) continue; RESET_CHECKRUNAPP_VARS(); ExpectedReason = Reason = (1 << n); ret = call_ApphelpCheckRunApp(INVALID_HANDLE_VALUE, NULL, Environment, ExeType, &Reason, &AppCompatData, &AppCompatDataSize, &SxsData, &SxsDataSize, &FusionFlags);
CHECK_BASICS(); if (ExpectedReason == 0x100) ExpectedReason = 0; ok_hex(Reason, CHECKREASON(ExpectedReason, (1 << n))); if (AppCompatData && AppCompatDataSize == sizeof(SDBQUERYRESULT_VISTA)) { if (ExpectedReason != 0x400 && g_ModuleVersion < WINVER_WIN7) expect_layeronly(AppCompatData, "256Color", expect_flags); else ok(!memcmp(AppCompatData, &empty_result, sizeof(empty_result)), "Expected result to be empty\n"); } }
/* NULL filename crashes, showing this in the log before going down:[Err ][SdbpGetLongFileName ] Failed to get NT path name for ""[Err ][SdbpCreateSearchDBContext] Unable to parse executable path for "".[Err ][SdbGetMatchingExe ] Failed to create search DB context.*/ RESET_CHECKRUNAPP_VARS();
ret = call_ApphelpCheckRunApp(FileHandle, EmptyName, Environment, ExeType, &Reason, &AppCompatData, &AppCompatDataSize, &SxsData, &SxsDataSize, &FusionFlags);
CHECK_BASICS(); ok_hex(Reason, CHECKREASON(0x30000, 0)); if (AppCompatData && AppCompatDataSize == sizeof(SDBQUERYRESULT_VISTA)) ok(!memcmp(AppCompatData, &empty_result, sizeof(empty_result)), "Expected result to be empty\n");
/* 0 ExeType = don't care? */ RESET_CHECKRUNAPP_VARS(); ExeType = 0;
ret = call_ApphelpCheckRunApp(FileHandle, ApplicationName, Environment, ExeType, &Reason, &AppCompatData, &AppCompatDataSize, &SxsData, &SxsDataSize, &FusionFlags);
CHECK_BASICS(); ok_hex(Reason, CHECKREASON(0x50000, 0)); if (AppCompatData && AppCompatDataSize == sizeof(SDBQUERYRESULT_VISTA)) expect_layeronly(AppCompatData, "256Color", expect_flags);
for (n = 0; n < 32; ++n) { ULONG ExpectedReason; if (!(kTestBits & (1<<n))) continue; RESET_CHECKRUNAPP_VARS(); ExeType = 0; ExpectedReason = Reason = (1 << n); ret = call_ApphelpCheckRunApp(FileHandle, ApplicationName, Environment, ExeType, &Reason, &AppCompatData, &AppCompatDataSize, &SxsData, &SxsDataSize, &FusionFlags);
CHECK_BASICS(); if (ExpectedReason == 2) ExpectedReason = 2; else if (ExpectedReason == 0x100) ExpectedReason = 0x50000; else if (ExpectedReason == 0x400) ExpectedReason = 0x30400; else ExpectedReason |= 0x50000; ok_hex(Reason, CHECKREASON(ExpectedReason, (1 << n))); if (AppCompatData && AppCompatDataSize == sizeof(SDBQUERYRESULT_VISTA)) { if (ExpectedReason != 0x30400 || g_ModuleVersion >= WINVER_WIN10) expect_layeronly(AppCompatData, "256Color", expect_flags); else ok(!memcmp(AppCompatData, &empty_result, sizeof(empty_result)), "Expected result to be empty\n"); } }
RESET_CHECKRUNAPP_VARS(); ExeType = IMAGE_FILE_MACHINE_POWERPCFP;
ret = call_ApphelpCheckRunApp(FileHandle, ApplicationName, Environment, ExeType, &Reason, &AppCompatData, &AppCompatDataSize, &SxsData, &SxsDataSize, &FusionFlags);
CHECK_BASICS(); ok_hex(Reason, CHECKREASON(0x50000, 0)); if (AppCompatData && AppCompatDataSize == sizeof(SDBQUERYRESULT_VISTA)) expect_layeronly(AppCompatData, "256Color", expect_flags);
for (n = 0; n < 32; ++n) { ULONG ExpectedReason; if (!(kTestBits & (1<<n))) continue; RESET_CHECKRUNAPP_VARS(); ExeType = IMAGE_FILE_MACHINE_POWERPCFP; ExpectedReason = Reason = (1 << n); ret = call_ApphelpCheckRunApp(FileHandle, ApplicationName, Environment, ExeType, &Reason, &AppCompatData, &AppCompatDataSize, &SxsData, &SxsDataSize, &FusionFlags);
CHECK_BASICS(); if (ExpectedReason == 2) ExpectedReason = 2; else if (ExpectedReason == 0x100) ExpectedReason = 0x50000; else if (ExpectedReason == 0x400) ExpectedReason = 0x30400; else ExpectedReason |= 0x50000; ok_hex(Reason, CHECKREASON(ExpectedReason, (1 << n))); if (AppCompatData && AppCompatDataSize == sizeof(SDBQUERYRESULT_VISTA)) { if (ExpectedReason != 0x30400 || g_ModuleVersion >= WINVER_WIN10) expect_layeronly(AppCompatData, "256Color", expect_flags); else ok(!memcmp(AppCompatData, &empty_result, sizeof(empty_result)), "Expected result to be empty\n"); } }
if (AppCompatData && AppCompatData != &Query) RtlFreeHeap(RtlGetProcessHeap(), 0, AppCompatData);
FreeEnvironmentStringsW(Environment); DestroyEnvironmentBlock(DuplicatedEnv); NtClose(FileHandle);}
START_TEST(env){ WCHAR szApphelp[MAX_PATH]; ShimData_QueryOffset QueryOffset; DWORD ShimDataType; NTSTATUS ExceptionStatus = STATUS_SUCCESS;
//SetEnvironmentVariable("SHIM_DEBUG_LEVEL", "127"); //SetEnvironmentVariable("SHIMENG_DEBUG_LEVEL", "127");
silence_debug_output();
hdll = LoadLibraryA("apphelp.dll");
g_WinVersion = get_host_winver(); g_ModuleVersion = get_module_version(hdll); trace("Detected host: 0x%lx, module: 0x%lx\n", g_WinVersion, g_ModuleVersion);
GetModuleFileNameW(hdll, szApphelp, _countof(szApphelp));
pSdbGetMatchingExe = (void*)GetProcAddress(hdll, "SdbGetMatchingExe"); pSdbInitDatabase = (void*)GetProcAddress(hdll, "SdbInitDatabase"); pSdbReleaseDatabase = (void*)GetProcAddress(hdll, "SdbReleaseDatabase"); pSdbTagRefToTagID = (void*)GetProcAddress(hdll, "SdbTagRefToTagID"); pSdbGetTagFromTagID = (void*)GetProcAddress(hdll, "SdbGetTagFromTagID"); pSdbGetLayerTagRef = (void*)GetProcAddress(hdll, "SdbGetLayerTagRef");
switch (g_ModuleVersion) { case WINVER_WIN7: pApphelpCheckRunAppEx_w7 = (void*)GetProcAddress(hdll, "ApphelpCheckRunAppEx"); break; case WINVER_WIN8: case WINVER_WIN81: case WINVER_WIN10: pApphelpCheckRunAppEx_w10 = (void*)GetProcAddress(hdll, "ApphelpCheckRunAppEx"); break; default: skip("Unknown apphelp.dll version %lx, cannot determine which ApphelpCheckRunApp(Ex) function to use\n", g_ModuleVersion); break; }
pSdbPackAppCompatData = (void*)GetProcAddress(hdll, "SdbPackAppCompatData"); pSdbUnpackAppCompatData = (void*)GetProcAddress(hdll, "SdbUnpackAppCompatData"); pSdbGetAppCompatDataSize = (void*)GetProcAddress(hdll, "SdbGetAppCompatDataSize");
memset(&QueryOffset, 0, sizeof(QueryOffset)); QueryOffset.dwMagic_2k3 = QueryOffset.dwMagic_7_10 = QueryOffset.dwMagic_10_v2 = SHIMDATA_MAGIC; QueryOffset.dwSize_2k3 = 1; QueryOffset.dwSize_7_10 = 2; QueryOffset.dwSize_10_v2 = 3;
g_ShimDataSize = g_WinVersion < WINVER_WIN8 ? 4096 : 8192; _SEH2_TRY { ShimDataType = pSdbGetAppCompatDataSize(&QueryOffset); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { ExceptionStatus = _SEH2_GetExceptionCode(); } _SEH2_END;
ok(ExceptionStatus == STATUS_SUCCESS, "Exception 0x%08lx, expected 0x%08lx\n", ExceptionStatus, STATUS_SUCCESS); if (ExceptionStatus != STATUS_SUCCESS) { skip("SdbGetAppCompatDataSize not functional\n"); return; }
#ifdef _M_IX86 /* New version of Win10 */ if (g_WinVersion == WINVER_WIN10 && ShimDataType == 3) g_ShimDataSize = 4096;
if (g_WinVersion == g_ModuleVersion) { Test_layers(szApphelp); Test_repeatlayer(szApphelp); } else { skip("Tests requiring process launch, reported OS version (0x%lx) does not match apphelp version (0x%lx)\n", g_WinVersion, g_ModuleVersion); }
{ Test_GetMatchingExe(); }
Test_ApphelpCheckRunApp(szApphelp);#else skip("FIXME: apphelp:env tests invalid for non-x86 platforms.\n");#endif if (g_LayerDB) pSdbReleaseDatabase(g_LayerDB);}