From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- include/uiautomationcore.idl | 153 +++++++++++++++++++++++++++++++++++ 1 file changed, 153 insertions(+)
diff --git a/include/uiautomationcore.idl b/include/uiautomationcore.idl index c4aa258b5af..5f39ac6d076 100644 --- a/include/uiautomationcore.idl +++ b/include/uiautomationcore.idl @@ -182,4 +182,157 @@ library UIA HRESULT GetSelection([out, retval] SAFEARRAY(VARIANT) *pvarSelectedChildren); [propget] HRESULT DefaultAction([out, retval] BSTR *pszDefaultAction); } + + enum UIAutomationType { + UIAutomationType_Int = 0x01, + UIAutomationType_Bool = 0x02, + UIAutomationType_String = 0x03, + UIAutomationType_Double = 0x04, + UIAutomationType_Point = 0x05, + UIAutomationType_Rect = 0x06, + UIAutomationType_Element = 0x07, + + UIAutomationType_Array = 0x00010000, + UIAutomationType_Out = 0x00020000, + + UIAutomationType_IntArray = ( UIAutomationType_Int | UIAutomationType_Array ), + UIAutomationType_BoolArray = ( UIAutomationType_Bool | UIAutomationType_Array ), + UIAutomationType_StringArray = ( UIAutomationType_String | UIAutomationType_Array ), + UIAutomationType_DoubleArray = ( UIAutomationType_Double | UIAutomationType_Array ), + UIAutomationType_PointArray = ( UIAutomationType_Point | UIAutomationType_Array ), + UIAutomationType_RectArray = ( UIAutomationType_Rect | UIAutomationType_Array ), + UIAutomationType_ElementArray = ( UIAutomationType_Element | UIAutomationType_Array ), + + UIAutomationType_OutInt = ( UIAutomationType_Int | UIAutomationType_Out ), + UIAutomationType_OutBool = ( UIAutomationType_Bool | UIAutomationType_Out ), + UIAutomationType_OutString = ( UIAutomationType_String | UIAutomationType_Out ), + UIAutomationType_OutDouble = ( UIAutomationType_Double | UIAutomationType_Out ), + UIAutomationType_OutPoint = ( UIAutomationType_Point | UIAutomationType_Out ), + UIAutomationType_OutRect = ( UIAutomationType_Rect | UIAutomationType_Out ), + UIAutomationType_OutElement = ( UIAutomationType_Element | UIAutomationType_Out ), + + UIAutomationType_OutIntArray = ( UIAutomationType_Int | UIAutomationType_Array | UIAutomationType_Out ), + UIAutomationType_OutBoolArray = ( UIAutomationType_Bool | UIAutomationType_Array | UIAutomationType_Out ), + UIAutomationType_OutStringArray = ( UIAutomationType_String | UIAutomationType_Array | UIAutomationType_Out ), + UIAutomationType_OutDoubleArray = ( UIAutomationType_Double | UIAutomationType_Array | UIAutomationType_Out ), + UIAutomationType_OutPointArray = ( UIAutomationType_Point | UIAutomationType_Array | UIAutomationType_Out ), + UIAutomationType_OutRectArray = ( UIAutomationType_Rect | UIAutomationType_Array | UIAutomationType_Out ), + UIAutomationType_OutElementArray = ( UIAutomationType_Element | UIAutomationType_Array | UIAutomationType_Out ), + }; + +cpp_quote("DEFINE_ENUM_FLAG_OPERATORS(UIAutomationType)") + + struct UIAutomationParameter { + enum UIAutomationType type; + void *pData; + }; + + struct UIAutomationPropertyInfo { + GUID guid; + LPCWSTR pProgrammaticName; + enum UIAutomationType type; + }; + + struct UIAutomationEventInfo { + GUID guid; + LPCWSTR pProgrammaticName; + }; + + struct UIAutomationMethodInfo { + LPCWSTR pProgrammaticName; + BOOL doSetFocus; + UINT cInParameters; + UINT cOutParameters; + [size_is(cInParameters + cOutParameters)]enum UIAutomationType *pParameterTypes; + [size_is(cInParameters + cOutParameters)]LPCWSTR *pParameterNames; + }; + + [ + object, + uuid(c03a7fe4-9431-409f-bed8-ae7c2299bc8d), + pointer_default(unique), + oleautomation + ] + interface IUIAutomationPatternInstance : IUnknown + { + [local] HRESULT GetProperty( + [in] UINT index, + [in] BOOL cached, + [in] enum UIAutomationType type, + [out] void *pPtr); + + [local] HRESULT CallMethod( + [in] UINT index, + [in] const struct UIAutomationParameter *pParams, + [in] UINT cParams); + } + + [ + object, + uuid(d97022f3-a947-465e-8b2a-ac4315fa54e8), + pointer_default(unique), + oleautomation + ] + interface IUIAutomationPatternHandler : IUnknown + { + HRESULT CreateClientWrapper( + [in] IUIAutomationPatternInstance *pPatternInstance, + [out] IUnknown **pClientWrapper); + + [local] HRESULT Dispatch( + [in] IUnknown *pTarget, + [in] UINT index, + [in] const struct UIAutomationParameter *pParams, + [in] UINT cParams); + } + + struct UIAutomationPatternInfo { + GUID guid; + LPCWSTR pProgrammaticName; + GUID providerInterfaceId; + GUID clientInterfaceId; + UINT cProperties; + [size_is(cProperties)]struct UIAutomationPropertyInfo *pProperties; + UINT cMethods; + [size_is(cMethods)]struct UIAutomationMethodInfo *pMethods; + UINT cEvents; + [size_is(cEvents)]struct UIAutomationEventInfo *pEvents; + IUIAutomationPatternHandler *pPatternHandler; + }; + + [ + object, + uuid(8609c4ec-4a1a-4d88-a357-5a66e060e1cf), + pointer_default(unique), + oleautomation + ] + interface IUIAutomationRegistrar : IUnknown + { + HRESULT RegisterProperty( + [in] const struct UIAutomationPropertyInfo *property, + [out] PROPERTYID *propertyId); + + HRESULT RegisterEvent( + [in] const struct UIAutomationEventInfo *event, + [out] EVENTID *eventId); + + HRESULT RegisterPattern( + [in] const struct UIAutomationPatternInfo *pattern, + [out] PATTERNID *pPatternId, + [out] PROPERTYID *pPatternAvailablePropertyId, + [in] UINT propertyIdCount, + [out, size_is(propertyIdCount)] PROPERTYID *pPropertyIds, + [in] UINT eventIdCount, + [out, size_is(eventIdCount)] EVENTID *pEventIds); + }; + + [ + uuid(6e29fabf-9977-42d1-8d0e-ca7e61ad87e6), + version(1.0), + threading(both) + ] + coclass CUIAutomationRegistrar + { + [default] interface IUIAutomationRegistrar; + } }
From: Connor McAdams cmcadams@codeweavers.com
Add tests for UIA properties that correspond directly with the GetPropertyValue method on IRawElementProviderSimple.
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/uiautomationcore/tests/uiautomation.c | 572 ++++++++++++++++++++- 1 file changed, 566 insertions(+), 6 deletions(-)
diff --git a/dlls/uiautomationcore/tests/uiautomation.c b/dlls/uiautomationcore/tests/uiautomation.c index 677933765a9..d6ebad03e3a 100644 --- a/dlls/uiautomationcore/tests/uiautomation.c +++ b/dlls/uiautomationcore/tests/uiautomation.c @@ -1100,7 +1100,57 @@ static struct Provider IRawElementProviderFragment *parent; enum ProviderOptions prov_opts; HWND hwnd; -} Provider, Provider2, Provider_child; + BOOL ret_invalid_prop_type; +} Provider, Provider2, Provider_child, Provider_child2; + +static const WCHAR *uia_bstr_prop_str = L"uia-string"; +static const ULONG uia_i4_prop_val = 0xdeadbeef; +static const ULONG uia_i4_arr_prop_val[] = { 0xfeedbeef, 0xdeadcafe, 0xfefedede }; +static const double uia_r8_prop_val = 128.256f; +static const double uia_r8_arr_prop_val[] = { 2.4, 8.16, 32.64 }; +static const IRawElementProviderSimple *uia_unk_arr_prop_val[] = { &Provider_child.IRawElementProviderSimple_iface, + &Provider_child2.IRawElementProviderSimple_iface }; +static SAFEARRAY *create_i4_safearray(void) +{ + SAFEARRAY *sa; + LONG idx; + + if (!(sa = SafeArrayCreateVector(VT_I4, 0, ARRAY_SIZE(uia_i4_arr_prop_val)))) + return NULL; + + for (idx = 0; idx < ARRAY_SIZE(uia_i4_arr_prop_val); idx++) + SafeArrayPutElement(sa, &idx, (void *)&uia_i4_arr_prop_val[idx]); + + return sa; +} + +static SAFEARRAY *create_r8_safearray(void) +{ + SAFEARRAY *sa; + LONG idx; + + if (!(sa = SafeArrayCreateVector(VT_R8, 0, ARRAY_SIZE(uia_r8_arr_prop_val)))) + return NULL; + + for (idx = 0; idx < ARRAY_SIZE(uia_r8_arr_prop_val); idx++) + SafeArrayPutElement(sa, &idx, (void *)&uia_r8_arr_prop_val[idx]); + + return sa; +} + +static SAFEARRAY *create_unk_safearray(void) +{ + SAFEARRAY *sa; + LONG idx; + + if (!(sa = SafeArrayCreateVector(VT_UNKNOWN, 0, ARRAY_SIZE(uia_unk_arr_prop_val)))) + return NULL; + + for (idx = 0; idx < ARRAY_SIZE(uia_unk_arr_prop_val); idx++) + SafeArrayPutElement(sa, &idx, (void *)uia_unk_arr_prop_val[idx]); + + return sa; +}
enum { PROV_GET_PROVIDER_OPTIONS, @@ -1422,8 +1472,163 @@ HRESULT WINAPI ProviderSimple_GetPropertyValue(IRawElementProviderSimple *iface, switch (prop_id) { case UIA_NativeWindowHandlePropertyId: - V_VT(ret_val) = VT_I4; - V_I4(ret_val) = HandleToULong(This->hwnd); + if (This->ret_invalid_prop_type) + { + V_VT(ret_val) = VT_R8; + V_R8(ret_val) = uia_r8_prop_val; + } + else + { + V_VT(ret_val) = VT_I4; + V_I4(ret_val) = HandleToULong(This->hwnd); + } + break; + + case UIA_ProcessIdPropertyId: + case UIA_ControlTypePropertyId: + case UIA_CulturePropertyId: + case UIA_OrientationPropertyId: + case UIA_LiveSettingPropertyId: + case UIA_PositionInSetPropertyId: + case UIA_SizeOfSetPropertyId: + case UIA_LevelPropertyId: + case UIA_LandmarkTypePropertyId: + case UIA_FillColorPropertyId: + case UIA_FillTypePropertyId: + case UIA_VisualEffectsPropertyId: + case UIA_HeadingLevelPropertyId: + if (This->ret_invalid_prop_type) + { + V_VT(ret_val) = VT_R8; + V_R8(ret_val) = uia_r8_prop_val; + } + else + { + V_VT(ret_val) = VT_I4; + V_I4(ret_val) = uia_i4_prop_val; + } + break; + + case UIA_RotationPropertyId: + if (This->ret_invalid_prop_type) + { + V_VT(ret_val) = VT_I4; + V_I4(ret_val) = uia_i4_prop_val; + } + else + { + V_VT(ret_val) = VT_R8; + V_R8(ret_val) = uia_r8_prop_val; + } + break; + + case UIA_LocalizedControlTypePropertyId: + case UIA_NamePropertyId: + case UIA_AcceleratorKeyPropertyId: + case UIA_AccessKeyPropertyId: + case UIA_AutomationIdPropertyId: + case UIA_ClassNamePropertyId: + case UIA_HelpTextPropertyId: + case UIA_ItemTypePropertyId: + case UIA_FrameworkIdPropertyId: + case UIA_ItemStatusPropertyId: + case UIA_AriaRolePropertyId: + case UIA_AriaPropertiesPropertyId: + case UIA_LocalizedLandmarkTypePropertyId: + case UIA_FullDescriptionPropertyId: + if (This->ret_invalid_prop_type) + { + V_VT(ret_val) = VT_I4; + V_I4(ret_val) = uia_i4_prop_val; + } + else + { + V_VT(ret_val) = VT_BSTR; + V_BSTR(ret_val) = SysAllocString(uia_bstr_prop_str); + } + break; + + case UIA_HasKeyboardFocusPropertyId: + case UIA_IsKeyboardFocusablePropertyId: + case UIA_IsEnabledPropertyId: + case UIA_IsControlElementPropertyId: + case UIA_IsContentElementPropertyId: + case UIA_IsPasswordPropertyId: + case UIA_IsOffscreenPropertyId: + case UIA_IsRequiredForFormPropertyId: + case UIA_IsDataValidForFormPropertyId: + case UIA_OptimizeForVisualContentPropertyId: + case UIA_IsPeripheralPropertyId: + case UIA_IsDialogPropertyId: + if (This->ret_invalid_prop_type) + { + V_VT(ret_val) = VT_R8; + V_R8(ret_val) = uia_r8_prop_val; + } + else + { + V_VT(ret_val) = VT_BOOL; + V_BOOL(ret_val) = VARIANT_TRUE; + } + break; + + case UIA_AnnotationTypesPropertyId: + case UIA_OutlineColorPropertyId: + if (This->ret_invalid_prop_type) + { + V_VT(ret_val) = VT_ARRAY | VT_R8; + V_ARRAY(ret_val) = create_r8_safearray(); + } + else + { + V_VT(ret_val) = VT_ARRAY | VT_I4; + V_ARRAY(ret_val) = create_i4_safearray(); + } + break; + + case UIA_OutlineThicknessPropertyId: + case UIA_SizePropertyId: + if (This->ret_invalid_prop_type) + { + V_VT(ret_val) = VT_ARRAY | VT_I4; + V_ARRAY(ret_val) = create_i4_safearray(); + } + else + { + V_VT(ret_val) = VT_ARRAY | VT_R8; + V_ARRAY(ret_val) = create_r8_safearray(); + } + break; + + case UIA_LabeledByPropertyId: + if (This->ret_invalid_prop_type) + { + V_VT(ret_val) = VT_I4; + V_I4(ret_val) = uia_i4_prop_val; + } + else + { + V_VT(ret_val) = VT_UNKNOWN; + V_UNKNOWN(ret_val) = (IUnknown *)&Provider_child.IRawElementProviderSimple_iface; + IUnknown_AddRef(V_UNKNOWN(ret_val)); + } + break; + + case UIA_AnnotationObjectsPropertyId: + case UIA_DescribedByPropertyId: + case UIA_FlowsFromPropertyId: + case UIA_FlowsToPropertyId: + case UIA_ControllerForPropertyId: + if (This->ret_invalid_prop_type) + { + V_VT(ret_val) = VT_ARRAY | VT_I4; + V_ARRAY(ret_val) = create_i4_safearray(); + } + else + { + V_VT(ret_val) = VT_UNKNOWN | VT_ARRAY; + V_ARRAY(ret_val) = create_unk_safearray(); + } break;
case UIA_ProviderDescriptionPropertyId: @@ -1563,7 +1768,7 @@ static struct Provider Provider = 1, "Provider", NULL, - 0, 0, + 0, 0, 0, };
static struct Provider Provider2 = @@ -1573,7 +1778,7 @@ static struct Provider Provider2 = 1, "Provider2", NULL, - 0, 0, + 0, 0, 0, };
static struct Provider Provider_child = @@ -1583,7 +1788,17 @@ static struct Provider Provider_child = 1, "Provider_child", &Provider.IRawElementProviderFragment_iface, - 0, 0, + ProviderOptions_ServerSideProvider, 0, 0, +}; + +static struct Provider Provider_child2 = +{ + { &ProviderSimpleVtbl }, + { &ProviderFragmentVtbl }, + 1, + "Provider_child2", + &Provider.IRawElementProviderFragment_iface, + ProviderOptions_ServerSideProvider, 0, 0, };
static IAccessible *acc_client; @@ -3532,6 +3747,18 @@ static const struct prov_method_sequence node_from_prov7[] = { { 0 } };
+static const struct prov_method_sequence node_from_prov8[] = { + { &Provider, PROV_GET_PROVIDER_OPTIONS }, + /* Win10v1507 and below call this. */ + { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */ + { &Provider, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_TODO }, + { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_NativeWindowHandlePropertyId */ + { &Provider, FRAG_NAVIGATE, METHOD_TODO }, /* NavigateDirection_Parent */ + /* Only called on Windows versions past Win10v1507. */ + { &Provider, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, + { 0 } +}; + static void test_UiaNodeFromProvider(void) { WNDCLASSA cls; @@ -3792,6 +4019,338 @@ static void test_UiaNodeFromProvider(void) prov_root = NULL; }
+/* Sequence for types other than UIAutomationType_Element. */ +static const struct prov_method_sequence get_prop_seq[] = { + { &Provider, PROV_GET_PROPERTY_VALUE }, + { 0 } +}; + +/* Sequence for getting a property that returns an invalid type. */ +static const struct prov_method_sequence get_prop_invalid_type_seq[] = { + { &Provider, PROV_GET_PROPERTY_VALUE }, + /* Windows 7 calls this. */ + { &Provider, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, + { 0 } +}; + +/* UIAutomationType_Element sequence. */ +static const struct prov_method_sequence get_elem_prop_seq[] = { + { &Provider, PROV_GET_PROPERTY_VALUE }, + { &Provider_child, PROV_GET_PROVIDER_OPTIONS }, + /* Win10v1507 and below call this. */ + { &Provider_child, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */ + { &Provider_child, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_TODO }, + { &Provider_child, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_NativeWindowHandlePropertyId */ + { &Provider_child, FRAG_NAVIGATE, METHOD_TODO }, /* NavigateDirection_Parent */ + /* Only called on Windows versions past Win10v1507. */ + { &Provider_child, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, + { &Provider_child, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, + { 0 } +}; + +/* UIAutomationType_ElementArray sequence. */ +static const struct prov_method_sequence get_elem_arr_prop_seq[] = { + { &Provider, PROV_GET_PROPERTY_VALUE }, + { &Provider_child, PROV_GET_PROVIDER_OPTIONS }, + /* Win10v1507 and below call this. */ + { &Provider_child, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */ + { &Provider_child, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_TODO }, + { &Provider_child, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_NativeWindowHandlePropertyId */ + { &Provider_child, FRAG_NAVIGATE, METHOD_TODO }, /* NavigateDirection_Parent */ + { &Provider_child, PROV_GET_PROVIDER_OPTIONS, METHOD_TODO }, + { &Provider_child2, PROV_GET_PROVIDER_OPTIONS }, + /* Win10v1507 and below call this. */ + { &Provider_child2, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */ + { &Provider_child2, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_TODO }, + { &Provider_child2, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_NativeWindowHandlePropertyId */ + { &Provider_child2, FRAG_NAVIGATE, METHOD_TODO }, /* NavigateDirection_Parent */ + { &Provider_child2, PROV_GET_PROVIDER_OPTIONS, METHOD_TODO }, + { &Provider_child, PROV_GET_PROPERTY_VALUE }, + { &Provider_child2, PROV_GET_PROPERTY_VALUE }, + { 0 } +}; + +static void check_uia_prop_val(PROPERTYID prop_id, enum UIAutomationType type, VARIANT *v) +{ + LONG idx; + + switch (type) + { + case UIAutomationType_String: + todo_wine ok(V_VT(v) == VT_BSTR, "Unexpected VT %d\n", V_VT(v)); + if (V_VT(v) != VT_BSTR) + break; + + ok(!lstrcmpW(V_BSTR(v), uia_bstr_prop_str), "Unexpected BSTR %s\n", wine_dbgstr_w(V_BSTR(v))); + ok_method_sequence(get_prop_seq, NULL); + break; + + case UIAutomationType_Bool: + todo_wine ok(V_VT(v) == VT_BOOL, "Unexpected VT %d\n", V_VT(v)); + if (V_VT(v) != VT_BOOL) + break; + + /* UIA_IsKeyboardFocusablePropertyId is broken on Win8 and Win10v1507. */ + if (prop_id == UIA_IsKeyboardFocusablePropertyId) + ok(check_variant_bool(v, TRUE) || broken(check_variant_bool(v, FALSE)), + "Unexpected BOOL %#x\n", V_BOOL(v)); + else + ok(check_variant_bool(v, TRUE), "Unexpected BOOL %#x\n", V_BOOL(v)); + ok_method_sequence(get_prop_seq, NULL); + break; + + case UIAutomationType_Int: + todo_wine ok(V_VT(v) == VT_I4, "Unexpected VT %d\n", V_VT(v)); + if (V_VT(v) != VT_I4) + break; + + if (prop_id == UIA_NativeWindowHandlePropertyId) + ok(ULongToHandle(V_I4(v)) == Provider.hwnd, "Unexpected I4 %#lx\n", V_I4(v)); + else + ok(V_I4(v) == uia_i4_prop_val, "Unexpected I4 %#lx\n", V_I4(v)); + ok_method_sequence(get_prop_seq, NULL); + break; + + case UIAutomationType_IntArray: + todo_wine ok(V_VT(v) == (VT_ARRAY | VT_I4), "Unexpected VT %d\n", V_VT(v)); + if (V_VT(v) != (VT_ARRAY | VT_I4)) + break; + + for (idx = 0; idx < ARRAY_SIZE(uia_i4_arr_prop_val); idx++) + { + ULONG val; + + SafeArrayGetElement(V_ARRAY(v), &idx, &val); + ok(val == uia_i4_arr_prop_val[idx], "Unexpected I4 %#lx at idx %ld\n", val, idx); + } + ok_method_sequence(get_prop_seq, NULL); + break; + + case UIAutomationType_Double: + todo_wine ok(V_VT(v) == VT_R8, "Unexpected VT %d\n", V_VT(v)); + if (V_VT(v) != VT_R8) + break; + + ok(V_R8(v) == uia_r8_prop_val, "Unexpected R8 %lf\n", V_R8(v)); + ok_method_sequence(get_prop_seq, NULL); + break; + + case UIAutomationType_DoubleArray: + todo_wine ok(V_VT(v) == (VT_ARRAY | VT_R8), "Unexpected VT %d\n", V_VT(v)); + if (V_VT(v) != (VT_ARRAY | VT_R8)) + break; + + for (idx = 0; idx < ARRAY_SIZE(uia_r8_arr_prop_val); idx++) + { + double val; + + SafeArrayGetElement(V_ARRAY(v), &idx, &val); + ok(val == uia_r8_arr_prop_val[idx], "Unexpected R8 %lf at idx %ld\n", val, idx); + } + ok_method_sequence(get_prop_seq, NULL); + break; + + case UIAutomationType_Element: + { + HUIANODE tmp_node; + HRESULT hr; + VARIANT v1; + +#ifdef _WIN64 + todo_wine ok(V_VT(v) == VT_I8, "Unexpected VT %d\n", V_VT(v)); + tmp_node = (HUIANODE)V_I8(v); + if (V_VT(v) != VT_I8) + break; +#else + todo_wine ok(V_VT(v) == VT_I4, "Unexpected VT %d\n", V_VT(v)); + tmp_node = (HUIANODE)V_I4(v); + if (V_VT(v) != VT_I4) + break; +#endif + ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref); + + hr = UiaGetPropertyValue(tmp_node, UIA_ControlTypePropertyId, &v1); + ok(hr == S_OK, "Unexpected hr %#lx\n", hr); + ok(V_VT(&v1) == VT_I4, "Unexpected VT %d\n", V_VT(&v1)); + ok(V_I4(&v1) == uia_i4_prop_val, "Unexpected I4 %#lx\n", V_I4(&v1)); + + ok(UiaNodeRelease(tmp_node), "Failed to release node\n"); + ok(Provider_child.ref == 1, "Unexpected refcnt %ld\n", Provider_child.ref); + ok_method_sequence(get_elem_prop_seq, NULL); + break; + } + + case UIAutomationType_ElementArray: + todo_wine ok(V_VT(v) == (VT_ARRAY | VT_UNKNOWN), "Unexpected VT %d\n", V_VT(v)); + if (V_VT(v) != (VT_ARRAY | VT_UNKNOWN)) + break; + + ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref); + ok(Provider_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child2.ref); + for (idx = 0; idx < ARRAY_SIZE(uia_unk_arr_prop_val); idx++) + { + HUIANODE tmp_node; + HRESULT hr; + VARIANT v1; + + SafeArrayGetElement(V_ARRAY(v), &idx, &tmp_node); + + hr = UiaGetPropertyValue(tmp_node, UIA_ControlTypePropertyId, &v1); + ok(hr == S_OK, "node[%ld] Unexpected hr %#lx\n", idx, hr); + ok(V_VT(&v1) == VT_I4, "node[%ld] Unexpected VT %d\n", idx, V_VT(&v1)); + ok(V_I4(&v1) == uia_i4_prop_val, "node[%ld] Unexpected I4 %#lx\n", idx, V_I4(&v1)); + + ok(UiaNodeRelease(tmp_node), "Failed to release node[%ld]\n", idx); + VariantClear(&v1); + } + + VariantClear(v); + ok(Provider_child.ref == 1, "Unexpected refcnt %ld\n", Provider_child.ref); + ok(Provider_child2.ref == 1, "Unexpected refcnt %ld\n", Provider_child2.ref); + ok_method_sequence(get_elem_arr_prop_seq, NULL); + break; + + default: + break; + } + + VariantClear(v); + V_VT(v) = VT_EMPTY; +} + +struct uia_element_property { + const GUID *prop_guid; + enum UIAutomationType type; + BOOL skip_invalid; +}; + +static const struct uia_element_property element_properties[] = { + { &ProcessId_Property_GUID, UIAutomationType_Int, TRUE }, + { &ControlType_Property_GUID, UIAutomationType_Int }, + { &LocalizedControlType_Property_GUID, UIAutomationType_String, TRUE }, + { &Name_Property_GUID, UIAutomationType_String }, + { &AcceleratorKey_Property_GUID, UIAutomationType_String }, + { &AccessKey_Property_GUID, UIAutomationType_String }, + { &HasKeyboardFocus_Property_GUID, UIAutomationType_Bool }, + { &IsKeyboardFocusable_Property_GUID, UIAutomationType_Bool }, + { &IsEnabled_Property_GUID, UIAutomationType_Bool }, + { &AutomationId_Property_GUID, UIAutomationType_String }, + { &ClassName_Property_GUID, UIAutomationType_String }, + { &HelpText_Property_GUID, UIAutomationType_String }, + { &Culture_Property_GUID, UIAutomationType_Int }, + { &IsControlElement_Property_GUID, UIAutomationType_Bool }, + { &IsContentElement_Property_GUID, UIAutomationType_Bool }, + { &LabeledBy_Property_GUID, UIAutomationType_Element }, + { &IsPassword_Property_GUID, UIAutomationType_Bool }, + { &NewNativeWindowHandle_Property_GUID, UIAutomationType_Int }, + { &ItemType_Property_GUID, UIAutomationType_String }, + { &IsOffscreen_Property_GUID, UIAutomationType_Bool }, + { &Orientation_Property_GUID, UIAutomationType_Int }, + { &FrameworkId_Property_GUID, UIAutomationType_String }, + { &IsRequiredForForm_Property_GUID, UIAutomationType_Bool }, + { &ItemStatus_Property_GUID, UIAutomationType_String }, + { &AriaRole_Property_GUID, UIAutomationType_String }, + { &AriaProperties_Property_GUID, UIAutomationType_String }, + { &IsDataValidForForm_Property_GUID, UIAutomationType_Bool }, + { &ControllerFor_Property_GUID, UIAutomationType_ElementArray }, + { &DescribedBy_Property_GUID, UIAutomationType_ElementArray }, + { &FlowsTo_Property_GUID, UIAutomationType_ElementArray }, + /* Implemented on Win8+ */ + { &OptimizeForVisualContent_Property_GUID, UIAutomationType_Bool }, + { &LiveSetting_Property_GUID, UIAutomationType_Int }, + { &FlowsFrom_Property_GUID, UIAutomationType_ElementArray }, + { &IsPeripheral_Property_GUID, UIAutomationType_Bool }, + /* Implemented on Win10v1507+. */ + { &PositionInSet_Property_GUID, UIAutomationType_Int }, + { &SizeOfSet_Property_GUID, UIAutomationType_Int }, + { &Level_Property_GUID, UIAutomationType_Int }, + { &AnnotationTypes_Property_GUID, UIAutomationType_IntArray }, + { &AnnotationObjects_Property_GUID, UIAutomationType_ElementArray }, + /* Implemented on Win10v1809+. */ + { &LandmarkType_Property_GUID, UIAutomationType_Int }, + { &LocalizedLandmarkType_Property_GUID, UIAutomationType_String, TRUE }, + { &FullDescription_Property_GUID, UIAutomationType_String }, + { &FillColor_Property_GUID, UIAutomationType_Int }, + { &OutlineColor_Property_GUID, UIAutomationType_IntArray }, + { &FillType_Property_GUID, UIAutomationType_Int }, + { &VisualEffects_Property_GUID, UIAutomationType_Int }, + { &OutlineThickness_Property_GUID, UIAutomationType_DoubleArray }, + { &Rotation_Property_GUID, UIAutomationType_Double }, + { &Size_Property_GUID, UIAutomationType_DoubleArray }, + { &HeadingLevel_Property_GUID, UIAutomationType_Int }, + { &IsDialog_Property_GUID, UIAutomationType_Bool }, +}; + +static void test_UiaGetPropertyValue(void) +{ + const struct uia_element_property *elem_prop; + IUnknown *unk_ns; + unsigned int i; + HUIANODE node; + int prop_id; + HRESULT hr; + VARIANT v; + + CoInitializeEx(NULL, COINIT_MULTITHREADED); + + Provider.prov_opts = ProviderOptions_ServerSideProvider; + Provider_child.prov_opts = Provider_child2.prov_opts = ProviderOptions_ServerSideProvider; + Provider.hwnd = Provider_child.hwnd = Provider_child2.hwnd = NULL; + node = (void *)0xdeadbeef; + hr = UiaNodeFromProvider(&Provider.IRawElementProviderSimple_iface, &node); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref); + ok_method_sequence(node_from_prov8, NULL); + + hr = UiaGetReservedNotSupportedValue(&unk_ns); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + for (i = 0; i < ARRAY_SIZE(element_properties); i++) + { + elem_prop = &element_properties[i]; + + Provider.ret_invalid_prop_type = FALSE; + VariantClear(&v); + prop_id = UiaLookupId(AutomationIdentifierType_Property, elem_prop->prop_guid); + if (!prop_id) + { + win_skip("No propertyId for GUID %s, skipping further tests.\n", debugstr_guid(elem_prop->prop_guid)); + break; + } + winetest_push_context("prop_id %d", prop_id); + hr = UiaGetPropertyValue(node, prop_id, &v); + todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + check_uia_prop_val(prop_id, elem_prop->type, &v); + + /* + * Some properties have special behavior if an invalid value is + * returned, skip them here. + */ + if (!elem_prop->skip_invalid) + { + Provider.ret_invalid_prop_type = TRUE; + hr = UiaGetPropertyValue(node, prop_id, &v); + todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + if (SUCCEEDED(hr)) + { + ok_method_sequence(get_prop_invalid_type_seq, NULL); + ok(V_VT(&v) == VT_UNKNOWN, "Unexpected vt %d\n", V_VT(&v)); + ok(V_UNKNOWN(&v) == unk_ns, "unexpected IUnknown %p\n", V_UNKNOWN(&v)); + VariantClear(&v); + } + } + + winetest_pop_context(); + } + + Provider.ret_invalid_prop_type = FALSE; + ok(UiaNodeRelease(node), "UiaNodeRelease returned FALSE\n"); + ok(Provider.ref == 1, "Unexpected refcnt %ld\n", Provider.ref); + + IUnknown_Release(unk_ns); + CoUninitialize(); +} + START_TEST(uiautomation) { HMODULE uia_dll = LoadLibraryA("uiautomationcore.dll"); @@ -3800,6 +4359,7 @@ START_TEST(uiautomation) test_uia_reserved_value_ifaces(); test_UiaLookupId(); test_UiaNodeFromProvider(); + test_UiaGetPropertyValue(); if (uia_dll) { pUiaProviderFromIAccessible = (void *)GetProcAddress(uia_dll, "UiaProviderFromIAccessible");
From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/uiautomationcore/uia_classes.idl | 17 +++ dlls/uiautomationcore/uia_client.c | 165 +++++++++++++++++++++++--- dlls/uiautomationcore/uia_ids.c | 45 +++++-- dlls/uiautomationcore/uia_main.c | 13 +- dlls/uiautomationcore/uia_private.h | 24 ++++ dlls/uiautomationcore/uia_provider.c | 4 +- 6 files changed, 230 insertions(+), 38 deletions(-) create mode 100644 dlls/uiautomationcore/uia_private.h
diff --git a/dlls/uiautomationcore/uia_classes.idl b/dlls/uiautomationcore/uia_classes.idl index e654255a4d4..1ab09ebb9d0 100644 --- a/dlls/uiautomationcore/uia_classes.idl +++ b/dlls/uiautomationcore/uia_classes.idl @@ -20,6 +20,22 @@
import "oaidl.idl";
+struct uia_prop_info { + const GUID *guid; + int prop_id; + int type; +}; + +[ + object, + uuid(57865755-6c05-4522-98df-4ca658b768ef), + pointer_default(unique), +] +interface IWineUiaProvider : IUnknown +{ + HRESULT get_prop_val([in]const struct uia_prop_info *prop_info, [out, retval]VARIANT *ret_val); +} + [ object, uuid(bccb6799-d831-4057-bd50-6425823ff1a3), @@ -27,4 +43,5 @@ import "oaidl.idl"; ] interface IWineUiaNode : IUnknown { + HRESULT get_provider([out, retval]IWineUiaProvider **out_prov); } diff --git a/dlls/uiautomationcore/uia_client.c b/dlls/uiautomationcore/uia_client.c index 58b9bc07a79..7e710a25642 100644 --- a/dlls/uiautomationcore/uia_client.c +++ b/dlls/uiautomationcore/uia_client.c @@ -16,11 +16,7 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */
-#define COBJMACROS - -#include "uiautomation.h" -#include "initguid.h" -#include "uia_classes.h" +#include "uia_private.h"
#include "wine/debug.h" #include "wine/heap.h" @@ -34,7 +30,7 @@ struct uia_node { IWineUiaNode IWineUiaNode_iface; LONG ref;
- IRawElementProviderSimple *elprov; + IWineUiaProvider *prov; };
static inline struct uia_node *impl_from_IWineUiaNode(IWineUiaNode *iface) @@ -71,17 +67,28 @@ static ULONG WINAPI uia_node_Release(IWineUiaNode *iface) TRACE("%p, refcount %ld\n", node, ref); if (!ref) { - IRawElementProviderSimple_Release(node->elprov); + IWineUiaProvider_Release(node->prov); heap_free(node); }
return ref; }
+static HRESULT WINAPI uia_node_get_provider(IWineUiaNode *iface, IWineUiaProvider **out_prov) +{ + struct uia_node *node = impl_from_IWineUiaNode(iface); + + *out_prov = node->prov; + IWineUiaProvider_AddRef(node->prov); + + return S_OK; +} + static const IWineUiaNodeVtbl uia_node_vtbl = { uia_node_QueryInterface, uia_node_AddRef, uia_node_Release, + uia_node_get_provider, };
static struct uia_node *unsafe_impl_from_IWineUiaNode(IWineUiaNode *iface) @@ -92,13 +99,103 @@ static struct uia_node *unsafe_impl_from_IWineUiaNode(IWineUiaNode *iface) return CONTAINING_RECORD(iface, struct uia_node, IWineUiaNode_iface); }
+/* + * IWineUiaProvider interface. + */ +struct uia_provider { + IWineUiaProvider IWineUiaProvider_iface; + LONG ref; + + IRawElementProviderSimple *elprov; +}; + +static inline struct uia_provider *impl_from_IWineUiaProvider(IWineUiaProvider *iface) +{ + return CONTAINING_RECORD(iface, struct uia_provider, IWineUiaProvider_iface); +} + +static HRESULT WINAPI uia_provider_QueryInterface(IWineUiaProvider *iface, REFIID riid, void **ppv) +{ + *ppv = NULL; + if (IsEqualIID(riid, &IID_IWineUiaProvider) || IsEqualIID(riid, &IID_IUnknown)) + *ppv = iface; + else + return E_NOINTERFACE; + + IWineUiaProvider_AddRef(iface); + return S_OK; +} + +static ULONG WINAPI uia_provider_AddRef(IWineUiaProvider *iface) +{ + struct uia_provider *prov = impl_from_IWineUiaProvider(iface); + ULONG ref = InterlockedIncrement(&prov->ref); + + TRACE("%p, refcount %ld\n", prov, ref); + return ref; +} + +static ULONG WINAPI uia_provider_Release(IWineUiaProvider *iface) +{ + struct uia_provider *prov = impl_from_IWineUiaProvider(iface); + ULONG ref = InterlockedDecrement(&prov->ref); + + TRACE("%p, refcount %ld\n", prov, ref); + if (!ref) + { + IRawElementProviderSimple_Release(prov->elprov); + heap_free(prov); + } + + return ref; +} + +static HRESULT WINAPI uia_provider_get_prop_val(IWineUiaProvider *iface, + const struct uia_prop_info *prop_info, VARIANT *ret_val) +{ + FIXME("%p, %p, %p: stub\n", iface, prop_info, ret_val); + return E_NOTIMPL; +} + +static const IWineUiaProviderVtbl uia_provider_vtbl = { + uia_provider_QueryInterface, + uia_provider_AddRef, + uia_provider_Release, + uia_provider_get_prop_val, +}; + +static HRESULT create_wine_uia_provider(struct uia_node *node, IRawElementProviderSimple *elprov) +{ + static const int supported_prov_opts = ProviderOptions_ServerSideProvider; + enum ProviderOptions prov_opts; + struct uia_provider *prov; + HRESULT hr; + + hr = IRawElementProviderSimple_get_ProviderOptions(elprov, &prov_opts); + if (FAILED(hr)) + return hr; + + if (prov_opts & ~supported_prov_opts) + FIXME("Ignoring unsupported ProviderOption(s) %#x\n", prov_opts & ~supported_prov_opts); + + prov = heap_alloc_zero(sizeof(*prov)); + if (!prov) + return E_OUTOFMEMORY; + + prov->IWineUiaProvider_iface.lpVtbl = &uia_provider_vtbl; + prov->elprov = elprov; + IRawElementProviderSimple_AddRef(elprov); + prov->ref = 1; + node->prov = &prov->IWineUiaProvider_iface; + + return S_OK; +} + /*********************************************************************** * UiaNodeFromProvider (uiautomationcore.@) */ HRESULT WINAPI UiaNodeFromProvider(IRawElementProviderSimple *elprov, HUIANODE *huianode) { - static const int supported_prov_opts = ProviderOptions_ServerSideProvider; - enum ProviderOptions prov_opts; struct uia_node *node; HRESULT hr;
@@ -113,19 +210,14 @@ HRESULT WINAPI UiaNodeFromProvider(IRawElementProviderSimple *elprov, HUIANODE * if (!node) return E_OUTOFMEMORY;
- hr = IRawElementProviderSimple_get_ProviderOptions(elprov, &prov_opts); + hr = create_wine_uia_provider(node, elprov); if (FAILED(hr)) { heap_free(node); return hr; }
- if (prov_opts & ~supported_prov_opts) - FIXME("Ignoring unsupported ProviderOption(s) %#x\n", prov_opts & ~supported_prov_opts); - node->IWineUiaNode_iface.lpVtbl = &uia_node_vtbl; - node->elprov = elprov; - IRawElementProviderSimple_AddRef(elprov); node->ref = 1;
*huianode = (void *)&node->IWineUiaNode_iface; @@ -148,3 +240,46 @@ BOOL WINAPI UiaNodeRelease(HUIANODE huianode) IWineUiaNode_Release(&node->IWineUiaNode_iface); return TRUE; } + +/*********************************************************************** + * UiaGetPropertyValue (uiautomationcore.@) + */ +HRESULT WINAPI UiaGetPropertyValue(HUIANODE huianode, PROPERTYID prop_id, VARIANT *out_val) +{ + struct uia_node *node = unsafe_impl_from_IWineUiaNode((IWineUiaNode *)huianode); + const struct uia_prop_info *prop_info; + IWineUiaProvider *prov; + HRESULT hr; + VARIANT v; + + TRACE("(%p, %d, %p)\n", huianode, prop_id, out_val); + + if (!node || !out_val) + return E_INVALIDARG; + + V_VT(out_val) = VT_UNKNOWN; + UiaGetReservedNotSupportedValue(&V_UNKNOWN(out_val)); + + prop_info = uia_prop_info_from_id(prop_id); + if (!prop_info) + return E_INVALIDARG; + + if (!prop_info->type) + { + FIXME("No type info for prop_id %d\n", prop_id); + return E_NOTIMPL; + } + + hr = IWineUiaNode_get_provider(&node->IWineUiaNode_iface, &prov); + if (FAILED(hr)) + return hr; + + VariantInit(&v); + hr = IWineUiaProvider_get_prop_val(prov, prop_info, &v); + if (SUCCEEDED(hr) && V_VT(&v) != VT_EMPTY) + *out_val = v; + + IWineUiaProvider_Release(prov); + + return S_OK; +} diff --git a/dlls/uiautomationcore/uia_ids.c b/dlls/uiautomationcore/uia_ids.c index b80289b3372..8c6f1386fba 100644 --- a/dlls/uiautomationcore/uia_ids.c +++ b/dlls/uiautomationcore/uia_ids.c @@ -16,20 +16,13 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */
-#define COBJMACROS - -#include "uiautomation.h" +#include "uia_private.h" #include "ocidl.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(uiautomation);
-struct uia_prop_info { - const GUID *guid; - int prop_id; -}; - static int __cdecl uia_property_guid_compare(const void *a, const void *b) { const GUID *guid = a; @@ -216,6 +209,34 @@ static const struct uia_prop_info default_uia_properties[] = { { &FullDescription_Property_GUID, UIA_FullDescriptionPropertyId, }, };
+static const int prop_id_idx[] = { + 0xaa, 0x8b, 0x76, 0xa3, 0x3d, 0x0e, 0x9f, 0x08, + 0x2e, 0x1e, 0x65, 0x00, 0x0a, 0x69, 0x2f, 0x1b, + 0x68, 0x86, 0x3a, 0x88, 0x30, 0x3b, 0x52, 0x54, + 0x01, 0x98, 0x14, 0x93, 0x04, 0x17, 0x58, 0x2d, + 0xa4, 0x37, 0x38, 0x03, 0x24, 0x8f, 0x4f, 0x06, + 0x7a, 0x45, 0x02, 0x84, 0x89, 0x55, 0x28, 0x75, + 0x48, 0x8a, 0x09, 0x19, 0x4a, 0x07, 0x9e, 0x77, + 0x15, 0x34, 0x74, 0x7f, 0x82, 0x16, 0x90, 0x5c, + 0x1f, 0x4c, 0x0f, 0xa8, 0x42, 0x26, 0x35, 0x61, + 0xac, 0x33, 0x18, 0x51, 0x81, 0x71, 0x9c, 0x50, + 0x59, 0x6a, 0x21, 0x92, 0x7d, 0x80, 0x44, 0x3c, + 0x83, 0x36, 0x96, 0x4d, 0x32, 0x8c, 0x0c, 0x7b, + 0x46, 0x43, 0x87, 0xa1, 0x1c, 0x73, 0x6d, 0x67, + 0x6b, 0x8e, 0x13, 0x6c, 0x85, 0x41, 0x94, 0x40, + 0x78, 0x3e, 0x72, 0x53, 0x4e, 0x23, 0x2b, 0x11, + 0x27, 0x2a, 0x62, 0x12, 0xa9, 0xad, 0x7e, 0x9b, + 0x29, 0x64, 0x2c, 0x99, 0x20, 0x70, 0x39, 0x6e, + 0xa0, 0x8d, 0xa7, 0x60, 0x49, 0x25, 0x5b, 0xa5, + 0x22, 0x0d, 0x0b, 0x5f, 0x3f, 0x4b, 0x5e, 0x9d, + 0x47, 0x31, 0x1d, 0x5d, 0x97, 0xa6, 0x66, 0xae, + 0x9a, 0x91, 0xa2, 0x56, 0x95, 0x05, 0x63, 0x10, + 0xab, 0x57, 0x6f, 0x1a, 0x7c, 0x5a, 0x79, +}; + +#define PROP_ID_MIN 30000 +#define PROP_ID_MAX (PROP_ID_MIN + ARRAY_SIZE(default_uia_properties)) + static const struct uia_prop_info *uia_prop_info_from_guid(const GUID *guid) { struct uia_prop_info *prop; @@ -227,6 +248,14 @@ static const struct uia_prop_info *uia_prop_info_from_guid(const GUID *guid) return NULL; }
+const struct uia_prop_info *uia_prop_info_from_id(PROPERTYID prop_id) +{ + if ((prop_id < PROP_ID_MIN) || (prop_id > PROP_ID_MAX)) + return NULL; + + return &default_uia_properties[prop_id_idx[prop_id - PROP_ID_MIN]]; +} + /*********************************************************************** * UiaLookupId (uiautomationcore.@) */ diff --git a/dlls/uiautomationcore/uia_main.c b/dlls/uiautomationcore/uia_main.c index c74d3edbf07..b48fb262cd0 100644 --- a/dlls/uiautomationcore/uia_main.c +++ b/dlls/uiautomationcore/uia_main.c @@ -16,10 +16,8 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */
-#define COBJMACROS - #include "initguid.h" -#include "uiautomation.h" +#include "uia_private.h" #include "ocidl.h"
#include "wine/debug.h" @@ -359,12 +357,3 @@ HRESULT WINAPI UiaDisconnectProvider(IRawElementProviderSimple *provider) FIXME("(%p): stub\n", provider); return E_NOTIMPL; } - -/*********************************************************************** - * UiaGetPropertyValue (uiautomationcore.@) - */ -HRESULT WINAPI UiaGetPropertyValue(HUIANODE huianode, PROPERTYID prop_id, VARIANT *out_val) -{ - FIXME("(%p, %d, %p): stub\n", huianode, prop_id, out_val); - return E_NOTIMPL; -} diff --git a/dlls/uiautomationcore/uia_private.h b/dlls/uiautomationcore/uia_private.h new file mode 100644 index 00000000000..40ea9db5cfc --- /dev/null +++ b/dlls/uiautomationcore/uia_private.h @@ -0,0 +1,24 @@ +/* + * Copyright 2022 Connor McAdams for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#define COBJMACROS + +#include "uiautomation.h" +#include "uia_classes.h" + +const struct uia_prop_info *uia_prop_info_from_id(PROPERTYID prop_id) DECLSPEC_HIDDEN; diff --git a/dlls/uiautomationcore/uia_provider.c b/dlls/uiautomationcore/uia_provider.c index 2a36dc9b39d..9c2dfd65989 100644 --- a/dlls/uiautomationcore/uia_provider.c +++ b/dlls/uiautomationcore/uia_provider.c @@ -16,9 +16,7 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */
-#define COBJMACROS - -#include "uiautomation.h" +#include "uia_private.h" #include "ocidl.h"
#include "wine/debug.h"
From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/uiautomationcore/tests/uiautomation.c | 18 ++++---- dlls/uiautomationcore/uia_client.c | 42 ++++++++++++++++++- dlls/uiautomationcore/uia_ids.c | 48 ++++++++++++++-------- 3 files changed, 82 insertions(+), 26 deletions(-)
diff --git a/dlls/uiautomationcore/tests/uiautomation.c b/dlls/uiautomationcore/tests/uiautomation.c index d6ebad03e3a..dfd9f9b38df 100644 --- a/dlls/uiautomationcore/tests/uiautomation.c +++ b/dlls/uiautomationcore/tests/uiautomation.c @@ -4100,9 +4100,7 @@ static void check_uia_prop_val(PROPERTYID prop_id, enum UIAutomationType type, V break;
case UIAutomationType_Int: - todo_wine ok(V_VT(v) == VT_I4, "Unexpected VT %d\n", V_VT(v)); - if (V_VT(v) != VT_I4) - break; + ok(V_VT(v) == VT_I4, "Unexpected VT %d\n", V_VT(v));
if (prop_id == UIA_NativeWindowHandlePropertyId) ok(ULongToHandle(V_I4(v)) == Provider.hwnd, "Unexpected I4 %#lx\n", V_I4(v)); @@ -4112,9 +4110,7 @@ static void check_uia_prop_val(PROPERTYID prop_id, enum UIAutomationType type, V break;
case UIAutomationType_IntArray: - todo_wine ok(V_VT(v) == (VT_ARRAY | VT_I4), "Unexpected VT %d\n", V_VT(v)); - if (V_VT(v) != (VT_ARRAY | VT_I4)) - break; + ok(V_VT(v) == (VT_ARRAY | VT_I4), "Unexpected VT %d\n", V_VT(v));
for (idx = 0; idx < ARRAY_SIZE(uia_i4_arr_prop_val); idx++) { @@ -4319,7 +4315,10 @@ static void test_UiaGetPropertyValue(void) } winetest_push_context("prop_id %d", prop_id); hr = UiaGetPropertyValue(node, prop_id, &v); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + if (hr == E_NOTIMPL) + todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + else + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); check_uia_prop_val(prop_id, elem_prop->type, &v);
/* @@ -4330,7 +4329,10 @@ static void test_UiaGetPropertyValue(void) { Provider.ret_invalid_prop_type = TRUE; hr = UiaGetPropertyValue(node, prop_id, &v); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + if (hr == E_NOTIMPL) + todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + else + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); if (SUCCEEDED(hr)) { ok_method_sequence(get_prop_invalid_type_seq, NULL); diff --git a/dlls/uiautomationcore/uia_client.c b/dlls/uiautomationcore/uia_client.c index 7e710a25642..eae532d7b6c 100644 --- a/dlls/uiautomationcore/uia_client.c +++ b/dlls/uiautomationcore/uia_client.c @@ -153,8 +153,46 @@ static ULONG WINAPI uia_provider_Release(IWineUiaProvider *iface) static HRESULT WINAPI uia_provider_get_prop_val(IWineUiaProvider *iface, const struct uia_prop_info *prop_info, VARIANT *ret_val) { - FIXME("%p, %p, %p: stub\n", iface, prop_info, ret_val); - return E_NOTIMPL; + struct uia_provider *prov = impl_from_IWineUiaProvider(iface); + HRESULT hr; + VARIANT v; + + TRACE("%p, %p, %p\n", iface, prop_info, ret_val); + + VariantInit(&v); + hr = IRawElementProviderSimple_GetPropertyValue(prov->elprov, prop_info->prop_id, &v); + if (FAILED(hr)) + goto exit; + + switch (prop_info->type) + { + case UIAutomationType_Int: + if (V_VT(&v) != VT_I4) + { + WARN("Invalid vt %d for UIAutomationType_Int\n", V_VT(&v)); + goto exit; + } + *ret_val = v; + break; + + case UIAutomationType_IntArray: + if (V_VT(&v) != (VT_I4 | VT_ARRAY)) + { + WARN("Invalid vt %d for UIAutomationType_IntArray\n", V_VT(&v)); + goto exit; + } + *ret_val = v; + break; + + default: + break; + } + +exit: + if (V_VT(ret_val) == VT_EMPTY) + VariantClear(&v); + + return S_OK; }
static const IWineUiaProviderVtbl uia_provider_vtbl = { diff --git a/dlls/uiautomationcore/uia_ids.c b/dlls/uiautomationcore/uia_ids.c index 8c6f1386fba..864925f0936 100644 --- a/dlls/uiautomationcore/uia_ids.c +++ b/dlls/uiautomationcore/uia_ids.c @@ -59,9 +59,11 @@ static const struct uia_prop_info default_uia_properties[] = { { &Window_CanMinimize_Property_GUID, UIA_WindowCanMinimizePropertyId, }, { &RangeValue_LargeChange_Property_GUID, UIA_RangeValueLargeChangePropertyId, }, { &Selection2_CurrentSelectedItem_Property_GUID, UIA_Selection2CurrentSelectedItemPropertyId, }, - { &Culture_Property_GUID, UIA_CulturePropertyId, }, + { &Culture_Property_GUID, UIA_CulturePropertyId, + UIAutomationType_Int, }, { &LegacyIAccessible_DefaultAction_Property_GUID, UIA_LegacyIAccessibleDefaultActionPropertyId, }, - { &Level_Property_GUID, UIA_LevelPropertyId, }, + { &Level_Property_GUID, UIA_LevelPropertyId, + UIAutomationType_Int, }, { &IsKeyboardFocusable_Property_GUID, UIA_IsKeyboardFocusablePropertyId, }, { &GridItem_Row_Property_GUID, UIA_GridItemRowPropertyId, }, { &IsSpreadsheetItemPatternAvailable_Property_GUID, UIA_IsSpreadsheetItemPatternAvailablePropertyId, }, @@ -80,8 +82,10 @@ static const struct uia_prop_info default_uia_properties[] = { { &IsInvokePatternAvailable_Property_GUID, UIA_IsInvokePatternAvailablePropertyId, }, { &HasKeyboardFocus_Property_GUID, UIA_HasKeyboardFocusPropertyId, }, { &ClickablePoint_Property_GUID, UIA_ClickablePointPropertyId, }, - { &NewNativeWindowHandle_Property_GUID, UIA_NativeWindowHandlePropertyId, }, - { &SizeOfSet_Property_GUID, UIA_SizeOfSetPropertyId, }, + { &NewNativeWindowHandle_Property_GUID, UIA_NativeWindowHandlePropertyId, + UIAutomationType_Int, }, + { &SizeOfSet_Property_GUID, UIA_SizeOfSetPropertyId, + UIAutomationType_Int, }, { &LegacyIAccessible_Name_Property_GUID, UIA_LegacyIAccessibleNamePropertyId, }, { &Window_CanMaximize_Property_GUID, UIA_WindowCanMaximizePropertyId, }, { &Scroll_HorizontallyScrollable_Property_GUID, UIA_ScrollHorizontallyScrollablePropertyId, }, @@ -103,7 +107,8 @@ static const struct uia_prop_info default_uia_properties[] = { { &Toggle_ToggleState_Property_GUID, UIA_ToggleToggleStatePropertyId, }, { &IsTogglePatternAvailable_Property_GUID, UIA_IsTogglePatternAvailablePropertyId, }, { &LegacyIAccessible_State_Property_GUID, UIA_LegacyIAccessibleStatePropertyId, }, - { &PositionInSet_Property_GUID, UIA_PositionInSetPropertyId, }, + { &PositionInSet_Property_GUID, UIA_PositionInSetPropertyId, + UIAutomationType_Int, }, { &RangeValue_IsReadOnly_Property_GUID, UIA_RangeValueIsReadOnlyPropertyId, }, { &Drag_DropEffects_Property_GUID, UIA_DragDropEffectsPropertyId, }, { &RangeValue_SmallChange_Property_GUID, UIA_RangeValueSmallChangePropertyId, }, @@ -116,16 +121,20 @@ static const struct uia_prop_info default_uia_properties[] = { { &Window_WindowVisualState_Property_GUID, UIA_WindowWindowVisualStatePropertyId, }, { &IsOffscreen_Property_GUID, UIA_IsOffscreenPropertyId, }, { &Annotation_Author_Property_GUID, UIA_AnnotationAuthorPropertyId, }, - { &Orientation_Property_GUID, UIA_OrientationPropertyId, }, + { &Orientation_Property_GUID, UIA_OrientationPropertyId, + UIAutomationType_Int, }, { &Value_Value_Property_GUID, UIA_ValueValuePropertyId, }, - { &VisualEffects_Property_GUID, UIA_VisualEffectsPropertyId, }, + { &VisualEffects_Property_GUID, UIA_VisualEffectsPropertyId, + UIAutomationType_Int, }, { &Selection2_FirstSelectedItem_Property_GUID, UIA_Selection2FirstSelectedItemPropertyId, }, { &IsGridPatternAvailable_Property_GUID, UIA_IsGridPatternAvailablePropertyId, }, { &SelectionItem_SelectionContainer_Property_GUID, UIA_SelectionItemSelectionContainerPropertyId, }, - { &HeadingLevel_Property_GUID, UIA_HeadingLevelPropertyId, }, + { &HeadingLevel_Property_GUID, UIA_HeadingLevelPropertyId, + UIAutomationType_Int, }, { &DropTarget_DropTargetEffect_Property_GUID, UIA_DropTargetDropTargetEffectPropertyId, }, { &Grid_ColumnCount_Property_GUID, UIA_GridColumnCountPropertyId, }, - { &AnnotationTypes_Property_GUID, UIA_AnnotationTypesPropertyId, }, + { &AnnotationTypes_Property_GUID, UIA_AnnotationTypesPropertyId, + UIAutomationType_IntArray, }, { &IsPeripheral_Property_GUID, UIA_IsPeripheralPropertyId, }, { &Transform2_ZoomMaximum_Property_GUID, UIA_Transform2ZoomMaximumPropertyId, }, { &Drag_DropEffect_Property_GUID, UIA_DragDropEffectPropertyId, }, @@ -142,7 +151,8 @@ static const struct uia_prop_info default_uia_properties[] = { { &ControllerFor_Property_GUID, UIA_ControllerForPropertyId, }, { &ProviderDescription_Property_GUID, UIA_ProviderDescriptionPropertyId, }, { &AriaProperties_Property_GUID, UIA_AriaPropertiesPropertyId, }, - { &LiveSetting_Property_GUID, UIA_LiveSettingPropertyId, }, + { &LiveSetting_Property_GUID, UIA_LiveSettingPropertyId, + UIAutomationType_Int, }, { &Selection2_LastSelectedItem_Property_GUID, UIA_Selection2LastSelectedItemPropertyId, }, { &Transform2_CanZoom_Property_GUID, UIA_Transform2CanZoomPropertyId, }, { &Window_IsModal_Property_GUID, UIA_WindowIsModalPropertyId, }, @@ -150,7 +160,8 @@ static const struct uia_prop_info default_uia_properties[] = { { &AriaRole_Property_GUID, UIA_AriaRolePropertyId, }, { &Scroll_VerticallyScrollable_Property_GUID, UIA_ScrollVerticallyScrollablePropertyId, }, { &RangeValue_Value_Property_GUID, UIA_RangeValueValuePropertyId, }, - { &ProcessId_Property_GUID, UIA_ProcessIdPropertyId, }, + { &ProcessId_Property_GUID, UIA_ProcessIdPropertyId, + UIAutomationType_Int, }, { &Scroll_VerticalScrollPercent_Property_GUID, UIA_ScrollVerticalScrollPercentPropertyId, }, { &IsObjectModelPatternAvailable_Property_GUID, UIA_IsObjectModelPatternAvailablePropertyId, }, { &IsDialog_Property_GUID, UIA_IsDialogPropertyId, }, @@ -177,7 +188,8 @@ static const struct uia_prop_info default_uia_properties[] = { { &DescribedBy_Property_GUID, UIA_DescribedByPropertyId, }, { &IsSelectionPatternAvailable_Property_GUID, UIA_IsSelectionPatternAvailablePropertyId, }, { &Grid_RowCount_Property_GUID, UIA_GridRowCountPropertyId, }, - { &OutlineColor_Property_GUID, UIA_OutlineColorPropertyId, }, + { &OutlineColor_Property_GUID, UIA_OutlineColorPropertyId, + UIAutomationType_IntArray, }, { &Table_RowOrColumnMajor_Property_GUID, UIA_TableRowOrColumnMajorPropertyId, }, { &IsDockPatternAvailable_Property_GUID, UIA_IsDockPatternAvailablePropertyId, }, { &IsSynchronizedInputPatternAvailable_Property_GUID,UIA_IsSynchronizedInputPatternAvailablePropertyId, }, @@ -186,7 +198,8 @@ static const struct uia_prop_info default_uia_properties[] = { { &AnnotationObjects_Property_GUID, UIA_AnnotationObjectsPropertyId, }, { &IsRequiredForForm_Property_GUID, UIA_IsRequiredForFormPropertyId, }, { &SpreadsheetItem_AnnotationTypes_Property_GUID, UIA_SpreadsheetItemAnnotationTypesPropertyId, }, - { &FillColor_Property_GUID, UIA_FillColorPropertyId, }, + { &FillColor_Property_GUID, UIA_FillColorPropertyId, + UIAutomationType_Int, }, { &IsStylesPatternAvailable_Property_GUID, UIA_IsStylesPatternAvailablePropertyId, }, { &Window_IsTopmost_Property_GUID, UIA_WindowIsTopmostPropertyId, }, { &IsCustomNavigationPatternAvailable_Property_GUID, UIA_IsCustomNavigationPatternAvailablePropertyId, }, @@ -194,11 +207,14 @@ static const struct uia_prop_info default_uia_properties[] = { { &AcceleratorKey_Property_GUID, UIA_AcceleratorKeyPropertyId, }, { &IsTextChildPatternAvailable_Property_GUID, UIA_IsTextChildPatternAvailablePropertyId, }, { &LegacyIAccessible_Selection_Property_GUID, UIA_LegacyIAccessibleSelectionPropertyId, }, - { &FillType_Property_GUID, UIA_FillTypePropertyId, }, - { &ControlType_Property_GUID, UIA_ControlTypePropertyId, }, + { &FillType_Property_GUID, UIA_FillTypePropertyId, + UIAutomationType_Int, }, + { &ControlType_Property_GUID, UIA_ControlTypePropertyId, + UIAutomationType_Int, }, { &IsMultipleViewPatternAvailable_Property_GUID, UIA_IsMultipleViewPatternAvailablePropertyId, }, { &DropTarget_DropTargetEffects_Property_GUID, UIA_DropTargetDropTargetEffectsPropertyId, }, - { &LandmarkType_Property_GUID, UIA_LandmarkTypePropertyId, }, + { &LandmarkType_Property_GUID, UIA_LandmarkTypePropertyId, + UIAutomationType_Int, }, { &Drag_IsGrabbed_Property_GUID, UIA_DragIsGrabbedPropertyId, }, { &GridItem_ColumnSpan_Property_GUID, UIA_GridItemColumnSpanPropertyId, }, { &Styles_Shape_Property_GUID, UIA_StylesShapePropertyId, },
From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/uiautomationcore/tests/uiautomation.c | 10 +- dlls/uiautomationcore/uia_client.c | 189 ++++++++++++++++++++- dlls/uiautomationcore/uia_ids.c | 18 +- 3 files changed, 203 insertions(+), 14 deletions(-)
diff --git a/dlls/uiautomationcore/tests/uiautomation.c b/dlls/uiautomationcore/tests/uiautomation.c index dfd9f9b38df..ed3dfbb543c 100644 --- a/dlls/uiautomationcore/tests/uiautomation.c +++ b/dlls/uiautomationcore/tests/uiautomation.c @@ -4153,15 +4153,11 @@ static void check_uia_prop_val(PROPERTYID prop_id, enum UIAutomationType type, V VARIANT v1;
#ifdef _WIN64 - todo_wine ok(V_VT(v) == VT_I8, "Unexpected VT %d\n", V_VT(v)); + ok(V_VT(v) == VT_I8, "Unexpected VT %d\n", V_VT(v)); tmp_node = (HUIANODE)V_I8(v); - if (V_VT(v) != VT_I8) - break; #else - todo_wine ok(V_VT(v) == VT_I4, "Unexpected VT %d\n", V_VT(v)); + ok(V_VT(v) == VT_I4, "Unexpected VT %d\n", V_VT(v)); tmp_node = (HUIANODE)V_I4(v); - if (V_VT(v) != VT_I4) - break; #endif ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref);
@@ -4177,7 +4173,7 @@ static void check_uia_prop_val(PROPERTYID prop_id, enum UIAutomationType type, V }
case UIAutomationType_ElementArray: - todo_wine ok(V_VT(v) == (VT_ARRAY | VT_UNKNOWN), "Unexpected VT %d\n", V_VT(v)); + ok(V_VT(v) == (VT_ARRAY | VT_UNKNOWN), "Unexpected VT %d\n", V_VT(v)); if (V_VT(v) != (VT_ARRAY | VT_UNKNOWN)) break;
diff --git a/dlls/uiautomationcore/uia_client.c b/dlls/uiautomationcore/uia_client.c index eae532d7b6c..1ce540a885a 100644 --- a/dlls/uiautomationcore/uia_client.c +++ b/dlls/uiautomationcore/uia_client.c @@ -23,6 +23,131 @@
WINE_DEFAULT_DEBUG_CHANNEL(uiautomation);
+static void clear_uia_node_ptr_safearray(SAFEARRAY *sa, LONG elems) +{ + HUIANODE node; + HRESULT hr; + LONG i; + + for (i = 0; i < elems; i++) + { + hr = SafeArrayGetElement(sa, &i, &node); + if (FAILED(hr)) + break; + UiaNodeRelease(node); + } +} + +static void create_uia_node_safearray(VARIANT *in, VARIANT *out) +{ + LONG i, idx, lbound, ubound, elems; + HUIANODE node; + SAFEARRAY *sa; + HRESULT hr; + UINT dims; + + dims = SafeArrayGetDim(V_ARRAY(in)); + if (!dims || (dims > 1)) + { + WARN("Invalid dimensions %d for element safearray.\n", dims); + return; + } + + hr = SafeArrayGetLBound(V_ARRAY(in), 1, &lbound); + if (FAILED(hr)) + return; + + hr = SafeArrayGetUBound(V_ARRAY(in), 1, &ubound); + if (FAILED(hr)) + return; + + elems = (ubound - lbound) + 1; + if (!(sa = SafeArrayCreateVector(VT_UINT_PTR, 0, elems))) + return; + + for (i = 0; i < elems; i++) + { + IRawElementProviderSimple *elprov; + IUnknown *unk; + + idx = lbound + i; + hr = SafeArrayGetElement(V_ARRAY(in), &idx, &unk); + if (FAILED(hr)) + break; + + hr = IUnknown_QueryInterface(unk, &IID_IRawElementProviderSimple, (void **)&elprov); + IUnknown_Release(unk); + if (FAILED(hr)) + break; + + hr = UiaNodeFromProvider(elprov, &node); + if (FAILED(hr)) + break; + + IRawElementProviderSimple_Release(elprov); + hr = SafeArrayPutElement(sa, &i, &node); + if (FAILED(hr)) + break; + } + + if (FAILED(hr)) + { + clear_uia_node_ptr_safearray(sa, elems); + SafeArrayDestroy(sa); + return; + } + + V_VT(out) = VT_UINT_PTR | VT_ARRAY; + V_ARRAY(out) = sa; +} + +/* Convert a VT_UINT_PTR SAFEARRAY to VT_UNKNOWN. */ +static void uia_node_ptr_to_unk_safearray(VARIANT *in) +{ + SAFEARRAY *sa = NULL; + LONG ubound, i; + HUIANODE node; + HRESULT hr; + + hr = SafeArrayGetUBound(V_ARRAY(in), 1, &ubound); + if (FAILED(hr)) + goto exit; + + if (!(sa = SafeArrayCreateVector(VT_UNKNOWN, 0, ubound + 1))) + { + hr = E_FAIL; + goto exit; + } + + for (i = 0; i < (ubound + 1); i++) + { + hr = SafeArrayGetElement(V_ARRAY(in), &i, &node); + if (FAILED(hr)) + break; + + hr = SafeArrayPutElement(sa, &i, node); + if (FAILED(hr)) + break; + + UiaNodeRelease(node); + } + +exit: + if (FAILED(hr)) + { + clear_uia_node_ptr_safearray(V_ARRAY(in), ubound + 1); + if (sa) + SafeArrayDestroy(sa); + } + + VariantClear(in); + if (SUCCEEDED(hr)) + { + V_VT(in) = VT_UNKNOWN | VT_ARRAY; + V_ARRAY(in) = sa; + } +} + /* * IWineUiaNode interface. */ @@ -150,6 +275,17 @@ static ULONG WINAPI uia_provider_Release(IWineUiaProvider *iface) return ref; }
+static void get_variant_for_node(HUIANODE node, VARIANT *v) +{ +#ifdef _WIN64 + V_VT(v) = VT_I8; + V_I8(v) = (UINT64)node; +#else + V_VT(v) = VT_I4; + V_I4(v) = (UINT32)node; +#endif +} + static HRESULT WINAPI uia_provider_get_prop_val(IWineUiaProvider *iface, const struct uia_prop_info *prop_info, VARIANT *ret_val) { @@ -184,6 +320,43 @@ static HRESULT WINAPI uia_provider_get_prop_val(IWineUiaProvider *iface, *ret_val = v; break;
+ case UIAutomationType_Element: + { + IRawElementProviderSimple *elprov; + HUIANODE node; + + if (V_VT(&v) != VT_UNKNOWN) + { + WARN("Invalid vt %d for UIAutomationType_Element\n", V_VT(&v)); + goto exit; + } + + hr = IUnknown_QueryInterface(V_UNKNOWN(&v), &IID_IRawElementProviderSimple, + (void **)&elprov); + if (FAILED(hr)) + goto exit; + + hr = UiaNodeFromProvider(elprov, &node); + if (SUCCEEDED(hr)) + { + get_variant_for_node(node, ret_val); + VariantClear(&v); + IRawElementProviderSimple_Release(elprov); + } + break; + } + + case UIAutomationType_ElementArray: + if (V_VT(&v) != (VT_UNKNOWN | VT_ARRAY)) + { + WARN("Invalid vt %d for UIAutomationType_ElementArray\n", V_VT(&v)); + goto exit; + } + create_uia_node_safearray(&v, ret_val); + if (V_VT(ret_val) == (VT_UINT_PTR | VT_ARRAY)) + VariantClear(&v); + break; + default: break; } @@ -315,7 +488,21 @@ HRESULT WINAPI UiaGetPropertyValue(HUIANODE huianode, PROPERTYID prop_id, VARIAN VariantInit(&v); hr = IWineUiaProvider_get_prop_val(prov, prop_info, &v); if (SUCCEEDED(hr) && V_VT(&v) != VT_EMPTY) - *out_val = v; + { + /* + * ElementArray types come back as an array of pointers to prevent the + * HUIANODEs from getting marshaled. We need to convert them to + * VT_UNKNOWN here. + */ + if (prop_info->type == UIAutomationType_ElementArray) + { + uia_node_ptr_to_unk_safearray(&v); + if (V_VT(&v) != VT_EMPTY) + *out_val = v; + } + else + *out_val = v; + }
IWineUiaProvider_Release(prov);
diff --git a/dlls/uiautomationcore/uia_ids.c b/dlls/uiautomationcore/uia_ids.c index 864925f0936..cab22f969c6 100644 --- a/dlls/uiautomationcore/uia_ids.c +++ b/dlls/uiautomationcore/uia_ids.c @@ -51,7 +51,8 @@ static const struct uia_prop_info default_uia_properties[] = { { &Size_Property_GUID, UIA_SizePropertyId, }, { &IsTextPattern2Available_Property_GUID, UIA_IsTextPattern2AvailablePropertyId, }, { &Styles_FillPatternStyle_Property_GUID, UIA_StylesFillPatternStylePropertyId, }, - { &FlowsTo_Property_GUID, UIA_FlowsToPropertyId, }, + { &FlowsTo_Property_GUID, UIA_FlowsToPropertyId, + UIAutomationType_ElementArray, }, { &ItemStatus_Property_GUID, UIA_ItemStatusPropertyId, }, { &Scroll_VerticalViewSize_Property_GUID, UIA_ScrollVerticalViewSizePropertyId, }, { &Selection_IsSelectionRequired_Property_GUID, UIA_SelectionIsSelectionRequiredPropertyId, }, @@ -94,12 +95,14 @@ static const struct uia_prop_info default_uia_properties[] = { { &IsRangeValuePatternAvailable_Property_GUID, UIA_IsRangeValuePatternAvailablePropertyId, }, { &IsScrollPatternAvailable_Property_GUID, UIA_IsScrollPatternAvailablePropertyId, }, { &IsTransformPattern2Available_Property_GUID, UIA_IsTransformPattern2AvailablePropertyId, }, - { &LabeledBy_Property_GUID, UIA_LabeledByPropertyId, }, + { &LabeledBy_Property_GUID, UIA_LabeledByPropertyId, + UIAutomationType_Element, }, { &ItemType_Property_GUID, UIA_ItemTypePropertyId, }, { &Transform_CanMove_Property_GUID, UIA_TransformCanMovePropertyId, }, { &LocalizedControlType_Property_GUID, UIA_LocalizedControlTypePropertyId, }, { &Annotation_AnnotationTypeId_Property_GUID, UIA_AnnotationAnnotationTypeIdPropertyId, }, - { &FlowsFrom_Property_GUID, UIA_FlowsFromPropertyId, }, + { &FlowsFrom_Property_GUID, UIA_FlowsFromPropertyId, + UIAutomationType_ElementArray, }, { &OptimizeForVisualContent_Property_GUID, UIA_OptimizeForVisualContentPropertyId, }, { &IsVirtualizedItemPatternAvailable_Property_GUID, UIA_IsVirtualizedItemPatternAvailablePropertyId, }, { &GridItem_Parent_Property_GUID, UIA_GridItemContainingGridPropertyId, }, @@ -148,7 +151,8 @@ static const struct uia_prop_info default_uia_properties[] = { { &IsControlElement_Property_GUID, UIA_IsControlElementPropertyId, }, { &HelpText_Property_GUID, UIA_HelpTextPropertyId, }, { &Table_RowHeaders_Property_GUID, UIA_TableRowHeadersPropertyId, }, - { &ControllerFor_Property_GUID, UIA_ControllerForPropertyId, }, + { &ControllerFor_Property_GUID, UIA_ControllerForPropertyId, + UIAutomationType_ElementArray, }, { &ProviderDescription_Property_GUID, UIA_ProviderDescriptionPropertyId, }, { &AriaProperties_Property_GUID, UIA_AriaPropertiesPropertyId, }, { &LiveSetting_Property_GUID, UIA_LiveSettingPropertyId, @@ -185,7 +189,8 @@ static const struct uia_prop_info default_uia_properties[] = { { &BoundingRectangle_Property_GUID, UIA_BoundingRectanglePropertyId, }, { &LegacyIAccessible_Value_Property_GUID, UIA_LegacyIAccessibleValuePropertyId, }, { &IsDragPatternAvailable_Property_GUID, UIA_IsDragPatternAvailablePropertyId, }, - { &DescribedBy_Property_GUID, UIA_DescribedByPropertyId, }, + { &DescribedBy_Property_GUID, UIA_DescribedByPropertyId, + UIAutomationType_ElementArray, }, { &IsSelectionPatternAvailable_Property_GUID, UIA_IsSelectionPatternAvailablePropertyId, }, { &Grid_RowCount_Property_GUID, UIA_GridRowCountPropertyId, }, { &OutlineColor_Property_GUID, UIA_OutlineColorPropertyId, @@ -195,7 +200,8 @@ static const struct uia_prop_info default_uia_properties[] = { { &IsSynchronizedInputPatternAvailable_Property_GUID,UIA_IsSynchronizedInputPatternAvailablePropertyId, }, { &OutlineThickness_Property_GUID, UIA_OutlineThicknessPropertyId, }, { &IsLegacyIAccessiblePatternAvailable_Property_GUID,UIA_IsLegacyIAccessiblePatternAvailablePropertyId, }, - { &AnnotationObjects_Property_GUID, UIA_AnnotationObjectsPropertyId, }, + { &AnnotationObjects_Property_GUID, UIA_AnnotationObjectsPropertyId, + UIAutomationType_ElementArray, }, { &IsRequiredForForm_Property_GUID, UIA_IsRequiredForFormPropertyId, }, { &SpreadsheetItem_AnnotationTypes_Property_GUID, UIA_SpreadsheetItemAnnotationTypesPropertyId, }, { &FillColor_Property_GUID, UIA_FillColorPropertyId,
From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/uiautomationcore/tests/uiautomation.c | 126 +++++++++++++++++++++ dlls/uiautomationcore/uia_classes.idl | 39 ++++--- dlls/uiautomationcore/uia_client.c | 83 +++++++++++++- dlls/uiautomationcore/uia_main.c | 4 +- 4 files changed, 233 insertions(+), 19 deletions(-)
diff --git a/dlls/uiautomationcore/tests/uiautomation.c b/dlls/uiautomationcore/tests/uiautomation.c index ed3dfbb543c..7dd598822a4 100644 --- a/dlls/uiautomationcore/tests/uiautomation.c +++ b/dlls/uiautomationcore/tests/uiautomation.c @@ -1101,6 +1101,7 @@ static struct Provider enum ProviderOptions prov_opts; HWND hwnd; BOOL ret_invalid_prop_type; + DWORD expected_tid; } Provider, Provider2, Provider_child, Provider_child2;
static const WCHAR *uia_bstr_prop_str = L"uia-string"; @@ -1443,6 +1444,8 @@ HRESULT WINAPI ProviderSimple_get_ProviderOptions(IRawElementProviderSimple *ifa struct Provider *This = impl_from_ProviderSimple(iface);
add_method_call(This, PROV_GET_PROVIDER_OPTIONS); + if (This->expected_tid) + ok(This->expected_tid == GetCurrentThreadId(), "Unexpected tid %ld\n", GetCurrentThreadId());
*ret_val = 0; if (This->prov_opts) @@ -1467,6 +1470,8 @@ HRESULT WINAPI ProviderSimple_GetPropertyValue(IRawElementProviderSimple *iface, struct Provider *This = impl_from_ProviderSimple(iface);
add_method_call(This, PROV_GET_PROPERTY_VALUE); + if (This->expected_tid) + ok(This->expected_tid == GetCurrentThreadId(), "Unexpected tid %ld\n", GetCurrentThreadId());
VariantInit(ret_val); switch (prop_id) @@ -1654,6 +1659,8 @@ HRESULT WINAPI ProviderSimple_get_HostRawElementProvider(IRawElementProviderSimp struct Provider *This = impl_from_ProviderSimple(iface);
add_method_call(This, PROV_GET_HOST_RAW_ELEMENT_PROVIDER); + if (This->expected_tid) + ok(This->expected_tid == GetCurrentThreadId(), "Unexpected tid %ld\n", GetCurrentThreadId());
*ret_val = NULL; if (This->hwnd) @@ -1702,6 +1709,8 @@ static HRESULT WINAPI ProviderFragment_Navigate(IRawElementProviderFragment *ifa struct Provider *This = impl_from_ProviderFragment(iface);
add_method_call(This, FRAG_NAVIGATE); + if (This->expected_tid) + ok(This->expected_tid == GetCurrentThreadId(), "Unexpected tid %ld\n", GetCurrentThreadId());
*ret_val = NULL; if ((direction == NavigateDirection_Parent) && This->parent) @@ -3759,6 +3768,108 @@ static const struct prov_method_sequence node_from_prov8[] = { { 0 } };
+static void check_uia_prop_val(PROPERTYID prop_id, enum UIAutomationType type, VARIANT *v); +static DWORD WINAPI uia_node_from_provider_test_com_thread(LPVOID param) +{ + HUIANODE node = param; + HRESULT hr; + VARIANT v; + + /* + * Since this is a node representing an IRawElementProviderSimple with + * ProviderOptions_UseComThreading set, it is only usable in threads that + * have initialized COM. + */ + hr = UiaGetPropertyValue(node, UIA_ProcessIdPropertyId, &v); + ok(hr == CO_E_NOTINITIALIZED, "Unexpected hr %#lx\n", hr); + + CoInitializeEx(NULL, COINIT_MULTITHREADED); + + hr = UiaGetPropertyValue(node, UIA_ProcessIdPropertyId, &v); + ok(hr == S_OK, "Unexpected hr %#lx\n", hr); + check_uia_prop_val(UIA_ProcessIdPropertyId, UIAutomationType_Int, &v); + + /* + * When retrieving a UIAutomationType_Element property, if UseComThreading + * is set, we'll get an HUIANODE that will make calls inside of the + * apartment of the node it is retrieved from. I.e, if we received a node + * with UseComThreading set from another node with UseComThreading set + * inside of an STA, the returned node will have all of its methods called + * from the STA thread. + */ + Provider_child.prov_opts = ProviderOptions_UseComThreading | ProviderOptions_ServerSideProvider; + Provider_child.expected_tid = Provider.expected_tid; + hr = UiaGetPropertyValue(node, UIA_LabeledByPropertyId, &v); + ok(hr == S_OK, "Unexpected hr %#lx\n", hr); + check_uia_prop_val(UIA_LabeledByPropertyId, UIAutomationType_Element, &v); + + /* Unset ProviderOptions_UseComThreading. */ + Provider_child.prov_opts = ProviderOptions_ServerSideProvider; + hr = UiaGetPropertyValue(node, UIA_LabeledByPropertyId, &v); + ok(hr == S_OK, "Unexpected hr %#lx\n", hr); + + /* + * ProviderOptions_UseComThreading not set, GetPropertyValue will be + * called on the current thread. + */ + Provider_child.expected_tid = GetCurrentThreadId(); + check_uia_prop_val(UIA_LabeledByPropertyId, UIAutomationType_Element, &v); + + CoUninitialize(); + + return 0; +} + +static void test_uia_node_from_prov_com_threading(void) +{ + HANDLE thread; + HUIANODE node; + HRESULT hr; + + /* Test ProviderOptions_UseComThreading. */ + Provider.hwnd = NULL; + prov_root = NULL; + Provider.prov_opts = ProviderOptions_ServerSideProvider | ProviderOptions_UseComThreading; + hr = UiaNodeFromProvider(&Provider.IRawElementProviderSimple_iface, &node); + ok_method_sequence(node_from_prov8, "node_from_prov8"); + + /* + * On Windows versions prior to Windows 10, UiaNodeFromProvider ignores the + * ProviderOptions_UseComThreading flag. + */ + if (hr == S_OK) + { + win_skip("Skipping ProviderOptions_UseComThreading tests for UiaNodeFromProvider.\n"); + UiaNodeRelease(node); + return; + } + ok(hr == CO_E_NOTINITIALIZED, "Unexpected hr %#lx.\n", hr); + + CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); + hr = UiaNodeFromProvider(&Provider.IRawElementProviderSimple_iface, &node); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref); + ok_method_sequence(node_from_prov8, "node_from_prov8"); + + Provider.expected_tid = GetCurrentThreadId(); + thread = CreateThread(NULL, 0, uia_node_from_provider_test_com_thread, (void *)node, 0, NULL); + while (MsgWaitForMultipleObjects(1, &thread, FALSE, INFINITE, QS_ALLINPUT) != WAIT_OBJECT_0) + { + MSG msg; + while(PeekMessageW(&msg, 0, 0, 0, PM_REMOVE)) + { + TranslateMessage(&msg); + DispatchMessageW(&msg); + } + } + CloseHandle(thread); + + ok(UiaNodeRelease(node), "UiaNodeRelease returned FALSE\n"); + ok(Provider.ref == 1, "Unexpected refcnt %ld\n", Provider.ref); + Provider_child.expected_tid = Provider.expected_tid = 0; + + CoUninitialize(); +} static void test_UiaNodeFromProvider(void) { WNDCLASSA cls; @@ -3784,6 +3895,9 @@ static void test_UiaNodeFromProvider(void) hwnd = CreateWindowA("UiaNodeFromProvider class", "Test window", WS_OVERLAPPEDWINDOW, 0, 0, 100, 100, NULL, NULL, NULL, NULL);
+ /* Run these tests early, we end up in an implicit MTA later. */ + test_uia_node_from_prov_com_threading(); + CoInitializeEx(NULL, COINIT_MULTITHREADED);
hr = UiaNodeFromProvider(NULL, &node); @@ -4352,6 +4466,18 @@ static void test_UiaGetPropertyValue(void) START_TEST(uiautomation) { HMODULE uia_dll = LoadLibraryA("uiautomationcore.dll"); + BOOL (WINAPI *pImmDisableIME)(DWORD); + HMODULE hModuleImm32; + + /* Make sure COM isn't initialized by imm32. */ + hModuleImm32 = LoadLibraryA("imm32.dll"); + if (hModuleImm32) { + pImmDisableIME = (void *)GetProcAddress(hModuleImm32, "ImmDisableIME"); + if (pImmDisableIME) + pImmDisableIME(0); + } + pImmDisableIME = NULL; + FreeLibrary(hModuleImm32);
test_UiaHostProviderFromHwnd(); test_uia_reserved_value_ifaces(); diff --git a/dlls/uiautomationcore/uia_classes.idl b/dlls/uiautomationcore/uia_classes.idl index 1ab09ebb9d0..8781c451f99 100644 --- a/dlls/uiautomationcore/uia_classes.idl +++ b/dlls/uiautomationcore/uia_classes.idl @@ -17,6 +17,7 @@ */
#pragma makedep header +#pragma makedep regtypelib
import "oaidl.idl";
@@ -27,21 +28,31 @@ struct uia_prop_info { };
[ - object, - uuid(57865755-6c05-4522-98df-4ca658b768ef), - pointer_default(unique), + version(1.0), + uuid(8a9ca8eb-856b-43d9-abd7-4a590054064f), ] -interface IWineUiaProvider : IUnknown +library UIA_wine_private { - HRESULT get_prop_val([in]const struct uia_prop_info *prop_info, [out, retval]VARIANT *ret_val); -} + importlib("stdole2.tlb");
-[ - object, - uuid(bccb6799-d831-4057-bd50-6425823ff1a3), - pointer_default(unique), -] -interface IWineUiaNode : IUnknown -{ - HRESULT get_provider([out, retval]IWineUiaProvider **out_prov); + [ + object, + uuid(57865755-6c05-4522-98df-4ca658b768ef), + pointer_default(unique), + oleautomation, + ] + interface IWineUiaProvider : IUnknown + { + HRESULT get_prop_val([in]const struct uia_prop_info *prop_info, [out, retval]VARIANT *ret_val); + } + + [ + object, + uuid(bccb6799-d831-4057-bd50-6425823ff1a3), + pointer_default(unique), + ] + interface IWineUiaNode : IUnknown + { + HRESULT get_provider([out, retval]IWineUiaProvider **out_prov); + } } diff --git a/dlls/uiautomationcore/uia_client.c b/dlls/uiautomationcore/uia_client.c index 1ce540a885a..ba15ed0c1f1 100644 --- a/dlls/uiautomationcore/uia_client.c +++ b/dlls/uiautomationcore/uia_client.c @@ -148,6 +148,18 @@ exit: } }
+static HRESULT get_global_interface_table(IGlobalInterfaceTable **git) +{ + HRESULT hr; + + hr = CoCreateInstance(&CLSID_StdGlobalInterfaceTable, NULL, + CLSCTX_INPROC_SERVER, &IID_IGlobalInterfaceTable, (void **)git); + if (FAILED(hr)) + WARN("Failed to get GlobalInterfaceTable, hr %#lx\n", hr); + + return hr; +} + /* * IWineUiaNode interface. */ @@ -156,6 +168,7 @@ struct uia_node { LONG ref;
IWineUiaProvider *prov; + DWORD git_cookie; };
static inline struct uia_node *impl_from_IWineUiaNode(IWineUiaNode *iface) @@ -192,6 +205,20 @@ static ULONG WINAPI uia_node_Release(IWineUiaNode *iface) TRACE("%p, refcount %ld\n", node, ref); if (!ref) { + if (node->git_cookie) + { + IGlobalInterfaceTable *git; + HRESULT hr; + + hr = get_global_interface_table(&git); + if (SUCCEEDED(hr)) + { + hr = IGlobalInterfaceTable_RevokeInterfaceFromGlobal(git, node->git_cookie); + if (FAILED(hr)) + WARN("Failed to get revoke provider interface from Global Interface Table, hr %#lx\n", hr); + } + } + IWineUiaProvider_Release(node->prov); heap_free(node); } @@ -203,8 +230,30 @@ static HRESULT WINAPI uia_node_get_provider(IWineUiaNode *iface, IWineUiaProvide { struct uia_node *node = impl_from_IWineUiaNode(iface);
- *out_prov = node->prov; - IWineUiaProvider_AddRef(node->prov); + if (node->git_cookie) + { + IGlobalInterfaceTable *git; + IWineUiaProvider *prov; + HRESULT hr; + + hr = get_global_interface_table(&git); + if (FAILED(hr)) + return hr; + + hr = IGlobalInterfaceTable_GetInterfaceFromGlobal(git, node->git_cookie, + &IID_IWineUiaProvider, (void **)&prov); + if (FAILED(hr)) + { + ERR("Failed to get provider interface from GlobalInterfaceTable, hr %#lx\n", hr); + return hr; + } + *out_prov = prov; + } + else + { + *out_prov = node->prov; + IWineUiaProvider_AddRef(node->prov); + }
return S_OK; } @@ -377,7 +426,7 @@ static const IWineUiaProviderVtbl uia_provider_vtbl = {
static HRESULT create_wine_uia_provider(struct uia_node *node, IRawElementProviderSimple *elprov) { - static const int supported_prov_opts = ProviderOptions_ServerSideProvider; + static const int supported_prov_opts = ProviderOptions_ServerSideProvider | ProviderOptions_UseComThreading; enum ProviderOptions prov_opts; struct uia_provider *prov; HRESULT hr; @@ -395,10 +444,36 @@ static HRESULT create_wine_uia_provider(struct uia_node *node, IRawElementProvid
prov->IWineUiaProvider_iface.lpVtbl = &uia_provider_vtbl; prov->elprov = elprov; - IRawElementProviderSimple_AddRef(elprov); prov->ref = 1; node->prov = &prov->IWineUiaProvider_iface;
+ /* + * If the UseComThreading ProviderOption is specified, all calls to the + * provided IRawElementProviderSimple need to respect the apartment type + * of the thread that creates the HUIANODE. i.e, if it's created in an + * STA, and the HUIANODE is used in an MTA, we need to provide a proxy. + */ + if (prov_opts & ProviderOptions_UseComThreading) + { + IGlobalInterfaceTable *git; + + hr = get_global_interface_table(&git); + if (FAILED(hr)) + { + heap_free(prov); + return hr; + } + + hr = IGlobalInterfaceTable_RegisterInterfaceInGlobal(git, (IUnknown *)&prov->IWineUiaProvider_iface, + &IID_IWineUiaProvider, &node->git_cookie); + if (FAILED(hr)) + { + heap_free(prov); + return hr; + } + } + + IRawElementProviderSimple_AddRef(elprov); return S_OK; }
diff --git a/dlls/uiautomationcore/uia_main.c b/dlls/uiautomationcore/uia_main.c index b48fb262cd0..3a6f10c1647 100644 --- a/dlls/uiautomationcore/uia_main.c +++ b/dlls/uiautomationcore/uia_main.c @@ -16,9 +16,11 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */
+#define COBJMACROS + +#include "combaseapi.h" #include "initguid.h" #include "uia_private.h" -#include "ocidl.h"
#include "wine/debug.h" #include "wine/heap.h"
On Wed Jul 20 00:07:45 2022 +0000, **** wrote:
Marvin replied on the mailing list:
Hi, It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated. The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=119322 Your paranoid android. === debian11 (32 bit report) === uiautomationcore: uiautomation.c:3850: Test failed: Unexpected hr 0x80004002. uiautomation.c:3851: Test failed: Unexpected refcnt 1 uiautomation.c:3784: Test failed: Unexpected hr 0x80070057 uiautomation.c:3789: Test failed: Unexpected hr 0x80070057 uiautomation.c:4217: Test failed: Unexpected VT 0 uiautomation.c:4222: Test failed: Unexpected I4 0 uiautomation.c:4223: Test failed: incomplete sequence: expected Provider_GetPropertyValue, got nothing uiautomation.c:3803: Test failed: Unexpected hr 0x80070057 uiautomation.c:4273: Test failed: Unexpected VT 0 uiautomation.c:4276: Test failed: Unexpected refcnt 1 uiautomation.c:4279: Test failed: Unexpected hr 0x80070057 uiautomation.c:4280: Test failed: Unexpected VT 272 uiautomation.c:4281: Test failed: Unexpected I4 0x23 uiautomation.c:4283: Test failed: Failed to release node uiautomation.c:4285: Test failed: incomplete sequence: expected Provider_GetPropertyValue, got nothing uiautomation.c:3809: Test failed: Unexpected hr 0x80070057 uiautomation.c:4273: Test failed: Unexpected VT 0 uiautomation.c:4276: Test failed: Unexpected refcnt 1 uiautomation.c:4279: Test failed: Unexpected hr 0x80070057 uiautomation.c:4280: Test failed: Unexpected VT 272 uiautomation.c:4281: Test failed: Unexpected I4 0x23 uiautomation.c:4283: Test failed: Failed to release node uiautomation.c:4285: Test failed: incomplete sequence: expected Provider_GetPropertyValue, got nothing uiautomation.c:3867: Test failed: UiaNodeRelease returned FALSE === debian11 (32 bit Arabic:Morocco report) === uiautomationcore: uiautomation.c:3850: Test failed: Unexpected hr 0x80004002. uiautomation.c:3851: Test failed: Unexpected refcnt 1 uiautomation.c:3784: Test failed: Unexpected hr 0x80070057 uiautomation.c:3789: Test failed: Unexpected hr 0x80070057 uiautomation.c:4217: Test failed: Unexpected VT 0 uiautomation.c:4222: Test failed: Unexpected I4 0 uiautomation.c:4223: Test failed: incomplete sequence: expected Provider_GetPropertyValue, got nothing uiautomation.c:3803: Test failed: Unexpected hr 0x80070057 uiautomation.c:4273: Test failed: Unexpected VT 0 uiautomation.c:4276: Test failed: Unexpected refcnt 1 uiautomation.c:4279: Test failed: Unexpected hr 0x80070057 uiautomation.c:4280: Test failed: Unexpected VT 272 uiautomation.c:4281: Test failed: Unexpected I4 0x23 uiautomation.c:4283: Test failed: Failed to release node uiautomation.c:4285: Test failed: incomplete sequence: expected Provider_GetPropertyValue, got nothing uiautomation.c:3809: Test failed: Unexpected hr 0x80070057 uiautomation.c:4273: Test failed: Unexpected VT 0 uiautomation.c:4276: Test failed: Unexpected refcnt 1 uiautomation.c:4279: Test failed: Unexpected hr 0x80070057 uiautomation.c:4280: Test failed: Unexpected VT 272 uiautomation.c:4281: Test failed: Unexpected I4 0x23 uiautomation.c:4283: Test failed: Failed to release node uiautomation.c:4285: Test failed: incomplete sequence: expected Provider_GetPropertyValue, got nothing uiautomation.c:3867: Test failed: UiaNodeRelease returned FALSE === debian11 (32 bit German report) === uiautomationcore: uiautomation.c:3850: Test failed: Unexpected hr 0x80004002. uiautomation.c:3851: Test failed: Unexpected refcnt 1 uiautomation.c:3784: Test failed: Unexpected hr 0x80070057 uiautomation.c:3789: Test failed: Unexpected hr 0x80070057 uiautomation.c:4217: Test failed: Unexpected VT 0 uiautomation.c:4222: Test failed: Unexpected I4 0 uiautomation.c:4223: Test failed: incomplete sequence: expected Provider_GetPropertyValue, got nothing uiautomation.c:3803: Test failed: Unexpected hr 0x80070057 uiautomation.c:4273: Test failed: Unexpected VT 0 uiautomation.c:4276: Test failed: Unexpected refcnt 1 uiautomation.c:4279: Test failed: Unexpected hr 0x80070057 uiautomation.c:4280: Test failed: Unexpected VT 272 uiautomation.c:4281: Test failed: Unexpected I4 0x23 uiautomation.c:4283: Test failed: Failed to release node uiautomation.c:4285: Test failed: incomplete sequence: expected Provider_GetPropertyValue, got nothing uiautomation.c:3809: Test failed: Unexpected hr 0x80070057 uiautomation.c:4273: Test failed: Unexpected VT 0 uiautomation.c:4276: Test failed: Unexpected refcnt 1 uiautomation.c:4279: Test failed: Unexpected hr 0x80070057 uiautomation.c:4280: Test failed: Unexpected VT 272 uiautomation.c:4281: Test failed: Unexpected I4 0x23 uiautomation.c:4283: Test failed: Failed to release node uiautomation.c:4285: Test failed: incomplete sequence: expected Provider_GetPropertyValue, got nothing uiautomation.c:3867: Test failed: UiaNodeRelease returned FALSE === debian11 (32 bit French report) === uiautomationcore: uiautomation.c:3850: Test failed: Unexpected hr 0x80004002. uiautomation.c:3851: Test failed: Unexpected refcnt 1 uiautomation.c:3784: Test failed: Unexpected hr 0x80070057 uiautomation.c:3789: Test failed: Unexpected hr 0x80070057 uiautomation.c:4217: Test failed: Unexpected VT 0 uiautomation.c:4222: Test failed: Unexpected I4 0 uiautomation.c:4223: Test failed: incomplete sequence: expected Provider_GetPropertyValue, got nothing uiautomation.c:3803: Test failed: Unexpected hr 0x80070057 uiautomation.c:4273: Test failed: Unexpected VT 0 uiautomation.c:4276: Test failed: Unexpected refcnt 1 uiautomation.c:4279: Test failed: Unexpected hr 0x80070057 uiautomation.c:4280: Test failed: Unexpected VT 272 uiautomation.c:4281: Test failed: Unexpected I4 0x23 uiautomation.c:4283: Test failed: Failed to release node uiautomation.c:4285: Test failed: incomplete sequence: expected Provider_GetPropertyValue, got nothing uiautomation.c:3809: Test failed: Unexpected hr 0x80070057 uiautomation.c:4273: Test failed: Unexpected VT 0 uiautomation.c:4276: Test failed: Unexpected refcnt 1 uiautomation.c:4279: Test failed: Unexpected hr 0x80070057 uiautomation.c:4280: Test failed: Unexpected VT 272 uiautomation.c:4281: Test failed: Unexpected I4 0x23 uiautomation.c:4283: Test failed: Failed to release node uiautomation.c:4285: Test failed: incomplete sequence: expected Provider_GetPropertyValue, got nothing uiautomation.c:3867: Test failed: UiaNodeRelease returned FALSE === debian11 (32 bit Hebrew:Israel report) === uiautomationcore: uiautomation.c:3850: Test failed: Unexpected hr 0x80004002. uiautomation.c:3851: Test failed: Unexpected refcnt 1 uiautomation.c:3784: Test failed: Unexpected hr 0x80070057 uiautomation.c:3789: Test failed: Unexpected hr 0x80070057 uiautomation.c:4217: Test failed: Unexpected VT 0 uiautomation.c:4222: Test failed: Unexpected I4 0 uiautomation.c:4223: Test failed: incomplete sequence: expected Provider_GetPropertyValue, got nothing uiautomation.c:3803: Test failed: Unexpected hr 0x80070057 uiautomation.c:4273: Test failed: Unexpected VT 0 uiautomation.c:4276: Test failed: Unexpected refcnt 1 uiautomation.c:4279: Test failed: Unexpected hr 0x80070057 uiautomation.c:4280: Test failed: Unexpected VT 272 uiautomation.c:4281: Test failed: Unexpected I4 0x23 uiautomation.c:4283: Test failed: Failed to release node uiautomation.c:4285: Test failed: incomplete sequence: expected Provider_GetPropertyValue, got nothing uiautomation.c:3809: Test failed: Unexpected hr 0x80070057 uiautomation.c:4273: Test failed: Unexpected VT 0 uiautomation.c:4276: Test failed: Unexpected refcnt 1 uiautomation.c:4279: Test failed: Unexpected hr 0x80070057 uiautomation.c:4280: Test failed: Unexpected VT 272 uiautomation.c:4281: Test failed: Unexpected I4 0x23 uiautomation.c:4283: Test failed: Failed to release node uiautomation.c:4285: Test failed: incomplete sequence: expected Provider_GetPropertyValue, got nothing uiautomation.c:3867: Test failed: UiaNodeRelease returned FALSE === debian11 (32 bit Hindi:India report) === uiautomationcore: uiautomation.c:3850: Test failed: Unexpected hr 0x80004002. uiautomation.c:3851: Test failed: Unexpected refcnt 1 uiautomation.c:3784: Test failed: Unexpected hr 0x80070057 uiautomation.c:3789: Test failed: Unexpected hr 0x80070057 uiautomation.c:4217: Test failed: Unexpected VT 0 uiautomation.c:4222: Test failed: Unexpected I4 0 uiautomation.c:4223: Test failed: incomplete sequence: expected Provider_GetPropertyValue, got nothing uiautomation.c:3803: Test failed: Unexpected hr 0x80070057 uiautomation.c:4273: Test failed: Unexpected VT 0 uiautomation.c:4276: Test failed: Unexpected refcnt 1 uiautomation.c:4279: Test failed: Unexpected hr 0x80070057 uiautomation.c:4280: Test failed: Unexpected VT 272 uiautomation.c:4281: Test failed: Unexpected I4 0x23 uiautomation.c:4283: Test failed: Failed to release node uiautomation.c:4285: Test failed: incomplete sequence: expected Provider_GetPropertyValue, got nothing uiautomation.c:3809: Test failed: Unexpected hr 0x80070057 uiautomation.c:4273: Test failed: Unexpected VT 0 uiautomation.c:4276: Test failed: Unexpected refcnt 1 uiautomation.c:4279: Test failed: Unexpected hr 0x80070057 uiautomation.c:4280: Test failed: Unexpected VT 272 uiautomation.c:4281: Test failed: Unexpected I4 0x23 uiautomation.c:4283: Test failed: Failed to release node uiautomation.c:4285: Test failed: incomplete sequence: expected Provider_GetPropertyValue, got nothing uiautomation.c:3867: Test failed: UiaNodeRelease returned FALSE === debian11 (32 bit Japanese:Japan report) === uiautomationcore: uiautomation.c:3850: Test failed: Unexpected hr 0x80004002. uiautomation.c:3851: Test failed: Unexpected refcnt 1 uiautomation.c:3784: Test failed: Unexpected hr 0x80070057 uiautomation.c:3789: Test failed: Unexpected hr 0x80070057 uiautomation.c:4217: Test failed: Unexpected VT 0 uiautomation.c:4222: Test failed: Unexpected I4 0 uiautomation.c:4223: Test failed: incomplete sequence: expected Provider_GetPropertyValue, got nothing uiautomation.c:3803: Test failed: Unexpected hr 0x80070057 uiautomation.c:4273: Test failed: Unexpected VT 0 uiautomation.c:4276: Test failed: Unexpected refcnt 1 uiautomation.c:4279: Test failed: Unexpected hr 0x80070057 uiautomation.c:4280: Test failed: Unexpected VT 272 uiautomation.c:4281: Test failed: Unexpected I4 0x23 uiautomation.c:4283: Test failed: Failed to release node uiautomation.c:4285: Test failed: incomplete sequence: expected Provider_GetPropertyValue, got nothing uiautomation.c:3809: Test failed: Unexpected hr 0x80070057 uiautomation.c:4273: Test failed: Unexpected VT 0 uiautomation.c:4276: Test failed: Unexpected refcnt 1 uiautomation.c:4279: Test failed: Unexpected hr 0x80070057 uiautomation.c:4280: Test failed: Unexpected VT 272 uiautomation.c:4281: Test failed: Unexpected I4 0x23 uiautomation.c:4283: Test failed: Failed to release node uiautomation.c:4285: Test failed: incomplete sequence: expected Provider_GetPropertyValue, got nothing uiautomation.c:3867: Test failed: UiaNodeRelease returned FALSE === debian11 (32 bit Chinese:China report) === uiautomationcore: uiautomation.c:3850: Test failed: Unexpected hr 0x80004002. uiautomation.c:3851: Test failed: Unexpected refcnt 1 uiautomation.c:3784: Test failed: Unexpected hr 0x80070057 uiautomation.c:3789: Test failed: Unexpected hr 0x80070057 uiautomation.c:4217: Test failed: Unexpected VT 0 uiautomation.c:4222: Test failed: Unexpected I4 0 uiautomation.c:4223: Test failed: incomplete sequence: expected Provider_GetPropertyValue, got nothing uiautomation.c:3803: Test failed: Unexpected hr 0x80070057 uiautomation.c:4273: Test failed: Unexpected VT 0 uiautomation.c:4276: Test failed: Unexpected refcnt 1 uiautomation.c:4279: Test failed: Unexpected hr 0x80070057 uiautomation.c:4280: Test failed: Unexpected VT 272 uiautomation.c:4281: Test failed: Unexpected I4 0x23 uiautomation.c:4283: Test failed: Failed to release node uiautomation.c:4285: Test failed: incomplete sequence: expected Provider_GetPropertyValue, got nothing uiautomation.c:3809: Test failed: Unexpected hr 0x80070057 uiautomation.c:4273: Test failed: Unexpected VT 0 uiautomation.c:4276: Test failed: Unexpected refcnt 1 uiautomation.c:4279: Test failed: Unexpected hr 0x80070057 uiautomation.c:4280: Test failed: Unexpected VT 272 uiautomation.c:4281: Test failed: Unexpected I4 0x23 uiautomation.c:4283: Test failed: Failed to release node uiautomation.c:4285: Test failed: incomplete sequence: expected Provider_GetPropertyValue, got nothing uiautomation.c:3867: Test failed: UiaNodeRelease returned FALSE === debian11 (32 bit WoW report) === uiautomationcore: uiautomation.c:3850: Test failed: Unexpected hr 0x80004002. uiautomation.c:3851: Test failed: Unexpected refcnt 1 uiautomation.c:3784: Test failed: Unexpected hr 0x80070057 uiautomation.c:3789: Test failed: Unexpected hr 0x80070057 uiautomation.c:4217: Test failed: Unexpected VT 0 uiautomation.c:4222: Test failed: Unexpected I4 0 uiautomation.c:4223: Test failed: incomplete sequence: expected Provider_GetPropertyValue, got nothing uiautomation.c:3803: Test failed: Unexpected hr 0x80070057 uiautomation.c:4273: Test failed: Unexpected VT 0 uiautomation.c:4276: Test failed: Unexpected refcnt 1 uiautomation.c:4279: Test failed: Unexpected hr 0x80070057 uiautomation.c:4280: Test failed: Unexpected VT 272 uiautomation.c:4281: Test failed: Unexpected I4 0x23 uiautomation.c:4283: Test failed: Failed to release node uiautomation.c:4285: Test failed: incomplete sequence: expected Provider_GetPropertyValue, got nothing uiautomation.c:3809: Test failed: Unexpected hr 0x80070057 uiautomation.c:4273: Test failed: Unexpected VT 0 uiautomation.c:4276: Test failed: Unexpected refcnt 1 uiautomation.c:4279: Test failed: Unexpected hr 0x80070057 uiautomation.c:4280: Test failed: Unexpected VT 272 uiautomation.c:4281: Test failed: Unexpected I4 0x23 uiautomation.c:4283: Test failed: Failed to release node uiautomation.c:4285: Test failed: incomplete sequence: expected Provider_GetPropertyValue, got nothing uiautomation.c:3867: Test failed: UiaNodeRelease returned FALSE === debian11 (64 bit WoW report) === uiautomationcore: uiautomation.c:3850: Test failed: Unexpected hr 0x80004002. uiautomation.c:3851: Test failed: Unexpected refcnt 1 uiautomation.c:3784: Test failed: Unexpected hr 0x80070057 uiautomation.c:3789: Test failed: Unexpected hr 0x80070057 uiautomation.c:4217: Test failed: Unexpected VT 0 uiautomation.c:4222: Test failed: Unexpected I4 0 uiautomation.c:4223: Test failed: incomplete sequence: expected Provider_GetPropertyValue, got nothing uiautomation.c:3803: Test failed: Unexpected hr 0x80070057 uiautomation.c:4270: Test failed: Unexpected VT 0 uiautomation.c:4276: Test failed: Unexpected refcnt 1 uiautomation.c:4279: Test failed: Unexpected hr 0x80070057 uiautomation.c:4280: Test failed: Unexpected VT 0 uiautomation.c:4281: Test failed: Unexpected I4 0x75d110 uiautomation.c:4283: Test failed: Failed to release node uiautomation.c:4285: Test failed: incomplete sequence: expected Provider_GetPropertyValue, got nothing uiautomation.c:3809: Test failed: Unexpected hr 0x80070057 uiautomation.c:4270: Test failed: Unexpected VT 0 uiautomation.c:4276: Test failed: Unexpected refcnt 1 uiautomation.c:4279: Test failed: Unexpected hr 0x80070057 uiautomation.c:4280: Test failed: Unexpected VT 0 uiautomation.c:4281: Test failed: Unexpected I4 0x75d110 uiautomation.c:4283: Test failed: Failed to release node uiautomation.c:4285: Test failed: incomplete sequence: expected Provider_GetPropertyValue, got nothing uiautomation.c:3867: Test failed: UiaNodeRelease returned FALSE
Agh, seems like typelib registration shenanigans. I've ran into this issue locally before and `wineboot -u` fixed it, I must be missing a step with `regtypelib` somewhere.
I'll investigate this tomorrow.
So, the issue here is that adding `#pragma makedep regtypelib` to the existing `.idl` doesn't trigger a prefix update. We need a prefix update to register the typelib used to marshal `IWineUiaProvider`. Forcing a prefix update with `touch loader/wine.inf` fixes this. According to Julliard, these testbot failures are fine to ignore.
This merge request was approved by Huw Davies.