@@ -26,7 +26,6 @@ This license can be found at:
2626#include " dllmain.h"
2727#include " inProcess.h"
2828#include < remote/nvdaInProcUtils.h>
29- #include " COMProxyRegistration.h"
3029#include " IA2Support.h"
3130#include < atlcomcli.h>
3231#include " textFromIAccessible.h"
@@ -38,71 +37,77 @@ using namespace std;
3837// Used in isSuspendableProcess.
3938LONG WINAPI GetCurrentApplicationUserModelId (UINT32 * pBufSize,PWSTR buf);
4039
41- bool isIA2Installed=FALSE ;
42- COMProxyRegistration_t* IA2ProxyRegistration;
43- COMProxyRegistration_t* ISimpleDOMProxyRegistration;
44- HANDLE IA2UIThreadHandle=NULL ;
45- DWORD IA2UIThreadID=0 ;
46- HANDLE IA2UIThreadUninstalledEvent=NULL ;
47- UINT wm_uninstallIA2Support=0 ;
48- bool isIA2Initialized=FALSE ;
40+
41+ UINT wm_uninstallIA2Support = RegisterWindowMessage(L" wm_uninstallIA2Support" );
4942bool isIA2SupportDisabled=false ;
5043
51- bool installIA2Support () {
52- if (isIA2Installed) return FALSE ;
44+ map<DWORD , IA2InstallData> IA2InstallMap;
45+
46+ pair<map<DWORD , IA2InstallData>::iterator, bool > installIA2Support (DWORD threadID) {
47+ if (IA2InstallMap.find (threadID) != IA2InstallMap.end ()) {
48+ return {IA2InstallMap.end (), false };
49+ }
5350 APTTYPE appType;
5451 APTTYPEQUALIFIER aptQualifier;
5552 HRESULT res;
5653 if ((res=CoGetApartmentType (&appType,&aptQualifier))!=S_OK ) {
5754 if (res!=CO_E_NOTINITIALIZED ) {
5855 LOG_ERROR (L" Error getting apartment type, code " <<res);
5956 }
60- return false ;
57+ return {IA2InstallMap. end (), false } ;
6158 }
62- IA2ProxyRegistration=registerCOMProxy (L" IAccessible2Proxy.dll" );
63- if (!IA2ProxyRegistration) {
64- LOG_ERROR (L" Error registering IAccessible2 proxy" );
59+ IA2InstallData data{};
60+ data.IA2ProxyRegistration = registerCOMProxy (L" IAccessible2Proxy.dll" );
61+ if (!data.IA2ProxyRegistration ) {
62+ LOG_ERROR (L" Error registering IAccessible2 proxy for thread " << threadID);
6563 }
66- ISimpleDOMProxyRegistration= registerCOMProxy (L" ISimpleDOM.dll" );
67- if (! ISimpleDOMProxyRegistration) {
68- LOG_ERROR (L" Error registering ISimpleDOM proxy" );
64+ data. ISimpleDOMProxyRegistration = registerCOMProxy (L" ISimpleDOM.dll" );
65+ if (!data. ISimpleDOMProxyRegistration ) {
66+ LOG_ERROR (L" Error registering ISimpleDOM proxy for thread " << threadID );
6967 }
70- isIA2Installed=TRUE ;
71- return isIA2Installed;
68+ return IA2InstallMap.insert (make_pair (threadID, data));
7269}
7370
74- bool uninstallIA2Support () {
75- if (!isIA2Installed) return false ;
76- if (ISimpleDOMProxyRegistration&&!unregisterCOMProxy (ISimpleDOMProxyRegistration)) {
77- LOG_ERROR (L" Error unregistering ISimpleDOM proxy" );
71+ bool uninstallIA2Support (DWORD threadID) {
72+ auto it = IA2InstallMap.find (threadID);
73+ if (it == IA2InstallMap.end ()) {
74+ return false ;
75+ }
76+ auto & data = it->second ;
77+ if (data.ISimpleDOMProxyRegistration && !unregisterCOMProxy (data.ISimpleDOMProxyRegistration )) {
78+ LOG_ERROR (L" Error unregistering ISimpleDOM proxy for thread " << threadID);
7879 } else {
79- ISimpleDOMProxyRegistration= nullptr ;
80+ data. ISimpleDOMProxyRegistration = nullptr ;
8081 }
81- if ( IA2ProxyRegistration&& !unregisterCOMProxy (IA2ProxyRegistration)) {
82- LOG_ERROR (L" Error unregistering IAccessible2 proxy" );
82+ if (data. IA2ProxyRegistration && !unregisterCOMProxy (data. IA2ProxyRegistration )) {
83+ LOG_ERROR (L" Error unregistering IAccessible2 proxy for thread " << threadID );
8384 } else {
84- IA2ProxyRegistration= nullptr ;
85+ data. IA2ProxyRegistration = nullptr ;
8586 }
86- isIA2Installed=FALSE ;
87- return TRUE ;
87+ return true ;
8888}
8989
9090void CALLBACK IA2Support_winEventProcHook (HWINEVENTHOOK hookID, DWORD eventID, HWND hwnd, long objectID, long childID, DWORD threadID, DWORD time) {
91- if (eventID != EVENT_SYSTEM_FOREGROUND && eventID != EVENT_OBJECT_FOCUS )
91+ if (eventID != EVENT_SYSTEM_FOREGROUND && eventID != EVENT_OBJECT_FOCUS ) {
9292 return ;
93- if ( installIA2Support ()) {
94- IA2UIThreadHandle= OpenThread ( SYNCHRONIZE , false , threadID);
95- IA2UIThreadID=threadID;
96- // IA2 support successfully installed, so this hook isn't needed anymore.
97- unregisterWinEventHook (IA2Support_winEventProcHook );
93+ }
94+ auto installRes = installIA2Support ( threadID);
95+ if (installRes. second ) {
96+ auto & data = installRes. first -> second ;
97+ data. uiThreadHandle = OpenThread ( SYNCHRONIZE , false , threadID );
9898 }
9999}
100100
101101LRESULT CALLBACK IA2Support_uninstallerHook (int code, WPARAM wParam, LPARAM lParam) {
102102 MSG * pmsg=(MSG *)lParam;
103103 if (pmsg->message ==wm_uninstallIA2Support) {
104- uninstallIA2Support ();
105- SetEvent (IA2UIThreadUninstalledEvent);
104+ auto threadId = GetCurrentThreadId ();
105+ uninstallIA2Support (threadId);
106+ auto it = IA2InstallMap.find (threadId);
107+ if (it != IA2InstallMap.end ()) {
108+ auto & data = it->second ;
109+ SetEvent (data.uiThreadUninstalledEvent );
110+ }
106111 }
107112 return 0 ;
108113}
@@ -146,8 +151,9 @@ bool isAppContainerProcess() {
146151}
147152
148153void IA2Support_inProcess_initialize () {
149- if (isIA2Installed|| isIA2SupportDisabled)
154+ if (IA2InstallMap. size () > 0 || isIA2SupportDisabled) {
150155 return ;
156+ }
151157 // #5417: disable IAccessible2 support for suspendable processes to work around a deadlock in NVDAHelperRemote (specifically seen in Win10 searchUI)
152158 isIA2SupportDisabled = isSuspendableProcess ();
153159 if (isIA2SupportDisabled) {
@@ -162,37 +168,37 @@ void IA2Support_inProcess_initialize() {
162168 return ;
163169 }
164170 // Try to install IA2 support on focus/foreground changes.
165- // This hook will be unregistered by the callback once IA2 support is successfully installed.
166171 registerWinEventHook (IA2Support_winEventProcHook);
167172}
168173
169174void IA2Support_inProcess_terminate () {
170175 // This will do nothing if the hook isn't registered.
171176 unregisterWinEventHook (IA2Support_winEventProcHook);
172- if (!isIA2Installed||!IA2UIThreadHandle) {
173- return ;
174- }
175- // Check if the UI thread is still alive, if not there's nothing for us to do
176- if (WaitForSingleObject (IA2UIThreadHandle,0 )==0 ) {
177- return ;
178- }
179- // Instruct the UI thread to uninstall IA2
180- IA2UIThreadUninstalledEvent = CreateEvent (NULL , true , false , NULL );
181- if (IA2UIThreadUninstalledEvent == 0 ){
182- // unable to create the event, can't continue
177+ if (IA2InstallMap.size () == 0 ) {
183178 return ;
184179 }
185- registerWindowsHook (WH_GETMESSAGE ,IA2Support_uninstallerHook);
186- wm_uninstallIA2Support=RegisterWindowMessage (L" wm_uninstallIA2Support" );
187- PostThreadMessage (IA2UIThreadID,wm_uninstallIA2Support,0 ,0 );
188- HANDLE waitHandles[2 ]={IA2UIThreadUninstalledEvent,IA2UIThreadHandle};
189- int res=WaitForMultipleObjects (2 ,waitHandles,false ,10000 );
190- if (res!=WAIT_OBJECT_0 &&res!=WAIT_OBJECT_0 +1 ) {
191- LOG_DEBUGWARNING (L" WaitForMultipleObjects returned " <<res);
180+ registerWindowsHook (WH_GETMESSAGE , IA2Support_uninstallerHook);
181+ for (auto & [threadId, data] : IA2InstallMap) {
182+ // Check if the UI thread is still alive, if not there's nothing for us to do
183+ if (WaitForSingleObject (data.uiThreadHandle , 0 ) == 0 ) {
184+ continue ;
185+ }
186+ // Instruct the UI thread to uninstall IA2
187+ data.uiThreadUninstalledEvent = CreateEvent (NULL , true , false , NULL );
188+ if (data.uiThreadUninstalledEvent == 0 ) {
189+ // unable to create the event, can't continue
190+ continue ;
191+ }
192+ PostThreadMessage (threadId, wm_uninstallIA2Support, 0 , 0 );
193+ HANDLE waitHandles[2 ] = {data.uiThreadUninstalledEvent , data.uiThreadHandle };
194+ int res = WaitForMultipleObjects (2 , waitHandles, false , 10000 );
195+ if (res != WAIT_OBJECT_0 && res != WAIT_OBJECT_0 + 1 ) {
196+ LOG_DEBUGWARNING (L" WaitForMultipleObjects returned " <<res);
197+ }
198+ CloseHandle (data.uiThreadUninstalledEvent );
199+ CloseHandle (data.uiThreadHandle );
192200 }
193201 unregisterWindowsHook (WH_GETMESSAGE ,IA2Support_uninstallerHook);
194- CloseHandle (IA2UIThreadUninstalledEvent);
195- CloseHandle (IA2UIThreadHandle);
196202}
197203
198204const long FINDCONTENTDESCENDANT_FIRST =0 ;
0 commit comments