Repository: nvaccess/nvda

Issue:
Error sounds when navigating in UIA controls under Windows 7 after merge of PR 14222

### Steps to reproduce:
1. Start version of NVDA where PR #14222 is merged
2. Navigate in Windows Explorer / try searching in the start menu in Windows 7
### Actual behavior:
Error sound plays and the following is in the log:
```
ERROR - eventHandler.executeEvent (19:40:54.124) - MainThread (4480):
error executing event: UIA_elementSelected on <NVDAObjects.Dynamic_UIItemListItemUIA object at 0x06F9EE50> with extra args of {}
Traceback (most recent call last):
  File "eventHandler.pyc", line 300, in executeEvent
  File "eventHandler.pyc", line 101, in __init__
  File "eventHandler.pyc", line 110, in next
  File "NVDAObjects\UIA\__init__.pyc", line 2058, in event_UIA_elementSelected
  File "NVDAObjects\__init__.pyc", line 1189, in event_selection
  File "baseObject.pyc", line 42, in __get__
  File "baseObject.pyc", line 146, in _getPropertyViaCache
  File "NVDAObjects\UIA\__init__.pyc", line 2041, in _get_controllerFor
  File "NVDAObjects\UIA\__init__.pyc", line 987, in _getUIACacheablePropertyValue
  File "monkeyPatches\comtypesMonkeyPatches.pyc", line 32, in __call__
  File "comtypes\automation.pyc", line 516, in __ctypes_from_outparam__
  File "monkeyPatches\comtypesMonkeyPatches.pyc", line 146, in newVARIANT_value_fget
  File "comtypes\automation.pyc", line 467, in _get_value
KeyError: 13
```

### Expected behavior:
No error sounds
### NVDA logs, crash dumps and other attachments:

### System configuration
#### NVDA installed/portable/running from source:
Portable
#### NVDA version:
NVDA version alpha-26827,eff1aa45
#### Windows version:
Windows 7 X64
#### Name and version of other software in use when reproducing the issue:
None
#### Other information about your system:

### Other questions
#### Does the issue still occur after restarting your computer?
Not tried
#### Have you tried any other versions of NVDA? If so, please report their behaviors.
Regressed in latest Alpha versions
#### If NVDA add-ons are disabled, is your problem still occurring?
Yes
#### Does the issue still occur after you run the COM Registration Fixing Tool in NVDA's tools menu?
Not tried

cc @michaelDCurran 


Discussion:
Hi, I’m quite conflicted about this. On one hand, I think we still need to provide an exception to handle things not introduced until Windows 8 and later. On the other hand, some folks may ask NV Access to move to Python 3.10 and later, resulting in end of support for Windows 7. Perhaps a compromise, leaning more toward the second option, is to perhaps limit generic search suggestions implementation to Windows 8.1 and later, preferably Windows 10 and 11 (auto-suggest accessibility was properly introduced with Windows 8). Thanks.


I don't think there is any conflict here:
- As soon as we move to a version of Python which does not support Windows 7 this issue is no longer relevant, and can be closed
- Until then however, we should not introduce regressions for older system if possible.

