From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/uiautomationcore/Makefile.in | 4 +++- dlls/uiautomationcore/uia_classes.idl | 1 + dlls/uiautomationcore/uia_classes_client.idl | 21 ++++++++++++++++++++ dlls/uiautomationcore/uia_classes_core.idl | 21 ++++++++++++++++++++ include/uiautomationclient.idl | 1 + include/uiautomationcore.idl | 1 + 6 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 dlls/uiautomationcore/uia_classes_client.idl create mode 100644 dlls/uiautomationcore/uia_classes_core.idl
diff --git a/dlls/uiautomationcore/Makefile.in b/dlls/uiautomationcore/Makefile.in index 9910e8e336e..a597c580b24 100644 --- a/dlls/uiautomationcore/Makefile.in +++ b/dlls/uiautomationcore/Makefile.in @@ -11,4 +11,6 @@ C_SRCS = \ uia_provider.c
IDL_SRCS = \ - uia_classes.idl + uia_classes.idl \ + uia_classes_client.idl \ + uia_classes_core.idl diff --git a/dlls/uiautomationcore/uia_classes.idl b/dlls/uiautomationcore/uia_classes.idl index f0a20d61579..aee34c0221d 100644 --- a/dlls/uiautomationcore/uia_classes.idl +++ b/dlls/uiautomationcore/uia_classes.idl @@ -43,6 +43,7 @@ struct uia_pattern_info { [ version(1.0), uuid(8a9ca8eb-856b-43d9-abd7-4a590054064f), + id(1), ] library UIA_wine_private { diff --git a/dlls/uiautomationcore/uia_classes_client.idl b/dlls/uiautomationcore/uia_classes_client.idl new file mode 100644 index 00000000000..f6dcb236bea --- /dev/null +++ b/dlls/uiautomationcore/uia_classes_client.idl @@ -0,0 +1,21 @@ +/* + * 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 + */ + +#pragma makedep regtypelib + +#include "uiautomationclient.idl" diff --git a/dlls/uiautomationcore/uia_classes_core.idl b/dlls/uiautomationcore/uia_classes_core.idl new file mode 100644 index 00000000000..3cd0a7134ed --- /dev/null +++ b/dlls/uiautomationcore/uia_classes_core.idl @@ -0,0 +1,21 @@ +/* + * 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 + */ + +#pragma makedep regtypelib + +#include "uiautomationcore.idl" diff --git a/include/uiautomationclient.idl b/include/uiautomationclient.idl index ce0402a5d33..7a0b50288d4 100644 --- a/include/uiautomationclient.idl +++ b/include/uiautomationclient.idl @@ -69,6 +69,7 @@ typedef void * UIA_HWND; [ uuid(944de083-8fb8-45cf-bcb7-c477acb2f897), lcid(0), + id(2), version(1.0) ] library UIAutomationClient { diff --git a/include/uiautomationcore.idl b/include/uiautomationcore.idl index bd93bd04dff..319bc7be475 100644 --- a/include/uiautomationcore.idl +++ b/include/uiautomationcore.idl @@ -206,6 +206,7 @@ struct UiaChangeInfo { version(1.0), uuid(930299ce-9965-4dec-b0f4-a54848d4b667), lcid(0), + id(3), hidden ] library UIA
From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/uiautomationcore/Makefile.in | 1 + dlls/uiautomationcore/tests/uiautomation.c | 55 ++ dlls/uiautomationcore/uia_com_client.c | 702 ++++++++++++++++++++ dlls/uiautomationcore/uia_main.c | 123 ++++ dlls/uiautomationcore/uia_private.h | 3 + dlls/uiautomationcore/uiautomationcore.spec | 2 +- 6 files changed, 885 insertions(+), 1 deletion(-) create mode 100644 dlls/uiautomationcore/uia_com_client.c
diff --git a/dlls/uiautomationcore/Makefile.in b/dlls/uiautomationcore/Makefile.in index a597c580b24..28d814e6ee6 100644 --- a/dlls/uiautomationcore/Makefile.in +++ b/dlls/uiautomationcore/Makefile.in @@ -6,6 +6,7 @@ EXTRADLLFLAGS = -Wb,--prefer-native
C_SRCS = \ uia_client.c \ + uia_com_client.c \ uia_ids.c \ uia_main.c \ uia_provider.c diff --git a/dlls/uiautomationcore/tests/uiautomation.c b/dlls/uiautomationcore/tests/uiautomation.c index f0112cd2ffb..e08a3aab8e8 100644 --- a/dlls/uiautomationcore/tests/uiautomation.c +++ b/dlls/uiautomationcore/tests/uiautomation.c @@ -9629,6 +9629,60 @@ static void test_UiaFind(void) CoUninitialize(); }
+struct uia_com_classes { + const GUID *clsid; + const GUID *iid; +}; + +static const struct uia_com_classes com_classes[] = { + { &CLSID_CUIAutomation, &IID_IUnknown }, + { &CLSID_CUIAutomation, &IID_IUIAutomation }, + { &CLSID_CUIAutomation8, &IID_IUnknown }, + { &CLSID_CUIAutomation8, &IID_IUIAutomation }, + { &CLSID_CUIAutomation8, &IID_IUIAutomation2 }, + { &CLSID_CUIAutomation8, &IID_IUIAutomation3 }, + { &CLSID_CUIAutomation8, &IID_IUIAutomation4 }, + { &CLSID_CUIAutomation8, &IID_IUIAutomation5 }, + { &CLSID_CUIAutomation8, &IID_IUIAutomation6 }, +}; + +static void test_CUIAutomation(void) +{ + HRESULT hr; + int i; + + CoInitializeEx(NULL, COINIT_MULTITHREADED); + + for (i = 0; i < ARRAY_SIZE(com_classes); i++) + { + IUnknown *iface = NULL; + + hr = CoCreateInstance(com_classes[i].clsid, NULL, CLSCTX_INPROC_SERVER, com_classes[i].iid, + (void **)&iface); + + if ((com_classes[i].clsid == &CLSID_CUIAutomation8) && (hr == REGDB_E_CLASSNOTREG)) + { + win_skip("CLSID_CUIAutomation8 class not registered, skipping further tests.\n"); + break; + } + else if ((com_classes[i].clsid == &CLSID_CUIAutomation8) && (hr == E_NOINTERFACE) && + (com_classes[i].iid != &IID_IUIAutomation2) && (com_classes[i].iid != &IID_IUIAutomation) && + (com_classes[i].iid != &IID_IUnknown)) + { + win_skip("No object for clsid %s, iid %s, skipping further tests.\n", debugstr_guid(com_classes[i].clsid), + debugstr_guid(com_classes[i].iid)); + break; + } + + ok(hr == S_OK, "Failed to create interface for clsid %s, iid %s, hr %#lx\n", + debugstr_guid(com_classes[i].clsid), debugstr_guid(com_classes[i].iid), hr); + ok(!!iface, "iface == NULL\n"); + IUnknown_Release(iface); + } + + CoUninitialize(); +} + /* * Once a process returns a UI Automation provider with * UiaReturnRawElementProvider it ends up in an implicit MTA until exit. This @@ -9695,6 +9749,7 @@ START_TEST(uiautomation) test_UiaGetUpdatedCache(); test_UiaNavigate(); test_UiaFind(); + test_CUIAutomation(); if (uia_dll) { pUiaProviderFromIAccessible = (void *)GetProcAddress(uia_dll, "UiaProviderFromIAccessible"); diff --git a/dlls/uiautomationcore/uia_com_client.c b/dlls/uiautomationcore/uia_com_client.c new file mode 100644 index 00000000000..6b25e851c04 --- /dev/null +++ b/dlls/uiautomationcore/uia_com_client.c @@ -0,0 +1,702 @@ +/* + * 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 + */ + +#include "uia_private.h" + +#include "wine/debug.h" +#include "wine/heap.h" + +WINE_DEFAULT_DEBUG_CHANNEL(uiautomation); + +/* + * IUIAutomation interface. + */ +struct uia_iface { + IUIAutomation6 IUIAutomation6_iface; + LONG ref; + + BOOL is_cui8; +}; + +static inline struct uia_iface *impl_from_IUIAutomation6(IUIAutomation6 *iface) +{ + return CONTAINING_RECORD(iface, struct uia_iface, IUIAutomation6_iface); +} + +static HRESULT WINAPI uia_iface_QueryInterface(IUIAutomation6 *iface, REFIID riid, void **ppv) +{ + struct uia_iface *uia_iface = impl_from_IUIAutomation6(iface); + + *ppv = NULL; + if (IsEqualIID(riid, &IID_IUIAutomation) || IsEqualIID(riid, &IID_IUnknown)) + *ppv = iface; + else if (uia_iface->is_cui8 && + (IsEqualIID(riid, &IID_IUIAutomation2) || + IsEqualIID(riid, &IID_IUIAutomation3) || + IsEqualIID(riid, &IID_IUIAutomation4) || + IsEqualIID(riid, &IID_IUIAutomation5) || + IsEqualIID(riid, &IID_IUIAutomation6))) + *ppv = iface; + else + return E_NOINTERFACE; + + IUIAutomation6_AddRef(iface); + return S_OK; +} + +static ULONG WINAPI uia_iface_AddRef(IUIAutomation6 *iface) +{ + struct uia_iface *uia_iface = impl_from_IUIAutomation6(iface); + ULONG ref = InterlockedIncrement(&uia_iface->ref); + + TRACE("%p, refcount %ld\n", uia_iface, ref); + return ref; +} + +static ULONG WINAPI uia_iface_Release(IUIAutomation6 *iface) +{ + struct uia_iface *uia_iface = impl_from_IUIAutomation6(iface); + ULONG ref = InterlockedDecrement(&uia_iface->ref); + + TRACE("%p, refcount %ld\n", uia_iface, ref); + if (!ref) + heap_free(uia_iface); + return ref; +} + +static HRESULT WINAPI uia_iface_CompareElements(IUIAutomation6 *iface, IUIAutomationElement *elem1, + IUIAutomationElement *elem2, BOOL *match) +{ + FIXME("%p, %p, %p, %p: stub\n", iface, elem1, elem2, match); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_iface_CompareRuntimeIds(IUIAutomation6 *iface, SAFEARRAY *rt_id1, SAFEARRAY *rt_id2, + BOOL *match) +{ + FIXME("%p, %p, %p, %p: stub\n", iface, rt_id1, rt_id2, match); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_iface_GetRootElement(IUIAutomation6 *iface, IUIAutomationElement **root) +{ + FIXME("%p, %p: stub\n", iface, root); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_iface_ElementFromHandle(IUIAutomation6 *iface, UIA_HWND hwnd, IUIAutomationElement **out_elem) +{ + FIXME("%p, %p, %p: stub\n", iface, hwnd, out_elem); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_iface_ElementFromPoint(IUIAutomation6 *iface, POINT pt, IUIAutomationElement **out_elem) +{ + FIXME("%p, %s, %p: stub\n", iface, wine_dbgstr_point(&pt), out_elem); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_iface_GetFocusedElement(IUIAutomation6 *iface, IUIAutomationElement **out_elem) +{ + FIXME("%p, %p: stub\n", iface, out_elem); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_iface_GetRootElementBuildCache(IUIAutomation6 *iface, IUIAutomationCacheRequest *cache_req, + IUIAutomationElement **out_root) +{ + FIXME("%p, %p, %p: stub\n", iface, cache_req, out_root); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_iface_ElementFromHandleBuildCache(IUIAutomation6 *iface, UIA_HWND hwnd, + IUIAutomationCacheRequest *cache_req, IUIAutomationElement **out_elem) +{ + FIXME("%p, %p, %p, %p: stub\n", iface, hwnd, cache_req, out_elem); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_iface_ElementFromPointBuildCache(IUIAutomation6 *iface, POINT pt, + IUIAutomationCacheRequest *cache_req, IUIAutomationElement **out_elem) +{ + FIXME("%p, %s, %p, %p: stub\n", iface, wine_dbgstr_point(&pt), cache_req, out_elem); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_iface_GetFocusedElementBuildCache(IUIAutomation6 *iface, + IUIAutomationCacheRequest *cache_req, IUIAutomationElement **out_elem) +{ + FIXME("%p, %p, %p: stub\n", iface, cache_req, out_elem); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_iface_CreateTreeWalker(IUIAutomation6 *iface, IUIAutomationCondition *cond, + IUIAutomationTreeWalker **out_walker) +{ + FIXME("%p, %p, %p: stub\n", iface, cond, out_walker); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_iface_get_ControlViewWalker(IUIAutomation6 *iface, IUIAutomationTreeWalker **out_walker) +{ + FIXME("%p, %p: stub\n", iface, out_walker); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_iface_get_ContentViewWalker(IUIAutomation6 *iface, IUIAutomationTreeWalker **out_walker) +{ + FIXME("%p, %p: stub\n", iface, out_walker); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_iface_get_RawViewWalker(IUIAutomation6 *iface, IUIAutomationTreeWalker **out_walker) +{ + FIXME("%p, %p: stub\n", iface, out_walker); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_iface_get_RawViewCondition(IUIAutomation6 *iface, IUIAutomationCondition **out_condition) +{ + FIXME("%p, %p: stub\n", iface, out_condition); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_iface_get_ControlViewCondition(IUIAutomation6 *iface, IUIAutomationCondition **out_condition) +{ + FIXME("%p, %p: stub\n", iface, out_condition); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_iface_get_ContentViewCondition(IUIAutomation6 *iface, IUIAutomationCondition **out_condition) +{ + FIXME("%p, %p: stub\n", iface, out_condition); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_iface_CreateCacheRequest(IUIAutomation6 *iface, IUIAutomationCacheRequest **out_cache_req) +{ + FIXME("%p, %p: stub\n", iface, out_cache_req); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_iface_CreateTrueCondition(IUIAutomation6 *iface, IUIAutomationCondition **out_condition) +{ + FIXME("%p, %p: stub\n", iface, out_condition); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_iface_CreateFalseCondition(IUIAutomation6 *iface, IUIAutomationCondition **out_condition) +{ + FIXME("%p, %p: stub\n", iface, out_condition); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_iface_CreatePropertyCondition(IUIAutomation6 *iface, PROPERTYID prop_id, VARIANT val, + IUIAutomationCondition **out_condition) +{ + FIXME("%p, %d, %s, %p: stub\n", iface, prop_id, debugstr_variant(&val), out_condition); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_iface_CreatePropertyConditionEx(IUIAutomation6 *iface, PROPERTYID prop_id, VARIANT val, + enum PropertyConditionFlags flags, IUIAutomationCondition **out_condition) +{ + FIXME("%p, %d, %s, %#x, %p: stub\n", iface, prop_id, debugstr_variant(&val), flags, out_condition); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_iface_CreateAndCondition(IUIAutomation6 *iface, IUIAutomationCondition *cond1, + IUIAutomationCondition *cond2, IUIAutomationCondition **out_condition) +{ + FIXME("%p, %p, %p, %p: stub\n", iface, cond1, cond2, out_condition); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_iface_CreateAndConditionFromArray(IUIAutomation6 *iface, SAFEARRAY *conds, + IUIAutomationCondition **out_condition) +{ + FIXME("%p, %p, %p: stub\n", iface, conds, out_condition); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_iface_CreateAndConditionFromNativeArray(IUIAutomation6 *iface, IUIAutomationCondition **conds, + int conds_count, IUIAutomationCondition **out_condition) +{ + FIXME("%p, %p, %d, %p: stub\n", iface, conds, conds_count, out_condition); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_iface_CreateOrCondition(IUIAutomation6 *iface, IUIAutomationCondition *cond1, + IUIAutomationCondition *cond2, IUIAutomationCondition **out_condition) +{ + FIXME("%p, %p, %p, %p: stub\n", iface, cond1, cond2, out_condition); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_iface_CreateOrConditionFromArray(IUIAutomation6 *iface, SAFEARRAY *conds, + IUIAutomationCondition **out_condition) +{ + FIXME("%p, %p, %p: stub\n", iface, conds, out_condition); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_iface_CreateOrConditionFromNativeArray(IUIAutomation6 *iface, IUIAutomationCondition **conds, + int conds_count, IUIAutomationCondition **out_condition) +{ + FIXME("%p, %p, %d, %p: stub\n", iface, conds, conds_count, out_condition); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_iface_CreateNotCondition(IUIAutomation6 *iface, IUIAutomationCondition *cond, + IUIAutomationCondition **out_condition) +{ + FIXME("%p, %p, %p: stub\n", iface, cond, out_condition); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_iface_AddAutomationEventHandler(IUIAutomation6 *iface, EVENTID event_id, + IUIAutomationElement *elem, enum TreeScope scope, IUIAutomationCacheRequest *cache_req, + IUIAutomationEventHandler *handler) +{ + FIXME("%p, %d, %p, %#x, %p, %p: stub\n", iface, event_id, elem, scope, cache_req, handler); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_iface_RemoveAutomationEventHandler(IUIAutomation6 *iface, EVENTID event_id, + IUIAutomationElement *elem, IUIAutomationEventHandler *handler) +{ + FIXME("%p, %d, %p, %p: stub\n", iface, event_id, elem, handler); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_iface_AddPropertyChangedEventHandlerNativeArray(IUIAutomation6 *iface, + IUIAutomationElement *elem, enum TreeScope scope, IUIAutomationCacheRequest *cache_req, + IUIAutomationPropertyChangedEventHandler *handler, PROPERTYID *props, int props_count) +{ + FIXME("%p, %p, %#x, %p, %p, %p, %d: stub\n", iface, elem, scope, cache_req, handler, props, props_count); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_iface_AddPropertyChangedEventHandler(IUIAutomation6 *iface, + IUIAutomationElement *elem, enum TreeScope scope, IUIAutomationCacheRequest *cache_req, + IUIAutomationPropertyChangedEventHandler *handler, SAFEARRAY *props) +{ + FIXME("%p, %p, %#x, %p, %p, %p: stub\n", iface, elem, scope, cache_req, handler, props); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_iface_RemovePropertyChangedEventHandler(IUIAutomation6 *iface, + IUIAutomationElement *elem, IUIAutomationPropertyChangedEventHandler *handler) +{ + FIXME("%p, %p, %p: stub\n", iface, elem, handler); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_iface_AddStructureChangedEventHandler(IUIAutomation6 *iface, + IUIAutomationElement *elem, enum TreeScope scope, IUIAutomationCacheRequest *cache_req, + IUIAutomationStructureChangedEventHandler *handler) +{ + FIXME("%p, %p, %#x, %p, %p: stub\n", iface, elem, scope, cache_req, handler); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_iface_RemoveStructureChangedEventHandler(IUIAutomation6 *iface, + IUIAutomationElement *elem, IUIAutomationStructureChangedEventHandler *handler) +{ + FIXME("%p, %p, %p: stub\n", iface, elem, handler); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_iface_AddFocusChangedEventHandler(IUIAutomation6 *iface, + IUIAutomationCacheRequest *cache_req, IUIAutomationFocusChangedEventHandler *handler) +{ + FIXME("%p, %p, %p: stub\n", iface, cache_req, handler); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_iface_RemoveFocusChangedEventHandler(IUIAutomation6 *iface, + IUIAutomationFocusChangedEventHandler *handler) +{ + FIXME("%p, %p: stub\n", iface, handler); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_iface_RemoveAllEventHandlers(IUIAutomation6 *iface) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_iface_IntNativeArrayToSafeArray(IUIAutomation6 *iface, int *arr, int arr_count, + SAFEARRAY **out_sa) +{ + FIXME("%p, %p, %d, %p: stub\n", iface, arr, arr_count, out_sa); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_iface_IntSafeArrayToNativeArray(IUIAutomation6 *iface, SAFEARRAY *sa, int **out_arr, + int *out_arr_count) +{ + FIXME("%p, %p, %p, %p: stub\n", iface, sa, out_arr, out_arr_count); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_iface_RectToVariant(IUIAutomation6 *iface, RECT rect, VARIANT *out_var) +{ + FIXME("%p, %s, %p: stub\n", iface, wine_dbgstr_rect(&rect), out_var); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_iface_VariantToRect(IUIAutomation6 *iface, VARIANT var, RECT *out_rect) +{ + FIXME("%p, %s, %p: stub\n", iface, debugstr_variant(&var), out_rect); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_iface_SafeArrayToRectNativeArray(IUIAutomation6 *iface, SAFEARRAY *sa, RECT **out_rect_arr, + int *out_rect_arr_count) +{ + FIXME("%p, %p, %p, %p: stub\n", iface, sa, out_rect_arr, out_rect_arr_count); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_iface_CreateProxyFactoryEntry(IUIAutomation6 *iface, IUIAutomationProxyFactory *factory, + IUIAutomationProxyFactoryEntry **out_entry) +{ + FIXME("%p, %p, %p: stub\n", iface, factory, out_entry); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_iface_get_ProxyFactoryMapping(IUIAutomation6 *iface, + IUIAutomationProxyFactoryMapping **out_factory_map) +{ + FIXME("%p, %p: stub\n", iface, out_factory_map); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_iface_GetPropertyProgrammaticName(IUIAutomation6 *iface, PROPERTYID prop_id, BSTR *out_name) +{ + FIXME("%p, %d, %p: stub\n", iface, prop_id, out_name); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_iface_GetPatternProgrammaticName(IUIAutomation6 *iface, PATTERNID pattern_id, BSTR *out_name) +{ + FIXME("%p, %d, %p: stub\n", iface, pattern_id, out_name); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_iface_PollForPotentialSupportedPatterns(IUIAutomation6 *iface, IUIAutomationElement *elem, + SAFEARRAY **out_pattern_ids, SAFEARRAY **out_pattern_names) +{ + FIXME("%p, %p, %p, %p: stub\n", iface, elem, out_pattern_ids, out_pattern_names); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_iface_PollForPotentialSupportedProperties(IUIAutomation6 *iface, IUIAutomationElement *elem, + SAFEARRAY **out_prop_ids, SAFEARRAY **out_prop_names) +{ + FIXME("%p, %p, %p, %p: stub\n", iface, elem, out_prop_ids, out_prop_names); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_iface_CheckNotSupported(IUIAutomation6 *iface, VARIANT in_val, BOOL *match) +{ + FIXME("%p, %s, %p: stub\n", iface, debugstr_variant(&in_val), match); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_iface_get_ReservedNotSupportedValue(IUIAutomation6 *iface, IUnknown **out_unk) +{ + FIXME("%p, %p: stub\n", iface, out_unk); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_iface_get_ReservedMixedAttributeValue(IUIAutomation6 *iface, IUnknown **out_unk) +{ + FIXME("%p, %p: stub\n", iface, out_unk); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_iface_ElementFromIAccessible(IUIAutomation6 *iface, IAccessible *acc, int cid, + IUIAutomationElement **out_elem) +{ + FIXME("%p, %p, %d, %p: stub\n", iface, acc, cid, out_elem); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_iface_ElementFromIAccessibleBuildCache(IUIAutomation6 *iface, IAccessible *acc, int cid, + IUIAutomationCacheRequest *cache_req, IUIAutomationElement **out_elem) +{ + FIXME("%p, %p, %d, %p, %p: stub\n", iface, acc, cid, cache_req, out_elem); + return E_NOTIMPL; +} + +/* IUIAutomation2 methods */ +static HRESULT WINAPI uia_iface_get_AutoSetFocus(IUIAutomation6 *iface, BOOL *out_auto_set_focus) +{ + FIXME("%p, %p: stub\n", iface, out_auto_set_focus); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_iface_put_AutoSetFocus(IUIAutomation6 *iface, BOOL auto_set_focus) +{ + FIXME("%p, %d: stub\n", iface, auto_set_focus); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_iface_get_ConnectionTimeout(IUIAutomation6 *iface, DWORD *out_timeout) +{ + FIXME("%p, %p: stub\n", iface, out_timeout); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_iface_put_ConnectionTimeout(IUIAutomation6 *iface, DWORD timeout) +{ + FIXME("%p, %ld: stub\n", iface, timeout); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_iface_get_TransactionTimeout(IUIAutomation6 *iface, DWORD *out_timeout) +{ + FIXME("%p, %p: stub\n", iface, out_timeout); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_iface_put_TransactionTimeout(IUIAutomation6 *iface, DWORD timeout) +{ + FIXME("%p, %ld: stub\n", iface, timeout); + return E_NOTIMPL; +} + +/* IUIAutomation3 methods */ +static HRESULT WINAPI uia_iface_AddTextEditTextChangedEventHandler(IUIAutomation6 *iface, IUIAutomationElement *elem, + enum TreeScope scope, enum TextEditChangeType change_type, IUIAutomationCacheRequest *cache_req, + IUIAutomationTextEditTextChangedEventHandler *handler) +{ + FIXME("%p, %p, %#x, %d, %p, %p: stub\n", iface, elem, scope, change_type, cache_req, handler); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_iface_RemoveTextEditTextChangedEventHandler(IUIAutomation6 *iface, IUIAutomationElement *elem, + IUIAutomationTextEditTextChangedEventHandler *handler) +{ + FIXME("%p, %p, %p: stub\n", iface, elem, handler); + return E_NOTIMPL; +} + +/* IUIAutomation4 methods */ +static HRESULT WINAPI uia_iface_AddChangesEventHandler(IUIAutomation6 *iface, IUIAutomationElement *elem, + enum TreeScope scope, int *change_types, int change_types_count, IUIAutomationCacheRequest *cache_req, + IUIAutomationChangesEventHandler *handler) +{ + FIXME("%p, %p, %#x, %p, %d, %p, %p: stub\n", iface, elem, scope, change_types, change_types_count, cache_req, + handler); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_iface_RemoveChangesEventHandler(IUIAutomation6 *iface, IUIAutomationElement *elem, + IUIAutomationChangesEventHandler *handler) +{ + FIXME("%p, %p, %p: stub\n", iface, elem, handler); + return E_NOTIMPL; +} + +/* IUIAutomation5 methods */ +static HRESULT WINAPI uia_iface_AddNotificationEventHandler(IUIAutomation6 *iface, IUIAutomationElement *elem, + enum TreeScope scope, IUIAutomationCacheRequest *cache_req, IUIAutomationNotificationEventHandler *handler) +{ + FIXME("%p, %p, %#x, %p, %p: stub\n", iface, elem, scope, cache_req, handler); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_iface_RemoveNotificationEventHandler(IUIAutomation6 *iface, IUIAutomationElement *elem, + IUIAutomationNotificationEventHandler *handler) +{ + FIXME("%p, %p, %p: stub\n", iface, elem, handler); + return E_NOTIMPL; +} + +/* IUIAutomation6 methods */ +static HRESULT WINAPI uia_iface_CreateEventHandlerGroup(IUIAutomation6 *iface, + IUIAutomationEventHandlerGroup **out_handler_group) +{ + FIXME("%p, %p: stub\n", iface, out_handler_group); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_iface_AddEventHandlerGroup(IUIAutomation6 *iface, IUIAutomationElement *elem, + IUIAutomationEventHandlerGroup *handler_group) +{ + FIXME("%p, %p, %p: stub\n", iface, elem, handler_group); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_iface_RemoveEventHandlerGroup(IUIAutomation6 *iface, IUIAutomationElement *elem, + IUIAutomationEventHandlerGroup *handler_group) +{ + FIXME("%p, %p, %p: stub\n", iface, elem, handler_group); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_iface_get_ConnectionRecoveryBehavior(IUIAutomation6 *iface, + enum ConnectionRecoveryBehaviorOptions *out_conn_recovery_opts) +{ + FIXME("%p, %p: stub\n", iface, out_conn_recovery_opts); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_iface_put_ConnectionRecoveryBehavior(IUIAutomation6 *iface, + enum ConnectionRecoveryBehaviorOptions conn_recovery_opts) +{ + FIXME("%p, %#x: stub\n", iface, conn_recovery_opts); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_iface_get_CoalesceEvents(IUIAutomation6 *iface, + enum CoalesceEventsOptions *out_coalesce_events_opts) +{ + FIXME("%p, %p: stub\n", iface, out_coalesce_events_opts); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_iface_put_CoalesceEvents(IUIAutomation6 *iface, + enum CoalesceEventsOptions coalesce_events_opts) +{ + FIXME("%p, %#x: stub\n", iface, coalesce_events_opts); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_iface_AddActiveTextPositionChangedEventHandler(IUIAutomation6 *iface, + IUIAutomationElement *elem, enum TreeScope scope, IUIAutomationCacheRequest *cache_req, + IUIAutomationActiveTextPositionChangedEventHandler *handler) +{ + FIXME("%p, %p, %#x, %p, %p: stub\n", iface, elem, scope, cache_req, handler); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_iface_RemoveActiveTextPositionChangedEventHandler(IUIAutomation6 *iface, + IUIAutomationElement *elem, IUIAutomationActiveTextPositionChangedEventHandler *handler) +{ + FIXME("%p, %p, %p\n", iface, elem, handler); + return E_NOTIMPL; +} + +static const IUIAutomation6Vtbl uia_iface_vtbl = { + uia_iface_QueryInterface, + uia_iface_AddRef, + uia_iface_Release, + /* IUIAutomation methods */ + uia_iface_CompareElements, + uia_iface_CompareRuntimeIds, + uia_iface_GetRootElement, + uia_iface_ElementFromHandle, + uia_iface_ElementFromPoint, + uia_iface_GetFocusedElement, + uia_iface_GetRootElementBuildCache, + uia_iface_ElementFromHandleBuildCache, + uia_iface_ElementFromPointBuildCache, + uia_iface_GetFocusedElementBuildCache, + uia_iface_CreateTreeWalker, + uia_iface_get_ControlViewWalker, + uia_iface_get_ContentViewWalker, + uia_iface_get_RawViewWalker, + uia_iface_get_RawViewCondition, + uia_iface_get_ControlViewCondition, + uia_iface_get_ContentViewCondition, + uia_iface_CreateCacheRequest, + uia_iface_CreateTrueCondition, + uia_iface_CreateFalseCondition, + uia_iface_CreatePropertyCondition, + uia_iface_CreatePropertyConditionEx, + uia_iface_CreateAndCondition, + uia_iface_CreateAndConditionFromArray, + uia_iface_CreateAndConditionFromNativeArray, + uia_iface_CreateOrCondition, + uia_iface_CreateOrConditionFromArray, + uia_iface_CreateOrConditionFromNativeArray, + uia_iface_CreateNotCondition, + uia_iface_AddAutomationEventHandler, + uia_iface_RemoveAutomationEventHandler, + uia_iface_AddPropertyChangedEventHandlerNativeArray, + uia_iface_AddPropertyChangedEventHandler, + uia_iface_RemovePropertyChangedEventHandler, + uia_iface_AddStructureChangedEventHandler, + uia_iface_RemoveStructureChangedEventHandler, + uia_iface_AddFocusChangedEventHandler, + uia_iface_RemoveFocusChangedEventHandler, + uia_iface_RemoveAllEventHandlers, + uia_iface_IntNativeArrayToSafeArray, + uia_iface_IntSafeArrayToNativeArray, + uia_iface_RectToVariant, + uia_iface_VariantToRect, + uia_iface_SafeArrayToRectNativeArray, + uia_iface_CreateProxyFactoryEntry, + uia_iface_get_ProxyFactoryMapping, + uia_iface_GetPropertyProgrammaticName, + uia_iface_GetPatternProgrammaticName, + uia_iface_PollForPotentialSupportedPatterns, + uia_iface_PollForPotentialSupportedProperties, + uia_iface_CheckNotSupported, + uia_iface_get_ReservedNotSupportedValue, + uia_iface_get_ReservedMixedAttributeValue, + uia_iface_ElementFromIAccessible, + uia_iface_ElementFromIAccessibleBuildCache, + /* IUIAutomation2 methods */ + uia_iface_get_AutoSetFocus, + uia_iface_put_AutoSetFocus, + uia_iface_get_ConnectionTimeout, + uia_iface_put_ConnectionTimeout, + uia_iface_get_TransactionTimeout, + uia_iface_put_TransactionTimeout, + /* IUIAutomation3 methods */ + uia_iface_AddTextEditTextChangedEventHandler, + uia_iface_RemoveTextEditTextChangedEventHandler, + /* IUIAutomation4 methods */ + uia_iface_AddChangesEventHandler, + uia_iface_RemoveChangesEventHandler, + /* IUIAutomation5 methods */ + uia_iface_AddNotificationEventHandler, + uia_iface_RemoveNotificationEventHandler, + /* IUIAutomation6 methods */ + uia_iface_CreateEventHandlerGroup, + uia_iface_AddEventHandlerGroup, + uia_iface_RemoveEventHandlerGroup, + uia_iface_get_ConnectionRecoveryBehavior, + uia_iface_put_ConnectionRecoveryBehavior, + uia_iface_get_CoalesceEvents, + uia_iface_put_CoalesceEvents, + uia_iface_AddActiveTextPositionChangedEventHandler, + uia_iface_RemoveActiveTextPositionChangedEventHandler, +}; + +HRESULT create_uia_iface(IUnknown **iface, BOOL is_cui8) +{ + struct uia_iface *uia; + + uia = heap_alloc_zero(sizeof(*uia)); + if (!uia) + return E_OUTOFMEMORY; + + uia->IUIAutomation6_iface.lpVtbl = &uia_iface_vtbl; + uia->is_cui8 = is_cui8; + uia->ref = 1; + + *iface = (IUnknown *)&uia->IUIAutomation6_iface; + return S_OK; +} diff --git a/dlls/uiautomationcore/uia_main.c b/dlls/uiautomationcore/uia_main.c index 00798bd9985..b2dbf85ec03 100644 --- a/dlls/uiautomationcore/uia_main.c +++ b/dlls/uiautomationcore/uia_main.c @@ -412,3 +412,126 @@ BOOL WINAPI DllMain(HINSTANCE hinst, DWORD reason, void *reserved)
return TRUE; } + +/* UIAutomation ClassFactory */ +struct uia_cf { + IClassFactory IClassFactory_iface; + LONG ref; + + const GUID *clsid; +}; + +static struct uia_cf *impl_from_IClassFactory(IClassFactory *iface) +{ + return CONTAINING_RECORD(iface, struct uia_cf, IClassFactory_iface); +} + +static HRESULT WINAPI uia_cf_QueryInterface(IClassFactory *iface, REFIID riid, void **ppv) +{ + *ppv = NULL; + if (IsEqualIID(riid, &IID_IClassFactory) || IsEqualIID(riid, &IID_IUnknown)) + *ppv = iface; + else + return E_NOINTERFACE; + + IClassFactory_AddRef(iface); + return S_OK; +} + +static ULONG WINAPI uia_cf_AddRef(IClassFactory *iface) +{ + struct uia_cf *cf = impl_from_IClassFactory(iface); + ULONG ref = InterlockedIncrement(&cf->ref); + + TRACE("%p, refcount %ld\n", cf, ref); + + return ref; +} + +static ULONG WINAPI uia_cf_Release(IClassFactory *iface) +{ + struct uia_cf *cf = impl_from_IClassFactory(iface); + ULONG ref = InterlockedDecrement(&cf->ref); + + TRACE("%p, refcount %ld\n", cf, ref); + + if (!ref) + heap_free(cf); + + return ref; +} + +static HRESULT WINAPI uia_cf_CreateInstance(IClassFactory *iface, IUnknown *pouter, REFIID riid, void **ppv) +{ + struct uia_cf *cf = impl_from_IClassFactory(iface); + IUnknown *obj = NULL; + HRESULT hr; + + TRACE("%p, %p, %s, %p\n", iface, pouter, debugstr_guid(riid), ppv); + + *ppv = NULL; + if (pouter) + return CLASS_E_NOAGGREGATION; + + if (IsEqualGUID(cf->clsid, &CLSID_CUIAutomation)) + hr = create_uia_iface(&obj, FALSE); + else if (IsEqualGUID(cf->clsid, &CLSID_CUIAutomation8)) + hr = create_uia_iface(&obj, TRUE); + else + return E_NOINTERFACE; + + if (SUCCEEDED(hr) && obj) + { + hr = IUnknown_QueryInterface(obj, riid, ppv); + IUnknown_Release(obj); + } + + return hr; +} + +static HRESULT WINAPI uia_cf_LockServer(IClassFactory *iface, BOOL do_lock) +{ + FIXME("%p, %d: stub\n", iface, do_lock); + return S_OK; +} + +static const IClassFactoryVtbl uia_cf_Vtbl = +{ + uia_cf_QueryInterface, + uia_cf_AddRef, + uia_cf_Release, + uia_cf_CreateInstance, + uia_cf_LockServer +}; + +static inline HRESULT create_uia_cf(REFCLSID clsid, REFIID riid, void **ppv) +{ + struct uia_cf *cf = heap_alloc_zero(sizeof(*cf)); + HRESULT hr; + + *ppv = NULL; + if (!cf) + return E_OUTOFMEMORY; + + cf->IClassFactory_iface.lpVtbl = &uia_cf_Vtbl; + cf->clsid = clsid; + cf->ref = 1; + + hr = IClassFactory_QueryInterface(&cf->IClassFactory_iface, riid, ppv); + IClassFactory_Release(&cf->IClassFactory_iface); + + return hr; +} + +/*********************************************************************** + * DllGetClassObject (uiautomationcore.@) + */ +HRESULT WINAPI DllGetClassObject(REFCLSID clsid, REFIID riid, void **ppv) +{ + TRACE("(%s, %s, %p)\n", debugstr_guid(clsid), debugstr_guid(riid), ppv); + + if (IsEqualGUID(clsid, &CLSID_CUIAutomation) || IsEqualGUID(clsid, &CLSID_CUIAutomation8)) + return create_uia_cf(clsid, riid, ppv); + + return CLASS_E_CLASSNOTAVAILABLE; +} diff --git a/dlls/uiautomationcore/uia_private.h b/dlls/uiautomationcore/uia_private.h index 2478fcc1bf0..814ad43d686 100644 --- a/dlls/uiautomationcore/uia_private.h +++ b/dlls/uiautomationcore/uia_private.h @@ -104,6 +104,9 @@ int get_node_provider_type_at_idx(struct uia_node *node, int idx) DECLSPEC_HIDDE HRESULT create_uia_node_from_elprov(IRawElementProviderSimple *elprov, HUIANODE *out_node, BOOL get_hwnd_providers) DECLSPEC_HIDDEN;
+/* uia_com_client.c */ +HRESULT create_uia_iface(IUnknown **iface, BOOL is_cui8) DECLSPEC_HIDDEN; + /* 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; diff --git a/dlls/uiautomationcore/uiautomationcore.spec b/dlls/uiautomationcore/uiautomationcore.spec index 4b7a69ca25c..7168135487b 100644 --- a/dlls/uiautomationcore/uiautomationcore.spec +++ b/dlls/uiautomationcore/uiautomationcore.spec @@ -1,5 +1,5 @@ @ stdcall -private DllCanUnloadNow() -@ stub DllGetClassObject +@ stdcall -private DllGetClassObject(ptr ptr ptr) @ stdcall -private DllRegisterServer() @ stdcall -private DllUnregisterServer() @ stub DockPattern_SetDockPosition
From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/uiautomationcore/tests/uiautomation.c | 88 ++ dlls/uiautomationcore/uia_com_client.c | 936 ++++++++++++++++++++- 2 files changed, 1022 insertions(+), 2 deletions(-)
diff --git a/dlls/uiautomationcore/tests/uiautomation.c b/dlls/uiautomationcore/tests/uiautomation.c index e08a3aab8e8..a5bc4c8a540 100644 --- a/dlls/uiautomationcore/tests/uiautomation.c +++ b/dlls/uiautomationcore/tests/uiautomation.c @@ -9629,6 +9629,79 @@ static void test_UiaFind(void) CoUninitialize(); }
+static HWND create_test_hwnd(const char *class_name) +{ + WNDCLASSA cls = { 0 }; + + cls.lpfnWndProc = test_wnd_proc; + cls.hInstance = GetModuleHandleA(NULL); + cls.lpszClassName = class_name; + RegisterClassA(&cls); + + return CreateWindowA(class_name, "Test window", WS_OVERLAPPEDWINDOW, + 0, 0, 100, 100, NULL, NULL, NULL, NULL); +} + +static IUIAutomationElement *create_test_element_from_hwnd(IUIAutomation *uia_iface, HWND hwnd) +{ + IUIAutomationElement *element; + HRESULT hr; + VARIANT v; + + initialize_provider(&Provider, ProviderOptions_ServerSideProvider, hwnd, TRUE); + prov_root = &Provider.IRawElementProviderSimple_iface; + SET_EXPECT(winproc_GETOBJECT_UiaRoot); + /* Only sent on Win7. */ + SET_EXPECT(winproc_GETOBJECT_CLIENT); + hr = IUIAutomation_ElementFromHandle(uia_iface, hwnd, &element); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(!!element, "element == NULL\n"); + ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref); + CHECK_CALLED(winproc_GETOBJECT_UiaRoot); + called_winproc_GETOBJECT_CLIENT = expect_winproc_GETOBJECT_CLIENT = 0; + + hr = IUIAutomationElement_GetCurrentPropertyValueEx(element, UIA_ProviderDescriptionPropertyId, TRUE, &v); + todo_wine ok(hr == S_OK, "Unexpected hr %#lx\n", hr); + if (SUCCEEDED(hr)) + { + check_node_provider_desc_prefix(V_BSTR(&v), GetCurrentProcessId(), hwnd); + check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider", FALSE); + check_node_provider_desc(V_BSTR(&v), L"Nonclient", NULL, FALSE); + check_node_provider_desc(V_BSTR(&v), L"Hwnd", NULL, TRUE); + VariantClear(&v); + } + + ok_method_sequence(node_from_hwnd2, "create_test_element"); + + return element; +} + +static void test_ElementFromHandle(IUIAutomation *uia_iface, BOOL is_cui8) +{ + HWND hwnd = create_test_hwnd("test_ElementFromHandle class"); + IUIAutomationElement2 *element_2; + IUIAutomationElement *element; + HRESULT hr; + + element = create_test_element_from_hwnd(uia_iface, hwnd); + hr = IUIAutomationElement_QueryInterface(element, &IID_IUIAutomationElement2, (void **)&element_2); + if (is_cui8) + { + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(!!element_2, "element_2 == NULL\n"); + IUIAutomationElement2_Release(element_2); + } + else + ok(hr == E_NOINTERFACE, "Unexpected hr %#lx.\n", hr); + + IUIAutomationElement_Release(element); + ok(Provider.ref == 1, "Unexpected refcnt %ld\n", Provider.ref); + + DestroyWindow(hwnd); + UnregisterClassA("test_ElementFromHandle class", NULL); + prov_root = NULL; +} + struct uia_com_classes { const GUID *clsid; const GUID *iid; @@ -9648,6 +9721,8 @@ static const struct uia_com_classes com_classes[] = {
static void test_CUIAutomation(void) { + IUIAutomation *uia_iface; + BOOL has_cui8 = TRUE; HRESULT hr; int i;
@@ -9663,6 +9738,7 @@ static void test_CUIAutomation(void) if ((com_classes[i].clsid == &CLSID_CUIAutomation8) && (hr == REGDB_E_CLASSNOTREG)) { win_skip("CLSID_CUIAutomation8 class not registered, skipping further tests.\n"); + has_cui8 = FALSE; break; } else if ((com_classes[i].clsid == &CLSID_CUIAutomation8) && (hr == E_NOINTERFACE) && @@ -9680,6 +9756,18 @@ static void test_CUIAutomation(void) IUnknown_Release(iface); }
+ if (has_cui8) + hr = CoCreateInstance(&CLSID_CUIAutomation8, NULL, CLSCTX_INPROC_SERVER, &IID_IUIAutomation, + (void **)&uia_iface); + else + hr = CoCreateInstance(&CLSID_CUIAutomation, NULL, CLSCTX_INPROC_SERVER, &IID_IUIAutomation, + (void **)&uia_iface); + ok(hr == S_OK, "Failed to create IUIAutomation interface, hr %#lx\n", hr); + ok(!!uia_iface, "uia_iface == NULL\n"); + + test_ElementFromHandle(uia_iface, has_cui8); + + IUIAutomation_Release(uia_iface); CoUninitialize(); }
diff --git a/dlls/uiautomationcore/uia_com_client.c b/dlls/uiautomationcore/uia_com_client.c index 6b25e851c04..df636f46197 100644 --- a/dlls/uiautomationcore/uia_com_client.c +++ b/dlls/uiautomationcore/uia_com_client.c @@ -23,6 +23,929 @@
WINE_DEFAULT_DEBUG_CHANNEL(uiautomation);
+/* + * IUIAutomationElement interface. + */ +struct uia_element { + IUIAutomationElement9 IUIAutomationElement9_iface; + LONG ref; + + BOOL from_cui8; + HUIANODE node; +}; + +static inline struct uia_element *impl_from_IUIAutomationElement9(IUIAutomationElement9 *iface) +{ + return CONTAINING_RECORD(iface, struct uia_element, IUIAutomationElement9_iface); +} + +static HRESULT WINAPI uia_element_QueryInterface(IUIAutomationElement9 *iface, REFIID riid, void **ppv) +{ + struct uia_element *element = impl_from_IUIAutomationElement9(iface); + + if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IUIAutomationElement) || (element->from_cui8 && + (IsEqualIID(riid, &IID_IUIAutomationElement2) || IsEqualIID(riid, &IID_IUIAutomationElement3) || + IsEqualIID(riid, &IID_IUIAutomationElement4) || IsEqualIID(riid, &IID_IUIAutomationElement5) || + IsEqualIID(riid, &IID_IUIAutomationElement6) || IsEqualIID(riid, &IID_IUIAutomationElement7) || + IsEqualIID(riid, &IID_IUIAutomationElement8) || IsEqualIID(riid, &IID_IUIAutomationElement9)))) + *ppv = iface; + else + return E_NOINTERFACE; + + IUIAutomationElement9_AddRef(iface); + return S_OK; +} + +static ULONG WINAPI uia_element_AddRef(IUIAutomationElement9 *iface) +{ + struct uia_element *element = impl_from_IUIAutomationElement9(iface); + ULONG ref = InterlockedIncrement(&element->ref); + + TRACE("%p, refcount %ld\n", element, ref); + return ref; +} + +static ULONG WINAPI uia_element_Release(IUIAutomationElement9 *iface) +{ + struct uia_element *element = impl_from_IUIAutomationElement9(iface); + ULONG ref = InterlockedDecrement(&element->ref); + + TRACE("%p, refcount %ld\n", element, ref); + if (!ref) + { + UiaNodeRelease(element->node); + heap_free(element); + } + + return ref; +} + +static HRESULT WINAPI uia_element_SetFocus(IUIAutomationElement9 *iface) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_GetRuntimeId(IUIAutomationElement9 *iface, SAFEARRAY **runtime_id) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_FindFirst(IUIAutomationElement9 *iface, enum TreeScope scope, + IUIAutomationCondition *condition, IUIAutomationElement **found) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_FindAll(IUIAutomationElement9 *iface, enum TreeScope scope, + IUIAutomationCondition *condition, IUIAutomationElementArray **found) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_FindFirstBuildCache(IUIAutomationElement9 *iface, enum TreeScope scope, + IUIAutomationCondition *condition, IUIAutomationCacheRequest *cache_req, IUIAutomationElement **found) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_FindAllBuildCache(IUIAutomationElement9 *iface, enum TreeScope scope, + IUIAutomationCondition *condition, IUIAutomationCacheRequest *cache_req, IUIAutomationElementArray **found) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_BuildUpdatedCache(IUIAutomationElement9 *iface, IUIAutomationCacheRequest *cache_req, + IUIAutomationElement **updated_elem) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_GetCurrentPropertyValue(IUIAutomationElement9 *iface, PROPERTYID prop_id, + VARIANT *ret_val) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_GetCurrentPropertyValueEx(IUIAutomationElement9 *iface, PROPERTYID prop_id, + BOOL ignore_default, VARIANT *ret_val) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_GetCachedPropertyValue(IUIAutomationElement9 *iface, PROPERTYID prop_id, + VARIANT *ret_val) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_GetCachedPropertyValueEx(IUIAutomationElement9 *iface, PROPERTYID prop_id, + BOOL ignore_default, VARIANT *ret_val) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_GetCurrentPatternAs(IUIAutomationElement9 *iface, PATTERNID pattern_id, + REFIID riid, void **out_pattern) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_GetCachedPatternAs(IUIAutomationElement9 *iface, PATTERNID pattern_id, + REFIID riid, void **out_pattern) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_GetCurrentPattern(IUIAutomationElement9 *iface, PATTERNID pattern_id, + IUnknown **out_pattern) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_GetCachedPattern(IUIAutomationElement9 *iface, PATTERNID pattern_id, + IUnknown **patternObject) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_GetCachedParent(IUIAutomationElement9 *iface, IUIAutomationElement **parent) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_GetCachedChildren(IUIAutomationElement9 *iface, + IUIAutomationElementArray **children) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_get_CurrentProcessId(IUIAutomationElement9 *iface, int *ret_val) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_get_CurrentControlType(IUIAutomationElement9 *iface, CONTROLTYPEID *ret_val) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_get_CurrentLocalizedControlType(IUIAutomationElement9 *iface, BSTR *ret_val) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_get_CurrentName(IUIAutomationElement9 *iface, BSTR *ret_val) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_get_CurrentAcceleratorKey(IUIAutomationElement9 *iface, BSTR *ret_val) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_get_CurrentAccessKey(IUIAutomationElement9 *iface, BSTR *ret_val) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_get_CurrentHasKeyboardFocus(IUIAutomationElement9 *iface, BOOL *ret_val) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_get_CurrentIsKeyboardFocusable(IUIAutomationElement9 *iface, BOOL *ret_val) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_get_CurrentIsEnabled(IUIAutomationElement9 *iface, BOOL *ret_val) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_get_CurrentAutomationId(IUIAutomationElement9 *iface, BSTR *ret_val) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_get_CurrentClassName(IUIAutomationElement9 *iface, BSTR *ret_val) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_get_CurrentHelpText(IUIAutomationElement9 *iface, BSTR *ret_val) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_get_CurrentCulture(IUIAutomationElement9 *iface, int *ret_val) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_get_CurrentIsControlElement(IUIAutomationElement9 *iface, BOOL *ret_val) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_get_CurrentIsContentElement(IUIAutomationElement9 *iface, BOOL *ret_val) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_get_CurrentIsPassword(IUIAutomationElement9 *iface, BOOL *ret_val) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_get_CurrentNativeWindowHandle(IUIAutomationElement9 *iface, UIA_HWND *ret_val) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_get_CurrentItemType(IUIAutomationElement9 *iface, BSTR *ret_val) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_get_CurrentIsOffscreen(IUIAutomationElement9 *iface, BOOL *ret_val) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_get_CurrentOrientation(IUIAutomationElement9 *iface, enum OrientationType *ret_val) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_get_CurrentFrameworkId(IUIAutomationElement9 *iface, BSTR *ret_val) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_get_CurrentIsRequiredForForm(IUIAutomationElement9 *iface, BOOL *ret_val) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_get_CurrentItemStatus(IUIAutomationElement9 *iface, BSTR *ret_val) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_get_CurrentBoundingRectangle(IUIAutomationElement9 *iface, RECT *ret_val) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_get_CurrentLabeledBy(IUIAutomationElement9 *iface, IUIAutomationElement **ret_val) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_get_CurrentAriaRole(IUIAutomationElement9 *iface, BSTR *ret_val) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_get_CurrentAriaProperties(IUIAutomationElement9 *iface, BSTR *ret_val) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_get_CurrentIsDataValidForForm(IUIAutomationElement9 *iface, BOOL *ret_val) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_get_CurrentControllerFor(IUIAutomationElement9 *iface, + IUIAutomationElementArray **ret_val) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_get_CurrentDescribedBy(IUIAutomationElement9 *iface, + IUIAutomationElementArray **ret_val) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_get_CurrentFlowsTo(IUIAutomationElement9 *iface, IUIAutomationElementArray **ret_val) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_get_CurrentProviderDescription(IUIAutomationElement9 *iface, BSTR *ret_val) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_get_CachedProcessId(IUIAutomationElement9 *iface, int *ret_val) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_get_CachedControlType(IUIAutomationElement9 *iface, CONTROLTYPEID *ret_val) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_get_CachedLocalizedControlType(IUIAutomationElement9 *iface, BSTR *ret_val) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_get_CachedName(IUIAutomationElement9 *iface, BSTR *ret_val) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_get_CachedAcceleratorKey(IUIAutomationElement9 *iface, BSTR *ret_val) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_get_CachedAccessKey(IUIAutomationElement9 *iface, BSTR *ret_val) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_get_CachedHasKeyboardFocus(IUIAutomationElement9 *iface, BOOL *ret_val) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_get_CachedIsKeyboardFocusable(IUIAutomationElement9 *iface, BOOL *ret_val) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_get_CachedIsEnabled(IUIAutomationElement9 *iface, BOOL *ret_val) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_get_CachedAutomationId(IUIAutomationElement9 *iface, BSTR *ret_val) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_get_CachedClassName(IUIAutomationElement9 *iface, BSTR *ret_val) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_get_CachedHelpText(IUIAutomationElement9 *iface, BSTR *ret_val) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_get_CachedCulture(IUIAutomationElement9 *iface, int *ret_val) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_get_CachedIsControlElement(IUIAutomationElement9 *iface, BOOL *ret_val) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_get_CachedIsContentElement(IUIAutomationElement9 *iface, BOOL *ret_val) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_get_CachedIsPassword(IUIAutomationElement9 *iface, BOOL *ret_val) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_get_CachedNativeWindowHandle(IUIAutomationElement9 *iface, UIA_HWND *ret_val) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_get_CachedItemType(IUIAutomationElement9 *iface, BSTR *ret_val) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_get_CachedIsOffscreen(IUIAutomationElement9 *iface, BOOL *ret_val) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_get_CachedOrientation(IUIAutomationElement9 *iface, + enum OrientationType *ret_val) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_get_CachedFrameworkId(IUIAutomationElement9 *iface, BSTR *ret_val) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_get_CachedIsRequiredForForm(IUIAutomationElement9 *iface, BOOL *ret_val) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_get_CachedItemStatus(IUIAutomationElement9 *iface, BSTR *ret_val) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_get_CachedBoundingRectangle(IUIAutomationElement9 *iface, RECT *ret_val) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_get_CachedLabeledBy(IUIAutomationElement9 *iface, IUIAutomationElement **ret_val) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_get_CachedAriaRole(IUIAutomationElement9 *iface, BSTR *ret_val) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_get_CachedAriaProperties(IUIAutomationElement9 *iface, BSTR *ret_val) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_get_CachedIsDataValidForForm(IUIAutomationElement9 *iface, BOOL *ret_val) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_get_CachedControllerFor(IUIAutomationElement9 *iface, + IUIAutomationElementArray **ret_val) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_get_CachedDescribedBy(IUIAutomationElement9 *iface, + IUIAutomationElementArray **ret_val) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_get_CachedFlowsTo(IUIAutomationElement9 *iface, IUIAutomationElementArray **ret_val) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_get_CachedProviderDescription(IUIAutomationElement9 *iface, BSTR *ret_val) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_GetClickablePoint(IUIAutomationElement9 *iface, POINT *clickable, BOOL *got_clickable) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_get_CurrentOptimizeForVisualContent(IUIAutomationElement9 *iface, BOOL *ret_val) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_get_CachedOptimizeForVisualContent(IUIAutomationElement9 *iface, BOOL *ret_val) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_get_CurrentLiveSetting(IUIAutomationElement9 *iface, enum LiveSetting *ret_val) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_get_CachedLiveSetting(IUIAutomationElement9 *iface, enum LiveSetting *ret_val) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_get_CurrentFlowsFrom(IUIAutomationElement9 *iface, + IUIAutomationElementArray **ret_val) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_get_CachedFlowsFrom(IUIAutomationElement9 *iface, IUIAutomationElementArray **ret_val) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_ShowContextMenu(IUIAutomationElement9 *iface) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_get_CurrentIsPeripheral(IUIAutomationElement9 *iface, BOOL *ret_val) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_get_CachedIsPeripheral(IUIAutomationElement9 *iface, BOOL *ret_val) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_get_CurrentPositionInSet(IUIAutomationElement9 *iface, int *ret_val) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_get_CurrentSizeOfSet(IUIAutomationElement9 *iface, int *ret_val) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_get_CurrentLevel(IUIAutomationElement9 *iface, int *ret_val) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_get_CurrentAnnotationTypes(IUIAutomationElement9 *iface, SAFEARRAY **ret_val) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_get_CurrentAnnotationObjects(IUIAutomationElement9 *iface, + IUIAutomationElementArray **ret_val) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_get_CachedPositionInSet(IUIAutomationElement9 *iface, int *ret_val) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_get_CachedSizeOfSet(IUIAutomationElement9 *iface, int *ret_val) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_get_CachedLevel(IUIAutomationElement9 *iface, int *ret_val) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_get_CachedAnnotationTypes(IUIAutomationElement9 *iface, SAFEARRAY **ret_val) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_get_CachedAnnotationObjects(IUIAutomationElement9 *iface, + IUIAutomationElementArray **ret_val) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_get_CurrentLandmarkType(IUIAutomationElement9 *iface, LANDMARKTYPEID *ret_val) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_get_CurrentLocalizedLandmarkType(IUIAutomationElement9 *iface, BSTR *ret_val) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_get_CachedLandmarkType(IUIAutomationElement9 *iface, LANDMARKTYPEID *ret_val) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_get_CachedLocalizedLandmarkType(IUIAutomationElement9 *iface, BSTR *ret_val) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_get_CurrentFullDescription(IUIAutomationElement9 *iface, BSTR *ret_val) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_get_CachedFullDescription(IUIAutomationElement9 *iface, BSTR *ret_val) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_FindFirstWithOptions(IUIAutomationElement9 *iface, enum TreeScope scope, + IUIAutomationCondition *condition, enum TreeTraversalOptions traversal_opts, IUIAutomationElement *root, + IUIAutomationElement **found) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_FindAllWithOptions(IUIAutomationElement9 *iface, enum TreeScope scope, + IUIAutomationCondition *condition, enum TreeTraversalOptions traversal_opts, IUIAutomationElement *root, + IUIAutomationElementArray **found) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_FindFirstWithOptionsBuildCache(IUIAutomationElement9 *iface, enum TreeScope scope, + IUIAutomationCondition *condition, IUIAutomationCacheRequest *cache_req, + enum TreeTraversalOptions traversal_opts, IUIAutomationElement *root, IUIAutomationElement **found) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_FindAllWithOptionsBuildCache(IUIAutomationElement9 *iface, enum TreeScope scope, + IUIAutomationCondition *condition, IUIAutomationCacheRequest *cache_req, + enum TreeTraversalOptions traversal_opts, IUIAutomationElement *root, IUIAutomationElementArray **found) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_GetCurrentMetadataValue(IUIAutomationElement9 *iface, int target_id, + METADATAID metadata_id, VARIANT *ret_val) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_get_CurrentHeadingLevel(IUIAutomationElement9 *iface, HEADINGLEVELID *ret_val) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_get_CachedHeadingLevel(IUIAutomationElement9 *iface, HEADINGLEVELID *ret_val) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_get_CurrentIsDialog(IUIAutomationElement9 *iface, BOOL *ret_val) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI uia_element_get_CachedIsDialog(IUIAutomationElement9 *iface, BOOL *ret_val) +{ + FIXME("%p: stub\n", iface); + return E_NOTIMPL; +} + +static const IUIAutomationElement9Vtbl uia_element_vtbl = { + uia_element_QueryInterface, + uia_element_AddRef, + uia_element_Release, + uia_element_SetFocus, + uia_element_GetRuntimeId, + uia_element_FindFirst, + uia_element_FindAll, + uia_element_FindFirstBuildCache, + uia_element_FindAllBuildCache, + uia_element_BuildUpdatedCache, + uia_element_GetCurrentPropertyValue, + uia_element_GetCurrentPropertyValueEx, + uia_element_GetCachedPropertyValue, + uia_element_GetCachedPropertyValueEx, + uia_element_GetCurrentPatternAs, + uia_element_GetCachedPatternAs, + uia_element_GetCurrentPattern, + uia_element_GetCachedPattern, + uia_element_GetCachedParent, + uia_element_GetCachedChildren, + uia_element_get_CurrentProcessId, + uia_element_get_CurrentControlType, + uia_element_get_CurrentLocalizedControlType, + uia_element_get_CurrentName, + uia_element_get_CurrentAcceleratorKey, + uia_element_get_CurrentAccessKey, + uia_element_get_CurrentHasKeyboardFocus, + uia_element_get_CurrentIsKeyboardFocusable, + uia_element_get_CurrentIsEnabled, + uia_element_get_CurrentAutomationId, + uia_element_get_CurrentClassName, + uia_element_get_CurrentHelpText, + uia_element_get_CurrentCulture, + uia_element_get_CurrentIsControlElement, + uia_element_get_CurrentIsContentElement, + uia_element_get_CurrentIsPassword, + uia_element_get_CurrentNativeWindowHandle, + uia_element_get_CurrentItemType, + uia_element_get_CurrentIsOffscreen, + uia_element_get_CurrentOrientation, + uia_element_get_CurrentFrameworkId, + uia_element_get_CurrentIsRequiredForForm, + uia_element_get_CurrentItemStatus, + uia_element_get_CurrentBoundingRectangle, + uia_element_get_CurrentLabeledBy, + uia_element_get_CurrentAriaRole, + uia_element_get_CurrentAriaProperties, + uia_element_get_CurrentIsDataValidForForm, + uia_element_get_CurrentControllerFor, + uia_element_get_CurrentDescribedBy, + uia_element_get_CurrentFlowsTo, + uia_element_get_CurrentProviderDescription, + uia_element_get_CachedProcessId, + uia_element_get_CachedControlType, + uia_element_get_CachedLocalizedControlType, + uia_element_get_CachedName, + uia_element_get_CachedAcceleratorKey, + uia_element_get_CachedAccessKey, + uia_element_get_CachedHasKeyboardFocus, + uia_element_get_CachedIsKeyboardFocusable, + uia_element_get_CachedIsEnabled, + uia_element_get_CachedAutomationId, + uia_element_get_CachedClassName, + uia_element_get_CachedHelpText, + uia_element_get_CachedCulture, + uia_element_get_CachedIsControlElement, + uia_element_get_CachedIsContentElement, + uia_element_get_CachedIsPassword, + uia_element_get_CachedNativeWindowHandle, + uia_element_get_CachedItemType, + uia_element_get_CachedIsOffscreen, + uia_element_get_CachedOrientation, + uia_element_get_CachedFrameworkId, + uia_element_get_CachedIsRequiredForForm, + uia_element_get_CachedItemStatus, + uia_element_get_CachedBoundingRectangle, + uia_element_get_CachedLabeledBy, + uia_element_get_CachedAriaRole, + uia_element_get_CachedAriaProperties, + uia_element_get_CachedIsDataValidForForm, + uia_element_get_CachedControllerFor, + uia_element_get_CachedDescribedBy, + uia_element_get_CachedFlowsTo, + uia_element_get_CachedProviderDescription, + uia_element_GetClickablePoint, + uia_element_get_CurrentOptimizeForVisualContent, + uia_element_get_CachedOptimizeForVisualContent, + uia_element_get_CurrentLiveSetting, + uia_element_get_CachedLiveSetting, + uia_element_get_CurrentFlowsFrom, + uia_element_get_CachedFlowsFrom, + uia_element_ShowContextMenu, + uia_element_get_CurrentIsPeripheral, + uia_element_get_CachedIsPeripheral, + uia_element_get_CurrentPositionInSet, + uia_element_get_CurrentSizeOfSet, + uia_element_get_CurrentLevel, + uia_element_get_CurrentAnnotationTypes, + uia_element_get_CurrentAnnotationObjects, + uia_element_get_CachedPositionInSet, + uia_element_get_CachedSizeOfSet, + uia_element_get_CachedLevel, + uia_element_get_CachedAnnotationTypes, + uia_element_get_CachedAnnotationObjects, + uia_element_get_CurrentLandmarkType, + uia_element_get_CurrentLocalizedLandmarkType, + uia_element_get_CachedLandmarkType, + uia_element_get_CachedLocalizedLandmarkType, + uia_element_get_CurrentFullDescription, + uia_element_get_CachedFullDescription, + uia_element_FindFirstWithOptions, + uia_element_FindAllWithOptions, + uia_element_FindFirstWithOptionsBuildCache, + uia_element_FindAllWithOptionsBuildCache, + uia_element_GetCurrentMetadataValue, + uia_element_get_CurrentHeadingLevel, + uia_element_get_CachedHeadingLevel, + uia_element_get_CurrentIsDialog, + uia_element_get_CachedIsDialog, +}; + +static HRESULT create_uia_element(IUIAutomationElement **iface, BOOL from_cui8, HUIANODE node) +{ + struct uia_element *element = heap_alloc_zero(sizeof(*element)); + + *iface = NULL; + if (!element) + return E_OUTOFMEMORY; + + element->IUIAutomationElement9_iface.lpVtbl = &uia_element_vtbl; + element->ref = 1; + element->from_cui8 = from_cui8; + element->node = node; + + *iface = (IUIAutomationElement *)&element->IUIAutomationElement9_iface; + return S_OK; +} + /* * IUIAutomation interface. */ @@ -101,8 +1024,17 @@ static HRESULT WINAPI uia_iface_GetRootElement(IUIAutomation6 *iface, IUIAutomat
static HRESULT WINAPI uia_iface_ElementFromHandle(IUIAutomation6 *iface, UIA_HWND hwnd, IUIAutomationElement **out_elem) { - FIXME("%p, %p, %p: stub\n", iface, hwnd, out_elem); - return E_NOTIMPL; + struct uia_iface *uia_iface = impl_from_IUIAutomation6(iface); + HUIANODE node; + HRESULT hr; + + TRACE("%p, %p, %p\n", iface, hwnd, out_elem); + + hr = UiaNodeFromHandle((HWND)hwnd, &node); + if (FAILED(hr) || !node) + return hr; + + return create_uia_element(out_elem, uia_iface->is_cui8, node); }
static HRESULT WINAPI uia_iface_ElementFromPoint(IUIAutomation6 *iface, POINT pt, IUIAutomationElement **out_elem)
From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/uiautomationcore/tests/uiautomation.c | 157 +++++++++++++++++---- dlls/uiautomationcore/uia_com_client.c | 39 ++++- 2 files changed, 170 insertions(+), 26 deletions(-)
diff --git a/dlls/uiautomationcore/tests/uiautomation.c b/dlls/uiautomationcore/tests/uiautomation.c index a5bc4c8a540..5b58525e10d 100644 --- a/dlls/uiautomationcore/tests/uiautomation.c +++ b/dlls/uiautomationcore/tests/uiautomation.c @@ -4504,7 +4504,7 @@ 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 void check_uia_prop_val(PROPERTYID prop_id, enum UIAutomationType type, VARIANT *v, BOOL from_com); static DWORD WINAPI uia_node_from_provider_test_com_thread(LPVOID param) { HUIANODE node = param; @@ -4523,7 +4523,7 @@ static DWORD WINAPI uia_node_from_provider_test_com_thread(LPVOID param)
hr = UiaGetPropertyValue(node, UIA_ProcessIdPropertyId, &v); ok(hr == S_OK, "Unexpected hr %#lx\n", hr); - check_uia_prop_val(UIA_ProcessIdPropertyId, UIAutomationType_Int, &v); + check_uia_prop_val(UIA_ProcessIdPropertyId, UIAutomationType_Int, &v, FALSE);
/* * When retrieving a UIAutomationType_Element property, if UseComThreading @@ -4537,7 +4537,7 @@ static DWORD WINAPI uia_node_from_provider_test_com_thread(LPVOID param) 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); + check_uia_prop_val(UIA_LabeledByPropertyId, UIAutomationType_Element, &v, FALSE);
/* Unset ProviderOptions_UseComThreading. */ Provider_child.prov_opts = ProviderOptions_ServerSideProvider; @@ -4549,7 +4549,7 @@ static DWORD WINAPI uia_node_from_provider_test_com_thread(LPVOID param) * called on the current thread. */ Provider_child.expected_tid = GetCurrentThreadId(); - check_uia_prop_val(UIA_LabeledByPropertyId, UIAutomationType_Element, &v); + check_uia_prop_val(UIA_LabeledByPropertyId, UIAutomationType_Element, &v, FALSE);
CoUninitialize();
@@ -4982,7 +4982,7 @@ static void check_uia_rect_val_(VARIANT *v, struct UiaRect *rect, const char *fi ok_(file, line)(tmp[3] == rect->height, "Unexpected height value %f, expected %f\n", tmp[3], rect->height); }
-static void check_uia_prop_val(PROPERTYID prop_id, enum UIAutomationType type, VARIANT *v) +static void check_uia_prop_val(PROPERTYID prop_id, enum UIAutomationType type, VARIANT *v, BOOL from_com) { LONG idx;
@@ -5053,22 +5053,40 @@ static void check_uia_prop_val(PROPERTYID prop_id, enum UIAutomationType type, V HRESULT hr; VARIANT v1;
+ if (from_com) + { + IUIAutomationElement *elem; + + ok(V_VT(v) == VT_UNKNOWN, "Unexpected VT %d\n", V_VT(v)); + hr = IUnknown_QueryInterface(V_UNKNOWN(v), &IID_IUIAutomationElement, (void **)&elem); + VariantClear(v); + ok(hr == S_OK, "Unexpected hr %#lx\n", hr); + ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref); + + hr = IUIAutomationElement_GetCurrentPropertyValueEx(elem, UIA_ControlTypePropertyId, TRUE, &v1); + ok(hr == S_OK, "Unexpected hr %#lx\n", hr); + IUIAutomationElement_Release(elem); + } + else + { #ifdef _WIN64 - ok(V_VT(v) == VT_I8, "Unexpected VT %d\n", V_VT(v)); - tmp_node = (HUIANODE)V_I8(v); + ok(V_VT(v) == VT_I8, "Unexpected VT %d\n", V_VT(v)); + tmp_node = (HUIANODE)V_I8(v); #else - ok(V_VT(v) == VT_I4, "Unexpected VT %d\n", V_VT(v)); - tmp_node = (HUIANODE)V_I4(v); + ok(V_VT(v) == VT_I4, "Unexpected VT %d\n", V_VT(v)); + tmp_node = (HUIANODE)V_I4(v); #endif - ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref); + 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(UiaNodeRelease(tmp_node), "Failed to release node\n"); + }
- 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; } @@ -5214,7 +5232,7 @@ static void test_UiaGetPropertyValue(void) winetest_push_context("prop_id %d", prop_id); hr = UiaGetPropertyValue(node, prop_id, &v); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - check_uia_prop_val(prop_id, elem_prop->type, &v); + check_uia_prop_val(prop_id, elem_prop->type, &v, FALSE);
/* * Some properties have special behavior if an invalid value is @@ -5973,7 +5991,7 @@ static DWORD WINAPI uia_node_from_handle_test_thread(LPVOID param)
hr = UiaGetPropertyValue(node, UIA_ControlTypePropertyId, &v); ok(hr == S_OK, "Unexpected hr %#lx\n", hr); - check_uia_prop_val(UIA_ControlTypePropertyId, UIAutomationType_Int, &v); + check_uia_prop_val(UIA_ControlTypePropertyId, UIAutomationType_Int, &v, FALSE);
/* * On Windows, nested providers are always called on a separate thread if @@ -6132,7 +6150,7 @@ static DWORD WINAPI uia_node_from_handle_test_thread(LPVOID param)
hr = UiaGetPropertyValue(node, UIA_ControlTypePropertyId, &v); ok(hr == S_OK, "Unexpected hr %#lx\n", hr); - check_uia_prop_val(UIA_ControlTypePropertyId, UIAutomationType_Int, &v); + check_uia_prop_val(UIA_ControlTypePropertyId, UIAutomationType_Int, &v, FALSE);
/* Nodes returned from a nested node will be tracked and disconnectable. */ Provider_child.prov_opts = ProviderOptions_ServerSideProvider; @@ -6225,7 +6243,7 @@ static DWORD WINAPI uia_node_from_handle_test_thread(LPVOID param)
hr = UiaGetPropertyValue(node, UIA_ControlTypePropertyId, &v); ok(hr == S_OK, "Unexpected hr %#lx\n", hr); - check_uia_prop_val(UIA_ControlTypePropertyId, UIAutomationType_Int, &v); + check_uia_prop_val(UIA_ControlTypePropertyId, UIAutomationType_Int, &v, FALSE);
/* Finally, disconnect node. */ Provider.hwnd = hwnd; @@ -6447,7 +6465,7 @@ static void test_UiaNodeFromHandle(const char *name) Provider.expected_tid = GetCurrentThreadId(); hr = UiaGetPropertyValue(node, UIA_ControlTypePropertyId, &v); ok(hr == S_OK, "Unexpected hr %#lx\n", hr); - check_uia_prop_val(UIA_ControlTypePropertyId, UIAutomationType_Int, &v); + check_uia_prop_val(UIA_ControlTypePropertyId, UIAutomationType_Int, &v, FALSE);
/* UIAutomationType_Element properties will return a normal node. */ Provider_child.prov_opts = ProviderOptions_ServerSideProvider; @@ -9642,12 +9660,22 @@ static HWND create_test_hwnd(const char *class_name) 0, 0, 100, 100, NULL, NULL, NULL, NULL); }
-static IUIAutomationElement *create_test_element_from_hwnd(IUIAutomation *uia_iface, HWND hwnd) +static IUIAutomationElement *create_test_element_from_hwnd(IUIAutomation *uia_iface, HWND hwnd, BOOL block_hwnd_provs) { IUIAutomationElement *element; HRESULT hr; VARIANT v;
+ if (block_hwnd_provs) + { + SET_EXPECT(prov_callback_base_hwnd); + SET_EXPECT(prov_callback_nonclient); + base_hwnd_prov = proxy_prov = parent_proxy_prov = nc_prov = NULL; + UiaRegisterProviderCallback(test_uia_provider_callback); + } + else + UiaRegisterProviderCallback(NULL); + initialize_provider(&Provider, ProviderOptions_ServerSideProvider, hwnd, TRUE); prov_root = &Provider.IRawElementProviderSimple_iface; SET_EXPECT(winproc_GETOBJECT_UiaRoot); @@ -9659,19 +9687,31 @@ static IUIAutomationElement *create_test_element_from_hwnd(IUIAutomation *uia_if ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref); CHECK_CALLED(winproc_GETOBJECT_UiaRoot); called_winproc_GETOBJECT_CLIENT = expect_winproc_GETOBJECT_CLIENT = 0; + if (block_hwnd_provs) + { + CHECK_CALLED(prov_callback_base_hwnd); + CHECK_CALLED(prov_callback_nonclient); + }
hr = IUIAutomationElement_GetCurrentPropertyValueEx(element, UIA_ProviderDescriptionPropertyId, TRUE, &v); todo_wine ok(hr == S_OK, "Unexpected hr %#lx\n", hr); if (SUCCEEDED(hr)) { check_node_provider_desc_prefix(V_BSTR(&v), GetCurrentProcessId(), hwnd); - check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider", FALSE); - check_node_provider_desc(V_BSTR(&v), L"Nonclient", NULL, FALSE); - check_node_provider_desc(V_BSTR(&v), L"Hwnd", NULL, TRUE); + if (!block_hwnd_provs) + { + check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider", FALSE); + check_node_provider_desc(V_BSTR(&v), L"Nonclient", NULL, FALSE); + check_node_provider_desc(V_BSTR(&v), L"Hwnd", NULL, TRUE); + } + else + check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider", TRUE); + VariantClear(&v); }
ok_method_sequence(node_from_hwnd2, "create_test_element"); + UiaRegisterProviderCallback(NULL);
return element; } @@ -9683,7 +9723,7 @@ static void test_ElementFromHandle(IUIAutomation *uia_iface, BOOL is_cui8) IUIAutomationElement *element; HRESULT hr;
- element = create_test_element_from_hwnd(uia_iface, hwnd); + element = create_test_element_from_hwnd(uia_iface, hwnd, FALSE); hr = IUIAutomationElement_QueryInterface(element, &IID_IUIAutomationElement2, (void **)&element_2); if (is_cui8) { @@ -9702,6 +9742,74 @@ static void test_ElementFromHandle(IUIAutomation *uia_iface, BOOL is_cui8) prov_root = NULL; }
+static void test_Element_GetPropertyValue(IUIAutomation *uia_iface) +{ + HWND hwnd = create_test_hwnd("test_Element_GetPropertyValue class"); + const struct uia_element_property *elem_prop; + IUIAutomationElement *element; + IUnknown *unk_ns; + int i, prop_id; + HRESULT hr; + VARIANT v; + + element = create_test_element_from_hwnd(uia_iface, hwnd, TRUE); + Provider.frag_root = &Provider.IRawElementProviderFragmentRoot_iface; + initialize_provider(&Provider_child, ProviderOptions_ServerSideProvider, NULL, TRUE); + provider_add_child(&Provider, &Provider_child); + + hr = UiaGetReservedNotSupportedValue(&unk_ns); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + VariantInit(&v); + for (i = 0; i < ARRAY_SIZE(element_properties); i++) + { + elem_prop = &element_properties[i]; + + /* Skip ElementArray properties for now. */ + if (elem_prop->type == UIAutomationType_ElementArray) + continue; + + Provider.ret_invalid_prop_type = FALSE; + VariantClear(&v); + if (!(prop_id = UiaLookupId(AutomationIdentifierType_Property, elem_prop->prop_guid))) + { + win_skip("No propertyId for GUID %s, skipping further tests.\n", debugstr_guid(elem_prop->prop_guid)); + break; + } + + winetest_push_context("Element prop_id %d", prop_id); + hr = IUIAutomationElement_GetCurrentPropertyValueEx(element, prop_id, TRUE, &v); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + check_uia_prop_val(prop_id, elem_prop->type, &v, TRUE); + + /* + * 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 = IUIAutomationElement_GetCurrentPropertyValueEx(element, prop_id, TRUE, &v); + 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(); + } + + IUIAutomationElement_Release(element); + ok(Provider.ref == 1, "Unexpected refcnt %ld\n", Provider.ref); + + DestroyWindow(hwnd); + UnregisterClassA("test_Element_GetPropertyValue class", NULL); +} + struct uia_com_classes { const GUID *clsid; const GUID *iid; @@ -9766,6 +9874,7 @@ static void test_CUIAutomation(void) ok(!!uia_iface, "uia_iface == NULL\n");
test_ElementFromHandle(uia_iface, has_cui8); + test_Element_GetPropertyValue(uia_iface);
IUIAutomation_Release(uia_iface); CoUninitialize(); diff --git a/dlls/uiautomationcore/uia_com_client.c b/dlls/uiautomationcore/uia_com_client.c index df636f46197..c6d77ce2622 100644 --- a/dlls/uiautomationcore/uia_com_client.c +++ b/dlls/uiautomationcore/uia_com_client.c @@ -134,11 +134,46 @@ static HRESULT WINAPI uia_element_GetCurrentPropertyValue(IUIAutomationElement9 return E_NOTIMPL; }
+static HRESULT create_uia_element(IUIAutomationElement **iface, BOOL from_cui8, HUIANODE node); static HRESULT WINAPI uia_element_GetCurrentPropertyValueEx(IUIAutomationElement9 *iface, PROPERTYID prop_id, BOOL ignore_default, VARIANT *ret_val) { - FIXME("%p: stub\n", iface); - return E_NOTIMPL; + const struct uia_prop_info *prop_info = uia_prop_info_from_id(prop_id); + struct uia_element *element = impl_from_IUIAutomationElement9(iface); + HRESULT hr; + + TRACE("%p, %d, %d, %p\n", iface, prop_id, ignore_default, ret_val); + + if (!ignore_default) + FIXME("Default values currently unimplemented\n"); + + VariantInit(ret_val); + if (prop_info->type == UIAutomationType_ElementArray) + { + FIXME("ElementArray property types currently unsupported for IUIAutomationElement\n"); + return E_NOTIMPL; + } + + hr = UiaGetPropertyValue(element->node, prop_id, ret_val); + if ((prop_info->type == UIAutomationType_Element) && (V_VT(ret_val) != VT_UNKNOWN)) + { + IUIAutomationElement *out_elem; + HUIANODE node; + + hr = UiaHUiaNodeFromVariant(ret_val, &node); + VariantClear(ret_val); + if (FAILED(hr)) + return hr; + + hr = create_uia_element(&out_elem, element->from_cui8, node); + if (SUCCEEDED(hr)) + { + V_VT(ret_val) = VT_UNKNOWN; + V_UNKNOWN(ret_val) = (IUnknown *)out_elem; + } + } + + return hr; }
static HRESULT WINAPI uia_element_GetCachedPropertyValue(IUIAutomationElement9 *iface, PROPERTYID prop_id,
The pipeline failure is unrelated to these patches.
Esme Povirk (@madewokherd) commented about dlls/uiautomationcore/uia_main.c:
- HRESULT hr;
- TRACE("%p, %p, %s, %p\n", iface, pouter, debugstr_guid(riid), ppv);
- *ppv = NULL;
- if (pouter)
return CLASS_E_NOAGGREGATION;
- if (IsEqualGUID(cf->clsid, &CLSID_CUIAutomation))
hr = create_uia_iface(&obj, FALSE);
- else if (IsEqualGUID(cf->clsid, &CLSID_CUIAutomation8))
hr = create_uia_iface(&obj, TRUE);
- else
return E_NOINTERFACE;
- if (SUCCEEDED(hr) && obj)
When can this succeed with NULL obj?
On Fri Feb 17 19:04:41 2023 +0000, Esme Povirk wrote:
When can this succeed with NULL obj?
Never, adding a check for an object being non-NULL is something I've gotten into the habit of doing for some reason even though it's largely unnecessary. It probably makes the code less clear, so I'll remove it here.
Esme Povirk (@madewokherd) commented about dlls/uiautomationcore/uia_com_client.c:
static HRESULT WINAPI uia_iface_ElementFromHandle(IUIAutomation6 *iface, UIA_HWND hwnd, IUIAutomationElement **out_elem) {
- FIXME("%p, %p, %p: stub\n", iface, hwnd, out_elem);
- return E_NOTIMPL;
- struct uia_iface *uia_iface = impl_from_IUIAutomation6(iface);
- HUIANODE node;
- HRESULT hr;
- TRACE("%p, %p, %p\n", iface, hwnd, out_elem);
- hr = UiaNodeFromHandle((HWND)hwnd, &node);
- if (FAILED(hr) || !node)
I think this NULL check is also unnecessary.