From 583cbd2383e91af7ed2a35021fa291d2bbaa8b87 Mon Sep 17 00:00:00 2001 From: Connor McAdams Date: Fri, 29 Apr 2022 09:46:55 -0400 Subject: [PATCH] uiautomationcore: Implement UiaProviderFromIAccessible. Signed-off-by: Connor McAdams Signed-off-by: Alexandre Julliard --- dlls/uiautomationcore/Makefile.in | 3 +- dlls/uiautomationcore/uia_main.c | 1 + dlls/uiautomationcore/uia_provider.c | 226 ++++++++++++++++++++ dlls/uiautomationcore/uiautomationcore.spec | 2 +- include/uiautomationcoreapi.h | 4 + 5 files changed, 234 insertions(+), 2 deletions(-) create mode 100644 dlls/uiautomationcore/uia_provider.c diff --git a/dlls/uiautomationcore/Makefile.in b/dlls/uiautomationcore/Makefile.in index f0973fdec4c..61a560d6c2e 100644 --- a/dlls/uiautomationcore/Makefile.in +++ b/dlls/uiautomationcore/Makefile.in @@ -5,4 +5,5 @@ IMPORTS = uuid ole32 oleaut32 user32 EXTRADLLFLAGS = -Wb,--prefer-native C_SRCS = \ - uia_main.c + uia_main.c \ + uia_provider.c diff --git a/dlls/uiautomationcore/uia_main.c b/dlls/uiautomationcore/uia_main.c index c250d82a1e6..e4bb83a3fc5 100644 --- a/dlls/uiautomationcore/uia_main.c +++ b/dlls/uiautomationcore/uia_main.c @@ -20,6 +20,7 @@ #include "initguid.h" #include "uiautomation.h" +#include "ocidl.h" #include "wine/debug.h" #include "wine/heap.h" diff --git a/dlls/uiautomationcore/uia_provider.c b/dlls/uiautomationcore/uia_provider.c new file mode 100644 index 00000000000..790593dbcab --- /dev/null +++ b/dlls/uiautomationcore/uia_provider.c @@ -0,0 +1,226 @@ +/* + * 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 + */ + +#define COBJMACROS + +#include "uiautomation.h" +#include "ocidl.h" + +#include "wine/debug.h" +#include "wine/heap.h" + +WINE_DEFAULT_DEBUG_CHANNEL(uiautomation); + +static void variant_init_i4(VARIANT *v, int val) +{ + V_VT(v) = VT_I4; + V_I4(v) = val; +} + +/* + * UiaProviderFromIAccessible IRawElementProviderSimple interface. + */ +struct msaa_provider { + IRawElementProviderSimple IRawElementProviderSimple_iface; + LONG refcount; + + IAccessible *acc; + VARIANT cid; + HWND hwnd; +}; + +static inline struct msaa_provider *impl_from_msaa_provider(IRawElementProviderSimple *iface) +{ + return CONTAINING_RECORD(iface, struct msaa_provider, IRawElementProviderSimple_iface); +} + +HRESULT WINAPI msaa_provider_QueryInterface(IRawElementProviderSimple *iface, REFIID riid, void **ppv) +{ + *ppv = NULL; + if (IsEqualIID(riid, &IID_IRawElementProviderSimple) || IsEqualIID(riid, &IID_IUnknown)) + *ppv = iface; + else + return E_NOINTERFACE; + + IRawElementProviderSimple_AddRef(iface); + return S_OK; +} + +ULONG WINAPI msaa_provider_AddRef(IRawElementProviderSimple *iface) +{ + struct msaa_provider *msaa_prov = impl_from_msaa_provider(iface); + ULONG refcount = InterlockedIncrement(&msaa_prov->refcount); + + TRACE("%p, refcount %ld\n", iface, refcount); + + return refcount; +} + +ULONG WINAPI msaa_provider_Release(IRawElementProviderSimple *iface) +{ + struct msaa_provider *msaa_prov = impl_from_msaa_provider(iface); + ULONG refcount = InterlockedDecrement(&msaa_prov->refcount); + + TRACE("%p, refcount %ld\n", iface, refcount); + + if (!refcount) + { + IAccessible_Release(msaa_prov->acc); + heap_free(msaa_prov); + } + + return refcount; +} + +HRESULT WINAPI msaa_provider_get_ProviderOptions(IRawElementProviderSimple *iface, + enum ProviderOptions *ret_val) +{ + TRACE("%p, %p\n", iface, ret_val); + *ret_val = ProviderOptions_ServerSideProvider | ProviderOptions_UseComThreading; + return S_OK; +} + +HRESULT WINAPI msaa_provider_GetPatternProvider(IRawElementProviderSimple *iface, + PATTERNID pattern_id, IUnknown **ret_val) +{ + FIXME("%p, %d, %p: stub!\n", iface, pattern_id, ret_val); + *ret_val = NULL; + return E_NOTIMPL; +} + +HRESULT WINAPI msaa_provider_GetPropertyValue(IRawElementProviderSimple *iface, + PROPERTYID prop_id, VARIANT *ret_val) +{ + TRACE("%p, %d, %p\n", iface, prop_id, ret_val); + + VariantInit(ret_val); + switch (prop_id) + { + case UIA_ProviderDescriptionPropertyId: + V_VT(ret_val) = VT_BSTR; + V_BSTR(ret_val) = SysAllocString(L"Wine: MSAA Proxy"); + break; + + default: + FIXME("Unimplemented propertyId %d\n", prop_id); + break; + } + + return S_OK; +} + +HRESULT WINAPI msaa_provider_get_HostRawElementProvider(IRawElementProviderSimple *iface, + IRawElementProviderSimple **ret_val) +{ + FIXME("%p, %p: stub!\n", iface, ret_val); + *ret_val = NULL; + return E_NOTIMPL; +} + +static const IRawElementProviderSimpleVtbl msaa_provider_vtbl = { + msaa_provider_QueryInterface, + msaa_provider_AddRef, + msaa_provider_Release, + msaa_provider_get_ProviderOptions, + msaa_provider_GetPatternProvider, + msaa_provider_GetPropertyValue, + msaa_provider_get_HostRawElementProvider, +}; + +/*********************************************************************** + * UiaProviderFromIAccessible (uiautomationcore.@) + */ +HRESULT WINAPI UiaProviderFromIAccessible(IAccessible *acc, long child_id, DWORD flags, + IRawElementProviderSimple **elprov) +{ + struct msaa_provider *msaa_prov; + IServiceProvider *serv_prov; + HWND hwnd = NULL; + IOleWindow *win; + HRESULT hr; + + TRACE("(%p, %ld, %#lx, %p)\n", acc, child_id, flags, elprov); + + if (elprov) + *elprov = NULL; + + if (!elprov) + return E_POINTER; + if (!acc) + return E_INVALIDARG; + + if (flags != UIA_PFIA_DEFAULT) + { + FIXME("unsupported flags %#lx\n", flags); + return E_NOTIMPL; + } + + hr = IAccessible_QueryInterface(acc, &IID_IServiceProvider, (void **)&serv_prov); + if (SUCCEEDED(hr)) + { + IUnknown *unk; + + hr = IServiceProvider_QueryService(serv_prov, &IIS_IsOleaccProxy, &IID_IUnknown, (void **)&unk); + if (SUCCEEDED(hr)) + { + WARN("Cannot wrap an oleacc proxy IAccessible!\n"); + IUnknown_Release(unk); + IServiceProvider_Release(serv_prov); + return E_INVALIDARG; + } + + IServiceProvider_Release(serv_prov); + } + + hr = IAccessible_QueryInterface(acc, &IID_IOleWindow, (void **)&win); + if (SUCCEEDED(hr)) + { + hr = IOleWindow_GetWindow(win, &hwnd); + if (FAILED(hr)) + hwnd = NULL; + IOleWindow_Release(win); + } + + if (!IsWindow(hwnd)) + { + VARIANT v, cid; + + VariantInit(&v); + variant_init_i4(&cid, CHILDID_SELF); + hr = IAccessible_accNavigate(acc, 10, cid, &v); + if (SUCCEEDED(hr) && V_VT(&v) == VT_I4) + hwnd = ULongToHandle(V_I4(&v)); + + if (!IsWindow(hwnd)) + return E_FAIL; + } + + msaa_prov = heap_alloc(sizeof(*msaa_prov)); + if (!msaa_prov) + return E_OUTOFMEMORY; + + msaa_prov->IRawElementProviderSimple_iface.lpVtbl = &msaa_provider_vtbl; + msaa_prov->refcount = 1; + msaa_prov->hwnd = hwnd; + variant_init_i4(&msaa_prov->cid, child_id); + msaa_prov->acc = acc; + IAccessible_AddRef(acc); + *elprov = &msaa_prov->IRawElementProviderSimple_iface; + + return S_OK; +} diff --git a/dlls/uiautomationcore/uiautomationcore.spec b/dlls/uiautomationcore/uiautomationcore.spec index 82071bd2317..70d78d52085 100644 --- a/dlls/uiautomationcore/uiautomationcore.spec +++ b/dlls/uiautomationcore/uiautomationcore.spec @@ -83,7 +83,7 @@ @ stub UiaNodeRelease @ stub UiaPatternRelease #@ stub UiaProviderForNonClient -#@ stub UiaProviderFromIAccessible +@ stdcall UiaProviderFromIAccessible(ptr long long ptr) @ stub UiaRaiseAsyncContentLoadedEvent @ stdcall UiaRaiseAutomationEvent(ptr long) @ stdcall UiaRaiseAutomationPropertyChangedEvent(ptr long int128 int128) diff --git a/include/uiautomationcoreapi.h b/include/uiautomationcoreapi.h index 563d5c602bd..22b3888dc6e 100644 --- a/include/uiautomationcoreapi.h +++ b/include/uiautomationcoreapi.h @@ -34,6 +34,9 @@ extern "C" { #define UiaAppendRuntimeId 3 #define UiaRootObjectId -25 +#define UIA_PFIA_DEFAULT 0x00 +#define UIA_PFIA_UNWRAP_BRIDGE 0x01 + DECLARE_HANDLE(HUIANODE); DECLARE_HANDLE(HUIAPATTERNOBJECT); DECLARE_HANDLE(HUIATEXTRANGE); @@ -71,6 +74,7 @@ void WINAPI UiaRegisterProviderCallback(UiaProviderCallback *pCallback); LRESULT WINAPI UiaReturnRawElementProvider(HWND hwnd, WPARAM wParam, LPARAM lParam, IRawElementProviderSimple *elprov); BOOL WINAPI UiaTextRangeRelease(HUIATEXTRANGE hobj); HRESULT WINAPI UiaHostProviderFromHwnd(HWND hwnd, IRawElementProviderSimple **elprov); +HRESULT WINAPI UiaProviderFromIAccessible(IAccessible *acc, long child_id, DWORD flags, IRawElementProviderSimple **elprov); #ifdef __cplusplus }