From: Connor McAdams cmcadams@codeweavers.com
When a client requests an HUIANODE for an HWND that belongs to the same thread, use an IRawElementProvider based provider rather than an IWineUiaNode based provider.
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/uiautomationcore/tests/uiautomation.c | 35 ++++++++--------- dlls/uiautomationcore/uia_client.c | 44 ++++++++++++++++++---- 2 files changed, 53 insertions(+), 26 deletions(-)
diff --git a/dlls/uiautomationcore/tests/uiautomation.c b/dlls/uiautomationcore/tests/uiautomation.c index ff711ccb325..aa5a9afab7f 100644 --- a/dlls/uiautomationcore/tests/uiautomation.c +++ b/dlls/uiautomationcore/tests/uiautomation.c @@ -5484,30 +5484,27 @@ static void test_UiaNodeFromHandle(const char *name) Provider_child.prov_opts = ProviderOptions_ServerSideProvider; Provider_child.hwnd = NULL; hr = UiaGetPropertyValue(node, UIA_LabeledByPropertyId, &v); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx\n", hr); + ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
+ hr = UiaHUiaNodeFromVariant(&v, &node2); + ok(hr == S_OK, "Unexpected hr %#lx\n", hr); + hr = UiaGetPropertyValue(node2, UIA_ProviderDescriptionPropertyId, &v); + todo_wine ok(hr == S_OK, "Unexpected hr %#lx\n", hr); if (SUCCEEDED(hr)) { - hr = UiaHUiaNodeFromVariant(&v, &node2); - ok(hr == S_OK, "Unexpected hr %#lx\n", hr); - hr = UiaGetPropertyValue(node2, UIA_ProviderDescriptionPropertyId, &v); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx\n", hr); - if (SUCCEEDED(hr)) - { - check_node_provider_desc_prefix(V_BSTR(&v), GetCurrentProcessId(), NULL); - check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider_child", TRUE); - VariantClear(&v); - } + check_node_provider_desc_prefix(V_BSTR(&v), GetCurrentProcessId(), NULL); + check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider_child", TRUE); + VariantClear(&v); + }
- Provider_child.expected_tid = GetCurrentThreadId(); - hr = UiaGetPropertyValue(node2, UIA_ControlTypePropertyId, &v); - ok(hr == S_OK, "Unexpected hr %#lx\n", hr); - ok(V_VT(&v) == VT_I4, "Unexpected VT %d\n", V_VT(&v)); - ok(V_I4(&v) == uia_i4_prop_val, "Unexpected I4 %#lx\n", V_I4(&v)); - ok_method_sequence(node_from_hwnd4, "node_from_hwnd4"); + Provider_child.expected_tid = GetCurrentThreadId(); + hr = UiaGetPropertyValue(node2, UIA_ControlTypePropertyId, &v); + ok(hr == S_OK, "Unexpected hr %#lx\n", hr); + ok(V_VT(&v) == VT_I4, "Unexpected VT %d\n", V_VT(&v)); + ok(V_I4(&v) == uia_i4_prop_val, "Unexpected I4 %#lx\n", V_I4(&v)); + ok_method_sequence(node_from_hwnd4, "node_from_hwnd4");
- ok(UiaNodeRelease(node2), "UiaNodeRelease returned FALSE\n"); - } + ok(UiaNodeRelease(node2), "UiaNodeRelease returned FALSE\n");
Provider.expected_tid = Provider_child.expected_tid = 0; ok(UiaNodeRelease(node), "UiaNodeRelease returned FALSE\n"); diff --git a/dlls/uiautomationcore/uia_client.c b/dlls/uiautomationcore/uia_client.c index 1d6360682c2..d29071aea23 100644 --- a/dlls/uiautomationcore/uia_client.c +++ b/dlls/uiautomationcore/uia_client.c @@ -787,6 +787,11 @@ struct uia_client_thread LONG ref; };
+struct uia_get_node_prov_args { + LRESULT lr; + BOOL unwrap; +}; + static struct uia_client_thread client_thread; static CRITICAL_SECTION client_thread_cs; static CRITICAL_SECTION_DEBUG client_thread_cs_debug = @@ -799,14 +804,17 @@ static CRITICAL_SECTION client_thread_cs = { &client_thread_cs_debug, -1, 0, 0,
#define WM_UIA_CLIENT_GET_NODE_PROV (WM_USER + 1) #define WM_UIA_CLIENT_THREAD_STOP (WM_USER + 2) -static HRESULT create_wine_uia_nested_node_provider(struct uia_node *node, LRESULT lr); +static HRESULT create_wine_uia_nested_node_provider(struct uia_node *node, LRESULT lr, BOOL unwrap); static LRESULT CALLBACK uia_client_thread_msg_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { switch (msg) { case WM_UIA_CLIENT_GET_NODE_PROV: - return create_wine_uia_nested_node_provider((struct uia_node *)lparam, (LRESULT)wparam); + { + struct uia_get_node_prov_args *args = (struct uia_get_node_prov_args *)wparam; + return create_wine_uia_nested_node_provider((struct uia_node *)lparam, args->lr, args->unwrap); + }
default: break; @@ -924,7 +932,8 @@ static void uia_stop_client_thread(void) LeaveCriticalSection(&client_thread_cs); }
-static HRESULT create_wine_uia_nested_node_provider(struct uia_node *node, LRESULT lr) +static HRESULT create_wine_uia_nested_node_provider(struct uia_node *node, LRESULT lr, + BOOL unwrap) { IGlobalInterfaceTable *git; struct uia_provider *prov; @@ -938,6 +947,26 @@ static HRESULT create_wine_uia_nested_node_provider(struct uia_node *node, LRESU return hr; }
+ /* + * If we're retrieving a node from an HWND that belongs to the same thread + * as the client making the request, return a normal provider instead of a + * nested node provider. + */ + if (unwrap) + { + struct uia_node *node_data = unsafe_impl_from_IWineUiaNode(nested_node); + + node->prov = node_data->prov; + IWineUiaProvider_AddRef(node->prov); + node->git_cookie = node_data->git_cookie; + + node_data->git_cookie = 0; + IWineUiaNode_Release(&node_data->IWineUiaNode_iface); + + uia_stop_client_thread(); + return S_OK; + } + prov = heap_alloc_zero(sizeof(*prov)); if (!prov) return E_OUTOFMEMORY; @@ -971,27 +1000,28 @@ exit: */ static HRESULT uia_get_provider_from_hwnd(struct uia_node *node) { - LRESULT lr; + struct uia_get_node_prov_args args;
if (!uia_start_client_thread()) return E_FAIL;
SetLastError(NOERROR); - lr = SendMessageW(node->hwnd, WM_GETOBJECT, 0, UiaRootObjectId); + args.lr = SendMessageW(node->hwnd, WM_GETOBJECT, 0, UiaRootObjectId); if (GetLastError() == ERROR_INVALID_WINDOW_HANDLE) { uia_stop_client_thread(); return UIA_E_ELEMENTNOTAVAILABLE; }
- if (!lr) + if (!args.lr) { FIXME("No native UIA provider for hwnd %p, MSAA proxy currently unimplemented.\n", node->hwnd); uia_stop_client_thread(); return E_NOTIMPL; }
- return SendMessageW(client_thread.hwnd, WM_UIA_CLIENT_GET_NODE_PROV, (WPARAM)lr, (LPARAM)node); + args.unwrap = GetCurrentThreadId() == GetWindowThreadProcessId(node->hwnd, NULL); + return SendMessageW(client_thread.hwnd, WM_UIA_CLIENT_GET_NODE_PROV, (WPARAM)&args, (LPARAM)node); }
/***********************************************************************