Would you be able to link to a documentation mentioning that auto suggest for UIA is available for Windows 8 and later? As far as I can tell it mostly relies on `UIA_ControllerForPropertyId` which according to the [Microsoft's list of property ID's](https://learn.microsoft.com/en-us/windows/win32/winauto/uiauto-automation-element-propids) does not require a specific minimum version of Windows.
At a minimum we should catch KeyError around the call to 
_getUIACacheablePropertyValue in UIA._get_controllerFor, log a 
debugWarning and return an empty list.

However, the KeyError is due to an incompleteness in comtypes, where it 
does not support a variant holding a type of VT_Unknown | VT_Array (an 
array of IUnknowns).

According to documentation fr controllerFor: 
https://learn.microsoft.com/en-us/windows/win32/winauto/uiauto-automation-element-propids
The UIA provider should return a variant of VT_Unknown | VT_Array, but 
the client should accept an IUIAutomationElementArray. Clearly in this 
case on Windows 7, the provider is doing the right thing, but the UIA 
client library does not yet know how to handle it.

So, we should also check for win8 (or win10?) and if not return an empty 
list.

> However, the KeyError is due to an incompleteness in comtypes, where it does not support a variant holding a type of VT_Unknown | VT_Array (an array of IUnknowns). 


Can this affect us in other scenarios? If so, and assuming this is possible perhaps it can be considered to add this support as a monkey patch similar to how we worked around different deficiencies in comTypes.

> Clearly in this case on Windows 7, the provider is doing the right thing, but the UIA client library does not yet know how to handle it. So, we should also check for win8 (or win10?) and if not return an empty list.


Would it still be necessary if the bug in comTypes is fixed?
Perhaps in other cases of VT_Unknown | VT_Array fixing this in comtypes 
would be useful. But in this particular case, the IUnknowns we would get 
back would be unusable as they would come straight from the provider, 
and would probably be some kind of IElementProvider object or something, 
which cannot be used on the client side. So in this case, the 
incompleteness of UIA's client library on Win 7, or in other words, the 
too newness of some Win 7 providers, eclipses the problem in comtypes.

Which  build can I download to test this? Does the error actually screw 
anything up if its silenced?
 I have to say, in the 7 machine, I seldom use the start menu search in any 
case.
 Brian

-- 
***@***.***
Sent via blueyonder.(Virgin media)
Please address personal E-mail to:-
***@***.***, putting 'Brian Gaff'
in the display name field.
----- Original Message ----- 
From: "Joseph Lee" ***@***.***>
To: "nvaccess/nvda" ***@***.***>
Cc: "Subscribed" ***@***.***>
Sent: Tuesday, October 18, 2022 7:12 PM
Subject: Re: [nvaccess/nvda] Error sounds when navigating in UIA controls 
under Windows 7 after merge of PR 14222 (Issue #14270)


Hi, I’m quite conflicted about this. On one hand, I think we still need to 
provide an exception to handle things not introduced until Windows 8 and 
later. On the other hand, some folks may ask NV Access to move to Python 
3.10 and later, resulting in end of support for Windows 7. Perhaps a 
compromise, leaning more toward the second option, is to perhaps limit 
generic search suggestions implementation to Windows 8.1 and later, 
preferably Windows 10 and 11 (auto-suggest accessibility was properly 
introduced with Windows 8). Thanks.



-- 
Reply to this email directly or view it on GitHub:
https://github.com/nvaccess/nvda/issues/14270#issuecomment-1282813568
You are receiving this because you are subscribed to this thread.

Message ID: ***@***.***> 



Resolving patch:
diff --git a/source/NVDAObjects/UIA/__init__.py b/source/NVDAObjects/UIA/__init__.py
--- a/source/NVDAObjects/UIA/__init__.py
+++ b/source/NVDAObjects/UIA/__init__.py
@@ -2038,7 +2038,20 @@ def isDescendantOf(self, obj: "NVDAObjects.NVDAObject") -> bool:
 			raise NotImplementedError
 
 	def _get_controllerFor(self):
-		e=self._getUIACacheablePropertyValue(UIAHandler.UIA_ControllerForPropertyId)
+		try:
+			e = self._getUIACacheablePropertyValue(UIAHandler.UIA_ControllerForPropertyId)
+		except KeyError:
+			# #14270: comtypes may raise KeyError as it does not know how to unpack a variant of VT_Unknown | VT_Array.
+			# this may be seen on Windows 7 where
+			# the UIA client library directly returns the provider's VT_Unknown | VT_Array variant,
+			# Which is useless for a client.
+			# On Newer Windows versions, the client library correctly marshals this to
+			# IUIAutomationElementArray per the UI Automation documentation.
+			# UI Automation documentation seems to suggest controllerFor is supported on Windows 7,
+			# So it is unclear as to what versions have this bug.
+			# Best just to catch KeyError.
+			log.debugWarning("Bad controllerFor property", exc_info=True)
+			return []
 		if UIAHandler.handler.clientObject.checkNotSupported(e):
 			return None
 		a=e.QueryInterface(UIAHandler.IUIAutomationElementArray)


Test patch: