From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/uiautomationcore/tests/uiautomation.c | 90 +++++++++++++++++++++ dlls/uiautomationcore/uia_client.c | 37 +++++++++ dlls/uiautomationcore/uiautomationcore.spec | 2 +- include/uiautomationcoreapi.h | 1 + 4 files changed, 129 insertions(+), 1 deletion(-)
diff --git a/dlls/uiautomationcore/tests/uiautomation.c b/dlls/uiautomationcore/tests/uiautomation.c index 06309566990..9af859f1a7a 100644 --- a/dlls/uiautomationcore/tests/uiautomation.c +++ b/dlls/uiautomationcore/tests/uiautomation.c @@ -4835,6 +4835,95 @@ static void test_UiaGetRuntimeId(void) CoUninitialize(); }
+static LONG Object_ref = 1; +static HRESULT WINAPI Object_QueryInterface(IUnknown *iface, REFIID riid, void **ppv) +{ + *ppv = NULL; + if (IsEqualIID(riid, &IID_IUnknown)) + { + *ppv = iface; + IUnknown_AddRef(iface); + return S_OK; + } + + return E_NOINTERFACE; +} + +static ULONG WINAPI Object_AddRef(IUnknown *iface) +{ + return InterlockedIncrement(&Object_ref); +} + +static ULONG WINAPI Object_Release(IUnknown *iface) +{ + return InterlockedDecrement(&Object_ref); +} + +static IUnknownVtbl ObjectVtbl = { + Object_QueryInterface, + Object_AddRef, + Object_Release +}; + +static IUnknown Object = {&ObjectVtbl}; +static void test_UiaHUiaNodeFromVariant(void) +{ + HUIANODE node; + HRESULT hr; + VARIANT v; + + hr = UiaHUiaNodeFromVariant(NULL, &node); + ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); + + hr = UiaHUiaNodeFromVariant(&v, NULL); + ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); + + node = (void *)0xdeadbeef; + V_VT(&v) = VT_R8; + hr = UiaHUiaNodeFromVariant(&v, &node); + ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); + ok(!node, "node != NULL\n"); + + node = (void *)0xdeadbeef; + V_VT(&v) = VT_UNKNOWN; + V_UNKNOWN(&v) = &Object; + hr = UiaHUiaNodeFromVariant(&v, &node); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(node == (void *)&Object, "node != NULL\n"); + ok(Object_ref == 2, "Unexpected Object_ref %ld\n", Object_ref); + VariantClear(&v); + +#ifdef _WIN64 + node = (void *)0xdeadbeef; + V_VT(&v) = VT_I4; + V_I4(&v) = 0xbeefdead; + hr = UiaHUiaNodeFromVariant(&v, &node); + ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); + ok(!node, "node != NULL\n"); + + node = (void *)0xdeadbeef; + V_VT(&v) = VT_I8; + V_I8(&v) = 0xbeefdead; + hr = UiaHUiaNodeFromVariant(&v, &node); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(node == (void *)V_I8(&v), "node != V_I8\n"); +#else + node = (void *)0xdeadbeef; + V_VT(&v) = VT_I8; + V_I8(&v) = 0xbeefdead; + hr = UiaHUiaNodeFromVariant(&v, &node); + ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); + ok(!node, "node != NULL\n"); + + node = (void *)0xdeadbeef; + V_VT(&v) = VT_I4; + V_I4(&v) = 0xbeefdead; + hr = UiaHUiaNodeFromVariant(&v, &node); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(node == (void *)V_I4(&v), "node != V_I8\n"); +#endif +} + START_TEST(uiautomation) { HMODULE uia_dll = LoadLibraryA("uiautomationcore.dll"); @@ -4857,6 +4946,7 @@ START_TEST(uiautomation) test_UiaNodeFromProvider(); test_UiaGetPropertyValue(); test_UiaGetRuntimeId(); + test_UiaHUiaNodeFromVariant(); if (uia_dll) { pUiaProviderFromIAccessible = (void *)GetProcAddress(uia_dll, "UiaProviderFromIAccessible"); diff --git a/dlls/uiautomationcore/uia_client.c b/dlls/uiautomationcore/uia_client.c index f166ed20b53..0ff01eba5af 100644 --- a/dlls/uiautomationcore/uia_client.c +++ b/dlls/uiautomationcore/uia_client.c @@ -979,3 +979,40 @@ HRESULT WINAPI UiaGetRuntimeId(HUIANODE huianode, SAFEARRAY **runtime_id)
return S_OK; } + +/*********************************************************************** + * UiaHUiaNodeFromVariant (uiautomationcore.@) + */ +HRESULT WINAPI UiaHUiaNodeFromVariant(VARIANT *in_val, HUIANODE *huianode) +{ + const VARTYPE expected_vt = sizeof(void *) == 8 ? VT_I8 : VT_I4; + + TRACE("(%p, %p)\n", in_val, huianode); + + if (!in_val || !huianode) + return E_INVALIDARG; + + *huianode = NULL; + if ((V_VT(in_val) != expected_vt) && (V_VT(in_val) != VT_UNKNOWN)) + { + WARN("Invalid vt %d\n", V_VT(in_val)); + return E_INVALIDARG; + } + + if (V_VT(in_val) == VT_UNKNOWN) + { + if (V_UNKNOWN(in_val)) + IUnknown_AddRef(V_UNKNOWN(in_val)); + *huianode = (HUIANODE)V_UNKNOWN(in_val); + } + else + { +#ifdef _WIN64 + *huianode = (HUIANODE)V_I8(in_val); +#else + *huianode = (HUIANODE)V_I4(in_val); +#endif + } + + return S_OK; +} diff --git a/dlls/uiautomationcore/uiautomationcore.spec b/dlls/uiautomationcore/uiautomationcore.spec index 17e34ee259a..f4e745a644a 100644 --- a/dlls/uiautomationcore/uiautomationcore.spec +++ b/dlls/uiautomationcore/uiautomationcore.spec @@ -70,7 +70,7 @@ @ stub UiaGetUpdatedCache @ stub UiaHPatternObjectFromVariant @ stub UiaHTextRangeFromVariant -@ stub UiaHUiaNodeFromVariant +@ stdcall UiaHUiaNodeFromVariant(ptr ptr) @ stub UiaHasServerSideProvider @ stdcall UiaHostProviderFromHwnd(long ptr) #@ stub UiaIAccessibleFromProvider diff --git a/include/uiautomationcoreapi.h b/include/uiautomationcoreapi.h index 78cbca2e25b..946c8b0fadc 100644 --- a/include/uiautomationcoreapi.h +++ b/include/uiautomationcoreapi.h @@ -396,6 +396,7 @@ HRESULT WINAPI UiaGetPropertyValue(HUIANODE huianode, PROPERTYID prop_id, VARIAN HRESULT WINAPI UiaNodeFromProvider(IRawElementProviderSimple *elprov, HUIANODE *huianode); BOOL WINAPI UiaNodeRelease(HUIANODE huianode); HRESULT WINAPI UiaGetRuntimeId(HUIANODE huianode, SAFEARRAY **runtime_id); +HRESULT WINAPI UiaHUiaNodeFromVariant(VARIANT *in_val, HUIANODE *huianode);
#ifdef __cplusplus }