Connor McAdams : uiautomationcore: Implement UiaProviderFromIAccessible.
Alexandre Julliard
julliard at winehq.org
Mon May 2 16:02:09 CDT 2022
Module: wine
Branch: master
Commit: 583cbd2383e91af7ed2a35021fa291d2bbaa8b87
URL: https://source.winehq.org/git/wine.git/?a=commit;h=583cbd2383e91af7ed2a35021fa291d2bbaa8b87
Author: Connor McAdams <cmcadams at codeweavers.com>
Date: Fri Apr 29 09:46:55 2022 -0400
uiautomationcore: Implement UiaProviderFromIAccessible.
Signed-off-by: Connor McAdams <cmcadams at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
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(-)
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
}
More information about the wine-cvs
mailing list