Module: wine Branch: master Commit: 59a629810aa827927b30ffc167b3386b00ae92a1 URL: https://gitlab.winehq.org/wine/wine/-/commit/59a629810aa827927b30ffc167b3386...
Author: Connor McAdams cmcadams@codeweavers.com Date: Wed Oct 12 13:22:29 2022 -0400
uiautomationcore: Determine provider type for nested node providers.
Signed-off-by: Connor McAdams cmcadams@codeweavers.com
---
dlls/uiautomationcore/tests/uiautomation.c | 8 ++-- dlls/uiautomationcore/uia_classes.idl | 1 + dlls/uiautomationcore/uia_client.c | 63 +++++++++++++++++++++++++++++- 3 files changed, 66 insertions(+), 6 deletions(-)
diff --git a/dlls/uiautomationcore/tests/uiautomation.c b/dlls/uiautomationcore/tests/uiautomation.c index 54d6fa710b5..604e488601f 100644 --- a/dlls/uiautomationcore/tests/uiautomation.c +++ b/dlls/uiautomationcore/tests/uiautomation.c @@ -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 } diff --git a/dlls/uiautomationcore/uia_classes.idl b/dlls/uiautomationcore/uia_classes.idl index 5877d14b8e5..4540613bba2 100644 --- a/dlls/uiautomationcore/uia_classes.idl +++ b/dlls/uiautomationcore/uia_classes.idl @@ -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); }
[ diff --git a/dlls/uiautomationcore/uia_client.c b/dlls/uiautomationcore/uia_client.c index 1385e1f94ee..4f2cdfd6391 100644 --- a/dlls/uiautomationcore/uia_client.c +++ b/dlls/uiautomationcore/uia_client.c @@ -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;