Commit 750d11a4 authored by Connor McAdams's avatar Connor McAdams Committed by Alexandre Julliard

uiautomationcore: Add support for getting HWND providers to UiaNodeFromProvider().

parent 59a62981
...@@ -3843,10 +3843,10 @@ static const struct prov_method_sequence node_from_prov5[] = { ...@@ -3843,10 +3843,10 @@ static const struct prov_method_sequence node_from_prov5[] = {
/* Win10v1507 and below call this. */ /* Win10v1507 and below call this. */
{ &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */ { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
{ &Provider, PROV_GET_HOST_RAW_ELEMENT_PROVIDER }, { &Provider, PROV_GET_HOST_RAW_ELEMENT_PROVIDER },
{ &Provider2, PROV_GET_PROVIDER_OPTIONS, METHOD_TODO }, { &Provider2, PROV_GET_PROVIDER_OPTIONS },
/* Win10v1507 and below call this. */ /* Win10v1507 and below call this. */
{ &Provider2, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */ { &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, FRAG_NAVIGATE, METHOD_TODO }, /* NavigateDirection_Parent */
/* These three are only done on Win10v1507 and below. */ /* These three are only done on Win10v1507 and below. */
{ &Provider2, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, { &Provider2, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
...@@ -3868,13 +3868,13 @@ static const struct prov_method_sequence node_from_prov6[] = { ...@@ -3868,13 +3868,13 @@ static const struct prov_method_sequence node_from_prov6[] = {
/* Win10v1507 and below call this. */ /* Win10v1507 and below call this. */
{ &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */ { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
{ &Provider, PROV_GET_HOST_RAW_ELEMENT_PROVIDER }, { &Provider, PROV_GET_HOST_RAW_ELEMENT_PROVIDER },
{ &Provider2, PROV_GET_PROVIDER_OPTIONS, METHOD_TODO }, { &Provider2, PROV_GET_PROVIDER_OPTIONS },
/* Win10v1507 and below call this. */ /* Win10v1507 and below call this. */
{ &Provider2, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */ { &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, FRAG_NAVIGATE, METHOD_TODO }, /* NavigateDirection_Parent */
{ &Provider2, PROV_GET_PROVIDER_OPTIONS, METHOD_TODO }, { &Provider2, PROV_GET_PROVIDER_OPTIONS },
{ &Provider2, PROV_GET_PROVIDER_OPTIONS, METHOD_TODO }, { &Provider2, PROV_GET_PROVIDER_OPTIONS },
/* Only called on Windows versions past Win10v1507. */ /* Only called on Windows versions past Win10v1507. */
{ &Provider, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_OPTIONAL }, { &Provider, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_OPTIONAL },
{ &Provider2, FRAG_NAVIGATE, METHOD_OPTIONAL }, /* NavigateDirection_Parent */ { &Provider2, FRAG_NAVIGATE, METHOD_OPTIONAL }, /* NavigateDirection_Parent */
...@@ -3893,13 +3893,13 @@ static const struct prov_method_sequence node_from_prov7[] = { ...@@ -3893,13 +3893,13 @@ static const struct prov_method_sequence node_from_prov7[] = {
/* Win10v1507 and below call this. */ /* Win10v1507 and below call this. */
{ &Provider_child, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */ { &Provider_child, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
{ &Provider_child, PROV_GET_HOST_RAW_ELEMENT_PROVIDER }, { &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. */ /* Win10v1507 and below call this. */
{ &Provider2, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */ { &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, FRAG_NAVIGATE, METHOD_TODO }, /* NavigateDirection_Parent */
{ &Provider2, PROV_GET_PROVIDER_OPTIONS, METHOD_TODO }, { &Provider2, PROV_GET_PROVIDER_OPTIONS },
{ &Provider2, PROV_GET_PROVIDER_OPTIONS, METHOD_TODO }, { &Provider2, PROV_GET_PROVIDER_OPTIONS },
/* Only called on Windows versions past Win10v1507. */ /* Only called on Windows versions past Win10v1507. */
{ &Provider_child, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_OPTIONAL }, { &Provider_child, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_OPTIONAL },
{ &Provider2, FRAG_NAVIGATE, METHOD_OPTIONAL }, /* NavigateDirection_Parent */ { &Provider2, FRAG_NAVIGATE, METHOD_OPTIONAL }, /* NavigateDirection_Parent */
...@@ -4136,7 +4136,7 @@ static void test_UiaNodeFromProvider(void) ...@@ -4136,7 +4136,7 @@ static void test_UiaNodeFromProvider(void)
hr = UiaNodeFromProvider(&Provider.IRawElementProviderSimple_iface, &node); hr = UiaNodeFromProvider(&Provider.IRawElementProviderSimple_iface, &node);
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref); 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; called_winproc_GETOBJECT_CLIENT = expect_winproc_GETOBJECT_CLIENT = 0;
hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v); hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
...@@ -4178,7 +4178,7 @@ static void test_UiaNodeFromProvider(void) ...@@ -4178,7 +4178,7 @@ static void test_UiaNodeFromProvider(void)
SET_EXPECT(winproc_GETOBJECT_CLIENT); SET_EXPECT(winproc_GETOBJECT_CLIENT);
hr = UiaNodeFromProvider(&Provider.IRawElementProviderSimple_iface, &node); hr = UiaNodeFromProvider(&Provider.IRawElementProviderSimple_iface, &node);
ok(hr == S_OK, "Unexpected hr %#lx\n", hr); 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; called_winproc_GETOBJECT_CLIENT = expect_winproc_GETOBJECT_CLIENT = 0;
/* Win10v1507 and below hold a reference to the root provider for the HWND */ /* Win10v1507 and below hold a reference to the root provider for the HWND */
...@@ -4227,7 +4227,7 @@ static void test_UiaNodeFromProvider(void) ...@@ -4227,7 +4227,7 @@ static void test_UiaNodeFromProvider(void)
SET_EXPECT(winproc_GETOBJECT_CLIENT); SET_EXPECT(winproc_GETOBJECT_CLIENT);
hr = UiaNodeFromProvider(&Provider.IRawElementProviderSimple_iface, &node); hr = UiaNodeFromProvider(&Provider.IRawElementProviderSimple_iface, &node);
ok(hr == S_OK, "Unexpected hr %#lx\n", hr); 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; called_winproc_GETOBJECT_CLIENT = expect_winproc_GETOBJECT_CLIENT = 0;
hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v); hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
...@@ -4242,7 +4242,7 @@ static void test_UiaNodeFromProvider(void) ...@@ -4242,7 +4242,7 @@ static void test_UiaNodeFromProvider(void)
} }
ok_method_sequence(node_from_prov6, "node_from_prov6"); 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(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
ok(!!node, "node == NULL\n"); ok(!!node, "node == NULL\n");
...@@ -4261,7 +4261,7 @@ static void test_UiaNodeFromProvider(void) ...@@ -4261,7 +4261,7 @@ static void test_UiaNodeFromProvider(void)
SET_EXPECT(winproc_GETOBJECT_CLIENT); SET_EXPECT(winproc_GETOBJECT_CLIENT);
hr = UiaNodeFromProvider(&Provider_child.IRawElementProviderSimple_iface, &node); hr = UiaNodeFromProvider(&Provider_child.IRawElementProviderSimple_iface, &node);
ok(hr == S_OK, "Unexpected hr %#lx\n", hr); 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; called_winproc_GETOBJECT_CLIENT = expect_winproc_GETOBJECT_CLIENT = 0;
hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v); hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
...@@ -4276,7 +4276,7 @@ static void test_UiaNodeFromProvider(void) ...@@ -4276,7 +4276,7 @@ static void test_UiaNodeFromProvider(void)
} }
ok_method_sequence(node_from_prov7, "node_from_prov7"); 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(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
ok(!!node, "node == NULL\n"); ok(!!node, "node == NULL\n");
...@@ -4839,7 +4839,7 @@ static void test_UiaGetRuntimeId(void) ...@@ -4839,7 +4839,7 @@ static void test_UiaGetRuntimeId(void)
SET_EXPECT(winproc_GETOBJECT_CLIENT); SET_EXPECT(winproc_GETOBJECT_CLIENT);
hr = UiaNodeFromProvider(&Provider.IRawElementProviderSimple_iface, &node); hr = UiaNodeFromProvider(&Provider.IRawElementProviderSimple_iface, &node);
ok(hr == S_OK, "Unexpected hr %#lx\n", hr); 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; called_winproc_GETOBJECT_CLIENT = expect_winproc_GETOBJECT_CLIENT = 0;
VariantInit(&v); VariantInit(&v);
......
...@@ -718,7 +718,7 @@ static HRESULT uia_provider_get_elem_prop_val(struct uia_provider *prov, ...@@ -718,7 +718,7 @@ static HRESULT uia_provider_get_elem_prop_val(struct uia_provider *prov,
if (FAILED(hr)) if (FAILED(hr))
goto exit; goto exit;
hr = UiaNodeFromProvider(elprov, &node); hr = create_uia_node_from_elprov(elprov, &node, !prov->return_nested_node);
IRawElementProviderSimple_Release(elprov); IRawElementProviderSimple_Release(elprov);
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
...@@ -897,10 +897,9 @@ static HRESULT create_wine_uia_provider(struct uia_node *node, IRawElementProvid ...@@ -897,10 +897,9 @@ static HRESULT create_wine_uia_provider(struct uia_node *node, IRawElementProvid
return S_OK; return S_OK;
} }
/*********************************************************************** static HRESULT uia_get_provider_from_hwnd(struct uia_node *node);
* UiaNodeFromProvider (uiautomationcore.@) HRESULT create_uia_node_from_elprov(IRawElementProviderSimple *elprov, HUIANODE *out_node,
*/ BOOL get_hwnd_providers)
HRESULT WINAPI UiaNodeFromProvider(IRawElementProviderSimple *elprov, HUIANODE *huianode)
{ {
static const int unsupported_prov_opts = ProviderOptions_ProviderOwnsSetFocus | ProviderOptions_HasNativeIAccessible | static const int unsupported_prov_opts = ProviderOptions_ProviderOwnsSetFocus | ProviderOptions_HasNativeIAccessible |
ProviderOptions_UseClientCoordinates; ProviderOptions_UseClientCoordinates;
...@@ -909,12 +908,7 @@ HRESULT WINAPI UiaNodeFromProvider(IRawElementProviderSimple *elprov, HUIANODE * ...@@ -909,12 +908,7 @@ HRESULT WINAPI UiaNodeFromProvider(IRawElementProviderSimple *elprov, HUIANODE *
int prov_type; int prov_type;
HRESULT hr; HRESULT hr;
TRACE("(%p, %p)\n", elprov, huianode); *out_node = NULL;
if (!elprov || !huianode)
return E_INVALIDARG;
*huianode = NULL;
hr = IRawElementProviderSimple_get_ProviderOptions(elprov, &prov_opts); hr = IRawElementProviderSimple_get_ProviderOptions(elprov, &prov_opts);
if (FAILED(hr)) if (FAILED(hr))
...@@ -951,6 +945,9 @@ HRESULT WINAPI UiaNodeFromProvider(IRawElementProviderSimple *elprov, HUIANODE * ...@@ -951,6 +945,9 @@ HRESULT WINAPI UiaNodeFromProvider(IRawElementProviderSimple *elprov, HUIANODE *
return hr; return hr;
} }
if (node->hwnd && get_hwnd_providers)
uia_get_provider_from_hwnd(node);
hr = prepare_uia_node(node); hr = prepare_uia_node(node);
if (FAILED(hr)) if (FAILED(hr))
{ {
...@@ -958,11 +955,24 @@ HRESULT WINAPI UiaNodeFromProvider(IRawElementProviderSimple *elprov, HUIANODE * ...@@ -958,11 +955,24 @@ HRESULT WINAPI UiaNodeFromProvider(IRawElementProviderSimple *elprov, HUIANODE *
return hr; return hr;
} }
*huianode = (void *)&node->IWineUiaNode_iface; *out_node = (void *)&node->IWineUiaNode_iface;
return S_OK; 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. * UI Automation client thread functions.
*/ */
...@@ -1277,6 +1287,14 @@ static HRESULT create_wine_uia_nested_node_provider(struct uia_node *node, LRESU ...@@ -1277,6 +1287,14 @@ static HRESULT create_wine_uia_nested_node_provider(struct uia_node *node, LRESU
else else
prov_type = PROV_TYPE_MAIN; 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 * 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 * as the client making the request, return a normal provider instead of a
......
...@@ -89,6 +89,8 @@ static inline struct uia_provider *impl_from_IWineUiaProvider(IWineUiaProvider * ...@@ -89,6 +89,8 @@ static inline struct uia_provider *impl_from_IWineUiaProvider(IWineUiaProvider *
/* uia_client.c */ /* uia_client.c */
int uia_compare_runtime_ids(SAFEARRAY *sa1, SAFEARRAY *sa2) DECLSPEC_HIDDEN; 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; 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 */ /* 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;
......
...@@ -1464,7 +1464,7 @@ LRESULT WINAPI UiaReturnRawElementProvider(HWND hwnd, WPARAM wparam, ...@@ -1464,7 +1464,7 @@ LRESULT WINAPI UiaReturnRawElementProvider(HWND hwnd, WPARAM wparam,
return 0; return 0;
} }
hr = UiaNodeFromProvider(elprov, &node); hr = create_uia_node_from_elprov(elprov, &node, FALSE);
if (FAILED(hr)) if (FAILED(hr))
{ {
WARN("Failed to create HUIANODE with hr %#lx\n", hr); WARN("Failed to create HUIANODE with hr %#lx\n", hr);
...@@ -1485,7 +1485,7 @@ HRESULT WINAPI UiaDisconnectProvider(IRawElementProviderSimple *elprov) ...@@ -1485,7 +1485,7 @@ HRESULT WINAPI UiaDisconnectProvider(IRawElementProviderSimple *elprov)
TRACE("(%p)\n", elprov); TRACE("(%p)\n", elprov);
hr = UiaNodeFromProvider(elprov, &node); hr = create_uia_node_from_elprov(elprov, &node, FALSE);
if (FAILED(hr)) if (FAILED(hr))
return hr; return hr;
......
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