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