Module: wine Branch: master Commit: dc79cdc50a2db10c6cdba51ae278c0d6320bf215 URL: https://gitlab.winehq.org/wine/wine/-/commit/dc79cdc50a2db10c6cdba51ae278c0d...
Author: Connor McAdams cmcadams@codeweavers.com Date: Fri Feb 3 13:33:32 2023 -0500
uiautomationcore: Implement IUIAutomation::IntSafeArrayToNativeArray.
Signed-off-by: Connor McAdams cmcadams@codeweavers.com
---
dlls/uiautomationcore/tests/uiautomation.c | 36 ++++++++++++++++++++++++ dlls/uiautomationcore/uia_client.c | 2 +- dlls/uiautomationcore/uia_com_client.c | 44 ++++++++++++++++++++++++++++-- dlls/uiautomationcore/uia_private.h | 1 + 4 files changed, 80 insertions(+), 3 deletions(-)
diff --git a/dlls/uiautomationcore/tests/uiautomation.c b/dlls/uiautomationcore/tests/uiautomation.c index 872f2b5950b..d5cfccf729f 100644 --- a/dlls/uiautomationcore/tests/uiautomation.c +++ b/dlls/uiautomationcore/tests/uiautomation.c @@ -10014,6 +10014,41 @@ exit: UnregisterClassA("test_Element_GetPropertyValue class", NULL); }
+static void test_CUIAutomation_value_conversion(IUIAutomation *uia_iface) +{ + static const VARTYPE invalid_int_vts[] = { VT_I8, VT_INT }; + int *out_arr, out_arr_count, i; + SAFEARRAY *sa; + VARTYPE vt; + HRESULT hr; + + for (i = 0; i < ARRAY_SIZE(invalid_int_vts); i++) + { + vt = invalid_int_vts[i]; + sa = SafeArrayCreateVector(vt, 0, 2); + ok(!!sa, "sa == NULL\n"); + + out_arr_count = 0xdeadbeef; + out_arr = (int *)0xdeadbeef; + hr = IUIAutomation_IntSafeArrayToNativeArray(uia_iface, sa, &out_arr, &out_arr_count); + ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); + ok(!out_arr, "out_arr != NULL\n"); + ok(out_arr_count == 0xdeadbeef, "Unexpected out_arr_count %#x\n", out_arr_count); + SafeArrayDestroy(sa); + } + + /* Only accepts VT_I4 as an input array type. */ + sa = create_i4_safearray(); + hr = IUIAutomation_IntSafeArrayToNativeArray(uia_iface, sa, &out_arr, &out_arr_count); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(out_arr_count == ARRAY_SIZE(uia_i4_arr_prop_val), "Unexpected out_arr_count %#x\n", out_arr_count); + for (i = 0; i < ARRAY_SIZE(uia_i4_arr_prop_val); i++) + ok(out_arr[i] == uia_i4_arr_prop_val[i], "out_arr[%d]: Expected %ld, got %d\n", i, uia_i4_arr_prop_val[i], out_arr[i]); + + SafeArrayDestroy(sa); + CoTaskMemFree(out_arr); +} + struct uia_com_classes { const GUID *clsid; const GUID *iid; @@ -10077,6 +10112,7 @@ static void test_CUIAutomation(void) ok(hr == S_OK, "Failed to create IUIAutomation interface, hr %#lx\n", hr); ok(!!uia_iface, "uia_iface == NULL\n");
+ test_CUIAutomation_value_conversion(uia_iface); test_ElementFromHandle(uia_iface, has_cui8); test_Element_GetPropertyValue(uia_iface);
diff --git a/dlls/uiautomationcore/uia_client.c b/dlls/uiautomationcore/uia_client.c index ce2aeb21622..8d543bd4dc7 100644 --- a/dlls/uiautomationcore/uia_client.c +++ b/dlls/uiautomationcore/uia_client.c @@ -107,7 +107,7 @@ static HRESULT get_safearray_dim_bounds(SAFEARRAY *sa, UINT dim, LONG *lbound, L return S_OK; }
-static HRESULT get_safearray_bounds(SAFEARRAY *sa, LONG *lbound, LONG *elems) +HRESULT get_safearray_bounds(SAFEARRAY *sa, LONG *lbound, LONG *elems) { UINT dims;
diff --git a/dlls/uiautomationcore/uia_com_client.c b/dlls/uiautomationcore/uia_com_client.c index b6f308275bb..e78fc4ee416 100644 --- a/dlls/uiautomationcore/uia_com_client.c +++ b/dlls/uiautomationcore/uia_com_client.c @@ -1373,8 +1373,48 @@ static HRESULT WINAPI uia_iface_IntNativeArrayToSafeArray(IUIAutomation6 *iface, static HRESULT WINAPI uia_iface_IntSafeArrayToNativeArray(IUIAutomation6 *iface, SAFEARRAY *sa, int **out_arr, int *out_arr_count) { - FIXME("%p, %p, %p, %p: stub\n", iface, sa, out_arr, out_arr_count); - return E_NOTIMPL; + LONG lbound, elems; + int *arr, *sa_arr; + VARTYPE vt; + HRESULT hr; + + TRACE("%p, %p, %p, %p\n", iface, sa, out_arr, out_arr_count); + + if (!sa || !out_arr || !out_arr_count) + return E_INVALIDARG; + + *out_arr = NULL; + hr = SafeArrayGetVartype(sa, &vt); + if (FAILED(hr)) + return hr; + + if (vt != VT_I4) + return E_INVALIDARG; + + hr = get_safearray_bounds(sa, &lbound, &elems); + if (FAILED(hr)) + return hr; + + if (!(arr = CoTaskMemAlloc(elems * sizeof(*arr)))) + return E_OUTOFMEMORY; + + hr = SafeArrayAccessData(sa, (void **)&sa_arr); + if (FAILED(hr)) + goto exit; + + memcpy(arr, sa_arr, sizeof(*arr) * elems); + hr = SafeArrayUnaccessData(sa); + if (FAILED(hr)) + goto exit; + + *out_arr = arr; + *out_arr_count = elems; + +exit: + if (FAILED(hr)) + CoTaskMemFree(arr); + + return hr; }
static HRESULT WINAPI uia_iface_RectToVariant(IUIAutomation6 *iface, RECT rect, VARIANT *out_var) diff --git a/dlls/uiautomationcore/uia_private.h b/dlls/uiautomationcore/uia_private.h index 157ae3583f8..2c6e41eac6d 100644 --- a/dlls/uiautomationcore/uia_private.h +++ b/dlls/uiautomationcore/uia_private.h @@ -99,6 +99,7 @@ static inline void variant_init_bool(VARIANT *v, BOOL val) }
/* uia_client.c */ +HRESULT get_safearray_bounds(SAFEARRAY *sa, LONG *lbound, LONG *elems) 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,