Enabling the compatibility property sheet for (almost) all programs in Windows 8/8.1

Windows 8 and 8.1 hide the compatibility property sheet for certain programs (namely programs included with Windows, like Notepad, and those on a whitelist of programs known to run correctly on Windows 8/8.1 – defined in %WinDir%apppatchpcamain.sdb). In some cases, one can still run the ‘troubleshoot compatibility’ wizard by right-clicking on the file, which just presents compatibility settings in a novice-friendly, poweruser-unfriendly way.

The compatibility property sheet and context menu are defined in acppage.dll. By patching this DLL, we can enable the compatibility property sheet for (almost) all programs, including programs like Notepad and those whitelisted in pcamain.sdb.

Patching Windows system DLL files is probably a bad idea, and I take no responsibility if your computer explodes after you take the following steps.

I’ll write a tool to automate this process at some point, but for now, here are the manual steps if you’re feeling adventurous:

  1. Make a backup of acppage.dll from %WinDir%System32
  2. Take ownership of acppage.dll in %WinDir%System32:
  3. Grant administrator users full control over acppage.dll:
  4. Using your favourite hex editor (I like XVI32), overwrite the two bytes at the relevant address to 0x31 0xC0:

    • Windows 8.1 64-bit: 5A92 (the original bytes should be 0x8B 0xC7)
    • Windows 8.1 32-bit: 4B26 (the original bytes should be 0x8B 0xC6)
    • Windows 8 64-bit: 4DBB (the original bytes should be 0x8B 0xC3)
    • Windows 8 32-bit: 3D44 (the original bytes should be 0x8B 0xC6)

    Warning: If the existing bytes don’t match with what I’ve written above, don’t overwrite them! The addresses change with patches to Windows. The above addresses were current as of 2013-09-04.

  5. Restart explorer.exe

Voilà – the compatibility property sheet will appear for most programs now (I’ve noticed that it doesn’t show up for File Explorer):

Screenshot of Notepad.exe and the Compatibility property sheet

How does this actually work?

These two bytes are in the CLayerUIPropPage::Initialize function – this basically does a bunch of checks to determine whether the property sheet should be displayed or not. The original code (0x8B …) sets the return value (the EAX register) to the result of these checks – a non-zero result means the sheet won’t be displayed. We modify the function to always return 0 by using the instruction xor eax, eax (0x31 0xC0).