From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/uiautomationcore/tests/uiautomation.c | 339 ++++++++++----------- dlls/uiautomationcore/uia_client.c | 180 ++++++++--- 2 files changed, 297 insertions(+), 222 deletions(-)
diff --git a/dlls/uiautomationcore/tests/uiautomation.c b/dlls/uiautomationcore/tests/uiautomation.c index 5c15c9344c9..75782b0f5e0 100644 --- a/dlls/uiautomationcore/tests/uiautomation.c +++ b/dlls/uiautomationcore/tests/uiautomation.c @@ -8668,37 +8668,34 @@ static void test_UiaFind(void) AutomationElementMode_Full); set_find_params(&find_params, -1, FALSE, FALSE, (struct UiaCondition *)&UiaTrueCondition); hr = UiaFind(node, &find_params, &cache_req, &out_req, &offsets, &tree_structs); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - todo_wine ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref); - todo_wine ok(Provider_child_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child_child.ref); - todo_wine ok(Provider_child_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child_child2.ref); - todo_wine ok(Provider_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child2.ref); - todo_wine ok(Provider_child2_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child2_child.ref); - todo_wine ok(Provider_child2_child_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child2_child_child.ref); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref); + ok(Provider_child_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child_child.ref); + ok(Provider_child_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child_child2.ref); + ok(Provider_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child2.ref); + ok(Provider_child2_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child2_child.ref); + ok(Provider_child2_child_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child2_child_child.ref);
- if (SUCCEEDED(hr)) - { - add_provider_desc(&exp_node_desc[0], L"Main", L"Provider", TRUE); - add_provider_desc(&exp_node_desc[1], L"Main", L"Provider_child", TRUE); - add_provider_desc(&exp_node_desc[2], L"Main", L"Provider_child_child", TRUE); - add_provider_desc(&exp_node_desc[3], L"Main", L"Provider_child_child2", TRUE); - add_provider_desc(&exp_node_desc[4], L"Main", L"Provider_child2", TRUE); - add_provider_desc(&exp_node_desc[5], L"Main", L"Provider_child2_child", TRUE); - add_provider_desc(&exp_node_desc[6], L"Main", L"Provider_child2_child_child", TRUE); - exp_lbound[0] = exp_lbound[1] = 0; - exp_elems[0] = 7; - exp_elems[1] = 1; + add_provider_desc(&exp_node_desc[0], L"Main", L"Provider", TRUE); + add_provider_desc(&exp_node_desc[1], L"Main", L"Provider_child", TRUE); + add_provider_desc(&exp_node_desc[2], L"Main", L"Provider_child_child", TRUE); + add_provider_desc(&exp_node_desc[3], L"Main", L"Provider_child_child2", TRUE); + add_provider_desc(&exp_node_desc[4], L"Main", L"Provider_child2", TRUE); + add_provider_desc(&exp_node_desc[5], L"Main", L"Provider_child2_child", TRUE); + add_provider_desc(&exp_node_desc[6], L"Main", L"Provider_child2_child_child", TRUE); + exp_lbound[0] = exp_lbound[1] = 0; + exp_elems[0] = 7; + exp_elems[1] = 1;
- test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc); + test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
- for (i = 0; i < exp_elems[0]; i++) - { - exp_offset[i] = i; - exp_tree_struct[i] = L"P)"; - } - test_find_sa_results(tree_structs, offsets, exp_elems[0], exp_tree_struct, exp_offset); - ok_method_sequence(find_seq1, "find_seq1"); + for (i = 0; i < exp_elems[0]; i++) + { + exp_offset[i] = i; + exp_tree_struct[i] = L"P)"; } + test_find_sa_results(tree_structs, offsets, exp_elems[0], exp_tree_struct, exp_offset); + ok_method_sequence(find_seq1, "find_seq1");
SafeArrayDestroy(out_req); SafeArrayDestroy(offsets); @@ -8714,31 +8711,28 @@ static void test_UiaFind(void) AutomationElementMode_Full); set_find_params(&find_params, 1, FALSE, FALSE, (struct UiaCondition *)&UiaTrueCondition); hr = UiaFind(node, &find_params, &cache_req, &out_req, &offsets, &tree_structs); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - todo_wine ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref); - todo_wine ok(Provider_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child2.ref); - - if (SUCCEEDED(hr)) - { - add_provider_desc(&exp_node_desc[0], L"Main", L"Provider", TRUE); - add_provider_desc(&exp_node_desc[1], L"Main", L"Provider_child", TRUE); - add_provider_desc(&exp_node_desc[2], L"Main", L"Provider_child2", TRUE); - exp_lbound[0] = exp_lbound[1] = 0; - exp_elems[0] = 3; - exp_elems[1] = 1; + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref); + ok(Provider_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child2.ref);
- test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc); + add_provider_desc(&exp_node_desc[0], L"Main", L"Provider", TRUE); + add_provider_desc(&exp_node_desc[1], L"Main", L"Provider_child", TRUE); + add_provider_desc(&exp_node_desc[2], L"Main", L"Provider_child2", TRUE); + exp_lbound[0] = exp_lbound[1] = 0; + exp_elems[0] = 3; + exp_elems[1] = 1;
- for (i = 0; i < exp_elems[0]; i++) - { - exp_offset[i] = i; - exp_tree_struct[i] = L"P)"; - } + test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
- test_find_sa_results(tree_structs, offsets, exp_elems[0], exp_tree_struct, exp_offset); - ok_method_sequence(find_seq2, "find_seq2"); + for (i = 0; i < exp_elems[0]; i++) + { + exp_offset[i] = i; + exp_tree_struct[i] = L"P)"; }
+ test_find_sa_results(tree_structs, offsets, exp_elems[0], exp_tree_struct, exp_offset); + ok_method_sequence(find_seq2, "find_seq2"); + SafeArrayDestroy(out_req); SafeArrayDestroy(offsets); SafeArrayDestroy(tree_structs); @@ -8753,28 +8747,25 @@ static void test_UiaFind(void) AutomationElementMode_Full); set_find_params(&find_params, 1, FALSE, TRUE, (struct UiaCondition *)&UiaTrueCondition); hr = UiaFind(node, &find_params, &cache_req, &out_req, &offsets, &tree_structs); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - todo_wine ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref); - todo_wine ok(Provider_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child2.ref); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref); + ok(Provider_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child2.ref);
- if (SUCCEEDED(hr)) - { - add_provider_desc(&exp_node_desc[0], L"Main", L"Provider_child", TRUE); - add_provider_desc(&exp_node_desc[1], L"Main", L"Provider_child2", TRUE); - exp_lbound[0] = exp_lbound[1] = 0; - exp_elems[0] = 2; - exp_elems[1] = 1; + add_provider_desc(&exp_node_desc[0], L"Main", L"Provider_child", TRUE); + add_provider_desc(&exp_node_desc[1], L"Main", L"Provider_child2", TRUE); + exp_lbound[0] = exp_lbound[1] = 0; + exp_elems[0] = 2; + exp_elems[1] = 1;
- test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc); + test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
- for (i = 0; i < exp_elems[0]; i++) - { - exp_offset[i] = i; - exp_tree_struct[i] = L"P)"; - } - test_find_sa_results(tree_structs, offsets, exp_elems[0], exp_tree_struct, exp_offset); - ok_method_sequence(find_seq3, "find_seq3"); + for (i = 0; i < exp_elems[0]; i++) + { + exp_offset[i] = i; + exp_tree_struct[i] = L"P)"; } + test_find_sa_results(tree_structs, offsets, exp_elems[0], exp_tree_struct, exp_offset); + ok_method_sequence(find_seq3, "find_seq3");
SafeArrayDestroy(out_req); SafeArrayDestroy(offsets); @@ -8834,27 +8825,24 @@ static void test_UiaFind(void) AutomationElementMode_Full); set_find_params(&find_params, 0, FALSE, FALSE, (struct UiaCondition *)&UiaTrueCondition); hr = UiaFind(node2, &find_params, &cache_req, &out_req, &offsets, &tree_structs); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - todo_wine ok(Provider_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child2.ref); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(Provider_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child2.ref);
- if (SUCCEEDED(hr)) - { - add_provider_desc(&exp_node_desc[0], L"Main", L"Provider_child", TRUE); - add_provider_desc(&exp_node_desc[1], L"Main", L"Provider_child2", TRUE); - exp_lbound[0] = exp_lbound[1] = 0; - exp_elems[0] = 2; - exp_elems[1] = 1; + add_provider_desc(&exp_node_desc[0], L"Main", L"Provider_child", TRUE); + add_provider_desc(&exp_node_desc[1], L"Main", L"Provider_child2", TRUE); + exp_lbound[0] = exp_lbound[1] = 0; + exp_elems[0] = 2; + exp_elems[1] = 1;
- test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc); + test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
- for (i = 0; i < exp_elems[0]; i++) - { - exp_offset[i] = i; - exp_tree_struct[i] = L"P)"; - } - test_find_sa_results(tree_structs, offsets, exp_elems[0], exp_tree_struct, exp_offset); - ok_method_sequence(find_seq5, "find_seq5"); + for (i = 0; i < exp_elems[0]; i++) + { + exp_offset[i] = i; + exp_tree_struct[i] = L"P)"; } + test_find_sa_results(tree_structs, offsets, exp_elems[0], exp_tree_struct, exp_offset); + ok_method_sequence(find_seq5, "find_seq5");
SafeArrayDestroy(out_req); SafeArrayDestroy(offsets); @@ -8874,24 +8862,21 @@ static void test_UiaFind(void) AutomationElementMode_Full); set_find_params(&find_params, 0, FALSE, FALSE, (struct UiaCondition *)&UiaTrueCondition); hr = UiaFind(node2, &find_params, &cache_req, &out_req, &offsets, &tree_structs); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
- if (SUCCEEDED(hr)) - { - add_provider_desc(&exp_node_desc[0], L"Main", L"Provider_child", TRUE); - exp_lbound[0] = exp_lbound[1] = 0; - exp_elems[0] = exp_elems[1] = 1; + add_provider_desc(&exp_node_desc[0], L"Main", L"Provider_child", TRUE); + 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); + test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
- for (i = 0; i < exp_elems[0]; i++) - { - exp_offset[i] = i; - exp_tree_struct[i] = L"P)"; - } - test_find_sa_results(tree_structs, offsets, exp_elems[0], exp_tree_struct, exp_offset); - ok_method_sequence(find_seq6, "find_seq6"); + for (i = 0; i < exp_elems[0]; i++) + { + exp_offset[i] = i; + exp_tree_struct[i] = L"P)"; } + test_find_sa_results(tree_structs, offsets, exp_elems[0], exp_tree_struct, exp_offset); + ok_method_sequence(find_seq6, "find_seq6");
SafeArrayDestroy(out_req); SafeArrayDestroy(offsets); @@ -8929,31 +8914,28 @@ static void test_UiaFind(void) AutomationElementMode_Full); set_find_params(&find_params, 1, FALSE, FALSE, (struct UiaCondition *)&prop_cond[1]); hr = UiaFind(node, &find_params, &cache_req, &out_req, &offsets, &tree_structs); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - todo_wine ok(Provider_child_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child_child.ref); - todo_wine ok(Provider_child_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child_child2.ref); - todo_wine ok(Provider_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child2.ref); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(Provider_child_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child_child.ref); + ok(Provider_child_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child_child2.ref); + ok(Provider_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child2.ref);
- if (SUCCEEDED(hr)) - { - add_provider_desc(&exp_node_desc[0], L"Main", L"Provider", TRUE); - add_provider_desc(&exp_node_desc[1], L"Main", L"Provider_child_child", TRUE); - add_provider_desc(&exp_node_desc[2], L"Main", L"Provider_child_child2", TRUE); - add_provider_desc(&exp_node_desc[3], L"Main", L"Provider_child2", TRUE); - exp_lbound[0] = exp_lbound[1] = 0; - exp_elems[0] = 4; - exp_elems[1] = 1; + add_provider_desc(&exp_node_desc[0], L"Main", L"Provider", TRUE); + add_provider_desc(&exp_node_desc[1], L"Main", L"Provider_child_child", TRUE); + add_provider_desc(&exp_node_desc[2], L"Main", L"Provider_child_child2", TRUE); + add_provider_desc(&exp_node_desc[3], L"Main", L"Provider_child2", TRUE); + exp_lbound[0] = exp_lbound[1] = 0; + exp_elems[0] = 4; + exp_elems[1] = 1;
- test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc); + test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
- for (i = 0; i < exp_elems[0]; i++) - { - exp_offset[i] = i; - exp_tree_struct[i] = L"P)"; - } - test_find_sa_results(tree_structs, offsets, exp_elems[0], exp_tree_struct, exp_offset); - ok_method_sequence(find_seq7, "find_seq7"); + for (i = 0; i < exp_elems[0]; i++) + { + exp_offset[i] = i; + exp_tree_struct[i] = L"P)"; } + test_find_sa_results(tree_structs, offsets, exp_elems[0], exp_tree_struct, exp_offset); + ok_method_sequence(find_seq7, "find_seq7");
SafeArrayDestroy(out_req); SafeArrayDestroy(offsets); @@ -8985,41 +8967,38 @@ static void test_UiaFind(void) AutomationElementMode_Full); set_find_params(&find_params, 1, FALSE, FALSE, (struct UiaCondition *)&prop_cond[1]); hr = UiaFind(node, &find_params, &cache_req, &out_req, &offsets, &tree_structs); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - todo_wine ok(Provider_child_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child_child.ref); - todo_wine ok(Provider_child_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child_child2.ref); - todo_wine ok(Provider_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child2.ref); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(Provider_child_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child_child.ref); + ok(Provider_child_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child_child2.ref); + ok(Provider_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child2.ref);
- if (SUCCEEDED(hr)) - { - add_provider_desc(&exp_node_desc[0], L"Main", L"Provider", TRUE); - add_provider_desc(&exp_node_desc[1], L"Main", L"Provider_child_child", TRUE); - add_provider_desc(&exp_node_desc[2], L"Main", L"Provider_child_child2", TRUE); - add_provider_desc(&exp_node_desc[3], L"Main", L"Provider_child2", TRUE); - exp_lbound[0] = exp_lbound[1] = 0; - exp_elems[0] = 4; - exp_elems[1] = 1; + add_provider_desc(&exp_node_desc[0], L"Main", L"Provider", TRUE); + add_provider_desc(&exp_node_desc[1], L"Main", L"Provider_child_child", TRUE); + add_provider_desc(&exp_node_desc[2], L"Main", L"Provider_child_child2", TRUE); + add_provider_desc(&exp_node_desc[3], L"Main", L"Provider_child2", TRUE); + exp_lbound[0] = exp_lbound[1] = 0; + exp_elems[0] = 4; + exp_elems[1] = 1;
- idx[0] = 2; - idx[1] = 0; - hr = SafeArrayGetElement(out_req, idx, &v); - ok(hr == S_OK, "Unexpected hr %#lx\n", hr); + idx[0] = 2; + idx[1] = 0; + hr = SafeArrayGetElement(out_req, idx, &v); + ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
- /* node2 is now set as Provider_child_child2. */ - hr = UiaHUiaNodeFromVariant(&v, &node2); - ok(hr == S_OK, "Unexpected hr %#lx\n", hr); - IUnknown_AddRef((IUnknown *)node2); + /* node2 is now set as Provider_child_child2. */ + hr = UiaHUiaNodeFromVariant(&v, &node2); + ok(hr == S_OK, "Unexpected hr %#lx\n", hr); + IUnknown_AddRef((IUnknown *)node2);
- test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc); + test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
- for (i = 0; i < exp_elems[0]; i++) - { - exp_offset[i] = i; - exp_tree_struct[i] = L"P)"; - } - test_find_sa_results(tree_structs, offsets, exp_elems[0], exp_tree_struct, exp_offset); - ok_method_sequence(find_seq8, "find_seq8"); + for (i = 0; i < exp_elems[0]; i++) + { + exp_offset[i] = i; + exp_tree_struct[i] = L"P)"; } + test_find_sa_results(tree_structs, offsets, exp_elems[0], exp_tree_struct, exp_offset); + ok_method_sequence(find_seq8, "find_seq8");
SafeArrayDestroy(out_req); SafeArrayDestroy(offsets); @@ -9056,29 +9035,26 @@ static void test_UiaFind(void) AutomationElementMode_Full); set_find_params(&find_params, 1, FALSE, FALSE, (struct UiaCondition *)&prop_cond[1]); hr = UiaFind(node2, &find_params, &cache_req, &out_req, &offsets, &tree_structs); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - todo_wine ok(Provider_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child2.ref); - todo_wine ok(Provider_child2_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child2_child.ref); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(Provider_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child2.ref); + ok(Provider_child2_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child2_child.ref);
- if (SUCCEEDED(hr)) - { - add_provider_desc(&exp_node_desc[0], L"Main", L"Provider_child_child2", TRUE); - add_provider_desc(&exp_node_desc[1], L"Main", L"Provider_child2", TRUE); - add_provider_desc(&exp_node_desc[2], L"Main", L"Provider_child2_child", TRUE); - exp_lbound[0] = exp_lbound[1] = 0; - exp_elems[0] = 3; - exp_elems[1] = 1; + add_provider_desc(&exp_node_desc[0], L"Main", L"Provider_child_child2", TRUE); + add_provider_desc(&exp_node_desc[1], L"Main", L"Provider_child2", TRUE); + add_provider_desc(&exp_node_desc[2], L"Main", L"Provider_child2_child", TRUE); + exp_lbound[0] = exp_lbound[1] = 0; + exp_elems[0] = 3; + exp_elems[1] = 1;
- test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc); + test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
- for (i = 0; i < exp_elems[0]; i++) - { - exp_offset[i] = i; - exp_tree_struct[i] = L"P)"; - } - test_find_sa_results(tree_structs, offsets, exp_elems[0], exp_tree_struct, exp_offset); - ok_method_sequence(find_seq9, "find_seq9"); + for (i = 0; i < exp_elems[0]; i++) + { + exp_offset[i] = i; + exp_tree_struct[i] = L"P)"; } + test_find_sa_results(tree_structs, offsets, exp_elems[0], exp_tree_struct, exp_offset); + ok_method_sequence(find_seq9, "find_seq9");
SafeArrayDestroy(out_req); SafeArrayDestroy(offsets); @@ -9088,7 +9064,7 @@ static void test_UiaFind(void) for (i = 0; i < ARRAY_SIZE(exp_node_desc); i++) init_node_provider_desc(&exp_node_desc[i], GetCurrentProcessId(), NULL);
- todo_wine ok(UiaNodeRelease(node2), "UiaNodeRelease returned FALSE\n"); + ok(UiaNodeRelease(node2), "UiaNodeRelease returned FALSE\n"); ok(Provider_child_child2.ref == 1, "Unexpected refcnt %ld\n", Provider_child_child2.ref);
/* @@ -9114,27 +9090,24 @@ static void test_UiaFind(void) AutomationElementMode_Full); set_find_params(&find_params, 1, FALSE, TRUE, (struct UiaCondition *)&prop_cond[1]); hr = UiaFind(node, &find_params, &cache_req, &out_req, &offsets, &tree_structs); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - todo_wine ok(Provider_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child2.ref); - - if (SUCCEEDED(hr)) - { - add_provider_desc(&exp_node_desc[0], L"Main", L"Provider_child2", TRUE); - exp_lbound[0] = exp_lbound[1] = 0; - exp_elems[0] = 1; - exp_elems[1] = 1; + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(Provider_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child2.ref);
- test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc); + add_provider_desc(&exp_node_desc[0], L"Main", L"Provider_child2", TRUE); + exp_lbound[0] = exp_lbound[1] = 0; + exp_elems[0] = 1; + exp_elems[1] = 1;
- for (i = 0; i < exp_elems[0]; i++) - { - exp_offset[i] = i; - exp_tree_struct[i] = L"P)"; - } - test_find_sa_results(tree_structs, offsets, exp_elems[0], exp_tree_struct, exp_offset); + test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
- ok_method_sequence(find_seq10, "find_seq10"); + for (i = 0; i < exp_elems[0]; i++) + { + exp_offset[i] = i; + exp_tree_struct[i] = L"P)"; } + test_find_sa_results(tree_structs, offsets, exp_elems[0], exp_tree_struct, exp_offset); + + ok_method_sequence(find_seq10, "find_seq10");
SafeArrayDestroy(out_req); SafeArrayDestroy(offsets); diff --git a/dlls/uiautomationcore/uia_client.c b/dlls/uiautomationcore/uia_client.c index 715d8b27fbd..130d8b9c3d8 100644 --- a/dlls/uiautomationcore/uia_client.c +++ b/dlls/uiautomationcore/uia_client.c @@ -86,25 +86,17 @@ static HRESULT add_node_to_node_array(struct uia_node_array *out_nodes, HUIANODE return S_OK; }
-static HRESULT get_safearray_bounds(SAFEARRAY *sa, LONG *lbound, LONG *elems) +static HRESULT get_safearray_dim_bounds(SAFEARRAY *sa, UINT dim, LONG *lbound, LONG *elems) { LONG ubound; HRESULT hr; - UINT dims;
*lbound = *elems = 0; - dims = SafeArrayGetDim(sa); - if (dims != 1) - { - WARN("Invalid dimensions %d for safearray.\n", dims); - return E_FAIL; - } - - hr = SafeArrayGetLBound(sa, 1, lbound); + hr = SafeArrayGetLBound(sa, dim, lbound); if (FAILED(hr)) return hr;
- hr = SafeArrayGetUBound(sa, 1, &ubound); + hr = SafeArrayGetUBound(sa, dim, &ubound); if (FAILED(hr)) return hr;
@@ -112,6 +104,21 @@ static HRESULT get_safearray_bounds(SAFEARRAY *sa, LONG *lbound, LONG *elems) return S_OK; }
+static HRESULT get_safearray_bounds(SAFEARRAY *sa, LONG *lbound, LONG *elems) +{ + UINT dims; + + *lbound = *elems = 0; + dims = SafeArrayGetDim(sa); + if (dims != 1) + { + WARN("Invalid dimensions %d for safearray.\n", dims); + return E_FAIL; + } + + return get_safearray_dim_bounds(sa, 1, lbound, elems); +} + int uia_compare_safearrays(SAFEARRAY *sa1, SAFEARRAY *sa2, int prop_type) { LONG i, idx, lbound[2], elems[2]; @@ -1006,7 +1013,7 @@ exit: */ static HRESULT traverse_uia_node_tree(HUIANODE huianode, struct UiaCondition *view_cond, struct UiaCondition *search_cond, struct UiaCondition *sibling_stop_cond, int traversal_opts, - BOOL at_root_level, BOOL exclude_root, BOOL *root_found, int max_depth, int *cur_depth, + BOOL at_root_level, BOOL exclude_root, BOOL *root_found, BOOL find_first, int max_depth, int *cur_depth, struct uia_node_array *out_nodes) { struct uia_node *node = unsafe_impl_from_IWineUiaNode((IWineUiaNode *)huianode); @@ -1038,8 +1045,11 @@ static HRESULT traverse_uia_node_tree(HUIANODE huianode, struct UiaCondition *vi if (FAILED(hr)) goto exit;
- hr = S_FALSE; - goto exit; + if (find_first) + { + hr = S_FALSE; + goto exit; + } } } *root_found = TRUE; @@ -1058,7 +1068,7 @@ static HRESULT traverse_uia_node_tree(HUIANODE huianode, struct UiaCondition *vi
if (SUCCEEDED(hr) && node2) hr = traverse_uia_node_tree(node2, view_cond, search_cond, sibling_stop_cond, traversal_opts, FALSE, - exclude_root, root_found, max_depth, cur_depth, out_nodes); + exclude_root, root_found, find_first, max_depth, cur_depth, out_nodes);
if (FAILED(hr) || hr == S_FALSE) goto exit; @@ -1083,7 +1093,7 @@ static HRESULT traverse_uia_node_tree(HUIANODE huianode, struct UiaCondition *vi
if (SUCCEEDED(hr) && node2) hr = traverse_uia_node_tree(node2, view_cond, search_cond, sibling_stop_cond, traversal_opts, at_root_level, - exclude_root, root_found, max_depth, cur_depth, out_nodes); + exclude_root, root_found, find_first, max_depth, cur_depth, out_nodes);
exit: UiaNodeRelease(huianode); @@ -2778,6 +2788,50 @@ HRESULT WINAPI UiaNavigate(HUIANODE huianode, enum NavigateDirection dir, struct return hr; }
+/* Combine multiple cache requests into a single SAFEARRAY. */ +static HRESULT uia_cache_request_combine(SAFEARRAY **reqs, int reqs_count, SAFEARRAY *out_req) +{ + LONG idx[2], lbound[2], elems[2], cur_offset; + int i, x, y; + HRESULT hr; + VARIANT v; + + for (i = cur_offset = 0; i < reqs_count; i++) + { + if (!reqs[i]) + continue; + + for (x = 0; x < 2; x++) + { + hr = get_safearray_dim_bounds(reqs[i], 1 + x, &lbound[x], &elems[x]); + if (FAILED(hr)) + return hr; + } + + for (x = 0; x < elems[0]; x++) + { + for (y = 0; y < elems[1]; y++) + { + idx[0] = x + lbound[0]; + idx[1] = y + lbound[1]; + hr = SafeArrayGetElement(reqs[i], idx, &v); + if (FAILED(hr)) + return hr; + + idx[0] = x + cur_offset; + idx[1] = y; + hr = SafeArrayPutElement(out_req, idx, &v); + if (FAILED(hr)) + return hr; + } + } + + cur_offset += elems[0]; + } + + return S_OK; +} + /*********************************************************************** * UiaFind (uiautomationcore.@) */ @@ -2786,14 +2840,15 @@ HRESULT WINAPI UiaFind(HUIANODE huianode, struct UiaFindParams *find_params, str { struct UiaPropertyCondition prop_cond = { ConditionType_Property, UIA_RuntimeIdPropertyId }; struct uia_node *node = unsafe_impl_from_IWineUiaNode((IWineUiaNode *)huianode); - SAFEARRAY *runtime_id, *req, *offsets, *tree_structs; + SAFEARRAY *runtime_id, *req, *offsets, *tree_structs, **tmp_reqs; struct UiaCondition *sibling_stop_cond; struct uia_node_array nodes = { 0 }; + LONG idx, lbound, elems, cur_offset; + SAFEARRAYBOUND sabound[2]; BOOL root_found = FALSE; - int cur_depth = 0; + int i, cur_depth = 0; BSTR tree_struct; HRESULT hr; - LONG idx;
TRACE("(%p, %p, %p, %p, %p, %p)\n", huianode, find_params, cache_req, out_req, out_offsets, out_tree_structs);
@@ -2801,12 +2856,7 @@ HRESULT WINAPI UiaFind(HUIANODE huianode, struct UiaFindParams *find_params, str return E_INVALIDARG;
*out_tree_structs = *out_offsets = *out_req = tree_structs = offsets = req = NULL; - - if (!find_params->FindFirst) - { - FIXME("Finding more than one HUIANODE is currently unimplemented.\n"); - return E_NOTIMPL; - } + tmp_reqs = NULL;
/* * If the initial node has a runtime ID, we'll use it as a stop @@ -2824,36 +2874,81 @@ HRESULT WINAPI UiaFind(HUIANODE huianode, struct UiaFindParams *find_params, str
IWineUiaNode_AddRef(&node->IWineUiaNode_iface); hr = traverse_uia_node_tree(huianode, cache_req->pViewCondition, find_params->pFindCondition, sibling_stop_cond, - TreeTraversalOptions_Default, TRUE, find_params->ExcludeRoot, &root_found, find_params->MaxDepth, - &cur_depth, &nodes); + TreeTraversalOptions_Default, TRUE, find_params->ExcludeRoot, &root_found, find_params->FindFirst, + find_params->MaxDepth, &cur_depth, &nodes); if (FAILED(hr) || !nodes.node_count) goto exit;
- if (!(offsets = SafeArrayCreateVector(VT_I4, 0, 1))) + if (!(offsets = SafeArrayCreateVector(VT_I4, 0, nodes.node_count))) { hr = E_FAIL; goto exit; }
- if (!(tree_structs = SafeArrayCreateVector(VT_BSTR, 0, 1))) + if (!(tree_structs = SafeArrayCreateVector(VT_BSTR, 0, nodes.node_count))) { hr = E_FAIL; goto exit; }
- hr = UiaGetUpdatedCache(nodes.nodes[0], cache_req, NormalizeState_None, NULL, &req, &tree_struct); - if (FAILED(hr)) + if (!(tmp_reqs = heap_alloc_zero(sizeof(*tmp_reqs) * nodes.node_count))) + { + hr = E_OUTOFMEMORY; goto exit; + }
- idx = 0; - hr = SafeArrayPutElement(tree_structs, &idx, tree_struct); - SysFreeString(tree_struct); - if (FAILED(hr)) - goto exit; + /* + * Get a count of how many total nodes we'll need to return, as well as + * set the tree structure strings and cache request offsets for our final + * combined SAFEARRAY. + */ + for (i = cur_offset = 0; i < nodes.node_count; i++) + { + hr = UiaGetUpdatedCache(nodes.nodes[i], cache_req, NormalizeState_None, NULL, &tmp_reqs[i], &tree_struct); + if (FAILED(hr)) + goto exit;
- hr = SafeArrayPutElement(offsets, &idx, &idx); - if (FAILED(hr)) - goto exit; + idx = i; + hr = SafeArrayPutElement(tree_structs, &idx, tree_struct); + SysFreeString(tree_struct); + if (FAILED(hr)) + goto exit; + + hr = SafeArrayPutElement(offsets, &idx, &cur_offset); + if (FAILED(hr)) + goto exit; + + if (!tmp_reqs[i]) + continue; + + hr = get_safearray_dim_bounds(tmp_reqs[i], 1, &lbound, &elems); + if (FAILED(hr)) + goto exit; + + cur_offset += elems; + } + + if (nodes.node_count == 1) + { + req = tmp_reqs[0]; + heap_free(tmp_reqs); + tmp_reqs = NULL; + } + else + { + sabound[0].lLbound = sabound[1].lLbound = 0; + sabound[0].cElements = cur_offset; + sabound[1].cElements = 1 + cache_req->cProperties + cache_req->cPatterns; + if (!(req = SafeArrayCreate(VT_VARIANT, 2, sabound))) + { + hr = E_FAIL; + goto exit; + } + + hr = uia_cache_request_combine(tmp_reqs, nodes.node_count, req); + if (FAILED(hr)) + goto exit; + }
*out_tree_structs = tree_structs; *out_offsets = offsets; @@ -2863,6 +2958,13 @@ exit: VariantClear(&prop_cond.Value); clear_node_array(&nodes);
+ if (tmp_reqs) + { + for (i = 0; i < nodes.node_count; i++) + SafeArrayDestroy(tmp_reqs[i]); + heap_free(tmp_reqs); + } + if (FAILED(hr)) { SafeArrayDestroy(tree_structs);