From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/uiautomationcore/tests/uiautomation.c | 64 ++++++++++------------ dlls/uiautomationcore/uia_client.c | 27 ++++++++- 2 files changed, 53 insertions(+), 38 deletions(-)
diff --git a/dlls/uiautomationcore/tests/uiautomation.c b/dlls/uiautomationcore/tests/uiautomation.c index 32ae4cb9b5f..19cebf79143 100644 --- a/dlls/uiautomationcore/tests/uiautomation.c +++ b/dlls/uiautomationcore/tests/uiautomation.c @@ -7132,17 +7132,15 @@ static void test_UiaGetUpdatedCache(void)
/* Equivalent to: if (1 && 1) */ hr = UiaGetUpdatedCache(node, &cache_req, NormalizeState_View, NULL, &out_req, &tree_struct); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - todo_wine ok(!!out_req, "out_req == NULL\n"); - todo_wine ok(!!tree_struct, "tree_struct == NULL\n"); - if (out_req) - { - exp_lbound[0] = exp_lbound[1] = 0; - exp_elems[0] = exp_elems[1] = 1; - test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc); - ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct)); - ok_method_sequence(cache_req_seq1, NULL); - } + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(!!out_req, "out_req == NULL\n"); + ok(!!tree_struct, "tree_struct == NULL\n"); + + exp_lbound[0] = exp_lbound[1] = 0; + exp_elems[0] = exp_elems[1] = 1; + test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc); + ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct)); + ok_method_sequence(cache_req_seq1, NULL);
SafeArrayDestroy(out_req); SysFreeString(tree_struct); @@ -7156,14 +7154,12 @@ static void test_UiaGetUpdatedCache(void)
/* Equivalent to: if (1 && 0) */ hr = UiaGetUpdatedCache(node, &cache_req, NormalizeState_View, NULL, &out_req, &tree_struct); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - if (SUCCEEDED(hr)) - ok_method_sequence(cache_req_seq2, NULL); - + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok_method_sequence(cache_req_seq2, NULL); ok(!out_req, "out_req != NULL\n"); - todo_wine ok(!!tree_struct, "tree_struct == NULL\n"); - if (tree_struct) - ok(!wcscmp(tree_struct, L""), "tree structure %s\n", debugstr_w(tree_struct)); + ok(!!tree_struct, "tree_struct == NULL\n"); + ok(!wcscmp(tree_struct, L""), "tree structure %s\n", debugstr_w(tree_struct)); + SysFreeString(tree_struct);
/* @@ -7178,17 +7174,15 @@ static void test_UiaGetUpdatedCache(void)
/* Equivalent to: if (1 || 0) */ hr = UiaGetUpdatedCache(node, &cache_req, NormalizeState_View, NULL, &out_req, &tree_struct); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - todo_wine ok(!!out_req, "out_req == NULL\n"); - todo_wine ok(!!tree_struct, "tree_struct == NULL\n"); - if (out_req) - { - exp_lbound[0] = exp_lbound[1] = 0; - exp_elems[0] = exp_elems[1] = 1; - test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc); - ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct)); - ok_method_sequence(cache_req_seq1, NULL); - } + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(!!out_req, "out_req == NULL\n"); + ok(!!tree_struct, "tree_struct == NULL\n"); + + exp_lbound[0] = exp_lbound[1] = 0; + exp_elems[0] = exp_elems[1] = 1; + test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc); + ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct)); + ok_method_sequence(cache_req_seq1, NULL);
SafeArrayDestroy(out_req); SysFreeString(tree_struct); @@ -7202,14 +7196,12 @@ static void test_UiaGetUpdatedCache(void)
/* Equivalent to: if (0 || 0) */ hr = UiaGetUpdatedCache(node, &cache_req, NormalizeState_View, NULL, &out_req, &tree_struct); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - if (SUCCEEDED(hr)) - ok_method_sequence(cache_req_seq2, NULL); - + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok_method_sequence(cache_req_seq2, NULL); ok(!out_req, "out_req != NULL\n"); - todo_wine ok(!!tree_struct, "tree_struct == NULL\n"); - if (tree_struct) - ok(!wcscmp(tree_struct, L""), "tree structure %s\n", debugstr_w(tree_struct)); + ok(!!tree_struct, "tree_struct == NULL\n"); + ok(!wcscmp(tree_struct, L""), "tree structure %s\n", debugstr_w(tree_struct)); + SysFreeString(tree_struct);
/* diff --git a/dlls/uiautomationcore/uia_client.c b/dlls/uiautomationcore/uia_client.c index 3897b036e09..4d3037b212c 100644 --- a/dlls/uiautomationcore/uia_client.c +++ b/dlls/uiautomationcore/uia_client.c @@ -1922,6 +1922,8 @@ static BOOL uia_condition_matched(HRESULT hr)
static HRESULT uia_condition_check(HUIANODE node, struct UiaCondition *condition) { + HRESULT hr; + switch (condition->ConditionType) { case ConditionType_True: @@ -1933,7 +1935,6 @@ static HRESULT uia_condition_check(HUIANODE node, struct UiaCondition *condition case ConditionType_Not: { struct UiaNotCondition *not_cond = (struct UiaNotCondition *)condition; - HRESULT hr;
hr = uia_condition_check(node, not_cond->pConditions); if (FAILED(hr)) @@ -1945,9 +1946,31 @@ static HRESULT uia_condition_check(HUIANODE node, struct UiaCondition *condition return S_OK; }
- case ConditionType_Property: case ConditionType_And: case ConditionType_Or: + { + struct UiaAndOrCondition *and_or_cond = (struct UiaAndOrCondition *)condition; + int i; + + for (i = 0; i < and_or_cond->cConditions; i++) + { + hr = uia_condition_check(node, and_or_cond->ppConditions[i]); + if (FAILED(hr)) + return hr; + + if (condition->ConditionType == ConditionType_And && !uia_condition_matched(hr)) + return S_FALSE; + else if (condition->ConditionType == ConditionType_Or && uia_condition_matched(hr)) + return S_OK; + } + + if (condition->ConditionType == ConditionType_Or) + return S_FALSE; + else + return S_OK; + } + + case ConditionType_Property: FIXME("Unhandled condition type %d\n", condition->ConditionType); return E_NOTIMPL;
From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/uiautomationcore/tests/uiautomation.c | 35 +++++++++----------- dlls/uiautomationcore/uia_client.c | 38 ++++++++++++++++++++-- 2 files changed, 52 insertions(+), 21 deletions(-)
diff --git a/dlls/uiautomationcore/tests/uiautomation.c b/dlls/uiautomationcore/tests/uiautomation.c index 19cebf79143..7a79ea2a4a5 100644 --- a/dlls/uiautomationcore/tests/uiautomation.c +++ b/dlls/uiautomationcore/tests/uiautomation.c @@ -6927,7 +6927,7 @@ static const struct prov_method_sequence cache_req_seq4[] = { /* Sequence for non-matching property condition. */ static const struct prov_method_sequence cache_req_seq5[] = { { &Provider, PROV_GET_PROPERTY_VALUE }, /* Dependent upon property condition. */ - { &Provider, PROV_GET_PROPERTY_VALUE }, /* Dependent upon property condition. */ + { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* Dependent upon property condition. */ /* Only done on Win10v1507 and below. */ { &Provider, FRAG_NAVIGATE, METHOD_OPTIONAL }, /* NavigateDirection_Parent */ { 0 } @@ -7343,21 +7343,19 @@ static void test_UiaGetUpdatedCache(void) tree_struct = NULL; out_req = NULL;
hr = UiaGetUpdatedCache(node, &cache_req, NormalizeState_View, NULL, &out_req, &tree_struct); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - todo_wine ok(!!out_req, "out_req == NULL\n"); - todo_wine ok(!!tree_struct, "tree_struct == NULL\n"); - if (out_req) - { - exp_lbound[0] = exp_lbound[1] = 0; - exp_elems[0] = exp_elems[1] = 1; - test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc); - ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct)); - ok_method_sequence(cache_req_seq4, NULL); - } + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(!!out_req, "out_req == NULL\n"); + ok(!!tree_struct, "tree_struct == NULL\n"); + + exp_lbound[0] = exp_lbound[1] = 0; + exp_elems[0] = exp_elems[1] = 1; + test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc); + ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct)); + ok_method_sequence(cache_req_seq4, NULL);
SafeArrayDestroy(out_req); SysFreeString(tree_struct); - VariantClear(&prop_cond.Value); + VariantClear(&v);
/* * Provider now returns VARIANT_TRUE for UIA_IsControlElementPropertyId, @@ -7377,13 +7375,12 @@ static void test_UiaGetUpdatedCache(void) tree_struct = NULL; out_req = NULL;
hr = UiaGetUpdatedCache(node, &cache_req, NormalizeState_View, NULL, &out_req, &tree_struct); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - if (SUCCEEDED(hr)) - ok_method_sequence(cache_req_seq5, NULL); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok_method_sequence(cache_req_seq5, NULL); ok(!out_req, "out_req != NULL\n"); - todo_wine ok(!!tree_struct, "tree_struct == NULL\n"); - if (tree_struct) - ok(!wcscmp(tree_struct, L""), "tree structure %s\n", debugstr_w(tree_struct)); + ok(!!tree_struct, "tree_struct == NULL\n"); + ok(!wcscmp(tree_struct, L""), "tree structure %s\n", debugstr_w(tree_struct)); + SysFreeString(tree_struct); VariantClear(&v);
diff --git a/dlls/uiautomationcore/uia_client.c b/dlls/uiautomationcore/uia_client.c index 4d3037b212c..328afa7acb2 100644 --- a/dlls/uiautomationcore/uia_client.c +++ b/dlls/uiautomationcore/uia_client.c @@ -1920,6 +1920,41 @@ static BOOL uia_condition_matched(HRESULT hr) return TRUE; }
+static HRESULT uia_property_condition_check(HUIANODE node, struct UiaPropertyCondition *prop_cond) +{ + const struct uia_prop_info *prop_info = uia_prop_info_from_id(prop_cond->PropertyId); + HRESULT hr; + VARIANT v; + + if (!prop_info) + return E_INVALIDARG; + + switch (prop_info->type) + { + case UIAutomationType_Bool: + hr = UiaGetPropertyValue(node, prop_info->prop_id, &v); + if (FAILED(hr) || V_VT(&v) == VT_UNKNOWN) + { + hr = S_FALSE; + break; + } + + if ((V_VT(&v) == V_VT(&prop_cond->Value)) && (V_BOOL(&v) == V_BOOL(&prop_cond->Value))) + hr = S_OK; + else + hr = S_FALSE; + + break; + + default: + FIXME("PropertyCondition comparison unimplemented for type %#x\n", prop_info->type); + return E_NOTIMPL; + } + + VariantClear(&v); + return hr; +} + static HRESULT uia_condition_check(HUIANODE node, struct UiaCondition *condition) { HRESULT hr; @@ -1971,8 +2006,7 @@ static HRESULT uia_condition_check(HUIANODE node, struct UiaCondition *condition }
case ConditionType_Property: - FIXME("Unhandled condition type %d\n", condition->ConditionType); - return E_NOTIMPL; + return uia_property_condition_check(node, (struct UiaPropertyCondition *)condition);
default: WARN("Invalid condition type %d\n", condition->ConditionType);
From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/uiautomationcore/tests/uiautomation.c | 51 ++++++++++------------ dlls/uiautomationcore/uia_client.c | 50 +++++++++++++++------ dlls/uiautomationcore/uia_private.h | 2 +- dlls/uiautomationcore/uia_provider.c | 2 +- 4 files changed, 62 insertions(+), 43 deletions(-)
diff --git a/dlls/uiautomationcore/tests/uiautomation.c b/dlls/uiautomationcore/tests/uiautomation.c index 7a79ea2a4a5..91c9e75c46a 100644 --- a/dlls/uiautomationcore/tests/uiautomation.c +++ b/dlls/uiautomationcore/tests/uiautomation.c @@ -7257,17 +7257,15 @@ static void test_UiaGetUpdatedCache(void) tree_struct = NULL; out_req = NULL;
hr = UiaGetUpdatedCache(node, &cache_req, NormalizeState_View, NULL, &out_req, &tree_struct); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - todo_wine ok(!!out_req, "out_req == NULL\n"); - todo_wine ok(!!tree_struct, "tree_struct == NULL\n"); - if (out_req) - { - exp_lbound[0] = exp_lbound[1] = 0; - exp_elems[0] = exp_elems[1] = 1; - test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc); - ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct)); - ok_method_sequence(cache_req_seq4, NULL); - } + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(!!out_req, "out_req == NULL\n"); + ok(!!tree_struct, "tree_struct == NULL\n"); + + exp_lbound[0] = exp_lbound[1] = 0; + exp_elems[0] = exp_elems[1] = 1; + test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc); + ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct)); + ok_method_sequence(cache_req_seq4, NULL);
SafeArrayDestroy(out_req); SysFreeString(tree_struct); @@ -7286,13 +7284,12 @@ static void test_UiaGetUpdatedCache(void) tree_struct = NULL; out_req = NULL;
hr = UiaGetUpdatedCache(node, &cache_req, NormalizeState_View, NULL, &out_req, &tree_struct); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - if (SUCCEEDED(hr)) - ok_method_sequence(cache_req_seq5, NULL); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok_method_sequence(cache_req_seq5, NULL); ok(!out_req, "out_req != NULL\n"); - todo_wine ok(!!tree_struct, "tree_struct == NULL\n"); - if (tree_struct) - ok(!wcscmp(tree_struct, L""), "tree structure %s\n", debugstr_w(tree_struct)); + ok(!!tree_struct, "tree_struct == NULL\n"); + ok(!wcscmp(tree_struct, L""), "tree structure %s\n", debugstr_w(tree_struct)); + SysFreeString(tree_struct); VariantClear(&v); } @@ -7312,17 +7309,15 @@ static void test_UiaGetUpdatedCache(void) tree_struct = NULL; out_req = NULL;
hr = UiaGetUpdatedCache(node, &cache_req, NormalizeState_View, NULL, &out_req, &tree_struct); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - todo_wine ok(!!out_req, "out_req == NULL\n"); - todo_wine ok(!!tree_struct, "tree_struct == NULL\n"); - if (out_req) - { - exp_lbound[0] = exp_lbound[1] = 0; - exp_elems[0] = exp_elems[1] = 1; - test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc); - ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct)); - ok_method_sequence(cache_req_seq6, NULL); - } + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(!!out_req, "out_req == NULL\n"); + ok(!!tree_struct, "tree_struct == NULL\n"); + + exp_lbound[0] = exp_lbound[1] = 0; + exp_elems[0] = exp_elems[1] = 1; + test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc); + ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct)); + ok_method_sequence(cache_req_seq6, NULL);
SafeArrayDestroy(out_req); SysFreeString(tree_struct); diff --git a/dlls/uiautomationcore/uia_client.c b/dlls/uiautomationcore/uia_client.c index 328afa7acb2..11a6e3ffc45 100644 --- a/dlls/uiautomationcore/uia_client.c +++ b/dlls/uiautomationcore/uia_client.c @@ -49,7 +49,7 @@ static HRESULT get_safearray_bounds(SAFEARRAY *sa, LONG *lbound, LONG *elems) return S_OK; }
-int uia_compare_runtime_ids(SAFEARRAY *sa1, SAFEARRAY *sa2) +int uia_compare_safearrays(SAFEARRAY *sa1, SAFEARRAY *sa2, int prop_type) { LONG i, idx, lbound[2], elems[2]; int val[2]; @@ -72,6 +72,12 @@ int uia_compare_runtime_ids(SAFEARRAY *sa1, SAFEARRAY *sa2) if (elems[0] != elems[1]) return (elems[0] > elems[1]) - (elems[0] < elems[1]);
+ if (prop_type != UIAutomationType_IntArray) + { + FIXME("Array type %#x value comparsion currently unimplemented.\n", prop_type); + return -1; + } + for (i = 0; i < elems[0]; i++) { idx = lbound[0] + i; @@ -1932,18 +1938,7 @@ static HRESULT uia_property_condition_check(HUIANODE node, struct UiaPropertyCon switch (prop_info->type) { case UIAutomationType_Bool: - hr = UiaGetPropertyValue(node, prop_info->prop_id, &v); - if (FAILED(hr) || V_VT(&v) == VT_UNKNOWN) - { - hr = S_FALSE; - break; - } - - if ((V_VT(&v) == V_VT(&prop_cond->Value)) && (V_BOOL(&v) == V_BOOL(&prop_cond->Value))) - hr = S_OK; - else - hr = S_FALSE; - + case UIAutomationType_IntArray: break;
default: @@ -1951,6 +1946,35 @@ static HRESULT uia_property_condition_check(HUIANODE node, struct UiaPropertyCon return E_NOTIMPL; }
+ hr = UiaGetPropertyValue(node, prop_info->prop_id, &v); + if (FAILED(hr) || V_VT(&v) == VT_UNKNOWN) + return S_FALSE; + + if (V_VT(&v) == V_VT(&prop_cond->Value)) + { + switch (prop_info->type) + { + case UIAutomationType_Bool: + if (V_BOOL(&v) == V_BOOL(&prop_cond->Value)) + hr = S_OK; + else + hr = S_FALSE; + break; + + case UIAutomationType_IntArray: + if (!uia_compare_safearrays(V_ARRAY(&v), V_ARRAY(&prop_cond->Value), prop_info->type)) + hr = S_OK; + else + hr = S_FALSE; + break; + + default: + break; + } + } + else + hr = S_FALSE; + VariantClear(&v); return hr; } diff --git a/dlls/uiautomationcore/uia_private.h b/dlls/uiautomationcore/uia_private.h index 697a1d6aa4e..39c9aac847b 100644 --- a/dlls/uiautomationcore/uia_private.h +++ b/dlls/uiautomationcore/uia_private.h @@ -87,7 +87,7 @@ static inline struct uia_provider *impl_from_IWineUiaProvider(IWineUiaProvider * }
/* uia_client.c */ -int uia_compare_runtime_ids(SAFEARRAY *sa1, SAFEARRAY *sa2) DECLSPEC_HIDDEN; +int uia_compare_safearrays(SAFEARRAY *sa1, SAFEARRAY *sa2, int prop_type) 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; diff --git a/dlls/uiautomationcore/uia_provider.c b/dlls/uiautomationcore/uia_provider.c index e88d4be9565..fc718fabe43 100644 --- a/dlls/uiautomationcore/uia_provider.c +++ b/dlls/uiautomationcore/uia_provider.c @@ -1159,7 +1159,7 @@ struct uia_provider_thread_map_entry static int uia_runtime_id_compare(const void *key, const struct rb_entry *entry) { struct uia_provider_thread_map_entry *prov_entry = RB_ENTRY_VALUE(entry, struct uia_provider_thread_map_entry, entry); - return uia_compare_runtime_ids(prov_entry->runtime_id, (SAFEARRAY *)key); + return uia_compare_safearrays(prov_entry->runtime_id, (SAFEARRAY *)key, UIAutomationType_IntArray); }
void uia_provider_thread_remove_node(HUIANODE node)
This merge request was approved by Esme Povirk.