1 /* 2 * PROJECT: ReactOS Win32 Base API 3 * LICENSE: GPL - See COPYING in the top level directory 4 * FILE: dll/win32/kernel32/client/appcache.c 5 * PURPOSE: Application Compatibility Cache 6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) 7 */ 8 9 /* INCLUDES *******************************************************************/ 10 11 #include <k32.h> 12 13 #define NDEBUG 14 #include <debug.h> 15 16 /* GLOBALS ********************************************************************/ 17 18 ULONG g_ShimsDisabled = -1; 19 static BOOL g_ApphelpInitialized = FALSE; 20 static PVOID g_pApphelpCheckRunAppEx; 21 static PVOID g_pSdbPackAppCompatData; 22 23 typedef BOOL (WINAPI *tApphelpCheckRunAppEx)(HANDLE FileHandle, PVOID Unk1, PVOID Unk2, PWCHAR ApplicationName, PVOID Environment, USHORT ExeType, PULONG Reason, 24 PVOID* SdbQueryAppCompatData, PULONG SdbQueryAppCompatDataSize, PVOID* SxsData, PULONG SxsDataSize, 25 PULONG FusionFlags, PULONG64 SomeFlag1, PULONG SomeFlag2); 26 typedef BOOL (WINAPI *tSdbPackAppCompatData)(PVOID hsdb, PVOID pQueryResult, PVOID* ppData, DWORD *dwSize); 27 28 #define APPHELP_VALID_RESULT 0x10000 29 #define APPHELP_RESULT_NOTFOUND 0x20000 30 #define APPHELP_RESULT_FOUND 0x40000 31 32 33 /* FUNCTIONS ******************************************************************/ 34 35 BOOLEAN 36 WINAPI 37 IsShimInfrastructureDisabled(VOID) 38 { 39 HANDLE KeyHandle; 40 NTSTATUS Status; 41 KEY_VALUE_PARTIAL_INFORMATION KeyInfo; 42 ULONG ResultLength; 43 UNICODE_STRING OptionKey = RTL_CONSTANT_STRING(L"\\Registry\\MACHINE\\System\\CurrentControlSet\\Control\\SafeBoot\\Option"); 44 UNICODE_STRING AppCompatKey = RTL_CONSTANT_STRING(L"\\Registry\\MACHINE\\System\\CurrentControlSet\\Control\\Session Manager\\AppCompatibility"); 45 UNICODE_STRING PolicyKey = RTL_CONSTANT_STRING(L"\\Registry\\MACHINE\\Software\\Policies\\Microsoft\\Windows\\AppCompat"); 46 UNICODE_STRING OptionValue = RTL_CONSTANT_STRING(L"OptionValue"); 47 UNICODE_STRING DisableAppCompat = RTL_CONSTANT_STRING(L"DisableAppCompat"); 48 UNICODE_STRING DisableEngine = RTL_CONSTANT_STRING(L"DisableEngine"); 49 OBJECT_ATTRIBUTES OptionKeyAttributes = RTL_CONSTANT_OBJECT_ATTRIBUTES(&OptionKey, OBJ_CASE_INSENSITIVE); 50 OBJECT_ATTRIBUTES AppCompatKeyAttributes = RTL_CONSTANT_OBJECT_ATTRIBUTES(&AppCompatKey, OBJ_CASE_INSENSITIVE); 51 OBJECT_ATTRIBUTES PolicyKeyAttributes = RTL_CONSTANT_OBJECT_ATTRIBUTES(&PolicyKey, OBJ_CASE_INSENSITIVE); 52 53 /* 54 * This is a TROOLEAN, -1 means we haven't yet figured it out. 55 * 0 means shims are enabled, and 1 means shims are disabled! 56 */ 57 if (g_ShimsDisabled == -1) 58 { 59 ULONG DisableShims = FALSE; 60 61 /* Open the safe mode key */ 62 Status = NtOpenKey(&KeyHandle, KEY_QUERY_VALUE, &OptionKeyAttributes); 63 if (NT_SUCCESS(Status)) 64 { 65 /* Check if this is safemode */ 66 Status = NtQueryValueKey(KeyHandle, 67 &OptionValue, 68 KeyValuePartialInformation, 69 &KeyInfo, 70 sizeof(KeyInfo), 71 &ResultLength); 72 NtClose(KeyHandle); 73 if ((NT_SUCCESS(Status)) && 74 (KeyInfo.Type == REG_DWORD) && 75 (KeyInfo.DataLength == sizeof(ULONG)) && 76 (KeyInfo.Data[0] != FALSE)) 77 { 78 /* It is, so disable shims! */ 79 DisableShims = TRUE; 80 } 81 } 82 83 if (!DisableShims) 84 { 85 /* Open the app compatibility engine settings key */ 86 Status = NtOpenKey(&KeyHandle, KEY_QUERY_VALUE, &AppCompatKeyAttributes); 87 if (NT_SUCCESS(Status)) 88 { 89 /* Check if the app compat engine is turned off */ 90 Status = NtQueryValueKey(KeyHandle, 91 &DisableAppCompat, 92 KeyValuePartialInformation, 93 &KeyInfo, 94 sizeof(KeyInfo), 95 &ResultLength); 96 NtClose(KeyHandle); 97 if ((NT_SUCCESS(Status)) && 98 (KeyInfo.Type == REG_DWORD) && 99 (KeyInfo.DataLength == sizeof(ULONG)) && 100 (KeyInfo.Data[0] == TRUE)) 101 { 102 /* It is, so disable shims! */ 103 DisableShims = TRUE; 104 } 105 } 106 } 107 if (!DisableShims) 108 { 109 /* Finally, open the app compatibility policy key */ 110 Status = NtOpenKey(&KeyHandle, KEY_QUERY_VALUE, &PolicyKeyAttributes); 111 if (NT_SUCCESS(Status)) 112 { 113 /* Check if the system policy disables app compat */ 114 Status = NtQueryValueKey(KeyHandle, 115 &DisableEngine, 116 KeyValuePartialInformation, 117 &KeyInfo, 118 sizeof(KeyInfo), 119 &ResultLength); 120 NtClose(KeyHandle); 121 if ((NT_SUCCESS(Status)) && 122 (KeyInfo.Type == REG_DWORD) && 123 (KeyInfo.DataLength == sizeof(ULONG)) && 124 (KeyInfo.Data[0] == TRUE)) 125 { 126 /* It does, so disable shims! */ 127 DisableShims = TRUE; 128 } 129 } 130 } 131 g_ShimsDisabled = DisableShims; 132 } 133 134 /* Return if shims are disabled or not ("Enabled == 1" means disabled!) */ 135 return g_ShimsDisabled ? TRUE : FALSE; 136 } 137 138 /* 139 * @unimplemented 140 */ 141 BOOL 142 WINAPI 143 BaseCheckAppcompatCache(IN PWCHAR ApplicationName, 144 IN HANDLE FileHandle, 145 IN PWCHAR Environment, 146 OUT PULONG Reason) 147 { 148 DPRINT("BaseCheckAppcompatCache is UNIMPLEMENTED\n"); 149 150 if (Reason) *Reason = 0; 151 152 // We don't know this app. 153 return FALSE; 154 } 155 156 static 157 VOID 158 BaseInitApphelp(VOID) 159 { 160 WCHAR Buffer[MAX_PATH*2]; 161 UNICODE_STRING DllPath = {0}; 162 PVOID ApphelpAddress; 163 PVOID pApphelpCheckRunAppEx = NULL, pSdbPackAppCompatData = NULL; 164 165 RtlInitEmptyUnicodeString(&DllPath, Buffer, sizeof(Buffer)); 166 RtlCopyUnicodeString(&DllPath, &BaseWindowsDirectory); 167 RtlAppendUnicodeToString(&DllPath, L"\\system32\\apphelp.dll"); 168 169 if (NT_SUCCESS(LdrLoadDll(NULL, NULL, &DllPath, &ApphelpAddress))) 170 { 171 ANSI_STRING ProcName; 172 173 RtlInitAnsiString(&ProcName, "ApphelpCheckRunAppEx"); 174 if (!NT_SUCCESS(LdrGetProcedureAddress(ApphelpAddress, &ProcName, 0, &pApphelpCheckRunAppEx))) 175 pApphelpCheckRunAppEx = NULL; 176 177 RtlInitAnsiString(&ProcName, "SdbPackAppCompatData"); 178 if (!NT_SUCCESS(LdrGetProcedureAddress(ApphelpAddress, &ProcName, 0, &pSdbPackAppCompatData))) 179 pSdbPackAppCompatData = NULL; 180 } 181 182 if (InterlockedCompareExchangePointer(&g_pApphelpCheckRunAppEx, RtlEncodeSystemPointer(pApphelpCheckRunAppEx), NULL) == NULL) 183 { 184 g_pSdbPackAppCompatData = RtlEncodeSystemPointer(pSdbPackAppCompatData); 185 } 186 } 187 188 /* 189 * 190 */ 191 BOOL 192 WINAPI 193 BaseCheckRunApp(IN HANDLE FileHandle, 194 IN PWCHAR ApplicationName, 195 IN PWCHAR Environment, 196 IN USHORT ExeType, 197 IN PULONG pReason, 198 IN PVOID* SdbQueryAppCompatData, 199 IN PULONG SdbQueryAppCompatDataSize, 200 IN PVOID* SxsData, 201 IN PULONG SxsDataSize, 202 OUT PULONG FusionFlags) 203 { 204 ULONG Reason = 0; 205 ULONG64 Flags1 = 0; 206 ULONG Flags2 = 0; 207 BOOL Continue, NeedCleanup = FALSE; 208 tApphelpCheckRunAppEx pApphelpCheckRunAppEx; 209 tSdbPackAppCompatData pSdbPackAppCompatData; 210 PVOID QueryResult = NULL; 211 ULONG QueryResultSize = 0; 212 213 if (!g_ApphelpInitialized) 214 { 215 BaseInitApphelp(); 216 g_ApphelpInitialized = TRUE; 217 } 218 219 pApphelpCheckRunAppEx = RtlDecodeSystemPointer(g_pApphelpCheckRunAppEx); 220 pSdbPackAppCompatData = RtlDecodeSystemPointer(g_pSdbPackAppCompatData); 221 222 if (!pApphelpCheckRunAppEx || !pSdbPackAppCompatData) 223 return TRUE; 224 225 if (pReason) 226 Reason = *pReason; 227 228 Continue = pApphelpCheckRunAppEx(FileHandle, NULL, NULL, ApplicationName, Environment, ExeType, &Reason, 229 &QueryResult, &QueryResultSize, SxsData, SxsDataSize, FusionFlags, &Flags1, &Flags2); 230 231 if (pReason) 232 *pReason = Reason; 233 234 if (Continue) 235 { 236 if ((Reason & (APPHELP_VALID_RESULT|APPHELP_RESULT_FOUND)) == (APPHELP_VALID_RESULT|APPHELP_RESULT_FOUND)) 237 { 238 if (!pSdbPackAppCompatData(NULL, QueryResult, SdbQueryAppCompatData, SdbQueryAppCompatDataSize)) 239 { 240 DPRINT1("SdbPackAppCompatData returned a failure!\n"); 241 NeedCleanup = TRUE; 242 } 243 } 244 else 245 { 246 NeedCleanup = TRUE; 247 } 248 } 249 250 if (QueryResult) 251 RtlFreeHeap(RtlGetProcessHeap(), 0, QueryResult); 252 253 if (NeedCleanup) 254 { 255 BasepFreeAppCompatData(*SdbQueryAppCompatData, *SxsData); 256 *SdbQueryAppCompatData = NULL; 257 if (SdbQueryAppCompatDataSize) 258 *SdbQueryAppCompatDataSize = 0; 259 *SxsData = NULL; 260 if (SxsDataSize) 261 *SxsDataSize = 0; 262 } 263 264 return Continue; 265 } 266 267 /* 268 * @implemented 269 */ 270 NTSTATUS 271 WINAPI 272 BasepCheckBadapp(IN HANDLE FileHandle, 273 IN PWCHAR ApplicationName, 274 IN PWCHAR Environment, 275 IN USHORT ExeType, 276 IN PVOID* SdbQueryAppCompatData, 277 IN PULONG SdbQueryAppCompatDataSize, 278 IN PVOID* SxsData, 279 IN PULONG SxsDataSize, 280 OUT PULONG FusionFlags) 281 { 282 NTSTATUS Status = STATUS_SUCCESS; 283 ULONG Reason = 0; 284 285 /* Is shimming enabled by group policy? */ 286 if (IsShimInfrastructureDisabled()) 287 { 288 /* Nothing to worry about */ 289 Status = STATUS_SUCCESS; 290 } 291 else 292 { 293 /* It is, check if we know about this app */ 294 if (!BaseCheckAppcompatCache(ApplicationName, 295 FileHandle, 296 Environment, 297 &Reason)) 298 { 299 if (!BaseCheckRunApp(FileHandle, ApplicationName, Environment, ExeType, &Reason, 300 SdbQueryAppCompatData, SdbQueryAppCompatDataSize, SxsData, SxsDataSize, FusionFlags)) 301 { 302 Status = STATUS_ACCESS_DENIED; 303 } 304 } 305 } 306 307 /* Return caller the status */ 308 return Status; 309 } 310 311 /* 312 * @implemented 313 */ 314 BOOL 315 WINAPI 316 BaseDumpAppcompatCache(VOID) 317 { 318 NTSTATUS Status; 319 320 Status = NtApphelpCacheControl(ApphelpCacheServiceDump, NULL); 321 return NT_SUCCESS(Status); 322 } 323 324 /* 325 * @implemented 326 */ 327 BOOL 328 WINAPI 329 BaseFlushAppcompatCache(VOID) 330 { 331 NTSTATUS Status; 332 333 Status = NtApphelpCacheControl(ApphelpCacheServiceFlush, NULL); 334 return NT_SUCCESS(Status); 335 } 336 337 /* 338 * @implemented 339 */ 340 VOID 341 WINAPI 342 BasepFreeAppCompatData(IN PVOID AppCompatData, 343 IN PVOID AppCompatSxsData) 344 { 345 /* Free the input pointers if present */ 346 if (AppCompatData) RtlFreeHeap(RtlGetProcessHeap(), 0, AppCompatData); 347 if (AppCompatSxsData) RtlFreeHeap(RtlGetProcessHeap(), 0, AppCompatSxsData); 348 } 349 350 /* 351 * @unimplemented 352 */ 353 VOID 354 WINAPI 355 BaseUpdateAppcompatCache(ULONG Unknown1, 356 ULONG Unknown2, 357 ULONG Unknown3) 358 { 359 STUB; 360 } 361 362 /* 363 * @unimplemented 364 */ 365 NTSTATUS 366 WINAPI 367 BaseCleanupAppcompatCache(VOID) 368 { 369 STUB; 370 return STATUS_NOT_IMPLEMENTED; 371 } 372 373 /* 374 * @unimplemented 375 */ 376 NTSTATUS 377 WINAPI 378 BaseCleanupAppcompatCacheSupport(PVOID pUnknown) 379 { 380 STUB; 381 return STATUS_NOT_IMPLEMENTED; 382 } 383 384 /* 385 * @unimplemented 386 */ 387 BOOL 388 WINAPI 389 BaseInitAppcompatCache(VOID) 390 { 391 STUB; 392 return FALSE; 393 } 394 395 /* 396 * @unimplemented 397 */ 398 BOOL 399 WINAPI 400 BaseInitAppcompatCacheSupport(VOID) 401 { 402 STUB; 403 return FALSE; 404 } 405 406 /* 407 * @unimplemented 408 */ 409 PVOID 410 WINAPI 411 GetComPlusPackageInstallStatus(VOID) 412 { 413 STUB; 414 return NULL; 415 } 416 417 /* 418 * @unimplemented 419 */ 420 BOOL 421 WINAPI 422 SetComPlusPackageInstallStatus(LPVOID lpInfo) 423 { 424 STUB; 425 return FALSE; 426 } 427 428 /* 429 * @unimplemented 430 */ 431 VOID 432 WINAPI 433 SetTermsrvAppInstallMode(IN BOOL bInstallMode) 434 { 435 STUB; 436 } 437 438 /* 439 * @unimplemented 440 */ 441 BOOL 442 WINAPI 443 TermsrvAppInstallMode(VOID) 444 { 445 STUB; 446 return FALSE; 447 } 448