From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/uiautomationcore/tests/uiautomation.c | 82 +++++++++++ dlls/uiautomationcore/uia_com_client.c | 163 ++++++++++++++++++++- 2 files changed, 243 insertions(+), 2 deletions(-)
diff --git a/dlls/uiautomationcore/tests/uiautomation.c b/dlls/uiautomationcore/tests/uiautomation.c index ca2529d87af..61bd3006244 100644 --- a/dlls/uiautomationcore/tests/uiautomation.c +++ b/dlls/uiautomationcore/tests/uiautomation.c @@ -10093,11 +10093,16 @@ static void test_CUIAutomation_value_conversion(IUIAutomation *uia_iface) static void test_CUIAutomation_condition_ifaces(IUIAutomation *uia_iface) { IUIAutomationConditionInternal *internal_cond; + struct UiaPropertyCondition *prop_cond_struct; + IUIAutomationPropertyCondition *prop_cond; + enum PropertyConditionFlags prop_flags; IUIAutomationBoolCondition *bool_cond; struct UiaCondition *cond_struct; IUIAutomationCondition *cond; + PROPERTYID prop_id; BOOL tmp_b; HRESULT hr; + VARIANT v;
hr = IUIAutomation_CreateTrueCondition(uia_iface, NULL); ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr); @@ -10166,6 +10171,83 @@ static void test_CUIAutomation_condition_ifaces(IUIAutomation *uia_iface) ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ok(tmp_b == FALSE, "tmp_b != FALSE\n"); IUIAutomationBoolCondition_Release(bool_cond); + + /* + * IUIAutomationPropertyCondition tests. + */ + /* Invalid property ID. */ + cond = (void *)0xdeadbeef; + VariantInit(&v); + hr = IUIAutomation_CreatePropertyCondition(uia_iface, 0, v, &cond); + ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); + ok(!cond, "cond != NULL\n"); + + /* Invalid variant type for property ID. */ + cond = (void *)0xdeadbeef; + VariantInit(&v); + hr = IUIAutomation_CreatePropertyCondition(uia_iface, UIA_RuntimeIdPropertyId, v, &cond); + ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); + ok(!cond, "cond != NULL\n"); + + /* NULL Condition. */ + V_VT(&v) = VT_I4 | VT_ARRAY; + V_ARRAY(&v) = create_i4_safearray(); + hr = IUIAutomation_CreatePropertyCondition(uia_iface, UIA_RuntimeIdPropertyId, v, NULL); + ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr); + + /* Finally, create property condition interface. */ + cond = NULL; + hr = IUIAutomation_CreatePropertyCondition(uia_iface, UIA_RuntimeIdPropertyId, v, &cond); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(!!cond, "cond == NULL\n"); + + internal_cond = NULL; + hr = IUIAutomationCondition_QueryInterface(cond, &IID_IUIAutomationConditionInternal, (void **)&internal_cond); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(!!internal_cond, "internal_cond == NULL\n"); + + prop_cond_struct = NULL; + hr = IUIAutomationConditionInternal_get_condition_struct(internal_cond, (struct UiaCondition **)&prop_cond_struct); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(!!cond_struct, "prop_cond_struct == NULL\n"); + ok(prop_cond_struct->ConditionType == ConditionType_Property, "Unexpected ConditionType %#x.\n", + prop_cond_struct->ConditionType); + ok(prop_cond_struct->PropertyId == UIA_RuntimeIdPropertyId, "Unexpected PropertyId %d\n", + prop_cond_struct->PropertyId); + ok(V_VT(&prop_cond_struct->Value) == (VT_I4 | VT_ARRAY), "Unexpected vt %d\n", V_VT(&prop_cond_struct->Value)); + ok(prop_cond_struct->Flags == PropertyConditionFlags_None, "Unexpected Flags %#x\n", prop_cond_struct->Flags); + IUIAutomationConditionInternal_Release(internal_cond); + + hr = IUIAutomationCondition_QueryInterface(cond, &IID_IUIAutomationPropertyCondition, (void **)&prop_cond); + IUIAutomationCondition_Release(cond); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(!!prop_cond, "prop_cond == NULL\n"); + + hr = IUIAutomationPropertyCondition_get_PropertyId(prop_cond, NULL); + ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr); + + hr = IUIAutomationPropertyCondition_get_PropertyId(prop_cond, &prop_id); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(prop_id == UIA_RuntimeIdPropertyId, "Unexpected prop_id %d.\n", prop_id); + + hr = IUIAutomationPropertyCondition_get_PropertyValue(prop_cond, NULL); + ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr); + + VariantClear(&v); + hr = IUIAutomationPropertyCondition_get_PropertyValue(prop_cond, &v); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(V_VT(&v) == (VT_I4 | VT_ARRAY), "Unexpected vt %d.\n", V_VT(&v)); + ok(!!V_ARRAY(&v), "V_ARRAY(&v) == NULL\n"); + VariantClear(&v); + + hr = IUIAutomationPropertyCondition_get_PropertyConditionFlags(prop_cond, NULL); + ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr); + + hr = IUIAutomationPropertyCondition_get_PropertyConditionFlags(prop_cond, &prop_flags); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(prop_flags == PropertyConditionFlags_None, "Unexpected flags %#x.\n", prop_flags); + + IUIAutomationPropertyCondition_Release(prop_cond); }
struct uia_com_classes { diff --git a/dlls/uiautomationcore/uia_com_client.c b/dlls/uiautomationcore/uia_com_client.c index 71c356305e4..96ec9c60d6f 100644 --- a/dlls/uiautomationcore/uia_com_client.c +++ b/dlls/uiautomationcore/uia_com_client.c @@ -84,6 +84,164 @@ static void uia_condition_internal_init(struct uia_condition_internal *internal, internal->condition = condition; }
+/* + * IUIAutomationPropertyCondition interface. + */ +struct uia_property_condition { + IUIAutomationPropertyCondition IUIAutomationPropertyCondition_iface; + LONG ref; + + struct UiaPropertyCondition condition; + struct uia_condition_internal condition_internal; +}; + +static inline struct uia_property_condition *impl_from_IUIAutomationPropertyCondition(IUIAutomationPropertyCondition *iface) +{ + return CONTAINING_RECORD(iface, struct uia_property_condition, IUIAutomationPropertyCondition_iface); +} + +static HRESULT WINAPI uia_property_condition_QueryInterface(IUIAutomationPropertyCondition *iface, REFIID riid, void **ppv) +{ + struct uia_property_condition *uia_property_condition = impl_from_IUIAutomationPropertyCondition(iface); + + *ppv = NULL; + if (IsEqualIID(riid, &IID_IUIAutomationPropertyCondition) || IsEqualIID(riid, &IID_IUIAutomationCondition) || + IsEqualIID(riid, &IID_IUnknown)) + *ppv = iface; + else if (IsEqualIID(riid, &IID_IUIAutomationConditionInternal)) + *ppv = &uia_property_condition->condition_internal.IUIAutomationConditionInternal_iface; + else + return E_NOINTERFACE; + + IUIAutomationPropertyCondition_AddRef(iface); + return S_OK; +} + +static ULONG WINAPI uia_property_condition_AddRef(IUIAutomationPropertyCondition *iface) +{ + struct uia_property_condition *uia_property_condition = impl_from_IUIAutomationPropertyCondition(iface); + ULONG ref = InterlockedIncrement(&uia_property_condition->ref); + + TRACE("%p, refcount %ld\n", uia_property_condition, ref); + return ref; +} + +static ULONG WINAPI uia_property_condition_Release(IUIAutomationPropertyCondition *iface) +{ + struct uia_property_condition *uia_property_condition = impl_from_IUIAutomationPropertyCondition(iface); + ULONG ref = InterlockedDecrement(&uia_property_condition->ref); + + TRACE("%p, refcount %ld\n", uia_property_condition, ref); + + if (!ref) + { + VariantClear(&uia_property_condition->condition.Value); + heap_free(uia_property_condition); + } + + return ref; +} + +static HRESULT WINAPI uia_property_condition_get_PropertyId(IUIAutomationPropertyCondition *iface, PROPERTYID *prop_id) +{ + struct uia_property_condition *uia_property_condition = impl_from_IUIAutomationPropertyCondition(iface); + + TRACE("%p, %p\n", iface, prop_id); + + if (!prop_id) + return E_POINTER; + + *prop_id = uia_property_condition->condition.PropertyId; + + return S_OK; +} + +static HRESULT WINAPI uia_property_condition_get_PropertyValue(IUIAutomationPropertyCondition *iface, VARIANT *val) +{ + struct uia_property_condition *uia_property_condition = impl_from_IUIAutomationPropertyCondition(iface); + + TRACE("%p, %p\n", iface, val); + + if (!val) + return E_POINTER; + + VariantCopy(val, &uia_property_condition->condition.Value); + + return S_OK; +} + +static HRESULT WINAPI uia_property_condition_get_PropertyConditionFlags(IUIAutomationPropertyCondition *iface, + enum PropertyConditionFlags *flags) +{ + struct uia_property_condition *uia_property_condition = impl_from_IUIAutomationPropertyCondition(iface); + + TRACE("%p, %p\n", iface, flags); + + if (!flags) + return E_POINTER; + + *flags = uia_property_condition->condition.Flags; + + return S_OK; +} + +static const IUIAutomationPropertyConditionVtbl uia_property_condition_vtbl = { + uia_property_condition_QueryInterface, + uia_property_condition_AddRef, + uia_property_condition_Release, + uia_property_condition_get_PropertyId, + uia_property_condition_get_PropertyValue, + uia_property_condition_get_PropertyConditionFlags, +}; + +static HRESULT create_uia_property_condition_iface(IUIAutomationCondition **out_cond, PROPERTYID prop_id, VARIANT val, + enum PropertyConditionFlags prop_flags) +{ + const struct uia_prop_info *prop_info = uia_prop_info_from_id(prop_id); + struct uia_property_condition *uia_property_condition; + + if (!out_cond) + return E_POINTER; + + *out_cond = NULL; + if (!prop_info) + return E_INVALIDARG; + + switch (prop_info->type) + { + case UIAutomationType_Bool: + if (V_VT(&val) != VT_BOOL) + return E_INVALIDARG; + break; + + case UIAutomationType_IntArray: + if (V_VT(&val) != (VT_I4 | VT_ARRAY)) + return E_INVALIDARG; + break; + + default: + FIXME("Property condition evaluation for property type %#x unimplemented\n", prop_info->type); + return E_NOTIMPL; + } + + uia_property_condition = heap_alloc_zero(sizeof(*uia_property_condition)); + if (!uia_property_condition) + return E_OUTOFMEMORY; + + uia_property_condition->IUIAutomationPropertyCondition_iface.lpVtbl = &uia_property_condition_vtbl; + uia_property_condition->condition.ConditionType = ConditionType_Property; + uia_property_condition->condition.PropertyId = prop_id; + VariantCopy(&uia_property_condition->condition.Value, &val); + uia_property_condition->condition.Flags = prop_flags; + uia_property_condition->ref = 1; + uia_condition_internal_init(&uia_property_condition->condition_internal, + (struct UiaCondition *)&uia_property_condition->condition, + (IUIAutomationCondition *)&uia_property_condition->IUIAutomationPropertyCondition_iface); + + *out_cond = uia_property_condition->condition_internal.condition; + return S_OK; +} + /* * IUIAutomationBoolCondition interface. */ @@ -1391,8 +1549,9 @@ static HRESULT WINAPI uia_iface_CreateFalseCondition(IUIAutomation6 *iface, IUIA static HRESULT WINAPI uia_iface_CreatePropertyCondition(IUIAutomation6 *iface, PROPERTYID prop_id, VARIANT val, IUIAutomationCondition **out_condition) { - FIXME("%p, %d, %s, %p: stub\n", iface, prop_id, debugstr_variant(&val), out_condition); - return E_NOTIMPL; + TRACE("%p, %d, %s, %p\n", iface, prop_id, debugstr_variant(&val), out_condition); + + return create_uia_property_condition_iface(out_condition, prop_id, val, PropertyConditionFlags_None); }
static HRESULT WINAPI uia_iface_CreatePropertyConditionEx(IUIAutomation6 *iface, PROPERTYID prop_id, VARIANT val,