First half of COM Registration Fixing Tool refactor: make the tool effective on 64-bit windows, and fix more problems (#12560)
Fixes #9039
The COM Registration Fixing Tool seems to have never worked fully on 64bit Windows, as a result of path confusion caused by the use of SysWOW64, and the executable names used.
In addition, modern browsers seem to check a typelib registration that could be damaged by certain uninstallations (e.g. older versions of MathPlayer). We didn't previously do anything about this.
Further background:
In 64 bit Windows, %WINDIR%\System32 contains 64-bit executables. Meanwhile, %WINDIR%\SysWOW64 contains 32-bit executables. That seems inverted from what it should be, but there is a good explanation here for why it's like that.
When a 32-bit application calls something in System32, SysWOW64 assumes that it wants the 32-bit version, and redirects the call to the version in the SysWOW64 directory.
If the 32-bit application really wants the 64-bit version of whatever it's calling, it has to use the virtual directory %WINDIR%\Sysnative, which SysWOW64 provides.
We were calling regedit.exe and regsvr32.exe in contexts where we assumed 32-bit, from either %WINDIR% or %WINDIR%\System32. Because NVDA is 32-bit, that would result in the 32-bit application being called. That's okay.
However when the test was made for 64-bit, executables in %WINDIR%\SysWOW64 were being used, which are also 32-bit.
At least one of those should be 64-bit for COM reregistrations, but neither are.
In no case should we ever call anything in %WINDIR%\SysWOW64 ourselves, which we currently do.
Description of how this pull request fixes the issue:
Taken from the commit that rewrites COMRegistrationFixes/__init__.py:
Repaired the COM Registration Fixing Tool so it is more effective on 64bit Windows (Partial fix of #9039).
• Problems:
◦ The registerServer function called the 32-bit version of regsvr32.exe, even in 64-bit contexts.
◦ The applyRegistryPatch function called the 32-bit version of regedit, even in 64-bit contexts.
◦ The Win7 32-bit run did not take into account 32-bit only systems (no Program Files (x86) folder).
• Remediation:
◦ Replaced applyRegistryPatch function with two new functions: apply32bitRegistryPatch and apply64bitRegistryPatch.
◦ Replaced registerServer function with register32bitServer and register64bitServer, to make clear what they do.
◦ The new functions don't check 32/64 bitness; they leave that to the caller and log errors on failure.
◦ Updated to more descriptive error logging.
◦ Adjusted the Windows 7 code to use server registration with proper bitness for each DLL.
• Path remediations:
◦ Moved the OLEACC_REG_FILE_PATH constant to the top of the file with the rest.
◦ Added Sysnative path to the list of path constants at the top of the file.
◦ Now use Sysnative in the path for intentional 64bit calls.
◦ Now use System32 in the path for 32-bit calls on either 32-bit or 64-bit systems.
◦ Now use reg.exe's import option to load .reg files instead of regedit.exe.
◦ Now check whether to use "Program Files" or "Program Files (x86)" on Win7.
◦ Removed now unused sysWow64 path constant.
• Misc:
◦ Added docstring note about 32 and 64 bit functions needing attention if NVDA goes 64-bit in the future.
◦ Converted path constants to uppercase-with-underscore style, and corrected case on some Windows paths.
◦ Moved comments with discussion links into module docstring, and rearranged.
◦ Used subprocess.STARTUPINFO to prevent console windows from showing during executions.
◦ In gui/__init__.py update the message shown on tool completion, to recommend a restart.
Separately, @michaelDCurran found a registry key that we should delete to restore browser functionality under certain circumstances. That is included as a separate joint commit.