-- v2: uiautomationcore: Implement IUIAutomationElement::GetCurrentPropertyValueEx. uiautomationcore: Implement IUIAutomation::ElementFromHandle. uiautomationcore: Add stub IUIAutomation implementation.
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..aa297983867 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)) + { + 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..6279f4e53cf 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)) + 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 6279f4e53cf..6eea03a4d32 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,
V2: Remove some unnecessary NULL pointer checks.
This merge request was approved by Esme Povirk.