From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/uiautomationcore/uia_client.c | 4 +++ dlls/uiautomationcore/uia_private.h | 3 +++ dlls/uiautomationcore/uia_provider.c | 40 +++++++++++++++++++++++++--- 3 files changed, 44 insertions(+), 3 deletions(-)
diff --git a/dlls/uiautomationcore/uia_client.c b/dlls/uiautomationcore/uia_client.c index c2946b03500..c0fa414accc 100644 --- a/dlls/uiautomationcore/uia_client.c +++ b/dlls/uiautomationcore/uia_client.c @@ -313,6 +313,8 @@ static ULONG WINAPI uia_node_Release(IWineUiaNode *iface) }
IWineUiaProvider_Release(node->prov); + if (!list_empty(&node->prov_thread_list_entry)) + uia_provider_thread_remove_node((HUIANODE)iface); if (node->nested_node) uia_stop_provider_thread();
@@ -769,6 +771,7 @@ HRESULT WINAPI UiaNodeFromProvider(IRawElementProviderSimple *elprov, HUIANODE * }
node->IWineUiaNode_iface.lpVtbl = &uia_node_vtbl; + list_init(&node->prov_thread_list_entry); node->ref = 1;
*huianode = (void *)&node->IWineUiaNode_iface; @@ -1063,6 +1066,7 @@ HRESULT WINAPI UiaNodeFromHandle(HWND hwnd, HUIANODE *huianode)
node->hwnd = hwnd; node->IWineUiaNode_iface.lpVtbl = &uia_node_vtbl; + list_init(&node->prov_thread_list_entry); node->ref = 1;
hr = uia_get_provider_from_hwnd(node); diff --git a/dlls/uiautomationcore/uia_private.h b/dlls/uiautomationcore/uia_private.h index 1efc8fbd1e4..da7f54c8ce3 100644 --- a/dlls/uiautomationcore/uia_private.h +++ b/dlls/uiautomationcore/uia_private.h @@ -20,6 +20,7 @@
#include "uiautomation.h" #include "uia_classes.h" +#include "wine/list.h"
extern HMODULE huia_module DECLSPEC_HIDDEN;
@@ -38,6 +39,7 @@ struct uia_node {
HWND hwnd; BOOL nested_node; + struct list prov_thread_list_entry; };
static inline struct uia_node *impl_from_IWineUiaNode(IWineUiaNode *iface) @@ -50,3 +52,4 @@ const struct uia_prop_info *uia_prop_info_from_id(PROPERTYID prop_id) DECLSPEC_H
/* uia_provider.c */ void uia_stop_provider_thread(void) DECLSPEC_HIDDEN; +void uia_provider_thread_remove_node(HUIANODE node) DECLSPEC_HIDDEN; diff --git a/dlls/uiautomationcore/uia_provider.c b/dlls/uiautomationcore/uia_provider.c index 7b4a6be4042..fe7dff9112e 100644 --- a/dlls/uiautomationcore/uia_provider.c +++ b/dlls/uiautomationcore/uia_provider.c @@ -1130,6 +1130,7 @@ HRESULT WINAPI UiaProviderFromIAccessible(IAccessible *acc, long child_id, DWORD */ struct uia_provider_thread { + struct list nodes_list; HANDLE hthread; HWND hwnd; LONG ref; @@ -1145,6 +1146,33 @@ static CRITICAL_SECTION_DEBUG provider_thread_cs_debug = }; static CRITICAL_SECTION provider_thread_cs = { &provider_thread_cs_debug, -1, 0, 0, 0, 0 };
+void uia_provider_thread_remove_node(HUIANODE node) +{ + struct uia_node *node_data = impl_from_IWineUiaNode((IWineUiaNode *)node); + + TRACE("Removing node %p\n", node); + + EnterCriticalSection(&provider_thread_cs); + list_remove(&node_data->prov_thread_list_entry); + list_init(&node_data->prov_thread_list_entry); + LeaveCriticalSection(&provider_thread_cs); +} + +static HRESULT uia_provider_thread_add_node(HUIANODE node) +{ + struct uia_node *node_data = impl_from_IWineUiaNode((IWineUiaNode *)node); + + TRACE("Adding node %p\n", node); + + node_data->nested_node = TRUE; + + EnterCriticalSection(&provider_thread_cs); + list_add_tail(&provider_thread.nodes_list, &node_data->prov_thread_list_entry); + LeaveCriticalSection(&provider_thread_cs); + + return S_OK; +} + #define WM_GET_OBJECT_UIA_NODE (WM_USER + 1) #define WM_UIA_PROVIDER_THREAD_STOP (WM_USER + 2) static LRESULT CALLBACK uia_provider_thread_msg_proc(HWND hwnd, UINT msg, WPARAM wparam, @@ -1155,11 +1183,14 @@ static LRESULT CALLBACK uia_provider_thread_msg_proc(HWND hwnd, UINT msg, WPARAM case WM_GET_OBJECT_UIA_NODE: { HUIANODE node = (HUIANODE)lparam; - struct uia_node *node_data; LRESULT lr;
- node_data = impl_from_IWineUiaNode((IWineUiaNode *)node); - node_data->nested_node = TRUE; + if (FAILED(uia_provider_thread_add_node(node))) + { + WARN("Failed to add node %p to provider thread list.\n", node); + UiaNodeRelease(node); + return 0; + }
/* * LresultFromObject returns an index into the global atom string table, @@ -1239,6 +1270,7 @@ static BOOL uia_start_provider_thread(void) GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (const WCHAR *)uia_start_provider_thread, &hmodule);
+ list_init(&provider_thread.nodes_list); events[0] = ready_event = CreateEventW(NULL, FALSE, FALSE, NULL); if (!(provider_thread.hthread = CreateThread(NULL, 0, uia_provider_thread_proc, ready_event, 0, NULL))) @@ -1276,6 +1308,8 @@ void uia_stop_provider_thread(void) { PostMessageW(provider_thread.hwnd, WM_UIA_PROVIDER_THREAD_STOP, 0, 0); CloseHandle(provider_thread.hthread); + if (!list_empty(&provider_thread.nodes_list)) + ERR("Provider thread shutdown with nodes still in the list\n"); memset(&provider_thread, 0, sizeof(provider_thread)); } LeaveCriticalSection(&provider_thread_cs);