[PATCH 2/2] uiautomationcore/tests: Add tests for UiaProviderFromIAccessible.
Connor McAdams
cmcadams at codeweavers.com
Fri Apr 29 08:46:56 CDT 2022
Signed-off-by: Connor McAdams <cmcadams at codeweavers.com>
---
dlls/uiautomationcore/tests/Makefile.in | 2 +-
dlls/uiautomationcore/tests/uiautomation.c | 424 +++++++++++++++++++++
2 files changed, 425 insertions(+), 1 deletion(-)
diff --git a/dlls/uiautomationcore/tests/Makefile.in b/dlls/uiautomationcore/tests/Makefile.in
index fbd53507fbe..53ed6f6e380 100644
--- a/dlls/uiautomationcore/tests/Makefile.in
+++ b/dlls/uiautomationcore/tests/Makefile.in
@@ -1,5 +1,5 @@
TESTDLL = uiautomationcore.dll
-IMPORTS = uiautomationcore user32 ole32 oleaut32
+IMPORTS = uiautomationcore user32 ole32 oleaut32 oleacc
C_SRCS = \
uiautomation.c
diff --git a/dlls/uiautomationcore/tests/uiautomation.c b/dlls/uiautomationcore/tests/uiautomation.c
index 501875a20e7..246f8aba7c1 100644
--- a/dlls/uiautomationcore/tests/uiautomation.c
+++ b/dlls/uiautomationcore/tests/uiautomation.c
@@ -23,9 +23,322 @@
#include "windows.h"
#include "initguid.h"
#include "uiautomation.h"
+#include "ocidl.h"
#include "wine/test.h"
+static HRESULT (WINAPI *pUiaProviderFromIAccessible)(IAccessible *, long, DWORD, IRawElementProviderSimple **);
+
+#define DEFINE_EXPECT(func) \
+ static BOOL expect_ ## func = FALSE, called_ ## func = FALSE
+
+#define SET_EXPECT(func) \
+ do { called_ ## func = FALSE; expect_ ## func = TRUE; } while(0)
+
+#define CHECK_EXPECT2(func) \
+ do { \
+ ok(expect_ ##func, "unexpected call " #func "\n"); \
+ called_ ## func = TRUE; \
+ }while(0)
+
+#define CHECK_EXPECT(func) \
+ do { \
+ CHECK_EXPECT2(func); \
+ expect_ ## func = FALSE; \
+ }while(0)
+
+#define CHECK_CALLED(func) \
+ do { \
+ ok(called_ ## func, "expected " #func "\n"); \
+ expect_ ## func = called_ ## func = FALSE; \
+ }while(0)
+
+DEFINE_EXPECT(Accessible_accNavigate);
+
+static LONG Accessible_ref = 1;
+static IAccessible Accessible;
+static IOleWindow OleWindow;
+static HWND Accessible_hwnd = NULL;
+static HWND OleWindow_hwnd = NULL;
+
+static BOOL check_variant_i4(VARIANT *v, int val)
+{
+ if (V_VT(v) == VT_I4 && V_I4(v) == val)
+ return TRUE;
+
+ return FALSE;
+}
+
+static HRESULT WINAPI Accessible_QueryInterface(IAccessible *iface, REFIID riid, void **obj)
+{
+ *obj = NULL;
+ if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDispatch) ||
+ IsEqualIID(riid, &IID_IAccessible))
+ *obj = iface;
+ else if (IsEqualIID(riid, &IID_IOleWindow))
+ *obj = &OleWindow;
+ else
+ return E_NOINTERFACE;
+
+ IAccessible_AddRef(iface);
+ return S_OK;
+}
+
+static ULONG WINAPI Accessible_AddRef(IAccessible *iface)
+{
+ return InterlockedIncrement(&Accessible_ref);
+}
+
+static ULONG WINAPI Accessible_Release(IAccessible *iface)
+{
+ return InterlockedDecrement(&Accessible_ref);
+}
+
+static HRESULT WINAPI Accessible_GetTypeInfoCount(IAccessible *iface, UINT *pctinfo)
+{
+ ok(0, "unexpected call\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI Accessible_GetTypeInfo(IAccessible *iface, UINT iTInfo,
+ LCID lcid, ITypeInfo **out_tinfo)
+{
+ ok(0, "unexpected call\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI Accessible_GetIDsOfNames(IAccessible *iface, REFIID riid,
+ LPOLESTR *rg_names, UINT name_count, LCID lcid, DISPID *rg_disp_id)
+{
+ ok(0, "unexpected call\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI Accessible_Invoke(IAccessible *iface, DISPID disp_id_member,
+ REFIID riid, LCID lcid, WORD flags, DISPPARAMS *disp_params,
+ VARIANT *var_result, EXCEPINFO *excep_info, UINT *arg_err)
+{
+ ok(0, "unexpected call\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI Accessible_get_accParent(IAccessible *iface, IDispatch **out_parent)
+{
+ ok(0, "unexpected call\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI Accessible_get_accChildCount(IAccessible *iface, LONG *out_count)
+{
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI Accessible_get_accChild(IAccessible *iface, VARIANT child_id,
+ IDispatch **out_child)
+{
+ ok(0, "unexpected call\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI Accessible_get_accName(IAccessible *iface, VARIANT child_id,
+ BSTR *out_name)
+{
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI Accessible_get_accValue(IAccessible *iface, VARIANT child_id,
+ BSTR *out_value)
+{
+ ok(0, "unexpected call\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI Accessible_get_accDescription(IAccessible *iface, VARIANT child_id,
+ BSTR *out_description)
+{
+ ok(0, "unexpected call\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI Accessible_get_accRole(IAccessible *iface, VARIANT child_id,
+ VARIANT *out_role)
+{
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI Accessible_get_accState(IAccessible *iface, VARIANT child_id,
+ VARIANT *out_state)
+{
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI Accessible_get_accHelp(IAccessible *iface, VARIANT child_id,
+ BSTR *out_help)
+{
+ ok(0, "unexpected call\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI Accessible_get_accHelpTopic(IAccessible *iface,
+ BSTR *out_help_file, VARIANT child_id, LONG *out_topic_id)
+{
+ ok(0, "unexpected call\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI Accessible_get_accKeyboardShortcut(IAccessible *iface, VARIANT child_id,
+ BSTR *out_kbd_shortcut)
+{
+ ok(0, "unexpected call\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI Accessible_get_accFocus(IAccessible *iface, VARIANT *pchild_id)
+{
+ ok(0, "unexpected call\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI Accessible_get_accSelection(IAccessible *iface, VARIANT *out_selection)
+{
+ ok(0, "unexpected call\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI Accessible_get_accDefaultAction(IAccessible *iface, VARIANT child_id,
+ BSTR *out_default_action)
+{
+ ok(0, "unexpected call\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI Accessible_accSelect(IAccessible *iface, LONG select_flags,
+ VARIANT child_id)
+{
+ ok(0, "unexpected call\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI Accessible_accLocation(IAccessible *iface, LONG *out_left,
+ LONG *out_top, LONG *out_width, LONG *out_height, VARIANT child_id)
+{
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI Accessible_accNavigate(IAccessible *iface, LONG nav_direction,
+ VARIANT child_id_start, VARIANT *out_var)
+{
+ CHECK_EXPECT(Accessible_accNavigate);
+ VariantInit(out_var);
+
+ /*
+ * This is an undocumented way for UI Automation to get an HWND for
+ * IAccessible's contained in a Direct Annotation wrapper object.
+ */
+ if ((nav_direction == 10) && check_variant_i4(&child_id_start, CHILDID_SELF))
+ {
+ V_VT(out_var) = VT_I4;
+ V_I4(out_var) = HandleToUlong(Accessible_hwnd);
+ return S_OK;
+ }
+ return S_FALSE;
+}
+
+static HRESULT WINAPI Accessible_accHitTest(IAccessible *iface, LONG left, LONG top,
+ VARIANT *out_child_id)
+{
+ ok(0, "unexpected call\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI Accessible_accDoDefaultAction(IAccessible *iface, VARIANT child_id)
+{
+ ok(0, "unexpected call\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI Accessible_put_accName(IAccessible *iface, VARIANT child_id,
+ BSTR name)
+{
+ ok(0, "unexpected call\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI Accessible_put_accValue(IAccessible *iface, VARIANT child_id,
+ BSTR value)
+{
+ ok(0, "unexpected call\n");
+ return E_NOTIMPL;
+}
+
+static IAccessibleVtbl AccessibleVtbl = {
+ Accessible_QueryInterface,
+ Accessible_AddRef,
+ Accessible_Release,
+ Accessible_GetTypeInfoCount,
+ Accessible_GetTypeInfo,
+ Accessible_GetIDsOfNames,
+ Accessible_Invoke,
+ Accessible_get_accParent,
+ Accessible_get_accChildCount,
+ Accessible_get_accChild,
+ Accessible_get_accName,
+ Accessible_get_accValue,
+ Accessible_get_accDescription,
+ Accessible_get_accRole,
+ Accessible_get_accState,
+ Accessible_get_accHelp,
+ Accessible_get_accHelpTopic,
+ Accessible_get_accKeyboardShortcut,
+ Accessible_get_accFocus,
+ Accessible_get_accSelection,
+ Accessible_get_accDefaultAction,
+ Accessible_accSelect,
+ Accessible_accLocation,
+ Accessible_accNavigate,
+ Accessible_accHitTest,
+ Accessible_accDoDefaultAction,
+ Accessible_put_accName,
+ Accessible_put_accValue
+};
+
+static HRESULT WINAPI OleWindow_QueryInterface(IOleWindow *iface, REFIID riid, void **obj)
+{
+ return IAccessible_QueryInterface(&Accessible, riid, obj);
+}
+
+static ULONG WINAPI OleWindow_AddRef(IOleWindow *iface)
+{
+ return IAccessible_AddRef(&Accessible);
+}
+
+static ULONG WINAPI OleWindow_Release(IOleWindow *iface)
+{
+ return IAccessible_Release(&Accessible);
+}
+
+static HRESULT WINAPI OleWindow_GetWindow(IOleWindow *iface, HWND *hwnd)
+{
+ *hwnd = OleWindow_hwnd;
+ return S_OK;
+}
+
+static HRESULT WINAPI OleWindow_ContextSensitiveHelp(IOleWindow *iface, BOOL f_enter_mode)
+{
+ return E_NOTIMPL;
+}
+
+static const IOleWindowVtbl OleWindowVtbl = {
+ OleWindow_QueryInterface,
+ OleWindow_AddRef,
+ OleWindow_Release,
+ OleWindow_GetWindow,
+ OleWindow_ContextSensitiveHelp
+};
+
+static IAccessible Accessible = {&AccessibleVtbl};
+static IOleWindow OleWindow = {&OleWindowVtbl};
+
static LRESULT WINAPI test_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
return DefWindowProcA(hwnd, message, wParam, lParam);
@@ -264,8 +577,119 @@ static void test_uia_reserved_value_ifaces(void)
CoUninitialize();
}
+static void test_UiaProviderFromIAccessible(void)
+{
+ IRawElementProviderSimple *elprov;
+ enum ProviderOptions prov_opt;
+ IAccessible *acc;
+ WNDCLASSA cls;
+ HRESULT hr;
+ HWND hwnd;
+ VARIANT v;
+
+
+ cls.style = 0;
+ cls.lpfnWndProc = test_wnd_proc;
+ cls.cbClsExtra = 0;
+ cls.cbWndExtra = 0;
+ cls.hInstance = GetModuleHandleA(NULL);
+ cls.hIcon = 0;
+ cls.hCursor = NULL;
+ cls.hbrBackground = NULL;
+ cls.lpszMenuName = NULL;
+ cls.lpszClassName = "UiaProviderFromIAccessible class";
+
+ RegisterClassA(&cls);
+
+ hwnd = CreateWindowA("UiaProviderFromIAccessible class", "Test window", WS_OVERLAPPEDWINDOW,
+ 0, 0, 100, 100, NULL, NULL, NULL, NULL);
+
+ hr = pUiaProviderFromIAccessible(NULL, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
+ ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
+
+ hr = pUiaProviderFromIAccessible(&Accessible, CHILDID_SELF, UIA_PFIA_DEFAULT, NULL);
+ ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
+
+ /*
+ * UiaProviderFromIAccessible will not wrap an MSAA proxy, this is
+ * detected by checking for the 'IIS_IsOleaccProxy' service from the
+ * IServiceProvider interface.
+ */
+ hr = CreateStdAccessibleObject(hwnd, OBJID_CLIENT, &IID_IAccessible, (void**)&acc);
+ ok(hr == S_OK, "got %#lx\n", hr);
+ ok(!!acc, "acc == NULL\n");
+
+ hr = pUiaProviderFromIAccessible(acc, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
+ ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
+ IAccessible_Release(acc);
+
+ /* Don't return an HWND from accNavigate or OleWindow. */
+ SET_EXPECT(Accessible_accNavigate);
+ Accessible_hwnd = NULL;
+ OleWindow_hwnd = NULL;
+ hr = pUiaProviderFromIAccessible(&Accessible, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
+ ok(hr == E_FAIL, "Unexpected hr %#lx.\n", hr);
+ CHECK_CALLED(Accessible_accNavigate);
+
+ /* Return an HWND from accNavigate, not OleWindow. */
+ SET_EXPECT(Accessible_accNavigate);
+ Accessible_hwnd = hwnd;
+ OleWindow_hwnd = NULL;
+ hr = pUiaProviderFromIAccessible(&Accessible, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
+ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+ CHECK_CALLED(Accessible_accNavigate);
+ ok(Accessible_ref == 2, "Unexpected refcnt %ld\n", Accessible_ref);
+ IRawElementProviderSimple_Release(elprov);
+ ok(Accessible_ref == 1, "Unexpected refcnt %ld\n", Accessible_ref);
+
+ /* Return an HWND from OleWindow, not accNavigate. */
+ Accessible_hwnd = NULL;
+ OleWindow_hwnd = hwnd;
+ hr = pUiaProviderFromIAccessible(&Accessible, 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);
+
+ hr = IRawElementProviderSimple_get_ProviderOptions(elprov, &prov_opt);
+ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+ ok((prov_opt == (ProviderOptions_ServerSideProvider | ProviderOptions_UseComThreading)) ||
+ broken(prov_opt == ProviderOptions_ClientSideProvider), /* Windows < 10 1507 */
+ "Unexpected provider options %#x\n", prov_opt);
+
+ hr = IRawElementProviderSimple_GetPropertyValue(elprov, UIA_ProviderDescriptionPropertyId, &v);
+ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+ ok(V_VT(&v) == VT_BSTR, "V_VT(&v) = %d\n", V_VT(&v));
+ VariantClear(&v);
+
+ IRawElementProviderSimple_Release(elprov);
+ ok(Accessible_ref == 1, "Unexpected refcnt %ld\n", Accessible_ref);
+
+ /* ChildID other than CHILDID_SELF. */
+ hr = pUiaProviderFromIAccessible(&Accessible, 1, UIA_PFIA_DEFAULT, &elprov);
+ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+ ok(Accessible_ref == 2, "Unexpected refcnt %ld\n", Accessible_ref);
+ IRawElementProviderSimple_Release(elprov);
+ ok(Accessible_ref == 1, "Unexpected refcnt %ld\n", Accessible_ref);
+
+ DestroyWindow(hwnd);
+ UnregisterClassA("pUiaProviderFromIAccessible class", NULL);
+ Accessible_hwnd = NULL;
+ OleWindow_hwnd = NULL;
+}
+
START_TEST(uiautomation)
{
+ HMODULE uia_dll = LoadLibraryA("uiautomationcore.dll");
+
test_UiaHostProviderFromHwnd();
test_uia_reserved_value_ifaces();
+ if (uia_dll)
+ {
+ pUiaProviderFromIAccessible = (void *)GetProcAddress(uia_dll, "UiaProviderFromIAccessible");
+ if (pUiaProviderFromIAccessible)
+ test_UiaProviderFromIAccessible();
+ else
+ win_skip("UiaProviderFromIAccessible not exported by uiautomationcore.dll\n");
+
+ FreeLibrary(uia_dll);
+ }
}
--
2.25.1
More information about the wine-devel
mailing list