User:Learn more/Appcompat
Contents
What is it?
The Application Compatibility Framework is a mechanism designed to work around bugs in applications. It can happen after upgrading your operating system that applications suddenly stop working. A common reason for this is because the application (unknowningly to the author) relies on a bug in the operating system. Once this bug is fixed, the application suddenly stops working, and without an update from the author would not be usable anymore. Because an author might not be available to create an update (or might not even be aware of the problem), the Application Compatiblity Framework has mitigations to work around common errors.
The part most visible to the user is the 'Compatibility' tab presented in the properties dialog.
How does it work?
Overview
There are various techniques used to 'fix' applications:
- Call a specific function
- For example: If an application needs to run in 640x480, a fix will call a function at process start to change the resolution.
- Alter the behavior of a function.
- For example: If an application cannot properly handle disks above 2GB, a fix can make it appear as if there was only 2GB available.
- Alter the (perceived) environment of the application.
- For example: If an application checks that it is running on a certain version of windows, a fix can make it appear to the application as if it is running on this version.
Technical details
Initialization
Outlined below is a rough outline of the initialization of the shim engine. (...)
is used as a placeholder to indicate some omitted (non-relevant) function calls
Parent process
This is where the shim engine checks if there should be a shim applied. The checks if shims need to be applied are called from the function that creates the process. When shims need to be applied, memory is allocated in the target process, and a pointer in the PEB (pShimData) is initialized, pointing to this data.
kernel32!CreateProcess
kernel32!CreateProcessInternal
(...)
kernel32!BasepCheckBadapp
kernel32!BaseCheckAppcompatCache
- TODO
kernel32!BaseCheckRunApp
apphelp!ApphelpCheckRunApp[Ex]
(...)
kernel32!BasePushProcessParameters
(...)
ntdll!NtAllocateVirtualMemory
(Peb->pShimData)ntdll!NtWriteVirtualMemory
(Peb->pShimData)
Child process, initialization
At process start, LdrpInitializeProcess checks pShimData. If this is set, the process will need a shim, and the Shim Engine is initialized with LdrpLoadShimEngine. The dll to load for this is specified in the pShimData, and in w2k3 this is still shimeng.dll. In later versions this is changed to apphelp.dll.
That process roughly looks like this:
ntoskrnl!PspUserThreadStartup
(...)
ntdll!LdrInitializeThunk
(...)
ntdll!LdrpInit
(...)
ntdll!LdrpInitializeProcess
(Peb->pShimData)(...)
ntdll!!LdrpLoadShimEngine
(Peb->pShimData)(...)
shimeng!SE_InstallbeforeInit
Child process, execution
SeiInit does most of the work:
- Creating a list of shims to load (
SeiBuildShimRefArray
) - Building lists of modules to include / exclude (global and per shim,
SeiBuildGlobalInclExclList
,SeiBuildInclExclList
) - Loading the shim modules (
LdrLoadDll
) - Calling into the loaded shim modules to retrieve a list of functions to redirect (
GetHookAPIs
) - Redirecting the api's specified by the shims (
SeiHookImports
)
Initialization roughly looks like this:
apphelp!SE_InstallBeforeInit
apphelp!SeiGetShimData
(...)
apphelp!SdbInitDatabase
(...)
apphelp!SdbUnpackAppCompatData
apphelp!SeiInit
(...)
apphelp!SeiCheckComPlusImage
(...)
apphelp!SeiBuildGlobalInclExclList
(...)
ntdll!LdrGetDllHandle
ntdll!LdrLoadDll
<loaded shim module>!GetHookAPIs
(...)
apphelp!SeiBuildInclExclList
(...)
apphelp!SeiAddInternalHooks
apphelp!SeiResolveAPIs
apphelp!PatchNewModules
apphelp!SeiHookImports
apphelp!SdbReleaseDatabase
Current state
Implemented shims
Shim | Description |
---|---|
DisableThemes | Disable themes while the application is running. |
Force640x480 | Change the resolution to 640 x 480 while the application is running. |
Force8BitColor | Change the bitdepth to 8 bits while the application is running. |
IgnoreDebugOutput | Silently ignore debug output from an application. |
IgnoreFreeLibrary | Ignore calls to the 'FreeLibrary' function. The commandline specifies for which DLL. |
VMHorizonSetup | Fix some known problems in the setup of VMWare Horizon. |
WinNT4SP5VersionLie | Lie to the application about the OS version it's running on. |
Win95VersionLie | Lie to the application about the OS version it's running on. |
Win98VersionLie | Lie to the application about the OS version it's running on. |
Win2000VersionLie | Lie to the application about the OS version it's running on. |
Win2000SP1VersionLie | Lie to the application about the OS version it's running on. |
Win2000SP2VersionLie | Lie to the application about the OS version it's running on. |
Win2000SP3VersionLie | Lie to the application about the OS version it's running on. |
WinXPVersionLie | Lie to the application about the OS version it's running on. |
WinXPSP1VersionLie | Lie to the application about the OS version it's running on. |
WinXPSP2VersionLie | Lie to the application about the OS version it's running on. |
WinXPSP3VersionLie | Lie to the application about the OS version it's running on. |
Win2k3RTMVersionLie | Lie to the application about the OS version it's running on. |
Win2k3SP1VersionLie | Lie to the application about the OS version it's running on. |
VistaRTMVersionLie | Lie to the application about the OS version it's running on. |
VistaSP1VersionLie | Lie to the application about the OS version it's running on. |
VistaSP2VersionLie | Lie to the application about the OS version it's running on. |
Win7RTMVersionLie | Lie to the application about the OS version it's running on. |
Win8RTMVersionLie | Lie to the application about the OS version it's running on. |
Win81RTMVersionLie | Lie to the application about the OS version it's running on. |
Source: https://git.reactos.org/?p=reactos.git&a=search&h=HEAD&st=grep&s=%23define+SHIM_NS&sr=1