Wine-Devel
By thread
wine-devel@list.winehq.org
By month
Messages by month
- ----- 2026 -----
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2002 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2001 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
June 2022
- 68 participants
- 3274 messages
Re: [PATCH 0/3] MR216: uiautomationcore: More UiaProviderFromIAccessible work.
by Huw Davies (@huw)
Huw Davies (@huw) commented about dlls/uiautomationcore/uia_provider.c:
> + matched = TRUE;
> + goto exit;
> + }
> + else
> + {
> + IUnknown *unk, *unk2;
> +
> + IAccessible_QueryInterface(acc, &IID_IUnknown, (void**)&unk);
> + IUnknown_Release(unk);
> + IAccessible_QueryInterface(acc2, &IID_IUnknown, (void**)&unk2);
> + IUnknown_Release(unk2);
> + if (unk == unk2)
> + {
> + matched = TRUE;
> + goto exit;
> + }
Releasing the ifaces before comparing them looks odd. This is also done in the tests of the third patch.
--
https://gitlab.winehq.org/wine/wine/-/merge_requests/216#note_1754
June 9, 2022
Re: [PATCH 0/3] MR216: uiautomationcore: More UiaProviderFromIAccessible work.
by Huw Davies (@huw)
Huw Davies (@huw) commented about dlls/uiautomationcore/uia_provider.c:
> +static BOOL msaa_acc_compare(IAccessible *acc, IAccessible *acc2)
> +{
> + LONG child_count[2], left[2], top[2], width[2], height[2];
> + BSTR name[2] = { NULL, NULL };
> + BOOL matched = FALSE;
> + int match_count = 0;
> + VARIANT cid, v, v2;
> + HRESULT hr, hr2;
> +
> + acc = msaa_acc_da_unwrap(acc);
> + acc2 = msaa_acc_da_unwrap(acc2);
> + if (acc == acc2)
> + {
> + matched = TRUE;
> + goto exit;
> + }
There's no need to compare the IAccessible ptrs, given that you compare their IUnknowns later.
--
https://gitlab.winehq.org/wine/wine/-/merge_requests/216#note_1753
June 9, 2022
June 9, 2022
[PATCH 3/3] uiautomationcore: Add ILegacyIAccessibleProvider implementation for MSAA providers.
by Connor McAdams
From: Connor McAdams <cmcadams(a)codeweavers.com>
Signed-off-by: Connor McAdams <cmcadams(a)codeweavers.com>
---
dlls/uiautomationcore/tests/uiautomation.c | 57 +++++++
dlls/uiautomationcore/uia_provider.c | 167 ++++++++++++++++++++-
2 files changed, 222 insertions(+), 2 deletions(-)
diff --git a/dlls/uiautomationcore/tests/uiautomation.c b/dlls/uiautomationcore/tests/uiautomation.c
index 6ed3c907a40..6a7e9afbdc0 100644
--- a/dlls/uiautomationcore/tests/uiautomation.c
+++ b/dlls/uiautomationcore/tests/uiautomation.c
@@ -89,6 +89,20 @@ static BOOL check_variant_bool(VARIANT *v, BOOL val)
return FALSE;
}
+static BOOL iface_cmp(IUnknown *iface1, IUnknown *iface2)
+{
+ IUnknown *unk1, *unk2;
+
+ if(iface1 == iface2)
+ return TRUE;
+
+ IUnknown_QueryInterface(iface1, &IID_IUnknown, (void**)&unk1);
+ IUnknown_Release(unk1);
+ IUnknown_QueryInterface(iface2, &IID_IUnknown, (void**)&unk2);
+ IUnknown_Release(unk2);
+ return unk1 == unk2;
+}
+
static struct Accessible
{
IAccessible IAccessible_iface;
@@ -977,13 +991,16 @@ static void test_uia_prov_from_acc_properties(void)
static void test_UiaProviderFromIAccessible(void)
{
+ ILegacyIAccessibleProvider *accprov;
IRawElementProviderSimple *elprov, *elprov2;
enum ProviderOptions prov_opt;
IAccessible *acc;
+ IUnknown *unk;
WNDCLASSA cls;
HRESULT hr;
HWND hwnd;
VARIANT v;
+ INT cid;
CoInitializeEx(NULL, COINIT_MULTITHREADED);
cls.style = 0;
@@ -1084,6 +1101,26 @@ static void test_UiaProviderFromIAccessible(void)
ok(V_VT(&v) == VT_BSTR, "V_VT(&v) = %d\n", V_VT(&v));
VariantClear(&v);
+ hr = IRawElementProviderSimple_GetPatternProvider(elprov, UIA_LegacyIAccessiblePatternId, &unk);
+ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+ ok(!!unk, "unk == NULL\n");
+ ok(iface_cmp((IUnknown *)elprov, unk), "unk != elprov\n");
+
+ hr = IUnknown_QueryInterface(unk, &IID_ILegacyIAccessibleProvider, (void **)&accprov);
+ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+ ok(!!accprov, "accprov == NULL\n");
+
+ hr = ILegacyIAccessibleProvider_get_ChildId(accprov, &cid);
+ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+ ok(cid == CHILDID_SELF, "cid != CHILDID_SELF\n");
+
+ hr = ILegacyIAccessibleProvider_GetIAccessible(accprov, &acc);
+ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+ ok(acc == &Accessible.IAccessible_iface, "acc != &Accessible.IAccessible_iface\n");
+ IAccessible_Release(acc);
+ IUnknown_Release(unk);
+ ILegacyIAccessibleProvider_Release(accprov);
+
IRawElementProviderSimple_Release(elprov);
ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
@@ -1101,6 +1138,26 @@ static void test_UiaProviderFromIAccessible(void)
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
ok(!elprov2, "elprov != NULL\n");
+ hr = IRawElementProviderSimple_GetPatternProvider(elprov, UIA_LegacyIAccessiblePatternId, &unk);
+ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+ ok(!!unk, "unk == NULL\n");
+ ok(iface_cmp((IUnknown *)elprov, unk), "unk != elprov\n");
+
+ hr = IUnknown_QueryInterface(unk, &IID_ILegacyIAccessibleProvider, (void **)&accprov);
+ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+ ok(!!accprov, "accprov == NULL\n");
+
+ hr = ILegacyIAccessibleProvider_get_ChildId(accprov, &cid);
+ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+ ok(cid == 1, "cid != CHILDID_SELF\n");
+
+ hr = ILegacyIAccessibleProvider_GetIAccessible(accprov, &acc);
+ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+ ok(acc == &Accessible.IAccessible_iface, "acc != &Accessible.IAccessible_iface\n");
+ IAccessible_Release(acc);
+ IUnknown_Release(unk);
+ ILegacyIAccessibleProvider_Release(accprov);
+
IRawElementProviderSimple_Release(elprov);
ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
diff --git a/dlls/uiautomationcore/uia_provider.c b/dlls/uiautomationcore/uia_provider.c
index 700eaae4a2c..f6a1a7d7bf3 100644
--- a/dlls/uiautomationcore/uia_provider.c
+++ b/dlls/uiautomationcore/uia_provider.c
@@ -272,6 +272,7 @@ static LONG msaa_role_to_uia_control_type(LONG role)
*/
struct msaa_provider {
IRawElementProviderSimple IRawElementProviderSimple_iface;
+ ILegacyIAccessibleProvider ILegacyIAccessibleProvider_iface;
LONG refcount;
IAccessible *acc;
@@ -313,9 +314,13 @@ static inline struct msaa_provider *impl_from_msaa_provider(IRawElementProviderS
HRESULT WINAPI msaa_provider_QueryInterface(IRawElementProviderSimple *iface, REFIID riid, void **ppv)
{
+ struct msaa_provider *msaa_prov = impl_from_msaa_provider(iface);
+
*ppv = NULL;
if (IsEqualIID(riid, &IID_IRawElementProviderSimple) || IsEqualIID(riid, &IID_IUnknown))
*ppv = iface;
+ else if (IsEqualIID(riid, &IID_ILegacyIAccessibleProvider))
+ *ppv = &msaa_prov->ILegacyIAccessibleProvider_iface;
else
return E_NOINTERFACE;
@@ -360,9 +365,20 @@ HRESULT WINAPI msaa_provider_get_ProviderOptions(IRawElementProviderSimple *ifac
HRESULT WINAPI msaa_provider_GetPatternProvider(IRawElementProviderSimple *iface,
PATTERNID pattern_id, IUnknown **ret_val)
{
- FIXME("%p, %d, %p: stub!\n", iface, pattern_id, ret_val);
+ TRACE("%p, %d, %p\n", iface, pattern_id, ret_val);
+
*ret_val = NULL;
- return E_NOTIMPL;
+ switch (pattern_id)
+ {
+ case UIA_LegacyIAccessiblePatternId:
+ return IRawElementProviderSimple_QueryInterface(iface, &IID_IUnknown, (void **)ret_val);
+
+ default:
+ FIXME("Unimplemented patternId %d\n", pattern_id);
+ break;
+ }
+
+ return S_OK;
}
HRESULT WINAPI msaa_provider_GetPropertyValue(IRawElementProviderSimple *iface,
@@ -448,6 +464,152 @@ static const IRawElementProviderSimpleVtbl msaa_provider_vtbl = {
msaa_provider_get_HostRawElementProvider,
};
+/*
+ * ILegacyIAccessibleProvider interface for UiaProviderFromIAccessible
+ * providers.
+ */
+static inline struct msaa_provider *impl_from_msaa_acc_provider(ILegacyIAccessibleProvider *iface)
+{
+ return CONTAINING_RECORD(iface, struct msaa_provider, ILegacyIAccessibleProvider_iface);
+}
+
+static HRESULT WINAPI msaa_acc_provider_QueryInterface(ILegacyIAccessibleProvider *iface, REFIID riid, void **ppv)
+{
+ struct msaa_provider *msaa_prov = impl_from_msaa_acc_provider(iface);
+ return IRawElementProviderSimple_QueryInterface(&msaa_prov->IRawElementProviderSimple_iface, riid, ppv);
+}
+
+static ULONG WINAPI msaa_acc_provider_AddRef(ILegacyIAccessibleProvider *iface)
+{
+ struct msaa_provider *msaa_prov = impl_from_msaa_acc_provider(iface);
+ return IRawElementProviderSimple_AddRef(&msaa_prov->IRawElementProviderSimple_iface);
+}
+
+static ULONG WINAPI msaa_acc_provider_Release(ILegacyIAccessibleProvider *iface)
+{
+ struct msaa_provider *msaa_prov = impl_from_msaa_acc_provider(iface);
+ return IRawElementProviderSimple_Release(&msaa_prov->IRawElementProviderSimple_iface);
+}
+
+static HRESULT WINAPI msaa_acc_provider_Select(ILegacyIAccessibleProvider *iface, LONG select_flags)
+{
+ FIXME("%p, %#lx: stub!\n", iface, select_flags);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI msaa_acc_provider_DoDefaultAction(ILegacyIAccessibleProvider *iface)
+{
+ FIXME("%p: stub!\n", iface);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI msaa_acc_provider_SetValue(ILegacyIAccessibleProvider *iface, LPCWSTR val)
+{
+ FIXME("%p, %p<%s>: stub!\n", iface, val, debugstr_w(val));
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI msaa_acc_provider_GetIAccessible(ILegacyIAccessibleProvider *iface,
+ IAccessible **out_acc)
+{
+ struct msaa_provider *msaa_prov = impl_from_msaa_acc_provider(iface);
+
+ TRACE("%p, %p\n", iface, out_acc);
+
+ IAccessible_AddRef(msaa_prov->acc);
+ *out_acc = msaa_prov->acc;
+
+ return S_OK;
+}
+
+static HRESULT WINAPI msaa_acc_provider_get_ChildId(ILegacyIAccessibleProvider *iface, int *out_cid)
+{
+ struct msaa_provider *msaa_prov = impl_from_msaa_acc_provider(iface);
+
+ TRACE("%p, %p\n", iface, out_cid);
+ *out_cid = V_I4(&msaa_prov->cid);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI msaa_acc_provider_get_Name(ILegacyIAccessibleProvider *iface, BSTR *out_name)
+{
+ FIXME("%p, %p: stub!\n", iface, out_name);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI msaa_acc_provider_get_Value(ILegacyIAccessibleProvider *iface, BSTR *out_value)
+{
+ FIXME("%p, %p: stub!\n", iface, out_value);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI msaa_acc_provider_get_Description(ILegacyIAccessibleProvider *iface,
+ BSTR *out_description)
+{
+ FIXME("%p, %p: stub!\n", iface, out_description);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI msaa_acc_provider_get_Role(ILegacyIAccessibleProvider *iface, DWORD *out_role)
+{
+ FIXME("%p, %p: stub!\n", iface, out_role);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI msaa_acc_provider_get_State(ILegacyIAccessibleProvider *iface, DWORD *out_state)
+{
+ FIXME("%p, %p: stub!\n", iface, out_state);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI msaa_acc_provider_get_Help(ILegacyIAccessibleProvider *iface, BSTR *out_help)
+{
+ FIXME("%p, %p: stub!\n", iface, out_help);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI msaa_acc_provider_get_KeyboardShortcut(ILegacyIAccessibleProvider *iface,
+ BSTR *out_kbd_shortcut)
+{
+ FIXME("%p, %p: stub!\n", iface, out_kbd_shortcut);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI msaa_acc_provider_GetSelection(ILegacyIAccessibleProvider *iface,
+ SAFEARRAY **out_selected)
+{
+ FIXME("%p, %p: stub!\n", iface, out_selected);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI msaa_acc_provider_get_DefaultAction(ILegacyIAccessibleProvider *iface,
+ BSTR *out_default_action)
+{
+ FIXME("%p, %p: stub!\n", iface, out_default_action);
+ return E_NOTIMPL;
+}
+
+static const ILegacyIAccessibleProviderVtbl msaa_acc_provider_vtbl = {
+ msaa_acc_provider_QueryInterface,
+ msaa_acc_provider_AddRef,
+ msaa_acc_provider_Release,
+ msaa_acc_provider_Select,
+ msaa_acc_provider_DoDefaultAction,
+ msaa_acc_provider_SetValue,
+ msaa_acc_provider_GetIAccessible,
+ msaa_acc_provider_get_ChildId,
+ msaa_acc_provider_get_Name,
+ msaa_acc_provider_get_Value,
+ msaa_acc_provider_get_Description,
+ msaa_acc_provider_get_Role,
+ msaa_acc_provider_get_State,
+ msaa_acc_provider_get_Help,
+ msaa_acc_provider_get_KeyboardShortcut,
+ msaa_acc_provider_GetSelection,
+ msaa_acc_provider_get_DefaultAction,
+};
+
/***********************************************************************
* UiaProviderFromIAccessible (uiautomationcore.@)
*/
@@ -503,6 +665,7 @@ HRESULT WINAPI UiaProviderFromIAccessible(IAccessible *acc, long child_id, DWORD
return E_OUTOFMEMORY;
msaa_prov->IRawElementProviderSimple_iface.lpVtbl = &msaa_provider_vtbl;
+ msaa_prov->ILegacyIAccessibleProvider_iface.lpVtbl = &msaa_acc_provider_vtbl;
msaa_prov->refcount = 1;
msaa_prov->hwnd = hwnd;
variant_init_i4(&msaa_prov->cid, child_id);
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/216
June 9, 2022
[PATCH 2/3] include: Add ILegacyIAccessibleProvider interface definition.
by Connor McAdams
From: Connor McAdams <cmcadams(a)codeweavers.com>
Signed-off-by: Connor McAdams <cmcadams(a)codeweavers.com>
---
include/uiautomationcore.idl | 31 +++++++++++++++++++++++++++++++
1 file changed, 31 insertions(+)
diff --git a/include/uiautomationcore.idl b/include/uiautomationcore.idl
index 170b0c76de1..c4aa258b5af 100644
--- a/include/uiautomationcore.idl
+++ b/include/uiautomationcore.idl
@@ -151,4 +151,35 @@ library UIA
HRESULT GetFocus([out, retval] IRawElementProviderFragment **pRetVal);
}
+
+ [
+ object,
+ uuid(e44c3566-915d-4070-99c6-047bff5a08f5),
+ pointer_default(unique),
+ oleautomation
+ ]
+ interface ILegacyIAccessibleProvider : IUnknown
+ {
+ HRESULT Select(long flagsSelect);
+ HRESULT DoDefaultAction();
+ HRESULT SetValue(LPCWSTR szValue);
+ HRESULT GetIAccessible([out, retval] IAccessible **ppAccessible);
+
+ [propget] HRESULT ChildId([out, retval] int *pRetVal);
+ [propget] HRESULT Name([out, retval] BSTR *pszName);
+ [propget] HRESULT Value([out, retval] BSTR *pszValue);
+ [propget] HRESULT Description([out, retval] BSTR *pszDescription);
+ [propget] HRESULT Role([out, retval] DWORD *pdwRole);
+ [propget] HRESULT State([out, retval] DWORD *pdwState);
+ [propget] HRESULT Help([out, retval] BSTR *pszHelp);
+ [propget] HRESULT KeyboardShortcut([out, retval] BSTR *pszKeyboardShortcut);
+ /*
+ * FIXME: Current versions of Windows SDK use
+ * SAFEARRAY(IRawElementProviderSimple *) instead of
+ * SAFEARRAY(VARIANT). The new type is currently unsupported
+ * in widl, we should switch to it when it is.
+ */
+ HRESULT GetSelection([out, retval] SAFEARRAY(VARIANT) *pvarSelectedChildren);
+ [propget] HRESULT DefaultAction([out, retval] BSTR *pszDefaultAction);
+ }
}
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/216
June 9, 2022
[PATCH 1/3] uiautomationcore: Implement get_HostRawElementProvider for MSAA providers.
by Connor McAdams
From: Connor McAdams <cmcadams(a)codeweavers.com>
Signed-off-by: Connor McAdams <cmcadams(a)codeweavers.com>
---
dlls/uiautomationcore/tests/uiautomation.c | 479 ++++++++++++++++++++-
dlls/uiautomationcore/uia_provider.c | 173 +++++++-
2 files changed, 637 insertions(+), 15 deletions(-)
diff --git a/dlls/uiautomationcore/tests/uiautomation.c b/dlls/uiautomationcore/tests/uiautomation.c
index f3e4b89a120..6ed3c907a40 100644
--- a/dlls/uiautomationcore/tests/uiautomation.c
+++ b/dlls/uiautomationcore/tests/uiautomation.c
@@ -58,13 +58,21 @@ static HRESULT (WINAPI *pUiaProviderFromIAccessible)(IAccessible *, long, DWORD,
DEFINE_EXPECT(winproc_GETOBJECT_CLIENT);
DEFINE_EXPECT(Accessible_accNavigate);
DEFINE_EXPECT(Accessible_get_accParent);
+DEFINE_EXPECT(Accessible_get_accChildCount);
+DEFINE_EXPECT(Accessible_get_accName);
DEFINE_EXPECT(Accessible_get_accRole);
DEFINE_EXPECT(Accessible_get_accState);
+DEFINE_EXPECT(Accessible_accLocation);
+DEFINE_EXPECT(Accessible2_get_accParent);
+DEFINE_EXPECT(Accessible2_get_accChildCount);
+DEFINE_EXPECT(Accessible2_get_accName);
+DEFINE_EXPECT(Accessible2_get_accRole);
+DEFINE_EXPECT(Accessible2_get_accState);
+DEFINE_EXPECT(Accessible2_accLocation);
+DEFINE_EXPECT(Accessible2_QI_IAccIdentity);
DEFINE_EXPECT(Accessible_child_accNavigate);
DEFINE_EXPECT(Accessible_child_get_accParent);
-static IAccessible *acc_client;
-
static BOOL check_variant_i4(VARIANT *v, int val)
{
if (V_VT(v) == VT_I4 && V_I4(v) == val)
@@ -92,7 +100,10 @@ static struct Accessible
HWND ow_hwnd;
INT role;
INT state;
-} Accessible, Accessible_child;
+ LONG child_count;
+ LPCWSTR name;
+ LONG left, top, width, height;
+} Accessible, Accessible2, Accessible_child;
static inline struct Accessible* impl_from_Accessible(IAccessible *iface)
{
@@ -104,6 +115,14 @@ static HRESULT WINAPI Accessible_QueryInterface(IAccessible *iface, REFIID riid,
struct Accessible *This = impl_from_Accessible(iface);
*obj = NULL;
+ if (IsEqualIID(riid, &IID_IAccIdentity))
+ {
+ if (This == &Accessible2)
+ CHECK_EXPECT(Accessible2_QI_IAccIdentity);
+ ok(This == &Accessible2, "unexpected call\n");
+ return E_NOINTERFACE;
+ }
+
if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDispatch) ||
IsEqualIID(riid, &IID_IAccessible))
*obj = iface;
@@ -162,6 +181,8 @@ static HRESULT WINAPI Accessible_get_accParent(IAccessible *iface, IDispatch **o
if (This == &Accessible_child)
CHECK_EXPECT(Accessible_child_get_accParent);
+ else if (This == &Accessible2)
+ CHECK_EXPECT(Accessible2_get_accParent);
else
CHECK_EXPECT(Accessible_get_accParent);
@@ -174,7 +195,19 @@ static HRESULT WINAPI Accessible_get_accParent(IAccessible *iface, IDispatch **o
static HRESULT WINAPI Accessible_get_accChildCount(IAccessible *iface, LONG *out_count)
{
- ok(0, "unexpected call\n");
+ struct Accessible *This = impl_from_Accessible(iface);
+
+ if (This == &Accessible2)
+ CHECK_EXPECT(Accessible2_get_accChildCount);
+ else
+ CHECK_EXPECT(Accessible_get_accChildCount);
+
+ if (This->child_count)
+ {
+ *out_count = This->child_count;
+ return S_OK;
+ }
+
return E_NOTIMPL;
}
@@ -188,7 +221,20 @@ static HRESULT WINAPI Accessible_get_accChild(IAccessible *iface, VARIANT child_
static HRESULT WINAPI Accessible_get_accName(IAccessible *iface, VARIANT child_id,
BSTR *out_name)
{
- ok(0, "unexpected call\n");
+ struct Accessible *This = impl_from_Accessible(iface);
+
+ *out_name = NULL;
+ if (This == &Accessible2)
+ CHECK_EXPECT(Accessible2_get_accName);
+ else
+ CHECK_EXPECT(Accessible_get_accName);
+
+ if (This->name)
+ {
+ *out_name = SysAllocString(This->name);
+ return S_OK;
+ }
+
return E_NOTIMPL;
}
@@ -211,8 +257,10 @@ static HRESULT WINAPI Accessible_get_accRole(IAccessible *iface, VARIANT child_i
{
struct Accessible *This = impl_from_Accessible(iface);
- ok(This == &Accessible, "unexpected call\n");
- CHECK_EXPECT(Accessible_get_accRole);
+ if (This == &Accessible2)
+ CHECK_EXPECT(Accessible2_get_accRole);
+ else
+ CHECK_EXPECT(Accessible_get_accRole);
if (This->role)
{
@@ -229,8 +277,10 @@ static HRESULT WINAPI Accessible_get_accState(IAccessible *iface, VARIANT child_
{
struct Accessible *This = impl_from_Accessible(iface);
- ok(This == &Accessible, "unexpected call\n");
- CHECK_EXPECT(Accessible_get_accState);
+ if (This == &Accessible2)
+ CHECK_EXPECT(Accessible2_get_accState);
+ else
+ CHECK_EXPECT(Accessible_get_accState);
if (This->state)
{
@@ -292,7 +342,22 @@ static HRESULT WINAPI Accessible_accSelect(IAccessible *iface, LONG select_flags
static HRESULT WINAPI Accessible_accLocation(IAccessible *iface, LONG *out_left,
LONG *out_top, LONG *out_width, LONG *out_height, VARIANT child_id)
{
- ok(0, "unexpected call\n");
+ struct Accessible *This = impl_from_Accessible(iface);
+
+ if (This == &Accessible2)
+ CHECK_EXPECT(Accessible2_accLocation);
+ else
+ CHECK_EXPECT(Accessible_accLocation);
+
+ if (This->width && This->height)
+ {
+ *out_left = This->left;
+ *out_top = This->top;
+ *out_width = This->width;
+ *out_height = This->height;
+ return S_OK;
+ }
+
return E_NOTIMPL;
}
@@ -430,8 +495,21 @@ static struct Accessible Accessible =
1,
NULL,
0, 0,
+ 0, 0, 0, NULL,
+ 0, 0, 0, 0,
+};
+
+static struct Accessible Accessible2 =
+{
+ { &AccessibleVtbl },
+ { &OleWindowVtbl },
+ 1,
+ NULL,
0, 0,
+ 0, 0, 0, NULL,
+ 0, 0, 0, 0,
};
+
static struct Accessible Accessible_child =
{
{ &AccessibleVtbl },
@@ -439,9 +517,11 @@ static struct Accessible Accessible_child =
1,
&Accessible.IAccessible_iface,
0, 0,
- 0, 0,
+ 0, 0, 0, NULL,
+ 0, 0, 0, 0,
};
+static IAccessible *acc_client;
static LRESULT WINAPI test_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
@@ -782,6 +862,20 @@ static const struct msaa_state_uia_prop msaa_state_uia_props[] = {
{ STATE_SYSTEM_PROTECTED, UIA_IsPasswordPropertyId },
};
+static void set_accessible_props(struct Accessible *acc, INT role, INT state,
+ LONG child_count, LPCWSTR name, LONG left, LONG top, LONG width, LONG height)
+{
+
+ acc->role = role;
+ acc->state = state;
+ acc->child_count = child_count;
+ acc->name = name;
+ acc->left = left;
+ acc->top = top;
+ acc->width = width;
+ acc->height = height;
+}
+
static void test_uia_prov_from_acc_properties(void)
{
IRawElementProviderSimple *elprov;
@@ -883,7 +977,7 @@ static void test_uia_prov_from_acc_properties(void)
static void test_UiaProviderFromIAccessible(void)
{
- IRawElementProviderSimple *elprov;
+ IRawElementProviderSimple *elprov, *elprov2;
enum ProviderOptions prov_opt;
IAccessible *acc;
WNDCLASSA cls;
@@ -891,7 +985,7 @@ static void test_UiaProviderFromIAccessible(void)
HWND hwnd;
VARIANT v;
-
+ CoInitializeEx(NULL, COINIT_MULTITHREADED);
cls.style = 0;
cls.lpfnWndProc = test_wnd_proc;
cls.cbClsExtra = 0;
@@ -997,11 +1091,370 @@ static void test_UiaProviderFromIAccessible(void)
hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, 1, UIA_PFIA_DEFAULT, &elprov);
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
+
+ /*
+ * Simple child element (IAccessible without CHILDID_SELF) cannot be root
+ * IAccessible. No checks against the root HWND IAccessible will be done.
+ */
+ elprov2 = (void *)0xdeadbeef;
+ hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
+ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+ ok(!elprov2, "elprov != NULL\n");
+
+ IRawElementProviderSimple_Release(elprov);
+ ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
+
+ /*
+ * &Accessible.IAccessible_iface will be compared against the default
+ * client accessible object. Since we have all properties set to 0,
+ * we return failure HRESULTs and all properties will get queried but not
+ * compared.
+ */
+ hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
+ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+ ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
+
+ SET_EXPECT(winproc_GETOBJECT_CLIENT);
+ SET_EXPECT(Accessible_get_accRole);
+ SET_EXPECT(Accessible_get_accState);
+ SET_EXPECT(Accessible_get_accChildCount);
+ SET_EXPECT(Accessible_accLocation);
+ SET_EXPECT(Accessible_get_accName);
+ elprov2 = (void *)0xdeadbeef;
+ hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
+ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+ ok(!elprov2, "elprov != NULL\n");
+ CHECK_CALLED(winproc_GETOBJECT_CLIENT);
+ CHECK_CALLED(Accessible_get_accRole);
+ CHECK_CALLED(Accessible_get_accState);
+ CHECK_CALLED(Accessible_get_accChildCount);
+ CHECK_CALLED(Accessible_accLocation);
+ CHECK_CALLED(Accessible_get_accName);
+
+ /* Second call won't send WM_GETOBJECT. */
+ elprov2 = (void *)0xdeadbeef;
+ hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
+ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+ ok(!elprov2, "elprov != NULL\n");
+
+ IRawElementProviderSimple_Release(elprov);
+ ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
+
+ /*
+ * Return &Accessible.IAccessible_iface in response to OBJID_CLIENT,
+ * interface pointers will be compared, no method calls to check property
+ * values.
+ */
+ hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
+ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+ ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
+
+ SET_EXPECT(winproc_GETOBJECT_CLIENT);
+ elprov2 = (void *)0xdeadbeef;
+ acc_client = &Accessible.IAccessible_iface;
+ hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
+ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+ ok(!!elprov2, "elprov == NULL, elprov %p\n", elprov2);
+ IRawElementProviderSimple_Release(elprov2);
+ CHECK_CALLED(winproc_GETOBJECT_CLIENT);
+
+ /* Second call, no checks. */
+ elprov2 = (void *)0xdeadbeef;
+ acc_client = NULL;
+ hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
+ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+ ok(!!elprov2, "elprov == NULL, elprov %p\n", elprov2);
+ IRawElementProviderSimple_Release(elprov2);
+
+ IRawElementProviderSimple_Release(elprov);
+ ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
+
+ /*
+ * Return &Accessible2.IAccessible_iface in response to OBJID_CLIENT,
+ * interface pointers won't match, so properties will be compared.
+ */
+ hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
+ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+ ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
+
+ set_accessible_props(&Accessible, ROLE_SYSTEM_DOCUMENT, STATE_SYSTEM_FOCUSABLE, 1,
+ L"acc_name", 0, 0, 50, 50);
+ set_accessible_props(&Accessible2, ROLE_SYSTEM_DOCUMENT, STATE_SYSTEM_FOCUSABLE, 1,
+ L"acc_name", 0, 0, 50, 50);
+
+ acc_client = &Accessible2.IAccessible_iface;
+ SET_EXPECT(winproc_GETOBJECT_CLIENT);
+ SET_EXPECT(Accessible_get_accRole);
+ SET_EXPECT(Accessible_get_accState);
+ SET_EXPECT(Accessible_get_accChildCount);
+ SET_EXPECT(Accessible_accLocation);
+ SET_EXPECT(Accessible_get_accName);
+ SET_EXPECT(Accessible2_get_accRole);
+ SET_EXPECT(Accessible2_get_accState);
+ SET_EXPECT(Accessible2_get_accChildCount);
+ SET_EXPECT(Accessible2_accLocation);
+ SET_EXPECT(Accessible2_get_accName);
+ /*
+ * The IAccessible returned by WM_GETOBJECT will be checked for an
+ * IAccIdentity interface to see if Dynamic Annotation properties should
+ * be queried. If not present on the current IAccessible, it will check
+ * the parent IAccessible for one.
+ */
+ SET_EXPECT(Accessible2_QI_IAccIdentity);
+ SET_EXPECT(Accessible2_get_accParent);
+ elprov2 = (void *)0xdeadbeef;
+ hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
+ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+ ok(!!elprov2, "elprov == NULL, elprov %p\n", elprov2);
+ ok(Accessible2.ref == 1, "Unexpected refcnt %ld\n", Accessible2.ref);
+ CHECK_CALLED(winproc_GETOBJECT_CLIENT);
+ CHECK_CALLED(Accessible_get_accRole);
+ CHECK_CALLED(Accessible_get_accState);
+ CHECK_CALLED(Accessible_get_accChildCount);
+ CHECK_CALLED(Accessible_accLocation);
+ CHECK_CALLED(Accessible_get_accName);
+ CHECK_CALLED(Accessible2_get_accRole);
+ CHECK_CALLED(Accessible2_get_accState);
+ CHECK_CALLED(Accessible2_get_accChildCount);
+ CHECK_CALLED(Accessible2_accLocation);
+ CHECK_CALLED(Accessible2_get_accName);
+ todo_wine CHECK_CALLED(Accessible2_QI_IAccIdentity);
+ todo_wine CHECK_CALLED(Accessible2_get_accParent);
+ IRawElementProviderSimple_Release(elprov2);
+
+ elprov2 = (void *)0xdeadbeef;
+ acc_client = NULL;
+ hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
+ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+ ok(!!elprov2, "elprov == NULL, elprov %p\n", elprov2);
+ IRawElementProviderSimple_Release(elprov2);
+
+ IRawElementProviderSimple_Release(elprov);
+ ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
+
+ /*
+ * If a failure HRESULT is returned from the IRawElementProviderSimple
+ * IAccessible, the corresponding AOFW IAccessible method isn't called.
+ * An exception is get_accChildCount, which is always called, but only
+ * checked if the HRESULT return value is not a failure. If Role/State/Name
+ * are not queried, no IAccIdentity check is done.
+ */
+ hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
+ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+ ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
+
+ set_accessible_props(&Accessible, 0, 0, 0, NULL, 0, 0, 0, 0);
+ set_accessible_props(&Accessible2, ROLE_SYSTEM_DOCUMENT, STATE_SYSTEM_FOCUSABLE, 1,
+ L"acc_name", 0, 0, 50, 50);
+
+ acc_client = &Accessible2.IAccessible_iface;
+ SET_EXPECT(winproc_GETOBJECT_CLIENT);
+ SET_EXPECT(Accessible_get_accRole);
+ SET_EXPECT(Accessible_get_accState);
+ SET_EXPECT(Accessible_get_accChildCount);
+ SET_EXPECT(Accessible2_get_accChildCount);
+ SET_EXPECT(Accessible_accLocation);
+ SET_EXPECT(Accessible_get_accName);
+ elprov2 = (void *)0xdeadbeef;
+ hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
+ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+ ok(!elprov2, "elprov != NULL, elprov %p\n", elprov2);
+ CHECK_CALLED(winproc_GETOBJECT_CLIENT);
+ CHECK_CALLED(Accessible_get_accRole);
+ CHECK_CALLED(Accessible_get_accState);
+ CHECK_CALLED(Accessible_get_accChildCount);
+ CHECK_CALLED(Accessible2_get_accChildCount);
+ CHECK_CALLED(Accessible_accLocation);
+ CHECK_CALLED(Accessible_get_accName);
+
+ acc_client = NULL;
+ elprov2 = (void *)0xdeadbeef;
+ hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
+ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+ ok(!elprov2, "elprov != NULL, elprov %p\n", elprov2);
+
+ IRawElementProviderSimple_Release(elprov);
+ ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
+
+ /*
+ * Properties are checked in a sequence of accRole, accState,
+ * accChildCount, accLocation, and finally accName. If a mismatch is found
+ * early in the sequence, the rest aren't checked.
+ */
+ hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
+ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+ ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
+
+ set_accessible_props(&Accessible, ROLE_SYSTEM_DOCUMENT, STATE_SYSTEM_FOCUSABLE, 0, NULL, 0, 0, 0, 0);
+ set_accessible_props(&Accessible2, ROLE_SYSTEM_CLIENT, STATE_SYSTEM_FOCUSABLE, 0, NULL, 0, 0, 0, 0);
+
+ acc_client = &Accessible2.IAccessible_iface;
+ SET_EXPECT(winproc_GETOBJECT_CLIENT);
+ SET_EXPECT(Accessible_get_accRole);
+ SET_EXPECT(Accessible2_get_accRole);
+ SET_EXPECT(Accessible2_QI_IAccIdentity);
+ SET_EXPECT(Accessible2_get_accParent);
+ elprov2 = (void *)0xdeadbeef;
+ hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
+ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+ ok(!elprov2, "elprov != NULL, elprov %p\n", elprov2);
+ CHECK_CALLED(winproc_GETOBJECT_CLIENT);
+ CHECK_CALLED(Accessible_get_accRole);
+ CHECK_CALLED(Accessible2_get_accRole);
+ todo_wine CHECK_CALLED(Accessible2_QI_IAccIdentity);
+ todo_wine CHECK_CALLED(Accessible2_get_accParent);
+
+ elprov2 = (void *)0xdeadbeef;
+ acc_client = NULL;
+ hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
+ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+ ok(!elprov2, "elprov != NULL, elprov %p\n", elprov2);
+
+ IRawElementProviderSimple_Release(elprov);
+ ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
+
+ /* 4/5 properties match, considered a match. */
+ hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
+ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+ ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
+
+ set_accessible_props(&Accessible, ROLE_SYSTEM_DOCUMENT, STATE_SYSTEM_FOCUSABLE, 1, NULL, 0, 0, 50, 50);
+ set_accessible_props(&Accessible2, ROLE_SYSTEM_DOCUMENT, STATE_SYSTEM_FOCUSABLE, 1, NULL, 0, 0, 50, 50);
+
+ acc_client = &Accessible2.IAccessible_iface;
+ SET_EXPECT(winproc_GETOBJECT_CLIENT);
+ SET_EXPECT(Accessible_get_accRole);
+ SET_EXPECT(Accessible_get_accState);
+ SET_EXPECT(Accessible_get_accChildCount);
+ SET_EXPECT(Accessible_accLocation);
+ SET_EXPECT(Accessible_get_accName);
+ SET_EXPECT(Accessible2_get_accRole);
+ SET_EXPECT(Accessible2_get_accState);
+ SET_EXPECT(Accessible2_get_accChildCount);
+ SET_EXPECT(Accessible2_accLocation);
+ SET_EXPECT(Accessible2_QI_IAccIdentity);
+ SET_EXPECT(Accessible2_get_accParent);
+ elprov2 = (void *)0xdeadbeef;
+ hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
+ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+ ok(!!elprov2, "elprov == NULL, elprov %p\n", elprov2);
+ ok(Accessible2.ref == 1, "Unexpected refcnt %ld\n", Accessible2.ref);
+ CHECK_CALLED(winproc_GETOBJECT_CLIENT);
+ CHECK_CALLED(Accessible_get_accRole);
+ CHECK_CALLED(Accessible_get_accState);
+ CHECK_CALLED(Accessible_get_accChildCount);
+ CHECK_CALLED(Accessible_accLocation);
+ CHECK_CALLED(Accessible_get_accName);
+ CHECK_CALLED(Accessible2_get_accRole);
+ CHECK_CALLED(Accessible2_get_accState);
+ CHECK_CALLED(Accessible2_get_accChildCount);
+ CHECK_CALLED(Accessible2_accLocation);
+ todo_wine CHECK_CALLED(Accessible2_QI_IAccIdentity);
+ todo_wine CHECK_CALLED(Accessible2_get_accParent);
+ IRawElementProviderSimple_Release(elprov2);
+
+ elprov2 = (void *)0xdeadbeef;
+ acc_client = NULL;
+ hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
+ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+ ok(!!elprov2, "elprov == NULL, elprov %p\n", elprov2);
+ IRawElementProviderSimple_Release(elprov2);
+
+ IRawElementProviderSimple_Release(elprov);
+ ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
+
+ /* 3/5 properties match, not considered a match. */
+ hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
+ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+ ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
+
+ set_accessible_props(&Accessible, ROLE_SYSTEM_DOCUMENT, STATE_SYSTEM_FOCUSABLE, 1, NULL, 0, 0, 0, 0);
+ set_accessible_props(&Accessible2, ROLE_SYSTEM_DOCUMENT, STATE_SYSTEM_FOCUSABLE, 1, NULL, 0, 0, 0, 0);
+
+ acc_client = &Accessible2.IAccessible_iface;
+ SET_EXPECT(winproc_GETOBJECT_CLIENT);
+ SET_EXPECT(Accessible_get_accRole);
+ SET_EXPECT(Accessible_get_accState);
+ SET_EXPECT(Accessible_get_accChildCount);
+ SET_EXPECT(Accessible_accLocation);
+ SET_EXPECT(Accessible_get_accName);
+ SET_EXPECT(Accessible2_get_accRole);
+ SET_EXPECT(Accessible2_get_accState);
+ SET_EXPECT(Accessible2_get_accChildCount);
+ SET_EXPECT(Accessible2_QI_IAccIdentity);
+ SET_EXPECT(Accessible2_get_accParent);
+ elprov2 = (void *)0xdeadbeef;
+ hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
+ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+ ok(!elprov2, "elprov != NULL, elprov %p\n", elprov2);
+ CHECK_CALLED(winproc_GETOBJECT_CLIENT);
+ CHECK_CALLED(Accessible_get_accRole);
+ CHECK_CALLED(Accessible_get_accState);
+ CHECK_CALLED(Accessible_get_accChildCount);
+ CHECK_CALLED(Accessible_accLocation);
+ CHECK_CALLED(Accessible_get_accName);
+ CHECK_CALLED(Accessible2_get_accRole);
+ CHECK_CALLED(Accessible2_get_accState);
+ CHECK_CALLED(Accessible2_get_accChildCount);
+ todo_wine CHECK_CALLED(Accessible2_QI_IAccIdentity);
+ todo_wine CHECK_CALLED(Accessible2_get_accParent);
+
+ elprov2 = (void *)0xdeadbeef;
+ acc_client = NULL;
+ hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
+ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+ ok(!elprov2, "elprov != NULL, elprov %p\n", elprov2);
+
+ IRawElementProviderSimple_Release(elprov);
+ ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
+
+ /* Only name matches, considered a match. */
+ hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
+ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+ ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
+
+ set_accessible_props(&Accessible, 0, 0, 0, L"acc_name", 0, 0, 0, 0);
+ set_accessible_props(&Accessible2, 0, 0, 0, L"acc_name", 0, 0, 0, 0);
+
+ acc_client = &Accessible2.IAccessible_iface;
+ SET_EXPECT(winproc_GETOBJECT_CLIENT);
+ SET_EXPECT(Accessible_get_accRole);
+ SET_EXPECT(Accessible_get_accState);
+ SET_EXPECT(Accessible_get_accChildCount);
+ SET_EXPECT(Accessible_accLocation);
+ SET_EXPECT(Accessible_get_accName);
+ SET_EXPECT(Accessible2_get_accChildCount);
+ SET_EXPECT(Accessible2_get_accName);
+ SET_EXPECT(Accessible2_QI_IAccIdentity);
+ SET_EXPECT(Accessible2_get_accParent);
+ elprov2 = (void *)0xdeadbeef;
+ hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
+ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+ ok(!!elprov2, "elprov == NULL, elprov %p\n", elprov2);
+ ok(Accessible2.ref == 1, "Unexpected refcnt %ld\n", Accessible2.ref);
+ CHECK_CALLED(winproc_GETOBJECT_CLIENT);
+ CHECK_CALLED(Accessible_get_accRole);
+ CHECK_CALLED(Accessible_get_accState);
+ CHECK_CALLED(Accessible_get_accChildCount);
+ CHECK_CALLED(Accessible_accLocation);
+ CHECK_CALLED(Accessible_get_accName);
+ CHECK_CALLED(Accessible2_get_accChildCount);
+ CHECK_CALLED(Accessible2_get_accName);
+ todo_wine CHECK_CALLED(Accessible2_QI_IAccIdentity);
+ todo_wine CHECK_CALLED(Accessible2_get_accParent);
+
+ elprov2 = (void *)0xdeadbeef;
+ acc_client = NULL;
+ hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
+ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+ ok(!!elprov2, "elprov == NULL, elprov %p\n", elprov2);
+
IRawElementProviderSimple_Release(elprov);
ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
test_uia_prov_from_acc_properties();
+ CoUninitialize();
DestroyWindow(hwnd);
UnregisterClassA("pUiaProviderFromIAccessible class", NULL);
Accessible.acc_hwnd = NULL;
diff --git a/dlls/uiautomationcore/uia_provider.c b/dlls/uiautomationcore/uia_provider.c
index dae0187596d..700eaae4a2c 100644
--- a/dlls/uiautomationcore/uia_provider.c
+++ b/dlls/uiautomationcore/uia_provider.c
@@ -23,9 +23,12 @@
#include "wine/debug.h"
#include "wine/heap.h"
+#include "initguid.h"
WINE_DEFAULT_DEBUG_CHANNEL(uiautomation);
+DEFINE_GUID(SID_AccFromDAWrapper, 0x33f139ee, 0xe509, 0x47f7, 0xbf,0x39, 0x83,0x76,0x44,0xf7,0x45,0x76);
+
static void variant_init_i4(VARIANT *v, int val)
{
V_VT(v) = VT_I4;
@@ -51,6 +54,140 @@ static BOOL msaa_check_acc_state(IAccessible *acc, VARIANT cid, ULONG flag)
return FALSE;
}
+static IAccessible *msaa_acc_da_unwrap(IAccessible *acc)
+{
+ IServiceProvider *sp;
+ IAccessible *acc2;
+ HRESULT hr;
+
+ hr = IAccessible_QueryInterface(acc, &IID_IServiceProvider, (void**)&sp);
+ if (SUCCEEDED(hr))
+ {
+ hr = IServiceProvider_QueryService(sp, &SID_AccFromDAWrapper, &IID_IAccessible, (void**)&acc2);
+ IServiceProvider_Release(sp);
+ }
+
+ if (SUCCEEDED(hr) && acc2)
+ return acc2;
+
+ IAccessible_AddRef(acc);
+ return acc;
+}
+
+static BOOL msaa_acc_compare(IAccessible *acc, IAccessible *acc2)
+{
+ LONG child_count[2], left[2], top[2], width[2], height[2];
+ BSTR name[2] = { NULL, NULL };
+ BOOL matched = FALSE;
+ int match_count = 0;
+ VARIANT cid, v, v2;
+ HRESULT hr, hr2;
+
+ acc = msaa_acc_da_unwrap(acc);
+ acc2 = msaa_acc_da_unwrap(acc2);
+ if (acc == acc2)
+ {
+ matched = TRUE;
+ goto exit;
+ }
+ else
+ {
+ IUnknown *unk, *unk2;
+
+ IAccessible_QueryInterface(acc, &IID_IUnknown, (void**)&unk);
+ IUnknown_Release(unk);
+ IAccessible_QueryInterface(acc2, &IID_IUnknown, (void**)&unk2);
+ IUnknown_Release(unk2);
+ if (unk == unk2)
+ {
+ matched = TRUE;
+ goto exit;
+ }
+ }
+
+ variant_init_i4(&cid, CHILDID_SELF);
+ VariantInit(&v);
+ hr = IAccessible_get_accRole(acc, cid, &v);
+ if (SUCCEEDED(hr) && (V_VT(&v) == VT_I4))
+ {
+ VariantInit(&v2);
+ hr = IAccessible_get_accRole(acc2, cid, &v2);
+ if (SUCCEEDED(hr) && (V_VT(&v2) == VT_I4))
+ {
+ if (V_I4(&v) != V_I4(&v2))
+ goto exit;
+
+ match_count++;
+ }
+ }
+
+ VariantInit(&v);
+ hr = IAccessible_get_accState(acc, cid, &v);
+ if (SUCCEEDED(hr) && (V_VT(&v) == VT_I4))
+ {
+ VariantInit(&v2);
+ hr = IAccessible_get_accState(acc2, cid, &v2);
+ if (SUCCEEDED(hr) && (V_VT(&v2) == VT_I4))
+ {
+ if (V_I4(&v) != V_I4(&v2))
+ goto exit;
+
+ match_count++;
+ }
+ }
+
+ hr = IAccessible_get_accChildCount(acc, &child_count[0]);
+ hr2 = IAccessible_get_accChildCount(acc2, &child_count[1]);
+ if (SUCCEEDED(hr) && SUCCEEDED(hr2))
+ {
+ if (child_count[0] != child_count[1])
+ goto exit;
+
+ match_count++;
+ }
+
+ hr = IAccessible_accLocation(acc, &left[0], &top[0], &width[0], &height[0], cid);
+ if (SUCCEEDED(hr))
+ {
+ hr = IAccessible_accLocation(acc2, &left[1], &top[1], &width[1], &height[1], cid);
+ if (SUCCEEDED(hr))
+ {
+ if ((left[0] != left[1]) || (top[0] != top[1]) || (width[0] != width[1]) ||
+ (height[0] != height[1]))
+ goto exit;
+
+ match_count++;
+ }
+ }
+
+ hr = IAccessible_get_accName(acc, cid, &name[0]);
+ if (SUCCEEDED(hr))
+ {
+ hr = IAccessible_get_accName(acc2, cid, &name[1]);
+ if (SUCCEEDED(hr))
+ {
+ if ((!(!name[0] && !name[1]) && (!name[0] || !name[1])) ||
+ ((name[0] && name[1]) && wcscmp(name[0], name[1])))
+ goto exit;
+
+ /* accName match is always a confirmed match. */
+ matched = TRUE;
+ }
+ }
+
+ if (match_count == 4)
+ matched = TRUE;
+
+exit:
+
+ SysFreeString(name[0]);
+ SysFreeString(name[1]);
+ IAccessible_Release(acc);
+ IAccessible_Release(acc2);
+
+ return matched;
+}
+
static LONG msaa_role_to_uia_control_type(LONG role)
{
switch (role)
@@ -141,8 +278,34 @@ struct msaa_provider {
VARIANT cid;
HWND hwnd;
LONG control_type;
+
+ BOOL root_acc_check_ran;
+ BOOL is_root_acc;
};
+static BOOL msaa_check_root_acc(struct msaa_provider *msaa_prov)
+{
+ IAccessible *acc;
+ HRESULT hr;
+
+ if (msaa_prov->root_acc_check_ran)
+ return msaa_prov->is_root_acc;
+
+ msaa_prov->root_acc_check_ran = TRUE;
+ if (V_I4(&msaa_prov->cid) != CHILDID_SELF)
+ return FALSE;
+
+ hr = AccessibleObjectFromWindow(msaa_prov->hwnd, OBJID_CLIENT, &IID_IAccessible, (void **)&acc);
+ if (FAILED(hr))
+ return FALSE;
+
+ if (msaa_acc_compare(msaa_prov->acc, acc))
+ msaa_prov->is_root_acc = TRUE;
+
+ IAccessible_Release(acc);
+ return msaa_prov->is_root_acc;
+}
+
static inline struct msaa_provider *impl_from_msaa_provider(IRawElementProviderSimple *iface)
{
return CONTAINING_RECORD(iface, struct msaa_provider, IRawElementProviderSimple_iface);
@@ -264,9 +427,15 @@ HRESULT WINAPI msaa_provider_GetPropertyValue(IRawElementProviderSimple *iface,
HRESULT WINAPI msaa_provider_get_HostRawElementProvider(IRawElementProviderSimple *iface,
IRawElementProviderSimple **ret_val)
{
- FIXME("%p, %p: stub!\n", iface, ret_val);
+ struct msaa_provider *msaa_prov = impl_from_msaa_provider(iface);
+
+ TRACE("%p, %p\n", iface, ret_val);
+
*ret_val = NULL;
- return E_NOTIMPL;
+ if (msaa_check_root_acc(msaa_prov))
+ return UiaHostProviderFromHwnd(msaa_prov->hwnd, ret_val);
+
+ return S_OK;
}
static const IRawElementProviderSimpleVtbl msaa_provider_vtbl = {
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/216
June 9, 2022
[PATCH 0/3] MR216: uiautomationcore: More UiaProviderFromIAccessible work.
by Connor McAdams (@cmcadams)
--
https://gitlab.winehq.org/wine/wine/-/merge_requests/216
June 9, 2022
[PATCH 1/1] winevulkan: Update to VK spec version 1.3.217.
by Georg Lehmann
From: Georg Lehmann <dadschoorse(a)gmail.com>
Signed-off-by: Georg Lehmann <dadschoorse(a)gmail.com>
---
dlls/winevulkan/make_vulkan | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/dlls/winevulkan/make_vulkan b/dlls/winevulkan/make_vulkan
index b031492fbfd..69e2f0cd256 100755
--- a/dlls/winevulkan/make_vulkan
+++ b/dlls/winevulkan/make_vulkan
@@ -64,7 +64,7 @@ from enum import Enum
LOGGER = logging.Logger("vulkan")
LOGGER.addHandler(logging.StreamHandler())
-VK_XML_VERSION = "1.3.215"
+VK_XML_VERSION = "1.3.217"
WINE_VK_VERSION = (1, 3)
# Filenames to create.
@@ -107,6 +107,7 @@ UNSUPPORTED_EXTENSIONS = [
# Extensions for other platforms
"VK_EXT_external_memory_dma_buf",
"VK_EXT_image_drm_format_modifier",
+ "VK_EXT_metal_objects",
"VK_EXT_physical_device_drm",
"VK_GOOGLE_surfaceless_query",
"VK_KHR_external_fence_fd",
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/215
June 9, 2022
[PATCH 0/1] MR215: winevulkan: Update to VK spec version 1.3.217.
by Georg Lehmann (@DadSchoorse)
--
https://gitlab.winehq.org/wine/wine/-/merge_requests/215
June 9, 2022