Exemplo n.º 1
0
 def getNearestWindowHandle(self, UIAElement):
     if hasattr(UIAElement, "_nearestWindowHandle"):
         # Called previously. Use cached result.
         return UIAElement._nearestWindowHandle
     try:
         processID = UIAElement.cachedProcessID
     except COMError:
         return None
     appModule = appModuleHandler.getAppModuleFromProcessID(processID)
     # WDAG (Windows Defender application Guard) UIA elements should be treated as being from a remote machine, and therefore their window handles are completely invalid on this machine.
     # Therefore, jump all the way up to the root of the WDAG process and use that window handle as it is local to this machine.
     if appModule.appName == WDAG_PROCESS_NAME:
         condition = UIAUtils.createUIAMultiPropertyCondition({
             UIA_ClassNamePropertyId:
             [u'ApplicationFrameWindow', u'CabinetWClass']
         })
         walker = self.clientObject.createTreeWalker(condition)
     else:
         # Not WDAG, just walk up to the nearest valid windowHandle
         walker = self.windowTreeWalker
     try:
         new = walker.NormalizeElementBuildCache(UIAElement,
                                                 self.windowCacheRequest)
     except COMError:
         return None
     try:
         window = new.cachedNativeWindowHandle
     except COMError:
         window = None
     # Cache for future use to improve performance.
     UIAElement._nearestWindowHandle = window
     return window
Exemplo n.º 2
0
 def _registerGlobalEventHandlers(self):
     self.clientObject.AddFocusChangedEventHandler(self.baseCacheRequest,
                                                   self)
     if isinstance(self.clientObject, UIA.IUIAutomation6):
         self.globalEventHandlerGroup = self.clientObject.CreateEventHandlerGroup(
         )
     else:
         self.globalEventHandlerGroup = UIAUtils.FakeEventHandlerGroup(
             self.clientObject)
     self.globalEventHandlerGroup.AddPropertyChangedEventHandler(
         UIA.TreeScope_Subtree, self.baseCacheRequest, self,
         *self.clientObject.IntSafeArrayToNativeArray(
             globalEventHandlerGroupUIAPropertyIds if config.
             conf['UIA']['selectiveEventRegistration'] else
             UIAPropertyIdsToNVDAEventNames))
     for eventId in (globalEventHandlerGroupUIAEventIds
                     if config.conf['UIA']['selectiveEventRegistration']
                     else UIAEventIdsToNVDAEventNames):
         self.globalEventHandlerGroup.AddAutomationEventHandler(
             eventId, UIA.TreeScope_Subtree, self.baseCacheRequest, self)
     # #7984: add support for notification event (IUIAutomation5, part of Windows 10 build 16299 and later).
     if isinstance(self.clientObject, UIA.IUIAutomation5):
         self.globalEventHandlerGroup.AddNotificationEventHandler(
             UIA.TreeScope_Subtree, self.baseCacheRequest, self)
     self.addEventHandlerGroup(self.rootElement,
                               self.globalEventHandlerGroup)
Exemplo n.º 3
0
	def getNearestWindowHandle(self,UIAElement):
		if hasattr(UIAElement,"_nearestWindowHandle"):
			# Called previously. Use cached result.
			return UIAElement._nearestWindowHandle
		try:
			processID=UIAElement.cachedProcessID
		except COMError:
			return None
		appModule=appModuleHandler.getAppModuleFromProcessID(processID)
		# WDAG (Windows Defender application Guard) UIA elements should be treated as being from a remote machine, and therefore their window handles are completely invalid on this machine.
		# Therefore, jump all the way up to the root of the WDAG process and use that window handle as it is local to this machine.
		if appModule.appName==WDAG_PROCESS_NAME:
			condition=UIAUtils.createUIAMultiPropertyCondition({UIA_ClassNamePropertyId:[u'ApplicationFrameWindow',u'CabinetWClass']})
			walker=self.clientObject.createTreeWalker(condition)
		else:
			# Not WDAG, just walk up to the nearest valid windowHandle
			walker=self.windowTreeWalker
		try:
			new=walker.NormalizeElementBuildCache(UIAElement,self.windowCacheRequest)
		except COMError:
			return None
		try:
			window=new.cachedNativeWindowHandle
		except COMError:
			window=None
		# Cache for future use to improve performance.
		UIAElement._nearestWindowHandle=window
		return window
Exemplo n.º 4
0
	def _isBadUIAWindowClassName(self, windowClass):
		"Given a windowClassName, returns True if this is a known problematic UIA implementation."
		if (
			windowClass == "ConsoleWindowClass"
			and not UIAUtils.shouldUseUIAConsole()
		):
			return True
		return windowClass in badUIAWindowClassNames
Exemplo n.º 5
0
 def _createLocalEventHandlerGroup(self):
     if isinstance(self.clientObject, UIA.IUIAutomation6):
         self.localEventHandlerGroup = self.clientObject.CreateEventHandlerGroup(
         )
     else:
         self.localEventHandlerGroup = UIAUtils.FakeEventHandlerGroup(
             self.clientObject)
     self.localEventHandlerGroup.AddPropertyChangedEventHandler(
         UIA.TreeScope_Ancestors | UIA.TreeScope_Element,
         self.baseCacheRequest, self,
         *self.clientObject.IntSafeArrayToNativeArray(
             localEventHandlerGroupUIAPropertyIds))
     for eventId in localEventHandlerGroupUIAEventIds:
         self.localEventHandlerGroup.AddAutomationEventHandler(
             eventId, UIA.TreeScope_Ancestors | UIA.TreeScope_Element,
             self.baseCacheRequest, self)
