.NET version
.NET 10.0.11 (System.Windows.Forms.dll from Microsoft.WindowsDesktop.App\10.0.11), Windows 11 Pro 26100 (build lab 26100.1.amd64fre.ge_release), UIAutomationCore.dll 7.2.26100.9278.
Did it work in .NET Framework?
Not tested. .NET Framework TextBox does not implement the UIA text provider in-process, so the code path does not exist there.
Did it work in any of the earlier releases of .NET Core or .NET 5+?
Not tested. The relevant code (AccessibleObject implementing IRawElementProviderFragment with FragmentRoot => null) is present on release/10.0; I have not bisected older releases.
Issue description
With the JAWS screen reader running and its Mouse Echo feature on, the first time the mouse pointer passes over a WinForms TextBox the whole application stops responding for 15–30 seconds. It happens once per process. Turning Mouse Echo off removes it. A Win32 application with a plain EDIT control does not reproduce.
A full process dump taken during the freeze (analyzed with cdb and public Microsoft symbols) shows the chain:
- JAWS calls
TextPattern.RangeFromPoint on the text box under the pointer. It is a cross-process COM call into the application, dispatched on the UI thread via combase!ThreadWndProc.
UIAutomationCore!RemotePatternStub::Text_RangeFromPoint → ScreenPointToProviderPointHelper → UiaUtils::TryGetCoordinateConverterForVisualRelativeRoot queries the element for IRawElementProviderFragment (succeeds) and calls get_FragmentRoot (returns S_OK).
- WinForms hands back
S_OK with a null IRawElementProviderFragmentRoot*. AccessibleObject.FragmentRoot defaults to null, TextBoxBase.TextBoxBaseAccessibleObject does not override it, and IRawElementProviderFragment.Interface.get_FragmentRoot does *pRetVal = ComHelpers.TryGetComPointer<IRawElementProviderFragmentRoot>(FragmentRoot); return HRESULT.S_OK; (AccessibleObject.cs, release/10.0).
- UIAutomationCore dereferences the null root:
mov rax,[rcx] with rcx = 0, EXCEPTION_ACCESS_VIOLATION at UIAutomationCore+0x1e9bb7.
- COM's server-side stub filter (
combase!ServerExceptionFilter) swallows the exception and calls SilentlyReportExceptions → RtlReportException → ntdll!WerpWaitForCrashReporting. The UI thread blocks there until Windows Error Reporting has written a minidump of the process. That wait is the visible freeze. COM reports only the first stub exception per process, hence once per launch.
UIAutomationCore should not dereference the null (separately reported to Windows), but the UIA contract for IRawElementProviderFragment::get_FragmentRoot is that a fragment returns its root, and WinForms exposes the fragment interface on every AccessibleObject while returning nothing from it.
Resolved UI-thread stack (newest first, abridged):
ntdll!NtWaitForMultipleObjects
ntdll!WerpWaitForCrashReporting
ntdll!RtlReportException
combase!SilentlyReportExceptions
combase!ServerExceptionFilter
combase!AppInvokeExceptionFilterWithMethodAddress
ntdll!KiUserExceptionDispatch
UIAutomationCore!UiaUtils::TryGetCoordinateConverterForVisualRelativeRoot+0x73 <- AV, rcx = 0
UIAutomationCore!`anonymous namespace'::ScreenPointToProviderPointHelper+0x7e
UIAutomationCore!RemotePatternStub::Text_RangeFromPoint+0xca
UIAutomationCore!InvokePatternMethodOnCorrectContext_Callback+0x26f
OneCoreCommonProxyStub!IServiceProvider_RemoteQueryService_Thunk+0x2f
rpcrt4!Ndr64StubWorker+0x862
combase!CStdStubBuffer_Invoke+0x7d
combase!ReentrantSTAInvokeInApartment+0x194
combase!ThreadDispatch+0x3ef
combase!ThreadWndProc+0x177
user32!DispatchMessageWorker+0x1dd
System.Windows.Forms.Application.LightThreadContext.FPushMessageLoop+0x160
System.Windows.Forms.Application.Run+0x6c
Disassembly at the fault, showing the successful get_FragmentRoot followed by the unchecked dereference:
call UIAutomationCore!wil::try_com_query<IRawElementProviderFragment,IRawElementProviderSimple*&>
mov rcx,qword ptr [rbp-28h]
test rcx,rcx
je +0xd4
and qword ptr [rbp+38h],rdi ; out param = null
lea rdx,[rbp+38h]
call UIAutomationCore!ProviderCallouts::get_FragmentRoot
mov rcx,qword ptr [rbp+18h]
test eax,eax
jns +0x6a ; S_OK
and qword ptr [rbp+28h],0
mov rcx,qword ptr [rbp+38h] ; rcx = 0
mov rax,qword ptr [rcx] ; <- access violation
Windows Event Log, Application: Application Error 1000 / Windows Error Reporting 1001, faulting module UIAutomationCore.DLL 7.2.26100.9278, exception code 0xc0000005, fault offset 0x1e9bb7, recorded for every launch that was touched by the mouse under JAWS.
Managed heap at the time of the dump contained System.Windows.Forms.TextBox+TextBoxAccessibleObject (×2) and System.Windows.Forms.TextBoxBase+TextBoxBaseUiaTextProvider (×2), matching the two text boxes on the form.
Steps to reproduce
- Windows 11, JAWS 2026 (tested with
jhook.dll 27.5.20) running, Mouse Echo enabled (Settings Center → Mouse Echo).
- Create a WinForms app targeting
net10.0-windows with a form containing one TextBox { Multiline = true, Dock = DockStyle.Fill } (a second control such as a ListBox is optional; a ListBox plus TextBox form reproduced identically).
- Run it and move the mouse pointer across the text box once.
- The window stops responding for 15–30 seconds, then recovers. Event Viewer → Application shows an Application Error 1000 for the app with faulting module
UIAutomationCore.DLL, exception 0xc0000005, offset 0x1e9bb7. Subsequent mouse passes do not freeze (COM reports only the first exception per process), but a new process freezes again.
Expected: a UIA client calling TextPattern.RangeFromPoint on a WinForms text box gets a range or an error HRESULT; the application never blocks on WER.
The same call should be reachable without a screen reader by any UIA client invoking IUIAutomationTextPattern::RangeFromPoint against the text box's element; I have only verified it via JAWS.
A dump of the freeze from a data-free test application can be provided on request.
.NET version
.NET 10.0.11 (
System.Windows.Forms.dllfromMicrosoft.WindowsDesktop.App\10.0.11), Windows 11 Pro 26100 (build lab 26100.1.amd64fre.ge_release),UIAutomationCore.dll7.2.26100.9278.Did it work in .NET Framework?
Not tested. .NET Framework
TextBoxdoes not implement the UIA text provider in-process, so the code path does not exist there.Did it work in any of the earlier releases of .NET Core or .NET 5+?
Not tested. The relevant code (
AccessibleObjectimplementingIRawElementProviderFragmentwithFragmentRoot => null) is present onrelease/10.0; I have not bisected older releases.Issue description
With the JAWS screen reader running and its Mouse Echo feature on, the first time the mouse pointer passes over a WinForms
TextBoxthe whole application stops responding for 15–30 seconds. It happens once per process. Turning Mouse Echo off removes it. A Win32 application with a plainEDITcontrol does not reproduce.A full process dump taken during the freeze (analyzed with
cdband public Microsoft symbols) shows the chain:TextPattern.RangeFromPointon the text box under the pointer. It is a cross-process COM call into the application, dispatched on the UI thread viacombase!ThreadWndProc.UIAutomationCore!RemotePatternStub::Text_RangeFromPoint→ScreenPointToProviderPointHelper→UiaUtils::TryGetCoordinateConverterForVisualRelativeRootqueries the element forIRawElementProviderFragment(succeeds) and callsget_FragmentRoot(returnsS_OK).S_OKwith a nullIRawElementProviderFragmentRoot*.AccessibleObject.FragmentRootdefaults tonull,TextBoxBase.TextBoxBaseAccessibleObjectdoes not override it, andIRawElementProviderFragment.Interface.get_FragmentRootdoes*pRetVal = ComHelpers.TryGetComPointer<IRawElementProviderFragmentRoot>(FragmentRoot); return HRESULT.S_OK;(AccessibleObject.cs, release/10.0).mov rax,[rcx]withrcx = 0,EXCEPTION_ACCESS_VIOLATIONatUIAutomationCore+0x1e9bb7.combase!ServerExceptionFilter) swallows the exception and callsSilentlyReportExceptions→RtlReportException→ntdll!WerpWaitForCrashReporting. The UI thread blocks there until Windows Error Reporting has written a minidump of the process. That wait is the visible freeze. COM reports only the first stub exception per process, hence once per launch.UIAutomationCore should not dereference the null (separately reported to Windows), but the UIA contract for
IRawElementProviderFragment::get_FragmentRootis that a fragment returns its root, and WinForms exposes the fragment interface on everyAccessibleObjectwhile returning nothing from it.Resolved UI-thread stack (newest first, abridged):
Disassembly at the fault, showing the successful
get_FragmentRootfollowed by the unchecked dereference:Windows Event Log, Application: Application Error 1000 / Windows Error Reporting 1001, faulting module
UIAutomationCore.DLL 7.2.26100.9278, exception code0xc0000005, fault offset0x1e9bb7, recorded for every launch that was touched by the mouse under JAWS.Managed heap at the time of the dump contained
System.Windows.Forms.TextBox+TextBoxAccessibleObject(×2) andSystem.Windows.Forms.TextBoxBase+TextBoxBaseUiaTextProvider(×2), matching the two text boxes on the form.Steps to reproduce
jhook.dll27.5.20) running, Mouse Echo enabled (Settings Center → Mouse Echo).net10.0-windowswith a form containing oneTextBox { Multiline = true, Dock = DockStyle.Fill }(a second control such as aListBoxis optional; aListBoxplusTextBoxform reproduced identically).UIAutomationCore.DLL, exception0xc0000005, offset0x1e9bb7. Subsequent mouse passes do not freeze (COM reports only the first exception per process), but a new process freezes again.Expected: a UIA client calling
TextPattern.RangeFromPointon a WinForms text box gets a range or an errorHRESULT; the application never blocks on WER.The same call should be reachable without a screen reader by any UIA client invoking
IUIAutomationTextPattern::RangeFromPointagainst the text box's element; I have only verified it via JAWS.A dump of the freeze from a data-free test application can be provided on request.