From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/uiautomationcore/tests/uiautomation.c | 34 +++++++++--------- dlls/uiautomationcore/uia_client.c | 42 +++++++++++++++------- dlls/uiautomationcore/uia_private.h | 2 ++ dlls/uiautomationcore/uia_provider.c | 4 +-- 4 files changed, 51 insertions(+), 31 deletions(-)
diff --git a/dlls/uiautomationcore/tests/uiautomation.c b/dlls/uiautomationcore/tests/uiautomation.c index 604e488601f..d8271ea048c 100644 --- a/dlls/uiautomationcore/tests/uiautomation.c +++ b/dlls/uiautomationcore/tests/uiautomation.c @@ -3843,10 +3843,10 @@ static const struct prov_method_sequence node_from_prov5[] = { /* Win10v1507 and below call this. */ { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */ { &Provider, PROV_GET_HOST_RAW_ELEMENT_PROVIDER }, - { &Provider2, PROV_GET_PROVIDER_OPTIONS, METHOD_TODO }, + { &Provider2, PROV_GET_PROVIDER_OPTIONS }, /* Win10v1507 and below call this. */ { &Provider2, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */ - { &Provider2, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_TODO }, + { &Provider2, PROV_GET_HOST_RAW_ELEMENT_PROVIDER }, { &Provider2, FRAG_NAVIGATE, METHOD_TODO }, /* NavigateDirection_Parent */ /* These three are only done on Win10v1507 and below. */ { &Provider2, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, @@ -3868,13 +3868,13 @@ static const struct prov_method_sequence node_from_prov6[] = { /* Win10v1507 and below call this. */ { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */ { &Provider, PROV_GET_HOST_RAW_ELEMENT_PROVIDER }, - { &Provider2, PROV_GET_PROVIDER_OPTIONS, METHOD_TODO }, + { &Provider2, PROV_GET_PROVIDER_OPTIONS }, /* Win10v1507 and below call this. */ { &Provider2, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */ - { &Provider2, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_TODO }, + { &Provider2, PROV_GET_HOST_RAW_ELEMENT_PROVIDER }, { &Provider2, FRAG_NAVIGATE, METHOD_TODO }, /* NavigateDirection_Parent */ - { &Provider2, PROV_GET_PROVIDER_OPTIONS, METHOD_TODO }, - { &Provider2, PROV_GET_PROVIDER_OPTIONS, METHOD_TODO }, + { &Provider2, PROV_GET_PROVIDER_OPTIONS }, + { &Provider2, PROV_GET_PROVIDER_OPTIONS }, /* Only called on Windows versions past Win10v1507. */ { &Provider, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_OPTIONAL }, { &Provider2, FRAG_NAVIGATE, METHOD_OPTIONAL }, /* NavigateDirection_Parent */ @@ -3893,13 +3893,13 @@ static const struct prov_method_sequence node_from_prov7[] = { /* Win10v1507 and below call this. */ { &Provider_child, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */ { &Provider_child, PROV_GET_HOST_RAW_ELEMENT_PROVIDER }, - { &Provider2, PROV_GET_PROVIDER_OPTIONS, METHOD_TODO }, + { &Provider2, PROV_GET_PROVIDER_OPTIONS }, /* Win10v1507 and below call this. */ { &Provider2, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */ - { &Provider2, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_TODO }, + { &Provider2, PROV_GET_HOST_RAW_ELEMENT_PROVIDER }, { &Provider2, FRAG_NAVIGATE, METHOD_TODO }, /* NavigateDirection_Parent */ - { &Provider2, PROV_GET_PROVIDER_OPTIONS, METHOD_TODO }, - { &Provider2, PROV_GET_PROVIDER_OPTIONS, METHOD_TODO }, + { &Provider2, PROV_GET_PROVIDER_OPTIONS }, + { &Provider2, PROV_GET_PROVIDER_OPTIONS }, /* Only called on Windows versions past Win10v1507. */ { &Provider_child, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_OPTIONAL }, { &Provider2, FRAG_NAVIGATE, METHOD_OPTIONAL }, /* NavigateDirection_Parent */ @@ -4136,7 +4136,7 @@ static void test_UiaNodeFromProvider(void) hr = UiaNodeFromProvider(&Provider.IRawElementProviderSimple_iface, &node); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref); - todo_wine CHECK_CALLED(winproc_GETOBJECT_UiaRoot); + CHECK_CALLED(winproc_GETOBJECT_UiaRoot); called_winproc_GETOBJECT_CLIENT = expect_winproc_GETOBJECT_CLIENT = 0;
hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v); @@ -4178,7 +4178,7 @@ static void test_UiaNodeFromProvider(void) SET_EXPECT(winproc_GETOBJECT_CLIENT); hr = UiaNodeFromProvider(&Provider.IRawElementProviderSimple_iface, &node); ok(hr == S_OK, "Unexpected hr %#lx\n", hr); - todo_wine CHECK_CALLED(winproc_GETOBJECT_UiaRoot); + CHECK_CALLED(winproc_GETOBJECT_UiaRoot); called_winproc_GETOBJECT_CLIENT = expect_winproc_GETOBJECT_CLIENT = 0;
/* Win10v1507 and below hold a reference to the root provider for the HWND */ @@ -4227,7 +4227,7 @@ static void test_UiaNodeFromProvider(void) SET_EXPECT(winproc_GETOBJECT_CLIENT); hr = UiaNodeFromProvider(&Provider.IRawElementProviderSimple_iface, &node); ok(hr == S_OK, "Unexpected hr %#lx\n", hr); - todo_wine CHECK_CALLED(winproc_GETOBJECT_UiaRoot); + CHECK_CALLED(winproc_GETOBJECT_UiaRoot); called_winproc_GETOBJECT_CLIENT = expect_winproc_GETOBJECT_CLIENT = 0;
hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v); @@ -4242,7 +4242,7 @@ static void test_UiaNodeFromProvider(void) } ok_method_sequence(node_from_prov6, "node_from_prov6");
- todo_wine ok(Provider2.ref == 2, "Unexpected refcnt %ld\n", Provider2.ref); + ok(Provider2.ref == 2, "Unexpected refcnt %ld\n", Provider2.ref); ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
ok(!!node, "node == NULL\n"); @@ -4261,7 +4261,7 @@ static void test_UiaNodeFromProvider(void) SET_EXPECT(winproc_GETOBJECT_CLIENT); hr = UiaNodeFromProvider(&Provider_child.IRawElementProviderSimple_iface, &node); ok(hr == S_OK, "Unexpected hr %#lx\n", hr); - todo_wine CHECK_CALLED(winproc_GETOBJECT_UiaRoot); + CHECK_CALLED(winproc_GETOBJECT_UiaRoot); called_winproc_GETOBJECT_CLIENT = expect_winproc_GETOBJECT_CLIENT = 0;
hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v); @@ -4276,7 +4276,7 @@ static void test_UiaNodeFromProvider(void) } ok_method_sequence(node_from_prov7, "node_from_prov7");
- todo_wine ok(Provider2.ref == 2, "Unexpected refcnt %ld\n", Provider2.ref); + ok(Provider2.ref == 2, "Unexpected refcnt %ld\n", Provider2.ref); ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
ok(!!node, "node == NULL\n"); @@ -4839,7 +4839,7 @@ static void test_UiaGetRuntimeId(void) SET_EXPECT(winproc_GETOBJECT_CLIENT); hr = UiaNodeFromProvider(&Provider.IRawElementProviderSimple_iface, &node); ok(hr == S_OK, "Unexpected hr %#lx\n", hr); - todo_wine CHECK_CALLED(winproc_GETOBJECT_UiaRoot); + CHECK_CALLED(winproc_GETOBJECT_UiaRoot); called_winproc_GETOBJECT_CLIENT = expect_winproc_GETOBJECT_CLIENT = 0;
VariantInit(&v); diff --git a/dlls/uiautomationcore/uia_client.c b/dlls/uiautomationcore/uia_client.c index 1dc509a7227..40688dc344d 100644 --- a/dlls/uiautomationcore/uia_client.c +++ b/dlls/uiautomationcore/uia_client.c @@ -718,7 +718,7 @@ static HRESULT uia_provider_get_elem_prop_val(struct uia_provider *prov, if (FAILED(hr)) goto exit;
- hr = UiaNodeFromProvider(elprov, &node); + hr = create_uia_node_from_elprov(elprov, &node, !prov->return_nested_node); IRawElementProviderSimple_Release(elprov); if (SUCCEEDED(hr)) { @@ -897,10 +897,9 @@ static HRESULT create_wine_uia_provider(struct uia_node *node, IRawElementProvid return S_OK; }
-/*********************************************************************** - * UiaNodeFromProvider (uiautomationcore.@) - */ -HRESULT WINAPI UiaNodeFromProvider(IRawElementProviderSimple *elprov, HUIANODE *huianode) +static HRESULT uia_get_provider_from_hwnd(struct uia_node *node); +HRESULT create_uia_node_from_elprov(IRawElementProviderSimple *elprov, HUIANODE *out_node, + BOOL get_hwnd_providers) { static const int unsupported_prov_opts = ProviderOptions_ProviderOwnsSetFocus | ProviderOptions_HasNativeIAccessible | ProviderOptions_UseClientCoordinates; @@ -909,12 +908,7 @@ HRESULT WINAPI UiaNodeFromProvider(IRawElementProviderSimple *elprov, HUIANODE * int prov_type; HRESULT hr;
- TRACE("(%p, %p)\n", elprov, huianode); - - if (!elprov || !huianode) - return E_INVALIDARG; - - *huianode = NULL; + *out_node = NULL;
hr = IRawElementProviderSimple_get_ProviderOptions(elprov, &prov_opts); if (FAILED(hr)) @@ -951,6 +945,9 @@ HRESULT WINAPI UiaNodeFromProvider(IRawElementProviderSimple *elprov, HUIANODE * return hr; }
+ if (node->hwnd && get_hwnd_providers) + uia_get_provider_from_hwnd(node); + hr = finalize_uia_node(node); if (FAILED(hr)) { @@ -958,11 +955,24 @@ HRESULT WINAPI UiaNodeFromProvider(IRawElementProviderSimple *elprov, HUIANODE * return hr; }
- *huianode = (void *)&node->IWineUiaNode_iface; + *out_node = (void *)&node->IWineUiaNode_iface;
return S_OK; }
+/*********************************************************************** + * UiaNodeFromProvider (uiautomationcore.@) + */ +HRESULT WINAPI UiaNodeFromProvider(IRawElementProviderSimple *elprov, HUIANODE *huianode) +{ + TRACE("(%p, %p)\n", elprov, huianode); + + if (!elprov || !huianode) + return E_INVALIDARG; + + return create_uia_node_from_elprov(elprov, huianode, TRUE); +} + /* * UI Automation client thread functions. */ @@ -1277,6 +1287,14 @@ static HRESULT create_wine_uia_nested_node_provider(struct uia_node *node, LRESU else prov_type = PROV_TYPE_MAIN;
+ if (node->prov[prov_type]) + { + TRACE("Already have a provider of type %d for this node.\n", prov_type); + IWineUiaNode_Release(nested_node); + uia_stop_client_thread(); + return S_OK; + } + /* * 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 diff --git a/dlls/uiautomationcore/uia_private.h b/dlls/uiautomationcore/uia_private.h index daa6df63044..697a1d6aa4e 100644 --- a/dlls/uiautomationcore/uia_private.h +++ b/dlls/uiautomationcore/uia_private.h @@ -89,6 +89,8 @@ static inline struct uia_provider *impl_from_IWineUiaProvider(IWineUiaProvider * /* uia_client.c */ int uia_compare_runtime_ids(SAFEARRAY *sa1, SAFEARRAY *sa2) DECLSPEC_HIDDEN; int get_node_provider_type_at_idx(struct uia_node *node, int idx) DECLSPEC_HIDDEN; +HRESULT create_uia_node_from_elprov(IRawElementProviderSimple *elprov, HUIANODE *out_node, + BOOL get_hwnd_providers) DECLSPEC_HIDDEN;
/* uia_ids.c */ const struct uia_prop_info *uia_prop_info_from_id(PROPERTYID prop_id) DECLSPEC_HIDDEN; diff --git a/dlls/uiautomationcore/uia_provider.c b/dlls/uiautomationcore/uia_provider.c index 99fdd07f40c..e88d4be9565 100644 --- a/dlls/uiautomationcore/uia_provider.c +++ b/dlls/uiautomationcore/uia_provider.c @@ -1464,7 +1464,7 @@ LRESULT WINAPI UiaReturnRawElementProvider(HWND hwnd, WPARAM wparam, return 0; }
- hr = UiaNodeFromProvider(elprov, &node); + hr = create_uia_node_from_elprov(elprov, &node, FALSE); if (FAILED(hr)) { WARN("Failed to create HUIANODE with hr %#lx\n", hr); @@ -1485,7 +1485,7 @@ HRESULT WINAPI UiaDisconnectProvider(IRawElementProviderSimple *elprov)
TRACE("(%p)\n", elprov);
- hr = UiaNodeFromProvider(elprov, &node); + hr = create_uia_node_from_elprov(elprov, &node, FALSE); if (FAILED(hr)) return hr;