Repository: nvaccess/nvda

Issue:
NVDA reading "edit blank" in date/time combo boxes in Outlook Desktop advanced search dialog
### Steps to reproduce:
1. Open Outlook Desktop
2. Enable NVDA
3. Press Ctrl+E to open Search
4. Tab to Advanced Search and press enter
5. Tab 7 times to Start Date edit field
6. Observe the screen reader only reads "edit blank"

### Actual behavior:
NVDA reads "edit blank" when user tabs to the start date and end date controls.
Note: Narrator and JAWS both read this control correctly.

### Expected behavior:
NVDA reads "start date combo edit"

### System configuration
#### NVDA installed/portable/running from source:
Portable

#### NVDA version:
2021.1

#### Windows version:
Windows 11

#### Name and version of other software in use when reproducing the issue:
Outlook desktop, version 2109, 14329.20000

#### Other information about your system:

### Other questions
#### Does the issue still occur after restarting your computer?
Yes

#### Have you tried any other versions of NVDA? If so, please report their behaviors.
N/A

#### If add-ons are disabled, is your problem still occurring?
N/A

#### Does the issue still occur after you run the COM Registration Fixing Tool in NVDA's tools menu?
N/A


Discussion:
Could you please [attach a debug level NVDA log](https://github.com/nvaccess/nvda/wiki/LogFilesAndCrashDumps) for this issue. This will help us to understand the cause, and be better equipped to reproduce the issue.
@feerrenrut log attached, 
DEBUG - NVDAObjects.NVDAObject._get_placeholder (15:37:07.545) - MainThread (30276):
Potential unimplemented child class: <NVDAObjects.Dynamic_IAccessibleRichEdit50WindowNVDAObject object at 0x03FDDE50>
IO - speech.speech.speak (15:37:07.561) - MainThread (30276):
Speaking [LangChangeCommand ('en_US'), 'edit', CancellableSpeech (still valid), 'blank']
IO - inputCore.InputManager.executeGesture (15:37:08.948) - winInputHook (36980):
Input: kb(laptop):tab
[nvda.log](https://github.com/nvaccess/nvda/files/7003385/nvda.log)

Technical:
It seems we use MSAA for these particular fields:
```
Developer info for navigator object:
name: ''
role: Role.EDITABLETEXT
roleText: None
states: State.FOCUSABLE, State.FOCUSED
isFocusable: True
hasFocus: True
Python object: <NVDAObjects.Dynamic_IAccessibleRichEdit50WindowNVDAObject object at 0x0772A2D0>
Python class mro: (<class 'NVDAObjects.Dynamic_IAccessibleRichEdit50WindowNVDAObject'>, <class 'NVDAObjects.IAccessible.IAccessible'>, <class 'NVDAObjects.window.edit.RichEdit50'>, <class 'NVDAObjects.window.edit.RichEdit'>, <class 'NVDAObjects.window.edit.Edit'>, <class 'NVDAObjects.behaviors.EditableTextWithAutoSelectDetection'>, <class 'NVDAObjects.behaviors.EditableText'>, <class 'editableText.EditableText'>, <class 'NVDAObjects.window.Window'>, <class 'NVDAObjects.NVDAObject'>, <class 'documentBase.TextContainerObject'>, <class 'baseObject.ScriptableObject'>, <class 'baseObject.AutoPropertyObject'>, <class 'garbageHandler.TrackedObject'>, <class 'object'>)
description: None
location: RectLTWH(left=456, top=291, width=178, height=23)
value: ''
appModule: <'outlook' (appName 'outlook', process ID 13180) at address 707a3d0>
appModule.productName: 'Microsoft Outlook'
appModule.productVersion: '16.0.14405.20002'
TextInfo: <class 'NVDAObjects.window.edit.ITextDocumentTextInfo'>
windowHandle: 396558
windowClassName: 'RICHEDIT60W'
windowControlID: 1
windowStyle: 1342177416
extendedWindowStyle: 0
windowThreadID: 21056
windowText: ''
displayText: ''
IAccessibleObject: <POINTER(IAccessible) ptr=0x5d30380 at 771ebc0>
IAccessibleChildID: 0
IAccessible event parameters: windowHandle=396558, objectID=-4, childID=0
IAccessible accName: ''
IAccessible accRole: ROLE_SYSTEM_TEXT
IAccessible accState: STATE_SYSTEM_FOCUSED, STATE_SYSTEM_FOCUSABLE, STATE_SYSTEM_VALID (1048580)
IAccessible accDescription: None
IAccessible accValue: ''
```
However, if I force NVDA to use UI Automation from the NVDA Python console:
```
import UIAHandler
UIAHandler.handler.isUIAWindow=lambda w: True
```
Then we get much better results, similar to Narrator.
When using UI Automation the edit field now has a parent which is the date picker combo box, and it is correctly labeled etc.
This requires further investigation from us to work out why when accessing that edit field via MSAA, that its parent is not the date picker combo box.

Resolving patch:
diff --git a/source/appModules/outlook.py b/source/appModules/outlook.py
--- a/source/appModules/outlook.py
+++ b/source/appModules/outlook.py
@@ -9,6 +9,7 @@
 import comtypes.client
 import comtypes.automation
 import ctypes
+import winVersion
 from hwPortUtils import SYSTEMTIME
 import scriptHandler
 from scriptHandler import script
@@ -99,6 +100,21 @@ def getSentMessageString(obj):
 
 class AppModule(appModuleHandler.AppModule):
 
+	def isGoodUIAWindow(self, hwnd: int) -> bool:
+		windowClass = winUser.getClassName(hwnd)
+		versionMajor = int(self.productVersion.split('.')[0])
+		if (
+			versionMajor >= 16
+			and windowClass == "RICHEDIT60W"
+			and winVersion.getWinVer() >= winVersion.WIN10
+		):
+			# #12726: RICHEDIT60W In Outlook 2016+ on Windows 10+
+			# has a very good UI Automation implementation,
+			# Though oddly IsServerSideProvider returns false for these windows.
+			# Examples: date picker in the Outlook Advanced search dialog
+			return True
+		return False
+
 	def __init__(self,*args,**kwargs):
 		super(AppModule,self).__init__(*args,**kwargs)
 		# Explicitly allow gainFocus events for the window class that hosts the active Outlook DatePicker cell


Test patch: