From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/uiautomationcore/tests/uiautomation.c | 129 ++++++++++++++++++++- dlls/uiautomationcore/uia_classes.idl | 1 + dlls/uiautomationcore/uia_client.c | 43 +++++++ dlls/uiautomationcore/uia_ids.c | 23 +++- dlls/uiautomationcore/uia_private.h | 8 ++ dlls/uiautomationcore/uia_provider.c | 6 - 6 files changed, 201 insertions(+), 9 deletions(-)
diff --git a/dlls/uiautomationcore/tests/uiautomation.c b/dlls/uiautomationcore/tests/uiautomation.c index 888d8e39002..0ce2693d479 100644 --- a/dlls/uiautomationcore/tests/uiautomation.c +++ b/dlls/uiautomationcore/tests/uiautomation.c @@ -1103,12 +1103,19 @@ struct Provider_prop_override VARIANT val; };
+struct Provider_value_pattern_data +{ + BOOL is_supported; + BOOL is_read_only; +}; + static struct Provider { IRawElementProviderSimple IRawElementProviderSimple_iface; IRawElementProviderFragment IRawElementProviderFragment_iface; IRawElementProviderFragmentRoot IRawElementProviderFragmentRoot_iface; IRawElementProviderHwndOverride IRawElementProviderHwndOverride_iface; + IValueProvider IValueProvider_iface; LONG ref;
const char *prov_name; @@ -1129,6 +1136,7 @@ static struct Provider struct Provider_prop_override *prop_override; int prop_override_count; struct UiaRect bounds_rect; + struct Provider_value_pattern_data value_pattern_data; } Provider, Provider2, Provider_child, Provider_child2; static struct Provider Provider_hwnd, Provider_nc, Provider_proxy, Provider_proxy2, Provider_override; static void initialize_provider(struct Provider *prov, int prov_opts, HWND hwnd, BOOL initialize_nav_links); @@ -1184,6 +1192,7 @@ static SAFEARRAY *create_unk_safearray(void)
enum { PROV_GET_PROVIDER_OPTIONS, + PROV_GET_PATTERN_PROV, PROV_GET_PROPERTY_VALUE, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, FRAG_NAVIGATE, @@ -1195,6 +1204,7 @@ enum {
static const char *prov_method_str[] = { "get_ProviderOptions", + "GetPatternProvider", "GetPropertyValue", "get_HostRawElementProvider", "Navigate", @@ -1544,6 +1554,8 @@ HRESULT WINAPI ProviderSimple_QueryInterface(IRawElementProviderSimple *iface, R *ppv = &This->IRawElementProviderFragmentRoot_iface; else if (IsEqualIID(riid, &IID_IRawElementProviderHwndOverride)) *ppv = &This->IRawElementProviderHwndOverride_iface; + else if (IsEqualIID(riid, &IID_IValueProvider)) + *ppv = &This->IValueProvider_iface; else return E_NOINTERFACE;
@@ -1586,8 +1598,29 @@ HRESULT WINAPI ProviderSimple_get_ProviderOptions(IRawElementProviderSimple *ifa HRESULT WINAPI ProviderSimple_GetPatternProvider(IRawElementProviderSimple *iface, PATTERNID pattern_id, IUnknown **ret_val) { - ok(0, "unexpected call\n"); - return E_NOTIMPL; + struct Provider *This = impl_from_ProviderSimple(iface); + + add_method_call(This, PROV_GET_PATTERN_PROV); + if (This->expected_tid) + ok(This->expected_tid == GetCurrentThreadId(), "Unexpected tid %ld\n", GetCurrentThreadId()); + This->last_call_tid = GetCurrentThreadId(); + + *ret_val = NULL; + switch (pattern_id) + { + case UIA_ValuePatternId: + if (This->value_pattern_data.is_supported) + *ret_val = (IUnknown *)iface; + break; + + default: + break; + } + + if (*ret_val) + IUnknown_AddRef(*ret_val); + + return S_OK; }
HRESULT WINAPI ProviderSimple_GetPropertyValue(IRawElementProviderSimple *iface, @@ -2071,12 +2104,67 @@ static const IRawElementProviderHwndOverrideVtbl ProviderHwndOverrideVtbl = { ProviderHwndOverride_GetOverrideProviderForHwnd, };
+static inline struct Provider *impl_from_ProviderValuePattern(IValueProvider *iface) +{ + return CONTAINING_RECORD(iface, struct Provider, IValueProvider_iface); +} + +static HRESULT WINAPI ProviderValuePattern_QueryInterface(IValueProvider *iface, REFIID riid, + void **ppv) +{ + struct Provider *Provider = impl_from_ProviderValuePattern(iface); + return IRawElementProviderSimple_QueryInterface(&Provider->IRawElementProviderSimple_iface, riid, ppv); +} + +static ULONG WINAPI ProviderValuePattern_AddRef(IValueProvider *iface) +{ + struct Provider *Provider = impl_from_ProviderValuePattern(iface); + return IRawElementProviderSimple_AddRef(&Provider->IRawElementProviderSimple_iface); +} + +static ULONG WINAPI ProviderValuePattern_Release(IValueProvider *iface) +{ + struct Provider *Provider = impl_from_ProviderValuePattern(iface); + return IRawElementProviderSimple_Release(&Provider->IRawElementProviderSimple_iface); +} + +static HRESULT WINAPI ProviderValuePattern_SetValue(IValueProvider *iface, LPCWSTR val) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ProviderValuePattern_get_Value(IValueProvider *iface, BSTR *ret_val) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ProviderValuePattern_get_IsReadOnly(IValueProvider *iface, BOOL *ret_val) +{ + struct Provider *Provider = impl_from_ProviderValuePattern(iface); + + *ret_val = Provider->value_pattern_data.is_read_only; + + return S_OK; +} + +static const IValueProviderVtbl ProviderValuePatternVtbl = { + ProviderValuePattern_QueryInterface, + ProviderValuePattern_AddRef, + ProviderValuePattern_Release, + ProviderValuePattern_SetValue, + ProviderValuePattern_get_Value, + ProviderValuePattern_get_IsReadOnly, +}; + static struct Provider Provider = { { &ProviderSimpleVtbl }, { &ProviderFragmentVtbl }, { &ProviderFragmentRootVtbl }, { &ProviderHwndOverrideVtbl }, + { &ProviderValuePatternVtbl }, 1, "Provider", NULL, NULL, @@ -2091,6 +2179,7 @@ static struct Provider Provider2 = { &ProviderFragmentVtbl }, { &ProviderFragmentRootVtbl }, { &ProviderHwndOverrideVtbl }, + { &ProviderValuePatternVtbl }, 1, "Provider2", NULL, NULL, @@ -2105,6 +2194,7 @@ static struct Provider Provider_child = { &ProviderFragmentVtbl }, { &ProviderFragmentRootVtbl }, { &ProviderHwndOverrideVtbl }, + { &ProviderValuePatternVtbl }, 1, "Provider_child", &Provider.IRawElementProviderFragment_iface, &Provider.IRawElementProviderFragmentRoot_iface, @@ -2119,6 +2209,7 @@ static struct Provider Provider_child2 = { &ProviderFragmentVtbl }, { &ProviderFragmentRootVtbl }, { &ProviderHwndOverrideVtbl }, + { &ProviderValuePatternVtbl }, 1, "Provider_child2", &Provider.IRawElementProviderFragment_iface, &Provider.IRawElementProviderFragmentRoot_iface, @@ -2133,6 +2224,7 @@ static struct Provider Provider_hwnd = { &ProviderFragmentVtbl }, { &ProviderFragmentRootVtbl }, { &ProviderHwndOverrideVtbl }, + { &ProviderValuePatternVtbl }, 1, "Provider_hwnd", NULL, NULL, @@ -2147,6 +2239,7 @@ static struct Provider Provider_nc = { &ProviderFragmentVtbl }, { &ProviderFragmentRootVtbl }, { &ProviderHwndOverrideVtbl }, + { &ProviderValuePatternVtbl }, 1, "Provider_nc", NULL, NULL, @@ -2162,6 +2255,7 @@ static struct Provider Provider_proxy = { &ProviderFragmentVtbl }, { &ProviderFragmentRootVtbl }, { &ProviderHwndOverrideVtbl }, + { &ProviderValuePatternVtbl }, 1, "Provider_proxy", NULL, NULL, @@ -2177,6 +2271,7 @@ static struct Provider Provider_proxy2 = { &ProviderFragmentVtbl }, { &ProviderFragmentRootVtbl }, { &ProviderHwndOverrideVtbl }, + { &ProviderValuePatternVtbl }, 1, "Provider_proxy2", NULL, NULL, @@ -2192,6 +2287,7 @@ static struct Provider Provider_override = { &ProviderFragmentVtbl }, { &ProviderFragmentRootVtbl }, { &ProviderHwndOverrideVtbl }, + { &ProviderValuePatternVtbl }, 1, "Provider_override", NULL, NULL, @@ -2208,6 +2304,7 @@ static struct Provider Provider_override = { &ProviderFragmentVtbl }, \ { &ProviderFragmentRootVtbl }, \ { &ProviderHwndOverrideVtbl }, \ + { &ProviderValuePatternVtbl }, \ 1, \ "Provider_" # name "", \ NULL, NULL, \ @@ -4699,6 +4796,11 @@ static const struct prov_method_sequence get_elem_arr_prop_seq[] = { { 0 } };
+static const struct prov_method_sequence get_pattern_prop_seq[] = { + { &Provider, PROV_GET_PATTERN_PROV }, + { 0 } +}; + static const struct prov_method_sequence get_bounding_rect_seq[] = { NODE_CREATE_SEQ(&Provider_child), { &Provider_child, FRAG_GET_BOUNDING_RECT }, @@ -5031,6 +5133,28 @@ static void test_UiaGetPropertyValue(void) winetest_pop_context(); }
+ /* IValueProvider pattern property IDs. */ + Provider.value_pattern_data.is_supported = FALSE; + hr = UiaGetPropertyValue(node, UIA_ValueIsReadOnlyPropertyId, &v); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + 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)); + ok_method_sequence(get_pattern_prop_seq, NULL); + VariantClear(&v); + + Provider.value_pattern_data.is_supported = TRUE; + for (i = 0; i < 2; i++) + { + Provider.value_pattern_data.is_read_only = i; + + hr = UiaGetPropertyValue(node, UIA_ValueIsReadOnlyPropertyId, &v); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(V_VT(&v) == VT_BOOL, "Unexpected VT %d\n", V_VT(&v)); + ok(check_variant_bool(&v, i), "Unexpected BOOL %#x\n", V_BOOL(&v)); + ok_method_sequence(get_pattern_prop_seq, NULL); + VariantClear(&v); + } + ok(UiaNodeRelease(node), "UiaNodeRelease returned FALSE\n"); ok(Provider.ref == 1, "Unexpected refcnt %ld\n", Provider.ref); initialize_provider(&Provider, ProviderOptions_ServerSideProvider, NULL, FALSE); @@ -8462,6 +8586,7 @@ static void initialize_provider(struct Provider *prov, int prov_opts, HWND hwnd, prov->prop_override = NULL; prov->prop_override_count = 0; memset(&prov->bounds_rect, 0, sizeof(prov->bounds_rect)); + memset(&prov->value_pattern_data, 0, sizeof(prov->value_pattern_data)); if (initialize_nav_links) { prov->frag_root = NULL; diff --git a/dlls/uiautomationcore/uia_classes.idl b/dlls/uiautomationcore/uia_classes.idl index 9954b465f90..f0a20d61579 100644 --- a/dlls/uiautomationcore/uia_classes.idl +++ b/dlls/uiautomationcore/uia_classes.idl @@ -25,6 +25,7 @@ struct uia_prop_info { int prop_id; int prop_type; int type; + int pattern_id; };
struct uia_event_info { diff --git a/dlls/uiautomationcore/uia_client.c b/dlls/uiautomationcore/uia_client.c index 793df3b6618..ce2aeb21622 100644 --- a/dlls/uiautomationcore/uia_client.c +++ b/dlls/uiautomationcore/uia_client.c @@ -1437,6 +1437,46 @@ static HRESULT uia_provider_get_special_prop_val(struct uia_provider *prov, return S_OK; }
+static HRESULT uia_provider_get_pattern_prop_val(struct uia_provider *prov, + const struct uia_prop_info *prop_info, VARIANT *ret_val) +{ + const struct uia_pattern_info *pattern_info = uia_pattern_info_from_id(prop_info->pattern_id); + IUnknown *unk, *pattern_prov; + HRESULT hr; + + unk = pattern_prov = NULL; + hr = IRawElementProviderSimple_GetPatternProvider(prov->elprov, prop_info->pattern_id, &unk); + if (FAILED(hr) || !unk) + return S_OK; + + hr = IUnknown_QueryInterface(unk, pattern_info->pattern_iid, (void **)&pattern_prov); + IUnknown_Release(unk); + if (FAILED(hr) || !pattern_prov) + { + WARN("Failed to get pattern interface from object\n"); + return S_OK; + } + + switch (prop_info->prop_id) + { + case UIA_ValueIsReadOnlyPropertyId: + { + BOOL val; + + hr = IValueProvider_get_IsReadOnly((IValueProvider *)pattern_prov, &val); + if (SUCCEEDED(hr)) + variant_init_bool(ret_val, val); + break; + } + + default: + break; + } + + IUnknown_Release(pattern_prov); + return S_OK; +} + static HRESULT WINAPI uia_provider_get_prop_val(IWineUiaProvider *iface, const struct uia_prop_info *prop_info, VARIANT *ret_val) { @@ -1453,6 +1493,9 @@ static HRESULT WINAPI uia_provider_get_prop_val(IWineUiaProvider *iface, case PROP_TYPE_SPECIAL: return uia_provider_get_special_prop_val(prov, prop_info, ret_val);
+ case PROP_TYPE_PATTERN_PROP: + return uia_provider_get_pattern_prop_val(prov, prop_info, ret_val); + default: break; } diff --git a/dlls/uiautomationcore/uia_ids.c b/dlls/uiautomationcore/uia_ids.c index 6f5b00cd5ca..7ad8da69cd4 100644 --- a/dlls/uiautomationcore/uia_ids.c +++ b/dlls/uiautomationcore/uia_ids.c @@ -97,7 +97,9 @@ static const struct uia_prop_info default_uia_properties[] = { { &IsDropTargetPatternAvailable_Property_GUID, UIA_IsDropTargetPatternAvailablePropertyId, }, { &Dock_DockPosition_Property_GUID, UIA_DockDockPositionPropertyId, }, { &Styles_StyleId_Property_GUID, UIA_StylesStyleIdPropertyId, }, - { &Value_IsReadOnly_Property_GUID, UIA_ValueIsReadOnlyPropertyId, }, + { &Value_IsReadOnly_Property_GUID, UIA_ValueIsReadOnlyPropertyId, + PROP_TYPE_PATTERN_PROP, UIAutomationType_Bool, + UIA_ValuePatternId, }, { &IsSpreadsheetPatternAvailable_Property_GUID, UIA_IsSpreadsheetPatternAvailablePropertyId, }, { &Styles_StyleName_Property_GUID, UIA_StylesStyleNamePropertyId, }, { &IsAnnotationPatternAvailable_Property_GUID, UIA_IsAnnotationPatternAvailablePropertyId, }, @@ -482,6 +484,17 @@ static const struct uia_pattern_info default_uia_patterns[] = { &IID_ISpreadsheetItemProvider, }, };
+static const int pattern_id_idx[] = { + 0x1f, 0x1d, 0x10, 0x0c, 0x15, 0x13, 0x19, 0x0b, + 0x1c, 0x04, 0x1e, 0x06, 0x0f, 0x17, 0x09, 0x0a, + 0x1b, 0x00, 0x11, 0x02, 0x05, 0x14, 0x20, 0x1a, + 0x12, 0x07, 0x18, 0x21, 0x01, 0x16, 0x03, 0x08, + 0x0d, 0x0e, +}; + +#define PATTERN_ID_MIN 10000 +#define PATTERN_ID_MAX (PATTERN_ID_MIN + ARRAY_SIZE(default_uia_patterns)) + static const struct uia_pattern_info *uia_pattern_info_from_guid(const GUID *guid) { struct uia_pattern_info *pattern; @@ -493,6 +506,14 @@ static const struct uia_pattern_info *uia_pattern_info_from_guid(const GUID *gui return NULL; }
+const struct uia_pattern_info *uia_pattern_info_from_id(PATTERNID pattern_id) +{ + if ((pattern_id < PATTERN_ID_MIN) || (pattern_id > PATTERN_ID_MAX)) + return NULL; + + return &default_uia_patterns[pattern_id_idx[pattern_id - PATTERN_ID_MIN]]; +} + /*********************************************************************** * UiaLookupId (uiautomationcore.@) */ diff --git a/dlls/uiautomationcore/uia_private.h b/dlls/uiautomationcore/uia_private.h index 63820d0b937..2478fcc1bf0 100644 --- a/dlls/uiautomationcore/uia_private.h +++ b/dlls/uiautomationcore/uia_private.h @@ -28,6 +28,7 @@ enum uia_prop_type { PROP_TYPE_UNKNOWN, PROP_TYPE_ELEM_PROP, PROP_TYPE_SPECIAL, + PROP_TYPE_PATTERN_PROP, };
/* @@ -91,6 +92,12 @@ static inline struct uia_provider *impl_from_IWineUiaProvider(IWineUiaProvider * return CONTAINING_RECORD(iface, struct uia_provider, IWineUiaProvider_iface); }
+static inline void variant_init_bool(VARIANT *v, BOOL val) +{ + V_VT(v) = VT_BOOL; + V_BOOL(v) = val ? VARIANT_TRUE : VARIANT_FALSE; +} + /* uia_client.c */ int uia_compare_safearrays(SAFEARRAY *sa1, SAFEARRAY *sa2, int prop_type) DECLSPEC_HIDDEN; int get_node_provider_type_at_idx(struct uia_node *node, int idx) DECLSPEC_HIDDEN; @@ -99,6 +106,7 @@ HRESULT create_uia_node_from_elprov(IRawElementProviderSimple *elprov, HUIANODE
/* uia_ids.c */ const struct uia_prop_info *uia_prop_info_from_id(PROPERTYID prop_id) DECLSPEC_HIDDEN; +const struct uia_pattern_info *uia_pattern_info_from_id(PATTERNID pattern_id) DECLSPEC_HIDDEN;
/* uia_provider.c */ void uia_stop_provider_thread(void) DECLSPEC_HIDDEN; diff --git a/dlls/uiautomationcore/uia_provider.c b/dlls/uiautomationcore/uia_provider.c index fc718fabe43..c851ecaf685 100644 --- a/dlls/uiautomationcore/uia_provider.c +++ b/dlls/uiautomationcore/uia_provider.c @@ -35,12 +35,6 @@ static void variant_init_i4(VARIANT *v, int val) V_I4(v) = val; }
-static void variant_init_bool(VARIANT *v, BOOL val) -{ - V_VT(v) = VT_BOOL; - V_BOOL(v) = val ? VARIANT_TRUE : VARIANT_FALSE; -} - static BOOL msaa_check_acc_state(IAccessible *acc, VARIANT cid, ULONG flag) { HRESULT hr;