From 61fa18aa04e31afeaa42ea768fa63161b427784c Mon Sep 17 00:00:00 2001 From: Connor McAdams Date: Fri, 17 Jun 2022 15:04:18 -0400 Subject: [PATCH] uiautomationcore: Implement UiaGetPropertyValue. Signed-off-by: Connor McAdams --- dlls/uiautomationcore/uia_classes.idl | 17 +++ dlls/uiautomationcore/uia_client.c | 165 +++++++++++++++++++-- dlls/uiautomationcore/uia_ids.c | 45 +++++- dlls/uiautomationcore/uia_main.c | 13 +- .../{uia_classes.idl => uia_private.h} | 14 +- dlls/uiautomationcore/uia_provider.c | 4 +- 6 files changed, 210 insertions(+), 48 deletions(-) copy dlls/uiautomationcore/{uia_classes.idl => uia_private.h} (82%) diff --git a/dlls/uiautomationcore/uia_classes.idl b/dlls/uiautomationcore/uia_classes.idl index e654255a4d4..1ab09ebb9d0 100644 --- a/dlls/uiautomationcore/uia_classes.idl +++ b/dlls/uiautomationcore/uia_classes.idl @@ -20,6 +20,22 @@ import "oaidl.idl"; +struct uia_prop_info { + const GUID *guid; + int prop_id; + int type; +}; + +[ + object, + uuid(57865755-6c05-4522-98df-4ca658b768ef), + pointer_default(unique), +] +interface IWineUiaProvider : IUnknown +{ + HRESULT get_prop_val([in]const struct uia_prop_info *prop_info, [out, retval]VARIANT *ret_val); +} + [ object, uuid(bccb6799-d831-4057-bd50-6425823ff1a3), @@ -27,4 +43,5 @@ import "oaidl.idl"; ] interface IWineUiaNode : IUnknown { + HRESULT get_provider([out, retval]IWineUiaProvider **out_prov); } diff --git a/dlls/uiautomationcore/uia_client.c b/dlls/uiautomationcore/uia_client.c index 58b9bc07a79..7e710a25642 100644 --- a/dlls/uiautomationcore/uia_client.c +++ b/dlls/uiautomationcore/uia_client.c @@ -16,11 +16,7 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ -#define COBJMACROS - -#include "uiautomation.h" -#include "initguid.h" -#include "uia_classes.h" +#include "uia_private.h" #include "wine/debug.h" #include "wine/heap.h" @@ -34,7 +30,7 @@ struct uia_node { IWineUiaNode IWineUiaNode_iface; LONG ref; - IRawElementProviderSimple *elprov; + IWineUiaProvider *prov; }; static inline struct uia_node *impl_from_IWineUiaNode(IWineUiaNode *iface) @@ -71,17 +67,28 @@ static ULONG WINAPI uia_node_Release(IWineUiaNode *iface) TRACE("%p, refcount %ld\n", node, ref); if (!ref) { - IRawElementProviderSimple_Release(node->elprov); + IWineUiaProvider_Release(node->prov); heap_free(node); } return ref; } +static HRESULT WINAPI uia_node_get_provider(IWineUiaNode *iface, IWineUiaProvider **out_prov) +{ + struct uia_node *node = impl_from_IWineUiaNode(iface); + + *out_prov = node->prov; + IWineUiaProvider_AddRef(node->prov); + + return S_OK; +} + static const IWineUiaNodeVtbl uia_node_vtbl = { uia_node_QueryInterface, uia_node_AddRef, uia_node_Release, + uia_node_get_provider, }; static struct uia_node *unsafe_impl_from_IWineUiaNode(IWineUiaNode *iface) @@ -92,13 +99,103 @@ static struct uia_node *unsafe_impl_from_IWineUiaNode(IWineUiaNode *iface) return CONTAINING_RECORD(iface, struct uia_node, IWineUiaNode_iface); } +/* + * IWineUiaProvider interface. + */ +struct uia_provider { + IWineUiaProvider IWineUiaProvider_iface; + LONG ref; + + IRawElementProviderSimple *elprov; +}; + +static inline struct uia_provider *impl_from_IWineUiaProvider(IWineUiaProvider *iface) +{ + return CONTAINING_RECORD(iface, struct uia_provider, IWineUiaProvider_iface); +} + +static HRESULT WINAPI uia_provider_QueryInterface(IWineUiaProvider *iface, REFIID riid, void **ppv) +{ + *ppv = NULL; + if (IsEqualIID(riid, &IID_IWineUiaProvider) || IsEqualIID(riid, &IID_IUnknown)) + *ppv = iface; + else + return E_NOINTERFACE; + + IWineUiaProvider_AddRef(iface); + return S_OK; +} + +static ULONG WINAPI uia_provider_AddRef(IWineUiaProvider *iface) +{ + struct uia_provider *prov = impl_from_IWineUiaProvider(iface); + ULONG ref = InterlockedIncrement(&prov->ref); + + TRACE("%p, refcount %ld\n", prov, ref); + return ref; +} + +static ULONG WINAPI uia_provider_Release(IWineUiaProvider *iface) +{ + struct uia_provider *prov = impl_from_IWineUiaProvider(iface); + ULONG ref = InterlockedDecrement(&prov->ref); + + TRACE("%p, refcount %ld\n", prov, ref); + if (!ref) + { + IRawElementProviderSimple_Release(prov->elprov); + heap_free(prov); + } + + return ref; +} + +static HRESULT WINAPI uia_provider_get_prop_val(IWineUiaProvider *iface, + const struct uia_prop_info *prop_info, VARIANT *ret_val) +{ + FIXME("%p, %p, %p: stub\n", iface, prop_info, ret_val); + return E_NOTIMPL; +} + +static const IWineUiaProviderVtbl uia_provider_vtbl = { + uia_provider_QueryInterface, + uia_provider_AddRef, + uia_provider_Release, + uia_provider_get_prop_val, +}; + +static HRESULT create_wine_uia_provider(struct uia_node *node, IRawElementProviderSimple *elprov) +{ + static const int supported_prov_opts = ProviderOptions_ServerSideProvider; + enum ProviderOptions prov_opts; + struct uia_provider *prov; + HRESULT hr; + + hr = IRawElementProviderSimple_get_ProviderOptions(elprov, &prov_opts); + if (FAILED(hr)) + return hr; + + if (prov_opts & ~supported_prov_opts) + FIXME("Ignoring unsupported ProviderOption(s) %#x\n", prov_opts & ~supported_prov_opts); + + prov = heap_alloc_zero(sizeof(*prov)); + if (!prov) + return E_OUTOFMEMORY; + + prov->IWineUiaProvider_iface.lpVtbl = &uia_provider_vtbl; + prov->elprov = elprov; + IRawElementProviderSimple_AddRef(elprov); + prov->ref = 1; + node->prov = &prov->IWineUiaProvider_iface; + + return S_OK; +} + /*********************************************************************** * UiaNodeFromProvider (uiautomationcore.@) */ HRESULT WINAPI UiaNodeFromProvider(IRawElementProviderSimple *elprov, HUIANODE *huianode) { - static const int supported_prov_opts = ProviderOptions_ServerSideProvider; - enum ProviderOptions prov_opts; struct uia_node *node; HRESULT hr; @@ -113,19 +210,14 @@ HRESULT WINAPI UiaNodeFromProvider(IRawElementProviderSimple *elprov, HUIANODE * if (!node) return E_OUTOFMEMORY; - hr = IRawElementProviderSimple_get_ProviderOptions(elprov, &prov_opts); + hr = create_wine_uia_provider(node, elprov); if (FAILED(hr)) { heap_free(node); return hr; } - if (prov_opts & ~supported_prov_opts) - FIXME("Ignoring unsupported ProviderOption(s) %#x\n", prov_opts & ~supported_prov_opts); - node->IWineUiaNode_iface.lpVtbl = &uia_node_vtbl; - node->elprov = elprov; - IRawElementProviderSimple_AddRef(elprov); node->ref = 1; *huianode = (void *)&node->IWineUiaNode_iface; @@ -148,3 +240,46 @@ BOOL WINAPI UiaNodeRelease(HUIANODE huianode) IWineUiaNode_Release(&node->IWineUiaNode_iface); return TRUE; } + +/*********************************************************************** + * UiaGetPropertyValue (uiautomationcore.@) + */ +HRESULT WINAPI UiaGetPropertyValue(HUIANODE huianode, PROPERTYID prop_id, VARIANT *out_val) +{ + struct uia_node *node = unsafe_impl_from_IWineUiaNode((IWineUiaNode *)huianode); + const struct uia_prop_info *prop_info; + IWineUiaProvider *prov; + HRESULT hr; + VARIANT v; + + TRACE("(%p, %d, %p)\n", huianode, prop_id, out_val); + + if (!node || !out_val) + return E_INVALIDARG; + + V_VT(out_val) = VT_UNKNOWN; + UiaGetReservedNotSupportedValue(&V_UNKNOWN(out_val)); + + prop_info = uia_prop_info_from_id(prop_id); + if (!prop_info) + return E_INVALIDARG; + + if (!prop_info->type) + { + FIXME("No type info for prop_id %d\n", prop_id); + return E_NOTIMPL; + } + + hr = IWineUiaNode_get_provider(&node->IWineUiaNode_iface, &prov); + if (FAILED(hr)) + return hr; + + VariantInit(&v); + hr = IWineUiaProvider_get_prop_val(prov, prop_info, &v); + if (SUCCEEDED(hr) && V_VT(&v) != VT_EMPTY) + *out_val = v; + + IWineUiaProvider_Release(prov); + + return S_OK; +} diff --git a/dlls/uiautomationcore/uia_ids.c b/dlls/uiautomationcore/uia_ids.c index b80289b3372..8c6f1386fba 100644 --- a/dlls/uiautomationcore/uia_ids.c +++ b/dlls/uiautomationcore/uia_ids.c @@ -16,20 +16,13 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ -#define COBJMACROS - -#include "uiautomation.h" +#include "uia_private.h" #include "ocidl.h" #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(uiautomation); -struct uia_prop_info { - const GUID *guid; - int prop_id; -}; - static int __cdecl uia_property_guid_compare(const void *a, const void *b) { const GUID *guid = a; @@ -216,6 +209,34 @@ static const struct uia_prop_info default_uia_properties[] = { { &FullDescription_Property_GUID, UIA_FullDescriptionPropertyId, }, }; +static const int prop_id_idx[] = { + 0xaa, 0x8b, 0x76, 0xa3, 0x3d, 0x0e, 0x9f, 0x08, + 0x2e, 0x1e, 0x65, 0x00, 0x0a, 0x69, 0x2f, 0x1b, + 0x68, 0x86, 0x3a, 0x88, 0x30, 0x3b, 0x52, 0x54, + 0x01, 0x98, 0x14, 0x93, 0x04, 0x17, 0x58, 0x2d, + 0xa4, 0x37, 0x38, 0x03, 0x24, 0x8f, 0x4f, 0x06, + 0x7a, 0x45, 0x02, 0x84, 0x89, 0x55, 0x28, 0x75, + 0x48, 0x8a, 0x09, 0x19, 0x4a, 0x07, 0x9e, 0x77, + 0x15, 0x34, 0x74, 0x7f, 0x82, 0x16, 0x90, 0x5c, + 0x1f, 0x4c, 0x0f, 0xa8, 0x42, 0x26, 0x35, 0x61, + 0xac, 0x33, 0x18, 0x51, 0x81, 0x71, 0x9c, 0x50, + 0x59, 0x6a, 0x21, 0x92, 0x7d, 0x80, 0x44, 0x3c, + 0x83, 0x36, 0x96, 0x4d, 0x32, 0x8c, 0x0c, 0x7b, + 0x46, 0x43, 0x87, 0xa1, 0x1c, 0x73, 0x6d, 0x67, + 0x6b, 0x8e, 0x13, 0x6c, 0x85, 0x41, 0x94, 0x40, + 0x78, 0x3e, 0x72, 0x53, 0x4e, 0x23, 0x2b, 0x11, + 0x27, 0x2a, 0x62, 0x12, 0xa9, 0xad, 0x7e, 0x9b, + 0x29, 0x64, 0x2c, 0x99, 0x20, 0x70, 0x39, 0x6e, + 0xa0, 0x8d, 0xa7, 0x60, 0x49, 0x25, 0x5b, 0xa5, + 0x22, 0x0d, 0x0b, 0x5f, 0x3f, 0x4b, 0x5e, 0x9d, + 0x47, 0x31, 0x1d, 0x5d, 0x97, 0xa6, 0x66, 0xae, + 0x9a, 0x91, 0xa2, 0x56, 0x95, 0x05, 0x63, 0x10, + 0xab, 0x57, 0x6f, 0x1a, 0x7c, 0x5a, 0x79, +}; + +#define PROP_ID_MIN 30000 +#define PROP_ID_MAX (PROP_ID_MIN + ARRAY_SIZE(default_uia_properties)) + static const struct uia_prop_info *uia_prop_info_from_guid(const GUID *guid) { struct uia_prop_info *prop; @@ -227,6 +248,14 @@ static const struct uia_prop_info *uia_prop_info_from_guid(const GUID *guid) return NULL; } +const struct uia_prop_info *uia_prop_info_from_id(PROPERTYID prop_id) +{ + if ((prop_id < PROP_ID_MIN) || (prop_id > PROP_ID_MAX)) + return NULL; + + return &default_uia_properties[prop_id_idx[prop_id - PROP_ID_MIN]]; +} + /*********************************************************************** * UiaLookupId (uiautomationcore.@) */ diff --git a/dlls/uiautomationcore/uia_main.c b/dlls/uiautomationcore/uia_main.c index c74d3edbf07..b48fb262cd0 100644 --- a/dlls/uiautomationcore/uia_main.c +++ b/dlls/uiautomationcore/uia_main.c @@ -16,10 +16,8 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ -#define COBJMACROS - #include "initguid.h" -#include "uiautomation.h" +#include "uia_private.h" #include "ocidl.h" #include "wine/debug.h" @@ -359,12 +357,3 @@ HRESULT WINAPI UiaDisconnectProvider(IRawElementProviderSimple *provider) FIXME("(%p): stub\n", provider); return E_NOTIMPL; } - -/*********************************************************************** - * UiaGetPropertyValue (uiautomationcore.@) - */ -HRESULT WINAPI UiaGetPropertyValue(HUIANODE huianode, PROPERTYID prop_id, VARIANT *out_val) -{ - FIXME("(%p, %d, %p): stub\n", huianode, prop_id, out_val); - return E_NOTIMPL; -} diff --git a/dlls/uiautomationcore/uia_classes.idl b/dlls/uiautomationcore/uia_private.h similarity index 82% copy from dlls/uiautomationcore/uia_classes.idl copy to dlls/uiautomationcore/uia_private.h index e654255a4d4..40ea9db5cfc 100644 --- a/dlls/uiautomationcore/uia_classes.idl +++ b/dlls/uiautomationcore/uia_private.h @@ -16,15 +16,9 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ -#pragma makedep header +#define COBJMACROS -import "oaidl.idl"; +#include "uiautomation.h" +#include "uia_classes.h" -[ - object, - uuid(bccb6799-d831-4057-bd50-6425823ff1a3), - pointer_default(unique), -] -interface IWineUiaNode : IUnknown -{ -} +const struct uia_prop_info *uia_prop_info_from_id(PROPERTYID prop_id) DECLSPEC_HIDDEN; diff --git a/dlls/uiautomationcore/uia_provider.c b/dlls/uiautomationcore/uia_provider.c index 2a36dc9b39d..9c2dfd65989 100644 --- a/dlls/uiautomationcore/uia_provider.c +++ b/dlls/uiautomationcore/uia_provider.c @@ -16,9 +16,7 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ -#define COBJMACROS - -#include "uiautomation.h" +#include "uia_private.h" #include "ocidl.h" #include "wine/debug.h" -- 2.11.4.GIT