Exemplo n.º 6
0
	def _isUIAWindowHelper(self,hwnd):
		# UIA in NVDA's process freezes in Windows 7 and below
		processID=winUser.getWindowThreadProcessID(hwnd)[0]
		if windll.kernel32.GetCurrentProcessId()==processID:
			return False
		import NVDAObjects.window
		windowClass=NVDAObjects.window.Window.normalizeWindowClassName(winUser.getClassName(hwnd))
		# For certain window classes, we always want to use UIA.
		if windowClass in goodUIAWindowClassNames:
			return True
		# allow the appModule for the window to also choose if this window is good
		# An appModule should be able to override bad UIA class names as prescribed by core
		appModule=appModuleHandler.getAppModuleFromProcessID(processID)
		if appModule and appModule.isGoodUIAWindow(hwnd):
			return True
		# There are certain window classes that just had bad UIA implementations
		if windowClass in badUIAWindowClassNames:
			return False
		# allow the appModule for the window to also choose if this window is bad
		if appModule and appModule.isBadUIAWindow(hwnd):
			return False
		if windowClass == "NetUIHWND" and appModule:
			# NetUIHWND is used for various controls in MS Office.
			# IAccessible should be used for NetUIHWND in versions older than 2016
			# Fixes: lack of focus reporting (#4207),
			# Fixes: strange reporting of context menu items(#9252),
			# fixes: not being able to report ribbon sections when they starts with an edit  field (#7067)
			# Note that #7067 is not fixed for Office 2016 and never.
			# Using IAccessible for NetUIHWND controls causes focus changes not to be reported
			# when the ribbon is collapsed.
			# Testing shows that these controls emits proper events but they are ignored by NVDA.
			isOfficeApp = appModule.productName.startswith(("Microsoft Office", "Microsoft Outlook"))
			isOffice2013OrOlder = int(appModule.productVersion.split(".")[0]) < 16
			if isOfficeApp and isOffice2013OrOlder:
				parentHwnd = winUser.getAncestor(hwnd, winUser.GA_PARENT)
				while parentHwnd:
					if winUser.getClassName(parentHwnd) in ("Net UI Tool Window", "MsoCommandBar",):
						return False
					parentHwnd = winUser.getAncestor(parentHwnd, winUser.GA_PARENT)
		# Ask the window if it supports UIA natively
		res=windll.UIAutomationCore.UiaHasServerSideProvider(hwnd)
		if res:
			# The window does support UIA natively.
			# Detect if we can also inject in-process
			canUseOlderInProcessApproach = bool(appModule.helperLocalBindingHandle)

			# MS Word documents now have a fairly usable UI Automation implementation.
			# However, builds of MS Office 2016 before build 13901 or so had bugs which
			# we cannot work around.
			# Therefore for less recent versions of Office,
			# if we can inject in-process, refuse to use UIA and instead
			# fall back to the MS Word object model.
			if windowClass == "_WwG":
				isOfficeApp = appModule.productName.startswith(("Microsoft Office", "Microsoft Outlook"))
				if (
					(
						winVersion.getWinVer() < winVersion.WIN10
						or (
							# An MS Office app before build 13901
							isOfficeApp
							and (
								tuple(int(x) for x in appModule.productVersion.split('.')[:3])
								< (16, 0, 13901)
							)
						)
					)
					# Disabling is only useful if we can inject in-process (and use our older code)
					and canUseOlderInProcessApproach
					# Allow the user to still explicitly force UIA support
					# no matter the Office version
					and not config.conf['UIA']['useInMSWordWhenAvailable']
				):
					return False
			# MS Excel spreadsheets now have a fairly usable UI Automation implementation.
			# However, builds of MS Office 2016 before build 9000 or so had bugs which we
			# cannot work around.
			# And even current builds of Office 2016 are still missing enough info from UIA
			# that it is still impossible to switch to UIA completely.
			# Therefore, if we can inject in-process, refuse to use UIA and instead fall
			# back to the MS Excel object model.
			elif (
				# An MS Excel spreadsheet window
				windowClass == "EXCEL7"
				# Disabling is only useful if we can inject in-process (and use our older code)
				and appModule.helperLocalBindingHandle
				# Allow the user to explicitly force UIA support for MS Excel spreadsheets
				# no matter the Office version
				and not config.conf['UIA']['useInMSExcelWhenAvailable']
			):
				return False
			# Unless explicitly allowed, all Chromium implementations (including Edge) should not be UIA,
			# As their IA2 implementation is still better at the moment.
			elif (
				windowClass == "Chrome_RenderWidgetHostHWND"
				and (
					AllowUiaInChromium.getConfig() == AllowUiaInChromium.NO
					# Disabling is only useful if we can inject in-process (and use our older code)
					or (
						canUseOlderInProcessApproach
						and AllowUiaInChromium.getConfig() != AllowUiaInChromium.YES  # Users can prefer to use UIA
					)
				)
			):
				return False
			elif windowClass == "ConsoleWindowClass":
				return UIAUtils._shouldUseUIAConsole(hwnd)
		return bool(res)