|
1 | 1 | # A part of NonVisual Desktop Access (NVDA) |
2 | | -# Copyright (C) 2018-2020 NV Access Limited |
| 2 | +# Copyright (C) 2018-2021 NV Access Limited |
3 | 3 | # This file is covered by the GNU General Public License. |
4 | 4 | # See the file COPYING for more details. |
5 | 5 |
|
|
11 | 11 | import globalVars |
12 | 12 | from logHandler import log |
13 | 13 |
|
| 14 | +OLEACC_REG_FILE_PATH = os.path.join(globalVars.appDir, "COMRegistrationFixes", "oleaccProxy.reg") |
14 | 15 | # Particular 64 bit / 32 bit system paths |
15 | | -systemRoot=os.path.expandvars('%SYSTEMROOT%') |
16 | | -system32=os.path.join(systemRoot,'system32') |
17 | | -sysWow64=os.path.join(systemRoot,'syswow64') |
18 | | -systemDrive=os.path.expandvars('%SYSTEMDRIVE%\\') |
19 | | -programFiles=os.path.join(systemDrive,'program files') |
20 | | -programFilesX86=os.path.join(systemDrive,'program files (x86)') |
| 16 | +systemRoot = os.path.expandvars("%SYSTEMROOT%") |
| 17 | +system32 = os.path.join(systemRoot, "System32") |
| 18 | +sysnative = os.path.join(systemRoot, "Sysnative") # Virtual folder for reaching 64-bit exes from 32-bit apps |
| 19 | +systemDrive = os.path.expandvars("%SYSTEMDRIVE%\\") |
| 20 | +programFiles = os.path.join(systemDrive, "program files") |
| 21 | +programFilesX86 = os.path.join(systemDrive, "program files (x86)") |
21 | 22 |
|
22 | | -def registerServer(fileName,wow64=False): |
| 23 | +def register32bitServer(fileName: str) -> None: |
| 24 | + """Registers the COM proxy dll with the given file name, using the 32-bit version of regsvr32. |
| 25 | + Note: this function is valid while NVDA remains a 32-bit app. Re-evaluate if we move to 64-bit. |
| 26 | + @param fileName: the path to the dll |
| 27 | + @type fileName: str |
23 | 28 | """ |
24 | | - Registers the COM proxy dll with the given file name |
25 | | - Using regsvr32. |
| 29 | + # Points to the 32-bit version, on Windows 32-bit or 64-bit. |
| 30 | + regsvr32 = os.path.join(system32, "regsvr32.exe") |
| 31 | + try: |
| 32 | + subprocess.check_call([regsvr32, "/s", fileName]) |
| 33 | + except subprocess.CalledProcessError as e: |
| 34 | + log.error(f"Error registering {fileName} in a 32-bit context: {e}") |
| 35 | + else: |
| 36 | + log.debug(f"Registered {fileName} in a 32-bit context.") |
| 37 | + |
| 38 | + |
| 39 | +def register64bitServer(fileName: str) -> None: |
| 40 | + """Registers the COM proxy dll with the given file name, using the 64-bit version of regsvr64. |
| 41 | + Note: this function is valid while NVDA remains a 32-bit app. Re-evaluate if we move to 64-bit. |
26 | 42 | @param fileName: the path to the dll |
27 | 43 | @type fileName: str |
28 | | - @param wow64: If true then the 32 bit (wow64) version of regsvr32 will be used. |
29 | | - @type wow64: bool |
30 | 44 | """ |
31 | | - regsvr32=os.path.join(sysWow64 if wow64 else system32,'regsvr32.exe') |
| 45 | + # SysWOW64 provides a virtual directory to allow 32-bit programs to reach 64-bit executables. |
| 46 | + regsvr32 = os.path.join(sysnative, "regsvr32.exe") |
32 | 47 | try: |
33 | | - subprocess.check_call([regsvr32,'/s',fileName]) |
| 48 | + subprocess.check_call([regsvr32, "/s", fileName]) |
34 | 49 | except subprocess.CalledProcessError as e: |
35 | | - log.error("Error registering %s, %s"%(fileName,e)) |
| 50 | + log.error(f"Error registering {fileName} in a 64-bit context: {e}") |
36 | 51 | else: |
37 | | - log.debug("Registered %s"%fileName) |
| 52 | + log.debug(f"Registered {fileName} in a 64-bit context.") |
38 | 53 |
|
39 | | -def applyRegistryPatch(fileName,wow64=False): |
| 54 | + |
| 55 | +def apply32bitRegistryPatch(fileName: str) -> None: |
| 56 | + """Applies the registry patch with the given file name, using 32-bit regedit. |
| 57 | + Note: this function is valid while NVDA remains a 32-bit app. Re-evaluate if we move to 64-bit. |
| 58 | + @param fileName: the path to the .reg file |
| 59 | + @type fileName: str |
40 | 60 | """ |
41 | | - Applies the registry patch with the given file name |
42 | | - using regedit. |
| 61 | + if not os.path.isfile(fileName): |
| 62 | + raise FileNotFoundError(f"Cannot apply 32-bit registry patch: {fileName} not found.") |
| 63 | + # On 32-bit systems, regedt32 is in System32. On 64-bit systems, SysWOW64 will redirect to 32-bit version. |
| 64 | + regedit = os.path.join(systemRoot, "System32", "regedt32.exe") |
| 65 | + try: |
| 66 | + subprocess.check_call([regedit, "/s", fileName]) |
| 67 | + except subprocess.CalledProcessError as e: |
| 68 | + log.error(f"Error applying 32-bit registry patch from {fileName} with {regedit}: {e}") |
| 69 | + else: |
| 70 | + log.debug(f"Applied 32-bit registry patch from {fileName}") |
| 71 | + |
| 72 | + |
| 73 | +def apply64bitRegistryPatch(fileName: str) -> None: |
| 74 | + """Applies the registry patch with the given file name, using 64-bit regedit. |
| 75 | + Note: this function is valid while NVDA remains a 32-bit app. Re-evaluate if we move to 64-bit. |
43 | 76 | @param fileName: the path to the .reg file |
44 | 77 | @type fileName: str |
45 | 78 | """ |
46 | 79 | if not os.path.isfile(fileName): |
47 | | - raise FileNotFoundError(f"Cannot apply registry patch, {fileName} not found.") |
48 | | - regedit=os.path.join(sysWow64 if wow64 else systemRoot,'regedit.exe') |
| 80 | + raise FileNotFoundError(f"Cannot apply 64-bit registry patch: {fileName} not found.") |
| 81 | + # On 64-bit systems, SysWOW64 provides 32-bit apps with a virtual directory to reach 64-bit executables. |
| 82 | + # For hard coded historical compatibility, regedt32.exe is still the name of the 64-bit app. |
| 83 | + regedit = os.path.join(sysnative, "regedt32.exe") |
49 | 84 | try: |
50 | | - subprocess.check_call([regedit,'/s',fileName]) |
| 85 | + subprocess.check_call([regedit, "/s", fileName]) |
51 | 86 | except subprocess.CalledProcessError as e: |
52 | | - log.error("Error applying registry patch: %s with %s, %s"%(fileName,regedit,e)) |
| 87 | + log.error(f"Error applying 64-bit registry patch from {fileName} with {regedit}: {e}") |
53 | 88 | else: |
54 | | - log.debug("Applied registry patch: %s with %s"%(fileName,regedit)) |
| 89 | + log.debug(f"Applied 64-bit registry patch from {fileName}") |
55 | 90 |
|
56 | 91 |
|
57 | | -OLEACC_REG_FILE_PATH = os.path.join(globalVars.appDir, "COMRegistrationFixes", "oleaccProxy.reg") |
58 | 92 | def fixCOMRegistrations(): |
| 93 | + """Registers most common COM proxies, in case they have accidentally been unregistered or overwritten by |
| 94 | + 3rd party software installs/uninstalls. |
59 | 95 | """ |
60 | | - Registers most common COM proxies, in case they had accidentally been unregistered or overwritten by 3rd party software installs/uninstalls. |
61 | | - """ |
62 | | - is64bit=os.environ.get("PROCESSOR_ARCHITEW6432","").endswith('64') |
| 96 | + is64bit = os.environ.get("PROCESSOR_ARCHITEW6432","").endswith('64') |
63 | 97 | winVer = winVersion.getWinVer() |
64 | 98 | OSMajorMinor = (winVer.major, winVer.minor) |
65 | | - log.debug("Fixing COM registration for Windows %s.%s, %s"%(OSMajorMinor[0],OSMajorMinor[1],"64 bit" if is64bit else "32 bit")) |
| 99 | + log.debug("Fixing COM registration for Windows {}.{}, {}".format(OSMajorMinor[0], OSMajorMinor[1], "64 bit" if is64bit else "32 bit")) |
66 | 100 | # Commands taken from NVDA issue #2807 comment https://github.com/nvaccess/nvda/issues/2807#issuecomment-320149243 |
| 101 | + # And also the discussions in #9039 https://github.com/nvaccess/nvda/issues/9039 |
67 | 102 | # OLEACC (MSAA) proxies |
68 | | - applyRegistryPatch(OLEACC_REG_FILE_PATH) |
| 103 | + apply32bitRegistryPatch(OLEACC_REG_FILE_PATH) |
69 | 104 | if is64bit: |
70 | | - applyRegistryPatch(OLEACC_REG_FILE_PATH, wow64=True) |
| 105 | + apply64bitRegistryPatch(OLEACC_REG_FILE_PATH) |
71 | 106 | # IDispatch and other common OLE interfaces |
72 | | - registerServer(os.path.join(system32,'oleaut32.dll')) |
73 | | - registerServer(os.path.join(system32,'actxprxy.dll')) |
| 107 | + register32bitServer(os.path.join(system32, "oleaut32.dll")) |
| 108 | + register32bitServer(os.path.join(system32, "actxprxy.dll")) |
74 | 109 | if is64bit: |
75 | | - registerServer(os.path.join(sysWow64,'oleaut32.dll'),wow64=True) |
76 | | - registerServer(os.path.join(sysWow64,'actxprxy.dll'),wow64=True) |
| 110 | + register64bitServer(os.path.join(sysnative, "oleaut32.dll")) |
| 111 | + register64bitServer(os.path.join(sysnative, "actxprxy.dll")) |
77 | 112 | # IServiceProvider on windows 7 can become unregistered |
78 | | - if OSMajorMinor==(6,1): # Windows 7 |
79 | | - registerServer(os.path.join(programFiles,'Internet Explorer','ieproxy.dll')) |
| 113 | + if OSMajorMinor == (6, 1): # Windows 7 |
| 114 | + register32bitServer(os.path.join(programFilesX86, "Internet Explorer", "ieproxy.dll")) |
80 | 115 | if is64bit: |
81 | | - registerServer(os.path.join(programFilesX86,'Internet Explorer','ieproxy.dll'),wow64=True) |
| 116 | + register64bitServer(os.path.join(programFiles, "Internet Explorer", "ieproxy.dll")) |
0 commit comments