Skip to content

Commit 88fcb44

Browse files
authored
Merge f141828 into 4b339e2
2 parents 4b339e2 + f141828 commit 88fcb44

3 files changed

Lines changed: 64 additions & 10 deletions

File tree

source/UIAHandler/__init__.py

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -798,21 +798,23 @@ def _isUIAWindowHelper(self,hwnd):
798798
and not config.conf['UIA']['useInMSExcelWhenAvailable']
799799
):
800800
return False
801-
# Unless explicitly allowed, all Chromium implementations (including Edge) should not be UIA,
802-
# As their IA2 implementation is still better at the moment.
803-
elif (
804-
windowClass == "Chrome_RenderWidgetHostHWND"
805-
and (
801+
elif windowClass == "Chrome_RenderWidgetHostHWND":
802+
# Unless explicitly allowed, all Chromium implementations (including Edge) should not be UIA,
803+
# As their IA2 implementation is still better at the moment.
804+
# However, in cases where Chromium is running under another logon session,
805+
# the IAccessible2 implementation is unavailable.
806+
hasAccessToIA2 = not appModule.isRunningUnderDifferentLogonSession
807+
if (
806808
AllowUiaInChromium.getConfig() == AllowUiaInChromium.NO
807809
# Disabling is only useful if we can inject in-process (and use our older code)
808810
or (
809811
canUseOlderInProcessApproach
812+
and hasAccessToIA2
810813
and AllowUiaInChromium.getConfig() != AllowUiaInChromium.YES # Users can prefer to use UIA
811814
)
812-
)
813-
):
814-
return False
815-
if windowClass == "ConsoleWindowClass":
815+
):
816+
return False
817+
elif windowClass == "ConsoleWindowClass":
816818
return utils._shouldUseUIAConsole(hwnd)
817819
return bool(res)
818820

source/appModuleHandler.py

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,15 @@
3737
import exceptions
3838
import extensionPoints
3939
from fileUtils import getFileVersionInfo
40+
from typing import Optional
41+
from systemUtils import getProcessTokenOrigin
4042

4143
# Dictionary of processID:appModule pairs used to hold the currently running modules
4244
runningTable: Dict[int, AppModule] = {}
4345
#: The process ID of NVDA itself.
4446
NVDAProcessID=None
47+
#: The logon session ID under which NVDA was started.
48+
NVDAProcessLogonSessionID: Optional[int] = None
4549
_importers=None
4650
_getAppModuleLock=threading.RLock()
4751
#: Notifies when another application is taking foreground.
@@ -230,8 +234,12 @@ def reloadAppModules():
230234
def initialize():
231235
"""Initializes the appModule subsystem.
232236
"""
233-
global NVDAProcessID,_importers
237+
global NVDAProcessID, NVDAProcessLogonSessionID, _importers
234238
NVDAProcessID=os.getpid()
239+
try:
240+
NVDAProcessLogonSessionID = getProcessTokenOrigin(winKernel.GetCurrentProcess())
241+
except WindowsError:
242+
log.error("Couldn't get NVDAProcessLogonSessionID", exc_info=True)
235243
config.addConfigDirsToPythonPackagePath(appModules)
236244
_importers=list(pkgutil.iter_importers("appModules.__init__"))
237245

@@ -520,6 +528,20 @@ def _get_isWindowsStoreApp(self):
520528
self.isWindowsStoreApp = False
521529
return self.isWindowsStoreApp
522530

531+
def _get_isRunningUnderDifferentLogonSession(self) -> bool:
532+
"""Returns whether the application for this appModule was started under a different logon session.
533+
This applies to applications started with the Windows runas command
534+
or when choosing "run as a different user" from an application's (shortcut) context menu.
535+
"""
536+
try:
537+
self.isRunningUnderDifferentLogonSession = (
538+
NVDAProcessLogonSessionID != getProcessTokenOrigin(self.processHandle)
539+
)
540+
except WindowsError:
541+
log.error(f"Couldn't get logon session ID for {self}", exc_info=True)
542+
self.isRunningUnderDifferentLogonSession = False
543+
return self.isRunningUnderDifferentLogonSession
544+
523545
def _get_appArchitecture(self):
524546
"""Returns the target architecture for the specified app.
525547
This is useful for detecting X86/X64 apps running on ARM64 releases of Windows 10.

source/systemUtils.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,36 @@ def hasUiAccess():
6363
ctypes.windll.kernel32.CloseHandle(token)
6464

6565

66+
TokenOrigin = 17
67+
68+
69+
class TOKEN_ORIGIN(ctypes.Structure):
70+
_fields_ = [("OriginatingLogonSession", ctypes.c_ulonglong)]
71+
72+
73+
def getProcessTokenOrigin(processHandle):
74+
token = ctypes.wintypes.HANDLE()
75+
if not ctypes.windll.advapi32.OpenProcessToken(
76+
processHandle,
77+
winKernel.MAXIMUM_ALLOWED,
78+
ctypes.byref(token)
79+
):
80+
raise ctypes.WinError()
81+
try:
82+
val = TOKEN_ORIGIN()
83+
if not ctypes.windll.advapi32.GetTokenInformation(
84+
token,
85+
TokenOrigin,
86+
ctypes.byref(val),
87+
ctypes.sizeof(val),
88+
ctypes.byref(ctypes.wintypes.DWORD())
89+
):
90+
raise ctypes.WinError()
91+
return val.OriginatingLogonSession
92+
finally:
93+
ctypes.windll.kernel32.CloseHandle(token)
94+
95+
6696
def execElevated(path, params=None, wait=False, handleAlreadyElevated=False):
6797
import subprocess
6898
if params is not None:

0 commit comments

Comments
 (0)