Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568/* * PROJECT: ReactOS Win32 Base API * LICENSE: GPL - See COPYING in the top level directory * FILE: dll/win32/kernel32/client/appcache.c * PURPOSE: Application Compatibility Cache * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) */
/* INCLUDES *******************************************************************/
#include <k32.h>
#define NDEBUG#include <debug.h>
/* GLOBALS ********************************************************************/
ULONG g_ShimsDisabled = -1;static BOOL g_ApphelpInitialized = FALSE;static PVOID g_pApphelpCheckRunAppEx;static PVOID g_pSdbPackAppCompatData;
typedef BOOL (WINAPI *tApphelpCheckRunAppEx)(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);typedef BOOL (WINAPI *tSdbPackAppCompatData)(PVOID hsdb, PVOID pQueryResult, PVOID* ppData, DWORD *dwSize);
#define APPHELP_VALID_RESULT 0x10000#define APPHELP_RESULT_NOTFOUND 0x20000#define APPHELP_RESULT_FOUND 0x40000
/* FUNCTIONS ******************************************************************/
BOOLEANWINAPIIsShimInfrastructureDisabled(VOID){ HANDLE KeyHandle; NTSTATUS Status; KEY_VALUE_PARTIAL_INFORMATION KeyInfo; ULONG ResultLength; UNICODE_STRING OptionKey = RTL_CONSTANT_STRING(L"\\Registry\\MACHINE\\System\\CurrentControlSet\\Control\\SafeBoot\\Option"); UNICODE_STRING AppCompatKey = RTL_CONSTANT_STRING(L"\\Registry\\MACHINE\\System\\CurrentControlSet\\Control\\Session Manager\\AppCompatibility"); UNICODE_STRING PolicyKey = RTL_CONSTANT_STRING(L"\\Registry\\MACHINE\\Software\\Policies\\Microsoft\\Windows\\AppCompat"); UNICODE_STRING OptionValue = RTL_CONSTANT_STRING(L"OptionValue"); UNICODE_STRING DisableAppCompat = RTL_CONSTANT_STRING(L"DisableAppCompat"); UNICODE_STRING DisableEngine = RTL_CONSTANT_STRING(L"DisableEngine"); OBJECT_ATTRIBUTES OptionKeyAttributes = RTL_CONSTANT_OBJECT_ATTRIBUTES(&OptionKey, OBJ_CASE_INSENSITIVE); OBJECT_ATTRIBUTES AppCompatKeyAttributes = RTL_CONSTANT_OBJECT_ATTRIBUTES(&AppCompatKey, OBJ_CASE_INSENSITIVE); OBJECT_ATTRIBUTES PolicyKeyAttributes = RTL_CONSTANT_OBJECT_ATTRIBUTES(&PolicyKey, OBJ_CASE_INSENSITIVE);
/* * This is a TROOLEAN, -1 means we haven't yet figured it out. * 0 means shims are enabled, and 1 means shims are disabled! */ if (g_ShimsDisabled == -1) { ULONG DisableShims = FALSE;
/* Open the safe mode key */ Status = NtOpenKey(&KeyHandle, KEY_QUERY_VALUE, &OptionKeyAttributes); if (NT_SUCCESS(Status)) { /* Check if this is safemode */ Status = NtQueryValueKey(KeyHandle, &OptionValue, KeyValuePartialInformation, &KeyInfo, sizeof(KeyInfo), &ResultLength); NtClose(KeyHandle); if ((NT_SUCCESS(Status)) && (KeyInfo.Type == REG_DWORD) && (KeyInfo.DataLength == sizeof(ULONG)) && (KeyInfo.Data[0] != FALSE)) { /* It is, so disable shims! */ DisableShims = TRUE; } }
if (!DisableShims) { /* Open the app compatibility engine settings key */ Status = NtOpenKey(&KeyHandle, KEY_QUERY_VALUE, &AppCompatKeyAttributes); if (NT_SUCCESS(Status)) { /* Check if the app compat engine is turned off */ Status = NtQueryValueKey(KeyHandle, &DisableAppCompat, KeyValuePartialInformation, &KeyInfo, sizeof(KeyInfo), &ResultLength); NtClose(KeyHandle); if ((NT_SUCCESS(Status)) && (KeyInfo.Type == REG_DWORD) && (KeyInfo.DataLength == sizeof(ULONG)) && (KeyInfo.Data[0] == TRUE)) { /* It is, so disable shims! */ DisableShims = TRUE; } } } if (!DisableShims) { /* Finally, open the app compatibility policy key */ Status = NtOpenKey(&KeyHandle, KEY_QUERY_VALUE, &PolicyKeyAttributes); if (NT_SUCCESS(Status)) { /* Check if the system policy disables app compat */ Status = NtQueryValueKey(KeyHandle, &DisableEngine, KeyValuePartialInformation, &KeyInfo, sizeof(KeyInfo), &ResultLength); NtClose(KeyHandle); if ((NT_SUCCESS(Status)) && (KeyInfo.Type == REG_DWORD) && (KeyInfo.DataLength == sizeof(ULONG)) && (KeyInfo.Data[0] == TRUE)) { /* It does, so disable shims! */ DisableShims = TRUE; } } } g_ShimsDisabled = DisableShims; }
/* Return if shims are disabled or not ("Enabled == 1" means disabled!) */ return g_ShimsDisabled ? TRUE : FALSE;}
/* * @unimplemented */BOOLBasepShimCacheCheckBypass( _In_ PCWSTR ApplicationName, _In_ HANDLE FileHandle, _In_opt_ PCWSTR Environment, _In_ BOOL bUnknown, _Out_opt_ PULONG pdwReason){ DPRINT("fixme:(%S, %p, %S, %d, %p)\n", ApplicationName, FileHandle, Environment, bUnknown, pdwReason); return FALSE;}
/* * @implemented */BOOLBasepShimCacheSearch( _In_ PCWSTR ApplicationName, _In_ HANDLE FileHandle){ APPHELP_CACHE_SERVICE_LOOKUP Lookup; RtlInitUnicodeString(&Lookup.ImageName, ApplicationName); Lookup.ImageHandle = FileHandle; return NT_SUCCESS(NtApphelpCacheControl(ApphelpCacheServiceLookup, &Lookup));}
/* * @unimplemented */BOOLBasepCheckCacheExcludeList( _In_ PCWSTR ApplicationName){ return FALSE;}
/* * @unimplemented */BOOLBasepCheckCacheExcludeCustom( _In_ PCWSTR ApplicationName){ return FALSE;}
/* * @implemented */VOIDBasepShimCacheRemoveEntry( _In_ PCWSTR ApplicationName){ APPHELP_CACHE_SERVICE_LOOKUP Lookup; RtlInitUnicodeString(&Lookup.ImageName, ApplicationName); Lookup.ImageHandle = INVALID_HANDLE_VALUE; NtApphelpCacheControl(ApphelpCacheServiceRemove, &Lookup);}
/* * @unimplemented */BOOLBasepShimCacheLookup( _In_ PCWSTR ApplicationName, _In_ HANDLE FileHandle){ DPRINT("fixme:(%S, %p)\n", ApplicationName, FileHandle);
if (!BasepShimCacheSearch(ApplicationName, FileHandle)) return FALSE;
if (!BasepCheckCacheExcludeList(ApplicationName) || !BasepCheckCacheExcludeCustom(ApplicationName)) { BasepShimCacheRemoveEntry(ApplicationName); return FALSE; }
return TRUE;}
/* * @implemented */BOOLWINAPIBaseCheckAppcompatCache( _In_ PCWSTR ApplicationName, _In_ HANDLE FileHandle, _In_opt_ PCWSTR Environment, _Out_opt_ PULONG pdwReason){ BOOL ret = FALSE; ULONG dwReason;
DPRINT("(%S, %p, %S, %p)\n", ApplicationName, FileHandle, Environment, pdwReason);
dwReason = 0; if (BasepShimCacheCheckBypass(ApplicationName, FileHandle, Environment, TRUE, &dwReason)) { dwReason |= 2; } else { ret = BasepShimCacheLookup(ApplicationName, FileHandle); if (!ret) dwReason |= 1; }
if (pdwReason) *pdwReason = dwReason;
return ret;}
staticVOIDBaseInitApphelp(VOID){ WCHAR Buffer[MAX_PATH*2]; UNICODE_STRING DllPath = {0}; PVOID ApphelpAddress; PVOID pApphelpCheckRunAppEx = NULL, pSdbPackAppCompatData = NULL;
RtlInitEmptyUnicodeString(&DllPath, Buffer, sizeof(Buffer)); RtlCopyUnicodeString(&DllPath, &BaseWindowsDirectory); RtlAppendUnicodeToString(&DllPath, L"\\system32\\apphelp.dll");
if (NT_SUCCESS(LdrLoadDll(NULL, NULL, &DllPath, &ApphelpAddress))) { ANSI_STRING ProcName;
RtlInitAnsiString(&ProcName, "ApphelpCheckRunAppEx"); if (!NT_SUCCESS(LdrGetProcedureAddress(ApphelpAddress, &ProcName, 0, &pApphelpCheckRunAppEx))) pApphelpCheckRunAppEx = NULL;
RtlInitAnsiString(&ProcName, "SdbPackAppCompatData"); if (!NT_SUCCESS(LdrGetProcedureAddress(ApphelpAddress, &ProcName, 0, &pSdbPackAppCompatData))) pSdbPackAppCompatData = NULL; }
if (InterlockedCompareExchangePointer(&g_pApphelpCheckRunAppEx, RtlEncodeSystemPointer(pApphelpCheckRunAppEx), NULL) == NULL) { g_pSdbPackAppCompatData = RtlEncodeSystemPointer(pSdbPackAppCompatData); }}
/* * */BOOLWINAPIBaseCheckRunApp(IN HANDLE FileHandle, IN PWCHAR ApplicationName, IN PWCHAR Environment, IN USHORT ExeType, IN PULONG pReason, IN PVOID* SdbQueryAppCompatData, IN PULONG SdbQueryAppCompatDataSize, IN PVOID* SxsData, IN PULONG SxsDataSize, OUT PULONG FusionFlags){ ULONG Reason = 0; ULONG64 Flags1 = 0; ULONG Flags2 = 0; BOOL Continue, NeedCleanup = FALSE; tApphelpCheckRunAppEx pApphelpCheckRunAppEx; tSdbPackAppCompatData pSdbPackAppCompatData; PVOID QueryResult = NULL; ULONG QueryResultSize = 0;
if (!g_ApphelpInitialized) { BaseInitApphelp(); g_ApphelpInitialized = TRUE; }
pApphelpCheckRunAppEx = RtlDecodeSystemPointer(g_pApphelpCheckRunAppEx); pSdbPackAppCompatData = RtlDecodeSystemPointer(g_pSdbPackAppCompatData);
if (!pApphelpCheckRunAppEx || !pSdbPackAppCompatData) return TRUE;
if (pReason) Reason = *pReason;
Continue = pApphelpCheckRunAppEx(FileHandle, NULL, NULL, ApplicationName, Environment, ExeType, &Reason, &QueryResult, &QueryResultSize, SxsData, SxsDataSize, FusionFlags, &Flags1, &Flags2);
if (pReason) *pReason = Reason;
if (Continue) { if ((Reason & (APPHELP_VALID_RESULT|APPHELP_RESULT_FOUND)) == (APPHELP_VALID_RESULT|APPHELP_RESULT_FOUND)) { if (!pSdbPackAppCompatData(NULL, QueryResult, SdbQueryAppCompatData, SdbQueryAppCompatDataSize)) { DPRINT1("SdbPackAppCompatData returned a failure!\n"); NeedCleanup = TRUE; } } else { NeedCleanup = TRUE; } }
if (QueryResult) RtlFreeHeap(RtlGetProcessHeap(), 0, QueryResult);
if (NeedCleanup) { BasepFreeAppCompatData(*SdbQueryAppCompatData, *SxsData); *SdbQueryAppCompatData = NULL; if (SdbQueryAppCompatDataSize) *SdbQueryAppCompatDataSize = 0; *SxsData = NULL; if (SxsDataSize) *SxsDataSize = 0; }
return Continue;}
/* * @implemented */NTSTATUSWINAPIBasepCheckBadapp(IN HANDLE FileHandle, IN PWCHAR ApplicationName, IN PWCHAR Environment, IN USHORT ExeType, IN PVOID* SdbQueryAppCompatData, IN PULONG SdbQueryAppCompatDataSize, IN PVOID* SxsData, IN PULONG SxsDataSize, OUT PULONG FusionFlags){ NTSTATUS Status = STATUS_SUCCESS; ULONG Reason = 0;
/* Is shimming enabled by group policy? */ if (IsShimInfrastructureDisabled()) { /* Nothing to worry about */ Status = STATUS_SUCCESS; } else { /* It is, check if we know about this app */ if (!BaseCheckAppcompatCache(ApplicationName, FileHandle, Environment, &Reason)) { if (!BaseCheckRunApp(FileHandle, ApplicationName, Environment, ExeType, &Reason, SdbQueryAppCompatData, SdbQueryAppCompatDataSize, SxsData, SxsDataSize, FusionFlags)) { Status = STATUS_ACCESS_DENIED; } } }
/* Return caller the status */ return Status;}
/* * @implemented */BOOLWINAPIBaseDumpAppcompatCache(VOID){ NTSTATUS Status;
Status = NtApphelpCacheControl(ApphelpCacheServiceDump, NULL); return NT_SUCCESS(Status);}
/* * @implemented */BOOLWINAPIBaseFlushAppcompatCache(VOID){ NTSTATUS Status;
Status = NtApphelpCacheControl(ApphelpCacheServiceFlush, NULL); return NT_SUCCESS(Status);}
/* * @implemented */VOIDWINAPIBasepFreeAppCompatData(IN PVOID AppCompatData, IN PVOID AppCompatSxsData){ /* Free the input pointers if present */ if (AppCompatData) RtlFreeHeap(RtlGetProcessHeap(), 0, AppCompatData); if (AppCompatSxsData) RtlFreeHeap(RtlGetProcessHeap(), 0, AppCompatSxsData);}
/* * @unimplemented */VOIDWINAPIBaseUpdateAppcompatCache(ULONG Unknown1, ULONG Unknown2, ULONG Unknown3){ STUB;}
/* * @unimplemented */NTSTATUSWINAPIBaseCleanupAppcompatCache(VOID){ STUB; return STATUS_NOT_IMPLEMENTED;}
/* * @unimplemented */NTSTATUSWINAPIBaseCleanupAppcompatCacheSupport(PVOID pUnknown){ STUB; return STATUS_NOT_IMPLEMENTED;}
/* * @unimplemented */BOOLWINAPIBaseInitAppcompatCache(VOID){ STUB; return FALSE;}
/* * @unimplemented */BOOLWINAPIBaseInitAppcompatCacheSupport(VOID){ STUB; return FALSE;}
/* * @unimplemented */PVOIDWINAPIGetComPlusPackageInstallStatus(VOID){ STUB; return NULL;}
/* * @implemented */BOOLWINAPISetComPlusPackageInstallStatus(IN ULONG ComPlusPackage){ NTSTATUS Status;
DPRINT("(0x%X)\n", ComPlusPackage);
if (ComPlusPackage & ~1) { DPRINT1("0x%lX\n", ComPlusPackage); BaseSetLastNTError(STATUS_INVALID_PARAMETER); return FALSE; }
Status = NtSetSystemInformation(SystemComPlusPackage, &ComPlusPackage, sizeof(ComPlusPackage)); if (!NT_SUCCESS(Status)) { DPRINT1("0x%lX\n", Status); BaseSetLastNTError(Status); return FALSE; }
return TRUE;}
/* * @unimplemented */VOIDWINAPISetTermsrvAppInstallMode(IN BOOL bInstallMode){ STUB;}
/* * @unimplemented */BOOLWINAPITermsrvAppInstallMode(VOID){ STUB; return FALSE;}