Commit 858596bb authored by Connor McAdams's avatar Connor McAdams Committed by Alexandre Julliard

uiautomationcore: Shutdown provider thread when all returned nodes are released.

parent d7c95765
...@@ -269,21 +269,6 @@ static IRawElementProviderSimple *get_provider_hwnd_fragment_root(IRawElementPro ...@@ -269,21 +269,6 @@ static IRawElementProviderSimple *get_provider_hwnd_fragment_root(IRawElementPro
/* /*
* IWineUiaNode interface. * IWineUiaNode interface.
*/ */
struct uia_node {
IWineUiaNode IWineUiaNode_iface;
LONG ref;
IWineUiaProvider *prov;
DWORD git_cookie;
HWND hwnd;
};
static inline struct uia_node *impl_from_IWineUiaNode(IWineUiaNode *iface)
{
return CONTAINING_RECORD(iface, struct uia_node, IWineUiaNode_iface);
}
static HRESULT WINAPI uia_node_QueryInterface(IWineUiaNode *iface, REFIID riid, void **ppv) static HRESULT WINAPI uia_node_QueryInterface(IWineUiaNode *iface, REFIID riid, void **ppv)
{ {
*ppv = NULL; *ppv = NULL;
...@@ -328,6 +313,9 @@ static ULONG WINAPI uia_node_Release(IWineUiaNode *iface) ...@@ -328,6 +313,9 @@ static ULONG WINAPI uia_node_Release(IWineUiaNode *iface)
} }
IWineUiaProvider_Release(node->prov); IWineUiaProvider_Release(node->prov);
if (node->nested_node)
uia_stop_provider_thread();
heap_free(node); heap_free(node);
} }
......
...@@ -29,4 +29,24 @@ enum uia_prop_type { ...@@ -29,4 +29,24 @@ enum uia_prop_type {
PROP_TYPE_SPECIAL, PROP_TYPE_SPECIAL,
}; };
struct uia_node {
IWineUiaNode IWineUiaNode_iface;
LONG ref;
IWineUiaProvider *prov;
DWORD git_cookie;
HWND hwnd;
BOOL nested_node;
};
static inline struct uia_node *impl_from_IWineUiaNode(IWineUiaNode *iface)
{
return CONTAINING_RECORD(iface, struct uia_node, IWineUiaNode_iface);
}
/* uia_ids.c */
const struct uia_prop_info *uia_prop_info_from_id(PROPERTYID prop_id) DECLSPEC_HIDDEN; const struct uia_prop_info *uia_prop_info_from_id(PROPERTYID prop_id) DECLSPEC_HIDDEN;
/* uia_provider.c */
void uia_stop_provider_thread(void) DECLSPEC_HIDDEN;
...@@ -1132,6 +1132,7 @@ struct uia_provider_thread ...@@ -1132,6 +1132,7 @@ struct uia_provider_thread
{ {
HANDLE hthread; HANDLE hthread;
HWND hwnd; HWND hwnd;
LONG ref;
}; };
static struct uia_provider_thread provider_thread; static struct uia_provider_thread provider_thread;
...@@ -1145,6 +1146,7 @@ static CRITICAL_SECTION_DEBUG provider_thread_cs_debug = ...@@ -1145,6 +1146,7 @@ static CRITICAL_SECTION_DEBUG provider_thread_cs_debug =
static CRITICAL_SECTION provider_thread_cs = { &provider_thread_cs_debug, -1, 0, 0, 0, 0 }; static CRITICAL_SECTION provider_thread_cs = { &provider_thread_cs_debug, -1, 0, 0, 0, 0 };
#define WM_GET_OBJECT_UIA_NODE (WM_USER + 1) #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, static LRESULT CALLBACK uia_provider_thread_msg_proc(HWND hwnd, UINT msg, WPARAM wparam,
LPARAM lparam) LPARAM lparam)
{ {
...@@ -1153,8 +1155,12 @@ static LRESULT CALLBACK uia_provider_thread_msg_proc(HWND hwnd, UINT msg, WPARAM ...@@ -1153,8 +1155,12 @@ static LRESULT CALLBACK uia_provider_thread_msg_proc(HWND hwnd, UINT msg, WPARAM
case WM_GET_OBJECT_UIA_NODE: case WM_GET_OBJECT_UIA_NODE:
{ {
HUIANODE node = (HUIANODE)lparam; HUIANODE node = (HUIANODE)lparam;
struct uia_node *node_data;
LRESULT lr; LRESULT lr;
node_data = impl_from_IWineUiaNode((IWineUiaNode *)node);
node_data->nested_node = TRUE;
/* /*
* LresultFromObject returns an index into the global atom string table, * LresultFromObject returns an index into the global atom string table,
* which has a valid range of 0xc000-0xffff. * which has a valid range of 0xc000-0xffff.
...@@ -1204,6 +1210,8 @@ static DWORD WINAPI uia_provider_thread_proc(void *arg) ...@@ -1204,6 +1210,8 @@ static DWORD WINAPI uia_provider_thread_proc(void *arg)
TRACE("Provider thread started.\n"); TRACE("Provider thread started.\n");
while (GetMessageW(&msg, NULL, 0, 0)) while (GetMessageW(&msg, NULL, 0, 0))
{ {
if (msg.message == WM_UIA_PROVIDER_THREAD_STOP)
break;
TranslateMessage(&msg); TranslateMessage(&msg);
DispatchMessageW(&msg); DispatchMessageW(&msg);
} }
...@@ -1220,7 +1228,7 @@ static BOOL uia_start_provider_thread(void) ...@@ -1220,7 +1228,7 @@ static BOOL uia_start_provider_thread(void)
BOOL started = TRUE; BOOL started = TRUE;
EnterCriticalSection(&provider_thread_cs); EnterCriticalSection(&provider_thread_cs);
if (!provider_thread.hwnd) if (++provider_thread.ref == 1)
{ {
HANDLE ready_event; HANDLE ready_event;
HANDLE events[2]; HANDLE events[2];
...@@ -1261,6 +1269,18 @@ exit: ...@@ -1261,6 +1269,18 @@ exit:
return started; return started;
} }
void uia_stop_provider_thread(void)
{
EnterCriticalSection(&provider_thread_cs);
if (!--provider_thread.ref)
{
PostMessageW(provider_thread.hwnd, WM_UIA_PROVIDER_THREAD_STOP, 0, 0);
CloseHandle(provider_thread.hthread);
memset(&provider_thread, 0, sizeof(provider_thread));
}
LeaveCriticalSection(&provider_thread_cs);
}
/* /*
* Pass our IWineUiaNode interface to the provider thread for marshaling. UI * Pass our IWineUiaNode interface to the provider thread for marshaling. UI
* Automation has to work regardless of whether or not COM is initialized on * Automation has to work regardless of whether or not COM is initialized on
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment