uiautomationcore: Determine provider type for nested node providers.

Signed-off-by: Connor McAdams <cmcadams@codeweavers.com>
This commit is contained in:
Connor McAdams 2022-10-12 13:22:29 -04:00 committed by Alexandre Julliard
parent edcd55bae2
commit 59a629810a
3 changed files with 66 additions and 6 deletions

View file

@ -4988,7 +4988,7 @@ static const struct prov_method_sequence node_from_hwnd3[] = {
{ &Provider, PROV_GET_HOST_RAW_ELEMENT_PROVIDER },
{ &Provider, FRAG_NAVIGATE, METHOD_TODO }, /* NavigateDirection_Parent */
{ &Provider, PROV_GET_PROVIDER_OPTIONS },
{ &Provider, PROV_GET_PROVIDER_OPTIONS, METHOD_TODO },
{ &Provider, PROV_GET_PROVIDER_OPTIONS },
{ &Provider, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ProviderDescriptionPropertyId */
{ 0 }
};
@ -5040,7 +5040,7 @@ static const struct prov_method_sequence node_from_hwnd6[] = {
{ &Provider_child, FRAG_GET_FRAGMENT_ROOT, METHOD_OPTIONAL },
{ &Provider, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_OPTIONAL },
{ &Provider, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
{ &Provider_child, PROV_GET_PROVIDER_OPTIONS, METHOD_TODO },
{ &Provider_child, PROV_GET_PROVIDER_OPTIONS },
/* Next two are only done on Win10v1809+. */
{ &Provider_child, FRAG_GET_FRAGMENT_ROOT, METHOD_OPTIONAL },
{ &Provider, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_OPTIONAL },
@ -5060,7 +5060,7 @@ static const struct prov_method_sequence node_from_hwnd7[] = {
{ &Provider_child, PROV_GET_HOST_RAW_ELEMENT_PROVIDER },
{ &Provider_child, FRAG_NAVIGATE, METHOD_TODO }, /* NavigateDirection_Parent */
{ &Provider_child, PROV_GET_PROVIDER_OPTIONS },
{ &Provider_child, PROV_GET_PROVIDER_OPTIONS, METHOD_TODO },
{ &Provider_child, PROV_GET_PROVIDER_OPTIONS },
{ &Provider, PROV_GET_PROVIDER_OPTIONS, METHOD_TODO },
{ &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
{ &Provider, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_TODO },
@ -5078,7 +5078,7 @@ static const struct prov_method_sequence node_from_hwnd8[] = {
{ &Provider, PROV_GET_HOST_RAW_ELEMENT_PROVIDER },
{ &Provider, FRAG_NAVIGATE, METHOD_TODO }, /* NavigateDirection_Parent */
{ &Provider, PROV_GET_PROVIDER_OPTIONS },
{ &Provider, PROV_GET_PROVIDER_OPTIONS, METHOD_TODO },
{ &Provider, PROV_GET_PROVIDER_OPTIONS },
{ &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
{ &Provider, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ControlTypePropertyId */
{ 0 }

View file

@ -44,6 +44,7 @@ library UIA_wine_private
interface IWineUiaProvider : IUnknown
{
HRESULT get_prop_val([in]const struct uia_prop_info *prop_info, [out, retval]VARIANT *ret_val);
HRESULT get_prov_opts([out, retval]int *out_opts);
}
[

View file

@ -333,6 +333,22 @@ int get_node_provider_type_at_idx(struct uia_node *node, int idx)
return 0;
}
static HRESULT get_prov_opts_from_node_provider(IWineUiaNode *node, int idx, int *out_opts)
{
IWineUiaProvider *prov;
HRESULT hr;
*out_opts = 0;
hr = IWineUiaNode_get_provider(node, idx, &prov);
if (FAILED(hr))
return hr;
hr = IWineUiaProvider_get_prov_opts(prov, out_opts);
IWineUiaProvider_Release(prov);
return hr;
}
/*
* IWineUiaNode interface.
*/
@ -839,11 +855,28 @@ static HRESULT WINAPI uia_provider_get_prop_val(IWineUiaProvider *iface,
return S_OK;
}
static HRESULT WINAPI uia_provider_get_prov_opts(IWineUiaProvider *iface, int *out_opts)
{
struct uia_provider *prov = impl_from_IWineUiaProvider(iface);
enum ProviderOptions prov_opts;
HRESULT hr;
TRACE("%p, %p\n", iface, out_opts);
*out_opts = 0;
hr = IRawElementProviderSimple_get_ProviderOptions(prov->elprov, &prov_opts);
if (SUCCEEDED(hr))
*out_opts = prov_opts;
return S_OK;
}
static const IWineUiaProviderVtbl uia_provider_vtbl = {
uia_provider_QueryInterface,
uia_provider_AddRef,
uia_provider_Release,
uia_provider_get_prop_val,
uia_provider_get_prov_opts,
};
static HRESULT create_wine_uia_provider(struct uia_node *node, IRawElementProviderSimple *elprov,
@ -1186,11 +1219,21 @@ static HRESULT WINAPI uia_nested_node_provider_get_prop_val(IWineUiaProvider *if
return S_OK;
}
static HRESULT WINAPI uia_nested_node_provider_get_prov_opts(IWineUiaProvider *iface, int *out_opts)
{
struct uia_nested_node_provider *prov = impl_from_nested_node_IWineUiaProvider(iface);
TRACE("%p, %p\n", iface, out_opts);
return get_prov_opts_from_node_provider(prov->nested_node, 0, out_opts);
}
static const IWineUiaProviderVtbl uia_nested_node_provider_vtbl = {
uia_nested_node_provider_QueryInterface,
uia_nested_node_provider_AddRef,
uia_nested_node_provider_Release,
uia_nested_node_provider_get_prop_val,
uia_nested_node_provider_get_prov_opts,
};
static BOOL is_nested_node_provider(IWineUiaProvider *iface)
@ -1208,6 +1251,7 @@ static HRESULT create_wine_uia_nested_node_provider(struct uia_node *node, LRESU
struct uia_nested_node_provider *prov;
IGlobalInterfaceTable *git;
IWineUiaNode *nested_node;
int prov_opts, prov_type;
DWORD git_cookie;
HRESULT hr;
@ -1218,6 +1262,21 @@ static HRESULT create_wine_uia_nested_node_provider(struct uia_node *node, LRESU
return hr;
}
hr = get_prov_opts_from_node_provider(nested_node, 0, &prov_opts);
if (FAILED(hr))
{
WARN("Failed to get provider options for node %p with hr %#lx\n", nested_node, hr);
IWineUiaNode_Release(nested_node);
uia_stop_client_thread();
return hr;
}
/* Nested nodes can only serve as override or main providers. */
if (prov_opts & ProviderOptions_OverrideProvider)
prov_type = PROV_TYPE_OVERRIDE;
else
prov_type = PROV_TYPE_MAIN;
/*
* 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
@ -1276,8 +1335,8 @@ static HRESULT create_wine_uia_nested_node_provider(struct uia_node *node, LRESU
}
}
node->prov[PROV_TYPE_MAIN] = provider_iface;
node->git_cookie[PROV_TYPE_MAIN] = git_cookie;
node->prov[prov_type] = provider_iface;
node->git_cookie[prov_type] = git_cookie;
node->prov_count++;
return S_OK;