-- v2: uiautomationcore: Implement UiaHUiaNodeFromVariant. uiautomationcore: Add support for UIA_RuntimeIdPropertyId. uiautomationcore: Partially implement UiaGetRuntimeId.
From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- include/uiautomationcoreapi.h | 137 ++++++++++++++++++++++++++++++++++ 1 file changed, 137 insertions(+)
diff --git a/include/uiautomationcoreapi.h b/include/uiautomationcoreapi.h index e74271007fe..66fa2119597 100644 --- a/include/uiautomationcoreapi.h +++ b/include/uiautomationcoreapi.h @@ -242,6 +242,143 @@ enum ProviderType ProviderType_NonClientArea, };
+#ifndef __uiautomationclient_h__ +enum TreeScope { + TreeScope_Element = 0x01, + TreeScope_Children = 0x02, + TreeScope_Descendants = 0x04, + TreeScope_Parent = 0x08, + TreeScope_Ancestors = 0x10, + TreeScope_SubTree = TreeScope_Element | TreeScope_Children | TreeScope_Descendants, +}; + +enum PropertyConditionFlags { + PropertyConditionFlags_None = 0x00, + PropertyConditionFlags_IgnoreCase = 0x01, + PropertyConditionFlags_MatchSubstring = 0x02, +}; + +enum AutomationElementMode { + AutomationElementMode_None = 0x00, + AutomationElementMode_Full = 0x01, +}; +#endif + +enum ConditionType { + ConditionType_True = 0x00, + ConditionType_False = 0x01, + ConditionType_Property = 0x02, + ConditionType_And = 0x03, + ConditionType_Or = 0x04, + ConditionType_Not = 0x05, +}; + +struct UiaCondition { + enum ConditionType ConditionType; +}; + +struct UiaPropertyCondition { + enum ConditionType ConditionType; + PROPERTYID PropertyId; + VARIANT Value; + enum PropertyConditionFlags Flags; +}; + +struct UiaAndOrCondition { + enum ConditionType ConditionType; + struct UiaCondition **ppConditions; + int cConditions; +}; + +struct UiaNotCondition { + enum ConditionType ConditionType; + struct UiaCondition *pConditions; +}; + +struct UiaCacheRequest { + struct UiaCondition *pViewCondition; + enum TreeScope Scope; + + PROPERTYID *pProperties; + int cProperties; + PATTERNID *pPatterns; + int cPatterns; + + enum AutomationElementMode automationElementMode; +}; + +enum EventArgsType { + EventArgsType_Simple = 0x00, + EventArgsType_PropertyChanged = 0x01, + EventArgsType_StructureChanged = 0x02, + EventArgsType_AsyncContentLoaded = 0x03, + EventArgsType_WindowClosed = 0x04, + EventArgsType_TextEditTextChanged = 0x05, + EventArgsType_Changes = 0x06, + EventArgsType_Notification = 0x07, +}; + +enum AsyncContentLoadedState { + AsyncContentLoadedState_Beginning = 0x00, + AsyncContentLoadedState_Progress = 0x01, + AsyncContentLoadedState_Completed = 0x02, +}; + +struct UiaEventArgs { + enum EventArgsType Type; + int EventId; +}; + +struct UiaPropertyChangedEventArgs { + enum EventArgsType Type; + int EventId; + + PROPERTYID PropertyId; + VARIANT OldValue; + VARIANT NewValue; +}; + +struct UiaStructureChangedEventArgs { + enum EventArgsType Type; + int EventId; + + enum StructureChangeType StructureChangeType; + int *pRuntimeId; + int cRuntimeIdLen; +}; + +struct UiaTextEditTextChangedEventArgs { + enum EventArgsType Type; + int EventId; + + enum TextEditChangeType TextEditChangeType; + SAFEARRAY *pTextChange; +}; + +struct UiaChangesEventArgs { + enum EventArgsType Type; + int EventId; + + int EventIdCount; + struct UiaChangeInfo *pUiaChanges; +}; + +struct UiaAsyncContentLoadedEventArgs { + enum EventArgsType Type; + int EventId; + + enum AsyncContentLoadedState AsyncContentLoadedState; + double percentComplete; +}; + +struct UiaWindowClosedEventArgs { + enum EventArgsType Type; + int EventId; + + int *pRuntimeId; + int cRuntimeIdLen; +}; + typedef SAFEARRAY * WINAPI UiaProviderCallback(HWND hwnd,enum ProviderType providerType);
HRESULT WINAPI UiaGetReservedMixedAttributeValue(IUnknown **value);
From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- include/uiautomationcore.idl | 14 ++++++++++++++ 1 file changed, 14 insertions(+)
diff --git a/include/uiautomationcore.idl b/include/uiautomationcore.idl index 8ddfb1d5653..98894407441 100644 --- a/include/uiautomationcore.idl +++ b/include/uiautomationcore.idl @@ -204,6 +204,20 @@ library UIA HRESULT GetFocus([out, retval] IRawElementProviderFragment **pRetVal); }
+ + [ + object, + uuid(1d5df27c-8947-4425-b8d9-79787bb460b8), + pointer_default(unique), + oleautomation + ] + interface IRawElementProviderHwndOverride : IUnknown + { + HRESULT GetOverrideProviderForHwnd( + [in] HWND hwnd, + [out, retval] IRawElementProviderSimple **pRetVal); + } + [ object, uuid(e44c3566-915d-4070-99c6-047bff5a08f5),
From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/uiautomationcore/tests/uiautomation.c | 32 ++++++++++---------- dlls/uiautomationcore/uia_client.c | 34 ++++++++++++++++++++++ 2 files changed, 50 insertions(+), 16 deletions(-)
diff --git a/dlls/uiautomationcore/tests/uiautomation.c b/dlls/uiautomationcore/tests/uiautomation.c index 4fd28f2ba8d..948198faea0 100644 --- a/dlls/uiautomationcore/tests/uiautomation.c +++ b/dlls/uiautomationcore/tests/uiautomation.c @@ -3647,8 +3647,8 @@ static const struct prov_method_sequence node_from_prov2[] = { { &Provider, PROV_GET_PROVIDER_OPTIONS }, /* Win10v1507 and below call this. */ { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */ - { &Provider, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_TODO }, - { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_NativeWindowHandlePropertyId */ + { &Provider, PROV_GET_HOST_RAW_ELEMENT_PROVIDER }, + { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_NativeWindowHandlePropertyId */ { &Provider, FRAG_NAVIGATE, METHOD_TODO }, /* NavigateDirection_Parent */ /* Only called on Windows versions past Win10v1507. */ { &Provider, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, @@ -3660,8 +3660,8 @@ static const struct prov_method_sequence node_from_prov3[] = { { &Provider_child, PROV_GET_PROVIDER_OPTIONS }, /* Win10v1507 and below call this. */ { &Provider_child, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */ - { &Provider_child, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_TODO }, - { &Provider_child, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_NativeWindowHandlePropertyId */ + { &Provider_child, PROV_GET_HOST_RAW_ELEMENT_PROVIDER }, + { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_NativeWindowHandlePropertyId */ { &Provider_child, FRAG_NAVIGATE, METHOD_TODO }, /* NavigateDirection_Parent */ /* Only called on Windows versions past Win10v1507. */ { &Provider_child, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, @@ -3673,7 +3673,7 @@ static const struct prov_method_sequence node_from_prov4[] = { { &Provider, PROV_GET_PROVIDER_OPTIONS }, /* Win10v1507 and below call this. */ { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */ - { &Provider, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_TODO }, + { &Provider, PROV_GET_HOST_RAW_ELEMENT_PROVIDER }, { &Provider, FRAG_NAVIGATE, METHOD_TODO }, /* NavigateDirection_Parent */ /* Only called on Windows versions past Win10v1507. */ { &Provider, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, @@ -3685,7 +3685,7 @@ static const struct prov_method_sequence node_from_prov5[] = { { &Provider, PROV_GET_PROVIDER_OPTIONS }, /* Win10v1507 and below call this. */ { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */ - { &Provider, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_TODO }, + { &Provider, PROV_GET_HOST_RAW_ELEMENT_PROVIDER }, { &Provider2, PROV_GET_PROVIDER_OPTIONS, METHOD_TODO }, /* Win10v1507 and below call this. */ { &Provider2, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */ @@ -3710,7 +3710,7 @@ static const struct prov_method_sequence node_from_prov6[] = { { &Provider, PROV_GET_PROVIDER_OPTIONS }, /* Win10v1507 and below call this. */ { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */ - { &Provider, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_TODO }, + { &Provider, PROV_GET_HOST_RAW_ELEMENT_PROVIDER }, { &Provider2, PROV_GET_PROVIDER_OPTIONS, METHOD_TODO }, /* Win10v1507 and below call this. */ { &Provider2, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */ @@ -3735,7 +3735,7 @@ static const struct prov_method_sequence node_from_prov7[] = { { &Provider_child, PROV_GET_PROVIDER_OPTIONS }, /* Win10v1507 and below call this. */ { &Provider_child, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */ - { &Provider_child, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_TODO }, + { &Provider_child, PROV_GET_HOST_RAW_ELEMENT_PROVIDER }, { &Provider2, PROV_GET_PROVIDER_OPTIONS, METHOD_TODO }, /* Win10v1507 and below call this. */ { &Provider2, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */ @@ -3760,8 +3760,8 @@ static const struct prov_method_sequence node_from_prov8[] = { { &Provider, PROV_GET_PROVIDER_OPTIONS }, /* Win10v1507 and below call this. */ { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */ - { &Provider, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_TODO }, - { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_NativeWindowHandlePropertyId */ + { &Provider, PROV_GET_HOST_RAW_ELEMENT_PROVIDER }, + { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_NativeWindowHandlePropertyId */ { &Provider, FRAG_NAVIGATE, METHOD_TODO }, /* NavigateDirection_Parent */ /* Only called on Windows versions past Win10v1507. */ { &Provider, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, @@ -4153,8 +4153,8 @@ static const struct prov_method_sequence get_elem_prop_seq[] = { { &Provider_child, PROV_GET_PROVIDER_OPTIONS }, /* Win10v1507 and below call this. */ { &Provider_child, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */ - { &Provider_child, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_TODO }, - { &Provider_child, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_NativeWindowHandlePropertyId */ + { &Provider_child, PROV_GET_HOST_RAW_ELEMENT_PROVIDER }, + { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_NativeWindowHandlePropertyId */ { &Provider_child, FRAG_NAVIGATE, METHOD_TODO }, /* NavigateDirection_Parent */ /* Only called on Windows versions past Win10v1507. */ { &Provider_child, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, @@ -4168,15 +4168,15 @@ static const struct prov_method_sequence get_elem_arr_prop_seq[] = { { &Provider_child, PROV_GET_PROVIDER_OPTIONS }, /* Win10v1507 and below call this. */ { &Provider_child, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */ - { &Provider_child, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_TODO }, - { &Provider_child, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_NativeWindowHandlePropertyId */ + { &Provider_child, PROV_GET_HOST_RAW_ELEMENT_PROVIDER }, + { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_NativeWindowHandlePropertyId */ { &Provider_child, FRAG_NAVIGATE, METHOD_TODO }, /* NavigateDirection_Parent */ { &Provider_child, PROV_GET_PROVIDER_OPTIONS, METHOD_TODO }, { &Provider_child2, PROV_GET_PROVIDER_OPTIONS }, /* Win10v1507 and below call this. */ { &Provider_child2, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */ - { &Provider_child2, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_TODO }, - { &Provider_child2, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_NativeWindowHandlePropertyId */ + { &Provider_child2, PROV_GET_HOST_RAW_ELEMENT_PROVIDER }, + { &Provider_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_NativeWindowHandlePropertyId */ { &Provider_child2, FRAG_NAVIGATE, METHOD_TODO }, /* NavigateDirection_Parent */ { &Provider_child2, PROV_GET_PROVIDER_OPTIONS, METHOD_TODO }, { &Provider_child, PROV_GET_PROPERTY_VALUE }, diff --git a/dlls/uiautomationcore/uia_client.c b/dlls/uiautomationcore/uia_client.c index 405beb02b15..b7e8f45636a 100644 --- a/dlls/uiautomationcore/uia_client.c +++ b/dlls/uiautomationcore/uia_client.c @@ -160,6 +160,37 @@ static HRESULT get_global_interface_table(IGlobalInterfaceTable **git) return hr; }
+static HWND get_hwnd_from_provider(IRawElementProviderSimple *elprov) +{ + IRawElementProviderSimple *host_prov; + HRESULT hr; + VARIANT v; + HWND hwnd; + + hwnd = NULL; + VariantInit(&v); + hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &host_prov); + if (SUCCEEDED(hr) && host_prov) + { + hr = IRawElementProviderSimple_GetPropertyValue(host_prov, UIA_NativeWindowHandlePropertyId, &v); + if (SUCCEEDED(hr) && (V_VT(&v) == VT_I4)) + hwnd = UlongToHandle(V_I4(&v)); + + VariantClear(&v); + IRawElementProviderSimple_Release(host_prov); + } + + if (!IsWindow(hwnd)) + { + hr = IRawElementProviderSimple_GetPropertyValue(elprov, UIA_NativeWindowHandlePropertyId, &v); + if (SUCCEEDED(hr) && (V_VT(&v) == VT_I4)) + hwnd = UlongToHandle(V_I4(&v)); + VariantClear(&v); + } + + return hwnd; +} + /* * IWineUiaNode interface. */ @@ -169,6 +200,8 @@ struct uia_node {
IWineUiaProvider *prov; DWORD git_cookie; + + HWND hwnd; };
static inline struct uia_node *impl_from_IWineUiaNode(IWineUiaNode *iface) @@ -482,6 +515,7 @@ static HRESULT create_wine_uia_provider(struct uia_node *node, IRawElementProvid prov->elprov = elprov; prov->ref = 1; node->prov = &prov->IWineUiaProvider_iface; + node->hwnd = get_hwnd_from_provider(elprov);
/* * If the UseComThreading ProviderOption is specified, all calls to the
From: Connor McAdams cmcadams@codeweavers.com
Add RuntimeId support for HUIANODEs associated with an HWND.
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/uiautomationcore/tests/uiautomation.c | 389 +++++++++++++++++++- dlls/uiautomationcore/uia_client.c | 54 +++ dlls/uiautomationcore/uiautomationcore.spec | 2 +- include/uiautomationcoreapi.h | 1 + 4 files changed, 437 insertions(+), 9 deletions(-)
diff --git a/dlls/uiautomationcore/tests/uiautomation.c b/dlls/uiautomationcore/tests/uiautomation.c index 948198faea0..761f492a7b5 100644 --- a/dlls/uiautomationcore/tests/uiautomation.c +++ b/dlls/uiautomationcore/tests/uiautomation.c @@ -64,6 +64,7 @@ static HRESULT (WINAPI *pUiaProviderFromIAccessible)(IAccessible *, long, DWORD, }while(0)
#define NAVDIR_INTERNAL_HWND 10 +#define UIA_RUNTIME_ID_PREFIX 42
DEFINE_EXPECT(winproc_GETOBJECT_CLIENT); DEFINE_EXPECT(winproc_GETOBJECT_UiaRoot); @@ -1094,14 +1095,17 @@ static struct Provider { IRawElementProviderSimple IRawElementProviderSimple_iface; IRawElementProviderFragment IRawElementProviderFragment_iface; + IRawElementProviderFragmentRoot IRawElementProviderFragmentRoot_iface; LONG ref;
const char *prov_name; IRawElementProviderFragment *parent; + IRawElementProviderFragmentRoot *frag_root; enum ProviderOptions prov_opts; HWND hwnd; BOOL ret_invalid_prop_type; DWORD expected_tid; + int runtime_id[2]; } Provider, Provider2, Provider_child, Provider_child2;
static const WCHAR *uia_bstr_prop_str = L"uia-string"; @@ -1158,6 +1162,8 @@ enum { PROV_GET_PROPERTY_VALUE, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, FRAG_NAVIGATE, + FRAG_GET_RUNTIME_ID, + FRAG_GET_FRAGMENT_ROOT, };
static const char *prov_method_str[] = { @@ -1165,6 +1171,8 @@ static const char *prov_method_str[] = { "GetPropertyValue", "get_HostRawElementProvider", "Navigate", + "GetRuntimeId", + "get_FragmentRoot", };
static const char *get_prov_method_str(int method) @@ -1405,6 +1413,36 @@ static void check_node_provider_desc_prefix_(BSTR prov_desc, DWORD pid, HWND pro ok_(file, line)(prov_hwnd == prov_id, "Unexpected hwnd %p\n", prov_hwnd); }
+#define check_runtime_id( exp_runtime_id, exp_size, runtime_id ) \ + check_runtime_id_( (exp_runtime_id), (exp_size), (runtime_id), __FILE__, __LINE__) +static void check_runtime_id_(int *exp_runtime_id, int exp_size, SAFEARRAY *runtime_id, const char *file, int line) +{ + LONG i, idx, lbound, ubound, elems; + HRESULT hr; + UINT dims; + int val; + + dims = SafeArrayGetDim(runtime_id); + ok_(file, line)(dims == 1, "Unexpected array dims %d\n", dims); + + hr = SafeArrayGetLBound(runtime_id, 1, &lbound); + ok_(file, line)(hr == S_OK, "Failed to get LBound with hr %#lx\n", hr); + + hr = SafeArrayGetUBound(runtime_id, 1, &ubound); + ok_(file, line)(hr == S_OK, "Failed to get UBound with hr %#lx\n", hr); + + elems = (ubound - lbound) + 1; + ok_(file, line)(exp_size == elems, "Unexpected runtime_id array size %#lx\n", elems); + + for (i = 0; i < elems; i++) + { + idx = lbound + i; + hr = SafeArrayGetElement(runtime_id, &idx, &val); + ok_(file, line)(hr == S_OK, "Failed to get element with hr %#lx\n", hr); + ok_(file, line)(val == exp_runtime_id[i], "Unexpected runtime_id[%ld] %#x\n", i, val); + } +} + static inline struct Provider *impl_from_ProviderSimple(IRawElementProviderSimple *iface) { return CONTAINING_RECORD(iface, struct Provider, IRawElementProviderSimple_iface); @@ -1419,6 +1457,8 @@ HRESULT WINAPI ProviderSimple_QueryInterface(IRawElementProviderSimple *iface, R *ppv = iface; else if (IsEqualIID(riid, &IID_IRawElementProviderFragment)) *ppv = &This->IRawElementProviderFragment_iface; + else if (IsEqualIID(riid, &IID_IRawElementProviderFragmentRoot)) + *ppv = &This->IRawElementProviderFragmentRoot_iface; else return E_NOINTERFACE;
@@ -1724,9 +1764,28 @@ static HRESULT WINAPI ProviderFragment_Navigate(IRawElementProviderFragment *ifa static HRESULT WINAPI ProviderFragment_GetRuntimeId(IRawElementProviderFragment *iface, SAFEARRAY **ret_val) { - ok(0, "unexpected call\n"); + struct Provider *This = impl_from_ProviderFragment(iface); + + add_method_call(This, FRAG_GET_RUNTIME_ID); + if (This->expected_tid) + ok(This->expected_tid == GetCurrentThreadId(), "Unexpected tid %ld\n", GetCurrentThreadId()); + *ret_val = NULL; - return E_NOTIMPL; + if (This->runtime_id[0] || This->runtime_id[1]) + { + SAFEARRAY *sa; + LONG idx; + + if (!(sa = SafeArrayCreateVector(VT_I4, 0, ARRAY_SIZE(This->runtime_id)))) + return E_FAIL; + + for (idx = 0; idx < ARRAY_SIZE(This->runtime_id); idx++) + SafeArrayPutElement(sa, &idx, (void *)&This->runtime_id[idx]); + + *ret_val = sa; + } + + return S_OK; }
static HRESULT WINAPI ProviderFragment_get_BoundingRectangle(IRawElementProviderFragment *iface, @@ -1753,9 +1812,20 @@ static HRESULT WINAPI ProviderFragment_SetFocus(IRawElementProviderFragment *ifa static HRESULT WINAPI ProviderFragment_get_FragmentRoot(IRawElementProviderFragment *iface, IRawElementProviderFragmentRoot **ret_val) { - ok(0, "unexpected call\n"); + struct Provider *This = impl_from_ProviderFragment(iface); + + add_method_call(This, FRAG_GET_FRAGMENT_ROOT); + if (This->expected_tid) + ok(This->expected_tid == GetCurrentThreadId(), "Unexpected tid %ld\n", GetCurrentThreadId()); + *ret_val = NULL; - return E_NOTIMPL; + if (This->frag_root) + { + *ret_val = This->frag_root; + IRawElementProviderFragmentRoot_AddRef(This->frag_root); + } + + return S_OK; }
static const IRawElementProviderFragmentVtbl ProviderFragmentVtbl = { @@ -1770,13 +1840,60 @@ static const IRawElementProviderFragmentVtbl ProviderFragmentVtbl = { ProviderFragment_get_FragmentRoot, };
+static inline struct Provider *impl_from_ProviderFragmentRoot(IRawElementProviderFragmentRoot *iface) +{ + return CONTAINING_RECORD(iface, struct Provider, IRawElementProviderFragmentRoot_iface); +} + +static HRESULT WINAPI ProviderFragmentRoot_QueryInterface(IRawElementProviderFragmentRoot *iface, REFIID riid, + void **ppv) +{ + struct Provider *Provider = impl_from_ProviderFragmentRoot(iface); + return IRawElementProviderSimple_QueryInterface(&Provider->IRawElementProviderSimple_iface, riid, ppv); +} + +static ULONG WINAPI ProviderFragmentRoot_AddRef(IRawElementProviderFragmentRoot *iface) +{ + struct Provider *Provider = impl_from_ProviderFragmentRoot(iface); + return IRawElementProviderSimple_AddRef(&Provider->IRawElementProviderSimple_iface); +} + +static ULONG WINAPI ProviderFragmentRoot_Release(IRawElementProviderFragmentRoot *iface) +{ + struct Provider *Provider = impl_from_ProviderFragmentRoot(iface); + return IRawElementProviderSimple_Release(&Provider->IRawElementProviderSimple_iface); +} + +static HRESULT WINAPI ProviderFragmentRoot_ElementProviderFromPoint(IRawElementProviderFragmentRoot *iface, + double x, double y, IRawElementProviderFragment **ret_val) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ProviderFragmentRoot_GetFocus(IRawElementProviderFragmentRoot *iface, + IRawElementProviderFragment **ret_val) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static const IRawElementProviderFragmentRootVtbl ProviderFragmentRootVtbl = { + ProviderFragmentRoot_QueryInterface, + ProviderFragmentRoot_AddRef, + ProviderFragmentRoot_Release, + ProviderFragmentRoot_ElementProviderFromPoint, + ProviderFragmentRoot_GetFocus, +}; + static struct Provider Provider = { { &ProviderSimpleVtbl }, { &ProviderFragmentVtbl }, + { &ProviderFragmentRootVtbl }, 1, "Provider", - NULL, + NULL, NULL, 0, 0, 0, };
@@ -1784,9 +1901,10 @@ static struct Provider Provider2 = { { &ProviderSimpleVtbl }, { &ProviderFragmentVtbl }, + { &ProviderFragmentRootVtbl }, 1, "Provider2", - NULL, + NULL, NULL, 0, 0, 0, };
@@ -1794,9 +1912,10 @@ static struct Provider Provider_child = { { &ProviderSimpleVtbl }, { &ProviderFragmentVtbl }, + { &ProviderFragmentRootVtbl }, 1, "Provider_child", - &Provider.IRawElementProviderFragment_iface, + &Provider.IRawElementProviderFragment_iface, &Provider.IRawElementProviderFragmentRoot_iface, ProviderOptions_ServerSideProvider, 0, 0, };
@@ -1804,9 +1923,10 @@ static struct Provider Provider_child2 = { { &ProviderSimpleVtbl }, { &ProviderFragmentVtbl }, + { &ProviderFragmentRootVtbl }, 1, "Provider_child2", - &Provider.IRawElementProviderFragment_iface, + &Provider.IRawElementProviderFragment_iface, &Provider.IRawElementProviderFragmentRoot_iface, ProviderOptions_ServerSideProvider, 0, 0, };
@@ -4449,6 +4569,258 @@ static void test_UiaGetPropertyValue(void) CoUninitialize(); }
+static const struct prov_method_sequence get_runtime_id1[] = { + { &Provider_child, FRAG_GET_RUNTIME_ID, METHOD_TODO }, + { 0 } +}; + +static const struct prov_method_sequence get_runtime_id2[] = { + { &Provider_child, FRAG_GET_RUNTIME_ID, METHOD_TODO }, + { &Provider_child, FRAG_GET_FRAGMENT_ROOT, METHOD_TODO }, + { 0 } +}; + +static const struct prov_method_sequence get_runtime_id3[] = { + { &Provider_child, FRAG_GET_RUNTIME_ID, METHOD_TODO }, + { &Provider_child, FRAG_GET_FRAGMENT_ROOT, METHOD_TODO }, + { &Provider, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_TODO }, + /* Not called on Windows 7. */ + { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */ + /* Only called on Win8+. */ + { &Provider, FRAG_GET_FRAGMENT_ROOT, METHOD_OPTIONAL }, + { &Provider2, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_OPTIONAL }, + { &Provider2, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */ + { &Provider2, FRAG_GET_FRAGMENT_ROOT, METHOD_OPTIONAL }, + { 0 } +}; + +static const struct prov_method_sequence get_runtime_id4[] = { + { &Provider_child, FRAG_GET_RUNTIME_ID, METHOD_TODO }, + { &Provider_child, FRAG_GET_FRAGMENT_ROOT, METHOD_TODO }, + { &Provider, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_TODO }, + /* Not called on Windows 7. */ + { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */ + /* These methods are only called on Win8+. */ + { &Provider, FRAG_GET_FRAGMENT_ROOT, METHOD_OPTIONAL }, + { &Provider2, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_OPTIONAL }, + { &Provider2, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, + { 0 } +}; + +static const struct prov_method_sequence get_runtime_id5[] = { + { &Provider_child, FRAG_GET_RUNTIME_ID, METHOD_TODO }, + { &Provider_child, FRAG_GET_FRAGMENT_ROOT, METHOD_TODO }, + { &Provider, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_TODO }, + { &Provider, PROV_GET_PROVIDER_OPTIONS, METHOD_TODO }, + { 0 } +}; + +static void test_UiaGetRuntimeId(void) +{ + const int root_prov_opts[] = { ProviderOptions_ServerSideProvider, ProviderOptions_ServerSideProvider | ProviderOptions_OverrideProvider, + ProviderOptions_ClientSideProvider | ProviderOptions_NonClientAreaProvider }; + int rt_id[4], tmp, i; + SAFEARRAY *sa; + WNDCLASSA cls; + HUIANODE node; + HRESULT hr; + HWND hwnd; + VARIANT v; + + VariantInit(&v); + cls.style = 0; + cls.lpfnWndProc = test_wnd_proc; + cls.cbClsExtra = 0; + cls.cbWndExtra = 0; + cls.hInstance = GetModuleHandleA(NULL); + cls.hIcon = 0; + cls.hCursor = NULL; + cls.hbrBackground = NULL; + cls.lpszMenuName = NULL; + cls.lpszClassName = "UiaGetRuntimeId class"; + + RegisterClassA(&cls); + + hwnd = CreateWindowA("UiaGetRuntimeId class", "Test window", WS_OVERLAPPEDWINDOW, + 0, 0, 100, 100, NULL, NULL, NULL, NULL); + + CoInitializeEx(NULL, COINIT_MULTITHREADED); + Provider.prov_opts = Provider2.prov_opts = Provider_child.prov_opts = ProviderOptions_ServerSideProvider; + Provider.hwnd = Provider2.hwnd = Provider_child.hwnd = NULL; + node = (void *)0xdeadbeef; + hr = UiaNodeFromProvider(&Provider_child.IRawElementProviderSimple_iface, &node); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref); + + hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v); + todo_wine ok(hr == S_OK, "Unexpected hr %#lx\n", hr); + if (SUCCEEDED(hr)) + { + check_node_provider_desc_prefix(V_BSTR(&v), GetCurrentProcessId(), NULL); + check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider_child", TRUE); + VariantClear(&v); + } + ok_method_sequence(node_from_prov3, NULL); + + /* NULL runtime ID. */ + Provider_child.runtime_id[0] = Provider_child.runtime_id[1] = 0; + sa = (void *)0xdeadbeef; + hr = UiaGetRuntimeId(node, &sa); + todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(!sa, "sa != NULL\n"); + ok_method_sequence(get_runtime_id1, "get_runtime_id1"); + + /* No UiaAppendRuntimeId prefix, returns GetRuntimeId array directly. */ + Provider_child.runtime_id[0] = rt_id[0] = 5; + Provider_child.runtime_id[1] = rt_id[1] = 2; + sa = (void *)0xdeadbeef; + hr = UiaGetRuntimeId(node, &sa); + todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + todo_wine ok(!!sa, "sa == NULL\n"); + if (sa) + check_runtime_id(rt_id, 2, sa); + SafeArrayDestroy(sa); + ok_method_sequence(get_runtime_id1, "get_runtime_id1"); + + /* + * If a provider returns a RuntimeId beginning with the constant + * UiaAppendRuntimeId, UI Automation will add a prefix based on the + * providers HWND fragment root before returning to the client. The added + * prefix is 3 int values, with: + * + * idx[0] always being 42. (UIA_RUNTIME_ID_PREFIX) + * idx[1] always being the HWND. + * idx[2] has three different values depending on what type of provider + * the fragment root is. Fragment roots can be an override provider, a + * nonclient provider, or a main provider. + */ + Provider_child.frag_root = NULL; + Provider_child.runtime_id[0] = UiaAppendRuntimeId; + Provider_child.runtime_id[1] = 2; + sa = (void *)0xdeadbeef; + + /* Provider_child has no fragment root for UiaAppendRuntimeId. */ + hr = UiaGetRuntimeId(node, &sa); + /* Windows 7 returns S_OK. */ + todo_wine ok(hr == E_FAIL || broken(hr == S_OK), "Unexpected hr %#lx.\n", hr); + ok(!sa, "sa != NULL\n"); + ok_method_sequence(get_runtime_id2, "get_runtime_id2"); + + /* + * Provider_child returns a fragment root that doesn't expose an HWND. On + * Win8+, fragment roots are navigated recursively until either a NULL + * fragment root is returned, the same fragment root as the current one is + * returned, or a fragment root with an HWND is returned. + */ + Provider_child.frag_root = &Provider.IRawElementProviderFragmentRoot_iface; + Provider2.prov_opts = ProviderOptions_ServerSideProvider; + Provider2.hwnd = NULL; + Provider.frag_root = &Provider2.IRawElementProviderFragmentRoot_iface; + Provider.hwnd = NULL; + Provider_child.runtime_id[0] = UiaAppendRuntimeId; + Provider_child.runtime_id[1] = 2; + sa = (void *)0xdeadbeef; + hr = UiaGetRuntimeId(node, &sa); + /* Windows 7 returns S_OK. */ + todo_wine ok(hr == E_FAIL || broken(hr == S_OK), "Unexpected hr %#lx.\n", hr); + ok(!sa, "sa != NULL\n"); + ok_method_sequence(get_runtime_id3, "get_runtime_id3"); + + /* Provider2 returns an HWND. */ + Provider.hwnd = NULL; + Provider.frag_root = &Provider2.IRawElementProviderFragmentRoot_iface; + Provider2.hwnd = hwnd; + Provider2.prov_opts = ProviderOptions_ServerSideProvider; + Provider_child.runtime_id[0] = UiaAppendRuntimeId; + Provider_child.runtime_id[1] = rt_id[3] = 2; + sa = NULL; + hr = UiaGetRuntimeId(node, &sa); + todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + /* Windows 7 returns a NULL RuntimeId due to no fragment recursion. */ + todo_wine ok(!!sa || broken(!sa), "sa == NULL\n"); + SafeArrayDestroy(sa); + + ok_method_sequence(get_runtime_id4, "get_runtime_id4"); + + /* Test RuntimeId values for different root fragment provider types. */ + Provider.frag_root = NULL; + Provider.hwnd = hwnd; + Provider_child.runtime_id[0] = UiaAppendRuntimeId; + Provider_child.runtime_id[1] = rt_id[3] = 2; + rt_id[0] = UIA_RUNTIME_ID_PREFIX; + rt_id[1] = HandleToULong(hwnd); + for (i = 0; i < ARRAY_SIZE(root_prov_opts); i++) + { + LONG lbound; + + Provider.prov_opts = root_prov_opts[i]; + sa = NULL; + hr = UiaGetRuntimeId(node, &sa); + todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + todo_wine ok(!!sa, "sa == NULL\n"); + + hr = SafeArrayGetLBound(sa, 1, &lbound); + todo_wine ok(hr == S_OK, "Failed to get LBound with hr %#lx\n", hr); + + lbound = lbound + 2; + hr = SafeArrayGetElement(sa, &lbound, &tmp); + todo_wine ok(hr == S_OK, "Failed to get element with hr %#lx\n", hr); + if (i && SUCCEEDED(hr)) + ok(rt_id[2] != tmp, "Expected different runtime id value from previous\n"); + + rt_id[2] = tmp; + if (sa) + check_runtime_id(rt_id, 4, sa); + SafeArrayDestroy(sa); + ok_method_sequence(get_runtime_id5, "get_runtime_id5"); + } + + UiaNodeRelease(node); + + /* Test behavior on a node with an associated HWND. */ + Provider.prov_opts = ProviderOptions_ClientSideProvider; + Provider2.prov_opts = ProviderOptions_ServerSideProvider; + Provider.hwnd = Provider2.hwnd = hwnd; + prov_root = &Provider2.IRawElementProviderSimple_iface; + node = (void *)0xdeadbeef; + SET_EXPECT(winproc_GETOBJECT_UiaRoot); + /* Windows 7 sends this. */ + SET_EXPECT(winproc_GETOBJECT_CLIENT); + hr = UiaNodeFromProvider(&Provider.IRawElementProviderSimple_iface, &node); + ok(hr == S_OK, "Unexpected hr %#lx\n", hr); + todo_wine CHECK_CALLED(winproc_GETOBJECT_UiaRoot); + called_winproc_GETOBJECT_CLIENT = expect_winproc_GETOBJECT_CLIENT = 0; + + VariantInit(&v); + hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &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"Provider2", TRUE); + check_node_provider_desc(V_BSTR(&v), L"Nonclient", NULL, FALSE); + check_node_provider_desc(V_BSTR(&v), L"Hwnd", L"Provider", FALSE); + VariantClear(&v); + } + ok_method_sequence(node_from_prov6, "node_from_prov6"); + + /* No methods called, RuntimeId is based on the node's HWND. */ + hr = UiaGetRuntimeId(node, &sa); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(!!sa, "sa == NULL\n"); + ok(!sequence_cnt, "Unexpected sequence_cnt %d\n", sequence_cnt); + + rt_id[0] = UIA_RUNTIME_ID_PREFIX; + rt_id[1] = HandleToULong(hwnd); + check_runtime_id(rt_id, 2, sa); + SafeArrayDestroy(sa); + UiaNodeRelease(node); + + DestroyWindow(hwnd); + UnregisterClassA("UiaGetRuntimeId class", NULL); + CoUninitialize(); +} + START_TEST(uiautomation) { HMODULE uia_dll = LoadLibraryA("uiautomationcore.dll"); @@ -4470,6 +4842,7 @@ START_TEST(uiautomation) test_UiaLookupId(); test_UiaNodeFromProvider(); test_UiaGetPropertyValue(); + test_UiaGetRuntimeId(); if (uia_dll) { pUiaProviderFromIAccessible = (void *)GetProcAddress(uia_dll, "UiaProviderFromIAccessible"); diff --git a/dlls/uiautomationcore/uia_client.c b/dlls/uiautomationcore/uia_client.c index b7e8f45636a..8e672b048a5 100644 --- a/dlls/uiautomationcore/uia_client.c +++ b/dlls/uiautomationcore/uia_client.c @@ -653,3 +653,57 @@ HRESULT WINAPI UiaGetPropertyValue(HUIANODE huianode, PROPERTYID prop_id, VARIAN
return S_OK; } + +#define UIA_RUNTIME_ID_PREFIX 42 +static HRESULT write_runtime_id_base(SAFEARRAY *sa, HWND hwnd) +{ + const int rt_id[2] = { UIA_RUNTIME_ID_PREFIX, HandleToUlong(hwnd) }; + HRESULT hr; + LONG idx; + + for (idx = 0; idx < ARRAY_SIZE(rt_id); idx++) + { + hr = SafeArrayPutElement(sa, &idx, (void *)&rt_id[idx]); + if (FAILED(hr)) + return hr; + } + + return S_OK; +} + +/*********************************************************************** + * UiaGetRuntimeId (uiautomationcore.@) + */ +HRESULT WINAPI UiaGetRuntimeId(HUIANODE huianode, SAFEARRAY **runtime_id) +{ + struct uia_node *node = unsafe_impl_from_IWineUiaNode((IWineUiaNode *)huianode); + HRESULT hr; + + FIXME("(%p, %p): partial stub\n", huianode, runtime_id); + + if (!node || !runtime_id) + return E_INVALIDARG; + + *runtime_id = NULL; + + /* Provide an HWND based runtime ID if the node has an HWND. */ + if (node->hwnd) + { + SAFEARRAY *sa; + + if (!(sa = SafeArrayCreateVector(VT_I4, 0, 2))) + return E_FAIL; + + hr = write_runtime_id_base(sa, node->hwnd); + if (FAILED(hr)) + { + SafeArrayDestroy(sa); + return hr; + } + + *runtime_id = sa; + return S_OK; + } + + return E_NOTIMPL; +} diff --git a/dlls/uiautomationcore/uiautomationcore.spec b/dlls/uiautomationcore/uiautomationcore.spec index 4315abf7433..17e34ee259a 100644 --- a/dlls/uiautomationcore/uiautomationcore.spec +++ b/dlls/uiautomationcore/uiautomationcore.spec @@ -66,7 +66,7 @@ @ stdcall UiaGetReservedMixedAttributeValue(ptr) @ stdcall UiaGetReservedNotSupportedValue(ptr) @ stub UiaGetRootNode -@ stub UiaGetRuntimeId +@ stdcall UiaGetRuntimeId(ptr ptr) @ stub UiaGetUpdatedCache @ stub UiaHPatternObjectFromVariant @ stub UiaHTextRangeFromVariant diff --git a/include/uiautomationcoreapi.h b/include/uiautomationcoreapi.h index 66fa2119597..78cbca2e25b 100644 --- a/include/uiautomationcoreapi.h +++ b/include/uiautomationcoreapi.h @@ -395,6 +395,7 @@ HRESULT WINAPI UiaProviderFromIAccessible(IAccessible *acc, long child_id, DWORD HRESULT WINAPI UiaGetPropertyValue(HUIANODE huianode, PROPERTYID prop_id, VARIANT *out_val); HRESULT WINAPI UiaNodeFromProvider(IRawElementProviderSimple *elprov, HUIANODE *huianode); BOOL WINAPI UiaNodeRelease(HUIANODE huianode); +HRESULT WINAPI UiaGetRuntimeId(HUIANODE huianode, SAFEARRAY **runtime_id);
#ifdef __cplusplus }
From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/uiautomationcore/tests/uiautomation.c | 72 +++-- dlls/uiautomationcore/uia_classes.idl | 1 + dlls/uiautomationcore/uia_client.c | 334 +++++++++++++++++++-- dlls/uiautomationcore/uia_ids.c | 105 +++---- dlls/uiautomationcore/uia_private.h | 6 + 5 files changed, 406 insertions(+), 112 deletions(-)
diff --git a/dlls/uiautomationcore/tests/uiautomation.c b/dlls/uiautomationcore/tests/uiautomation.c index 761f492a7b5..06309566990 100644 --- a/dlls/uiautomationcore/tests/uiautomation.c +++ b/dlls/uiautomationcore/tests/uiautomation.c @@ -4570,20 +4570,20 @@ static void test_UiaGetPropertyValue(void) }
static const struct prov_method_sequence get_runtime_id1[] = { - { &Provider_child, FRAG_GET_RUNTIME_ID, METHOD_TODO }, + { &Provider_child, FRAG_GET_RUNTIME_ID }, { 0 } };
static const struct prov_method_sequence get_runtime_id2[] = { - { &Provider_child, FRAG_GET_RUNTIME_ID, METHOD_TODO }, - { &Provider_child, FRAG_GET_FRAGMENT_ROOT, METHOD_TODO }, + { &Provider_child, FRAG_GET_RUNTIME_ID }, + { &Provider_child, FRAG_GET_FRAGMENT_ROOT }, { 0 } };
static const struct prov_method_sequence get_runtime_id3[] = { - { &Provider_child, FRAG_GET_RUNTIME_ID, METHOD_TODO }, - { &Provider_child, FRAG_GET_FRAGMENT_ROOT, METHOD_TODO }, - { &Provider, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_TODO }, + { &Provider_child, FRAG_GET_RUNTIME_ID }, + { &Provider_child, FRAG_GET_FRAGMENT_ROOT }, + { &Provider, PROV_GET_HOST_RAW_ELEMENT_PROVIDER }, /* Not called on Windows 7. */ { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */ /* Only called on Win8+. */ @@ -4595,9 +4595,9 @@ static const struct prov_method_sequence get_runtime_id3[] = { };
static const struct prov_method_sequence get_runtime_id4[] = { - { &Provider_child, FRAG_GET_RUNTIME_ID, METHOD_TODO }, - { &Provider_child, FRAG_GET_FRAGMENT_ROOT, METHOD_TODO }, - { &Provider, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_TODO }, + { &Provider_child, FRAG_GET_RUNTIME_ID }, + { &Provider_child, FRAG_GET_FRAGMENT_ROOT }, + { &Provider, PROV_GET_HOST_RAW_ELEMENT_PROVIDER }, /* Not called on Windows 7. */ { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */ /* These methods are only called on Win8+. */ @@ -4608,10 +4608,10 @@ static const struct prov_method_sequence get_runtime_id4[] = { };
static const struct prov_method_sequence get_runtime_id5[] = { - { &Provider_child, FRAG_GET_RUNTIME_ID, METHOD_TODO }, - { &Provider_child, FRAG_GET_FRAGMENT_ROOT, METHOD_TODO }, - { &Provider, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_TODO }, - { &Provider, PROV_GET_PROVIDER_OPTIONS, METHOD_TODO }, + { &Provider_child, FRAG_GET_RUNTIME_ID }, + { &Provider_child, FRAG_GET_FRAGMENT_ROOT }, + { &Provider, PROV_GET_HOST_RAW_ELEMENT_PROVIDER }, + { &Provider, PROV_GET_PROVIDER_OPTIONS }, { 0 } };
@@ -4620,6 +4620,7 @@ static void test_UiaGetRuntimeId(void) const int root_prov_opts[] = { ProviderOptions_ServerSideProvider, ProviderOptions_ServerSideProvider | ProviderOptions_OverrideProvider, ProviderOptions_ClientSideProvider | ProviderOptions_NonClientAreaProvider }; int rt_id[4], tmp, i; + IUnknown *unk_ns; SAFEARRAY *sa; WNDCLASSA cls; HUIANODE node; @@ -4644,6 +4645,9 @@ static void test_UiaGetRuntimeId(void) hwnd = CreateWindowA("UiaGetRuntimeId class", "Test window", WS_OVERLAPPEDWINDOW, 0, 0, 100, 100, NULL, NULL, NULL, NULL);
+ hr = UiaGetReservedNotSupportedValue(&unk_ns); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + CoInitializeEx(NULL, COINIT_MULTITHREADED); Provider.prov_opts = Provider2.prov_opts = Provider_child.prov_opts = ProviderOptions_ServerSideProvider; Provider.hwnd = Provider2.hwnd = Provider_child.hwnd = NULL; @@ -4666,7 +4670,7 @@ static void test_UiaGetRuntimeId(void) Provider_child.runtime_id[0] = Provider_child.runtime_id[1] = 0; sa = (void *)0xdeadbeef; hr = UiaGetRuntimeId(node, &sa); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ok(!sa, "sa != NULL\n"); ok_method_sequence(get_runtime_id1, "get_runtime_id1");
@@ -4675,10 +4679,9 @@ static void test_UiaGetRuntimeId(void) Provider_child.runtime_id[1] = rt_id[1] = 2; sa = (void *)0xdeadbeef; hr = UiaGetRuntimeId(node, &sa); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - todo_wine ok(!!sa, "sa == NULL\n"); - if (sa) - check_runtime_id(rt_id, 2, sa); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(!!sa, "sa == NULL\n"); + check_runtime_id(rt_id, 2, sa); SafeArrayDestroy(sa); ok_method_sequence(get_runtime_id1, "get_runtime_id1");
@@ -4702,10 +4705,21 @@ static void test_UiaGetRuntimeId(void) /* Provider_child has no fragment root for UiaAppendRuntimeId. */ hr = UiaGetRuntimeId(node, &sa); /* Windows 7 returns S_OK. */ - todo_wine ok(hr == E_FAIL || broken(hr == S_OK), "Unexpected hr %#lx.\n", hr); + ok(hr == E_FAIL || broken(hr == S_OK), "Unexpected hr %#lx.\n", hr); ok(!sa, "sa != NULL\n"); ok_method_sequence(get_runtime_id2, "get_runtime_id2");
+ /* + * UIA_RuntimeIdPropertyId won't return a failure code from + * UiaGetPropertyValue. + */ + hr = UiaGetPropertyValue(node, UIA_RuntimeIdPropertyId, &v); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + 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); + ok_method_sequence(get_runtime_id2, "get_runtime_id2"); + /* * Provider_child returns a fragment root that doesn't expose an HWND. On * Win8+, fragment roots are navigated recursively until either a NULL @@ -4722,7 +4736,7 @@ static void test_UiaGetRuntimeId(void) sa = (void *)0xdeadbeef; hr = UiaGetRuntimeId(node, &sa); /* Windows 7 returns S_OK. */ - todo_wine ok(hr == E_FAIL || broken(hr == S_OK), "Unexpected hr %#lx.\n", hr); + ok(hr == E_FAIL || broken(hr == S_OK), "Unexpected hr %#lx.\n", hr); ok(!sa, "sa != NULL\n"); ok_method_sequence(get_runtime_id3, "get_runtime_id3");
@@ -4735,9 +4749,9 @@ static void test_UiaGetRuntimeId(void) Provider_child.runtime_id[1] = rt_id[3] = 2; sa = NULL; hr = UiaGetRuntimeId(node, &sa); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); /* Windows 7 returns a NULL RuntimeId due to no fragment recursion. */ - todo_wine ok(!!sa || broken(!sa), "sa == NULL\n"); + ok(!!sa || broken(!sa), "sa == NULL\n"); SafeArrayDestroy(sa);
ok_method_sequence(get_runtime_id4, "get_runtime_id4"); @@ -4756,21 +4770,21 @@ static void test_UiaGetRuntimeId(void) Provider.prov_opts = root_prov_opts[i]; sa = NULL; hr = UiaGetRuntimeId(node, &sa); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - todo_wine ok(!!sa, "sa == NULL\n"); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(!!sa, "sa == NULL\n");
hr = SafeArrayGetLBound(sa, 1, &lbound); - todo_wine ok(hr == S_OK, "Failed to get LBound with hr %#lx\n", hr); + ok(hr == S_OK, "Failed to get LBound with hr %#lx\n", hr);
lbound = lbound + 2; hr = SafeArrayGetElement(sa, &lbound, &tmp); - todo_wine ok(hr == S_OK, "Failed to get element with hr %#lx\n", hr); - if (i && SUCCEEDED(hr)) + ok(hr == S_OK, "Failed to get element with hr %#lx\n", hr); + if (i) ok(rt_id[2] != tmp, "Expected different runtime id value from previous\n");
rt_id[2] = tmp; - if (sa) - check_runtime_id(rt_id, 4, sa); + check_runtime_id(rt_id, 4, sa); + SafeArrayDestroy(sa); ok_method_sequence(get_runtime_id5, "get_runtime_id5"); } diff --git a/dlls/uiautomationcore/uia_classes.idl b/dlls/uiautomationcore/uia_classes.idl index 8a627b92041..f7d3bb90c73 100644 --- a/dlls/uiautomationcore/uia_classes.idl +++ b/dlls/uiautomationcore/uia_classes.idl @@ -23,6 +23,7 @@ import "oaidl.idl"; struct uia_prop_info { const GUID *guid; int prop_id; + int prop_type; int type; };
diff --git a/dlls/uiautomationcore/uia_client.c b/dlls/uiautomationcore/uia_client.c index 8e672b048a5..f166ed20b53 100644 --- a/dlls/uiautomationcore/uia_client.c +++ b/dlls/uiautomationcore/uia_client.c @@ -23,6 +23,32 @@
WINE_DEFAULT_DEBUG_CHANNEL(uiautomation);
+static HRESULT get_safearray_bounds(SAFEARRAY *sa, LONG *lbound, LONG *elems) +{ + LONG ubound; + HRESULT hr; + UINT dims; + + *lbound = *elems = 0; + dims = SafeArrayGetDim(sa); + if (dims != 1) + { + WARN("Invalid dimensions %d for safearray.\n", dims); + return E_FAIL; + } + + hr = SafeArrayGetLBound(sa, 1, lbound); + if (FAILED(hr)) + return hr; + + hr = SafeArrayGetUBound(sa, 1, &ubound); + if (FAILED(hr)) + return hr; + + *elems = (ubound - (*lbound)) + 1; + return S_OK; +} + static void clear_uia_node_ptr_safearray(SAFEARRAY *sa, LONG elems) { HUIANODE node; @@ -40,28 +66,14 @@ static void clear_uia_node_ptr_safearray(SAFEARRAY *sa, LONG elems)
static void create_uia_node_safearray(VARIANT *in, VARIANT *out) { - LONG i, idx, lbound, ubound, elems; + LONG i, idx, lbound, elems; HUIANODE node; SAFEARRAY *sa; HRESULT hr; - UINT dims; - - dims = SafeArrayGetDim(V_ARRAY(in)); - if (!dims || (dims > 1)) - { - WARN("Invalid dimensions %d for element safearray.\n", dims); - return; - }
- hr = SafeArrayGetLBound(V_ARRAY(in), 1, &lbound); - if (FAILED(hr)) + if (FAILED(get_safearray_bounds(V_ARRAY(in), &lbound, &elems))) return;
- hr = SafeArrayGetUBound(V_ARRAY(in), 1, &ubound); - if (FAILED(hr)) - return; - - elems = (ubound - lbound) + 1; if (!(sa = SafeArrayCreateVector(VT_UINT_PTR, 0, elems))) return;
@@ -191,6 +203,69 @@ static HWND get_hwnd_from_provider(IRawElementProviderSimple *elprov) return hwnd; }
+static IRawElementProviderSimple *get_provider_hwnd_fragment_root(IRawElementProviderSimple *elprov, HWND *hwnd) +{ + IRawElementProviderFragmentRoot *elroot, *elroot2; + IRawElementProviderSimple *elprov2, *ret; + IRawElementProviderFragment *elfrag; + HRESULT hr; + int depth; + + *hwnd = NULL; + + hr = IRawElementProviderSimple_QueryInterface(elprov, &IID_IRawElementProviderFragment, (void **)&elfrag); + if (FAILED(hr) || !elfrag) + return NULL; + + depth = 0; + ret = NULL; + elroot = elroot2 = NULL; + + /* + * Recursively walk up the fragment root chain until: + * We get a fragment root that has an HWND associated with it. + * We get a NULL fragment root. + * We get the same fragment root as the current fragment root. + * We've gone up the chain ten times. + */ + while (depth < 10) + { + hr = IRawElementProviderFragment_get_FragmentRoot(elfrag, &elroot); + IRawElementProviderFragment_Release(elfrag); + if (FAILED(hr) || !elroot || (elroot == elroot2)) + break; + + hr = IRawElementProviderFragmentRoot_QueryInterface(elroot, &IID_IRawElementProviderSimple, (void **)&elprov2); + if (FAILED(hr) || !elprov2) + break; + + *hwnd = get_hwnd_from_provider(elprov2); + if (IsWindow(*hwnd)) + { + ret = elprov2; + break; + } + + hr = IRawElementProviderSimple_QueryInterface(elprov2, &IID_IRawElementProviderFragment, (void **)&elfrag); + IRawElementProviderSimple_Release(elprov2); + if (FAILED(hr) || !elfrag) + break; + + if (elroot2) + IRawElementProviderFragmentRoot_Release(elroot2); + elroot2 = elroot; + elroot = NULL; + depth++; + } + + if (elroot) + IRawElementProviderFragmentRoot_Release(elroot); + if (elroot2) + IRawElementProviderFragmentRoot_Release(elroot2); + + return ret; +} + /* * IWineUiaNode interface. */ @@ -368,15 +443,12 @@ static void get_variant_for_node(HUIANODE node, VARIANT *v) #endif }
-static HRESULT WINAPI uia_provider_get_prop_val(IWineUiaProvider *iface, +static HRESULT uia_provider_get_elem_prop_val(struct uia_provider *prov, const struct uia_prop_info *prop_info, VARIANT *ret_val) { - struct uia_provider *prov = impl_from_IWineUiaProvider(iface); HRESULT hr; VARIANT v;
- TRACE("%p, %p, %p\n", iface, prop_info, ret_val); - VariantInit(&v); hr = IRawElementProviderSimple_GetPropertyValue(prov->elprov, prop_info->prop_id, &v); if (FAILED(hr)) @@ -486,6 +558,100 @@ exit: return S_OK; }
+static SAFEARRAY *append_uia_runtime_id(SAFEARRAY *sa, HWND hwnd, enum ProviderOptions root_opts); +static HRESULT uia_provider_get_special_prop_val(struct uia_provider *prov, + const struct uia_prop_info *prop_info, VARIANT *ret_val) +{ + HRESULT hr; + + switch (prop_info->prop_id) + { + case UIA_RuntimeIdPropertyId: + { + IRawElementProviderFragment *elfrag; + SAFEARRAY *sa; + LONG lbound; + int val; + + hr = IRawElementProviderSimple_QueryInterface(prov->elprov, &IID_IRawElementProviderFragment, (void **)&elfrag); + if (FAILED(hr) || !elfrag) + break; + + hr = IRawElementProviderFragment_GetRuntimeId(elfrag, &sa); + IRawElementProviderFragment_Release(elfrag); + if (FAILED(hr) || !sa) + break; + + hr = SafeArrayGetLBound(sa, 1, &lbound); + if (FAILED(hr)) + { + SafeArrayDestroy(sa); + break; + } + + hr = SafeArrayGetElement(sa, &lbound, &val); + if (FAILED(hr)) + { + SafeArrayDestroy(sa); + break; + } + + if (val == UiaAppendRuntimeId) + { + enum ProviderOptions prov_opts = 0; + IRawElementProviderSimple *elprov; + HWND hwnd; + + elprov = get_provider_hwnd_fragment_root(prov->elprov, &hwnd); + if (!elprov) + { + SafeArrayDestroy(sa); + return E_FAIL; + } + + hr = IRawElementProviderSimple_get_ProviderOptions(elprov, &prov_opts); + IRawElementProviderSimple_Release(elprov); + if (FAILED(hr)) + WARN("get_ProviderOptions for root provider failed with %#lx\n", hr); + + if (!(sa = append_uia_runtime_id(sa, hwnd, prov_opts))) + break; + } + + V_VT(ret_val) = VT_I4 | VT_ARRAY; + V_ARRAY(ret_val) = sa; + break; + } + + default: + break; + } + + return S_OK; +} + +static HRESULT WINAPI uia_provider_get_prop_val(IWineUiaProvider *iface, + const struct uia_prop_info *prop_info, VARIANT *ret_val) +{ + struct uia_provider *prov = impl_from_IWineUiaProvider(iface); + + TRACE("%p, %p, %p\n", iface, prop_info, ret_val); + + switch (prop_info->prop_type) + { + case PROP_TYPE_ELEM_PROP: + return uia_provider_get_elem_prop_val(prov, prop_info, ret_val); + + case PROP_TYPE_SPECIAL: + return uia_provider_get_special_prop_val(prov, prop_info, ret_val); + + default: + break; + } + + return S_OK; +} + static const IWineUiaProviderVtbl uia_provider_vtbl = { uia_provider_QueryInterface, uia_provider_AddRef, @@ -597,6 +763,23 @@ BOOL WINAPI UiaNodeRelease(HUIANODE huianode) return TRUE; }
+static HRESULT get_prop_val_from_node_provider(struct uia_node *node, + const struct uia_prop_info *prop_info, VARIANT *v) +{ + IWineUiaProvider *prov; + HRESULT hr; + + hr = IWineUiaNode_get_provider(&node->IWineUiaNode_iface, &prov); + if (FAILED(hr)) + return hr; + + VariantInit(v); + hr = IWineUiaProvider_get_prop_val(prov, prop_info, v); + IWineUiaProvider_Release(prov); + + return hr; +} + /*********************************************************************** * UiaGetPropertyValue (uiautomationcore.@) */ @@ -604,7 +787,6 @@ HRESULT WINAPI UiaGetPropertyValue(HUIANODE huianode, PROPERTYID prop_id, VARIAN { struct uia_node *node = unsafe_impl_from_IWineUiaNode((IWineUiaNode *)huianode); const struct uia_prop_info *prop_info; - IWineUiaProvider *prov; HRESULT hr; VARIANT v;
@@ -626,12 +808,26 @@ HRESULT WINAPI UiaGetPropertyValue(HUIANODE huianode, PROPERTYID prop_id, VARIAN return E_NOTIMPL; }
- hr = IWineUiaNode_get_provider(&node->IWineUiaNode_iface, &prov); - if (FAILED(hr)) - return hr; + switch (prop_id) + { + case UIA_RuntimeIdPropertyId: + { + SAFEARRAY *sa;
- VariantInit(&v); - hr = IWineUiaProvider_get_prop_val(prov, prop_info, &v); + hr = UiaGetRuntimeId(huianode, &sa); + if (SUCCEEDED(hr) && sa) + { + V_VT(out_val) = VT_I4 | VT_ARRAY; + V_ARRAY(out_val) = sa; + } + return S_OK; + } + + default: + break; + } + + hr = get_prop_val_from_node_provider(node, prop_info, &v); if (SUCCEEDED(hr) && V_VT(&v) != VT_EMPTY) { /* @@ -649,12 +845,17 @@ HRESULT WINAPI UiaGetPropertyValue(HUIANODE huianode, PROPERTYID prop_id, VARIAN *out_val = v; }
- IWineUiaProvider_Release(prov); - - return S_OK; + return hr; }
#define UIA_RUNTIME_ID_PREFIX 42 + +enum fragment_root_prov_type_ids { + FRAGMENT_ROOT_NONCLIENT_TYPE_ID = 0x03, + FRAGMENT_ROOT_MAIN_TYPE_ID = 0x04, + FRAGMENT_ROOT_OVERRIDE_TYPE_ID = 0x05, +}; + static HRESULT write_runtime_id_base(SAFEARRAY *sa, HWND hwnd) { const int rt_id[2] = { UIA_RUNTIME_ID_PREFIX, HandleToUlong(hwnd) }; @@ -671,15 +872,72 @@ static HRESULT write_runtime_id_base(SAFEARRAY *sa, HWND hwnd) return S_OK; }
+static SAFEARRAY *append_uia_runtime_id(SAFEARRAY *sa, HWND hwnd, enum ProviderOptions root_opts) +{ + LONG i, idx, lbound, elems; + SAFEARRAY *sa2, *ret; + HRESULT hr; + int val; + + ret = sa2 = NULL; + hr = get_safearray_bounds(sa, &lbound, &elems); + if (FAILED(hr)) + goto exit; + + /* elems includes the UiaAppendRuntimeId value, so we only add 2. */ + if (!(sa2 = SafeArrayCreateVector(VT_I4, 0, elems + 2))) + goto exit; + + hr = write_runtime_id_base(sa2, hwnd); + if (FAILED(hr)) + goto exit; + + if (root_opts & ProviderOptions_NonClientAreaProvider) + val = FRAGMENT_ROOT_NONCLIENT_TYPE_ID; + else if (root_opts & ProviderOptions_OverrideProvider) + val = FRAGMENT_ROOT_OVERRIDE_TYPE_ID; + else + val = FRAGMENT_ROOT_MAIN_TYPE_ID; + + idx = 2; + hr = SafeArrayPutElement(sa2, &idx, &val); + if (FAILED(hr)) + goto exit; + + for (i = 0; i < (elems - 1); i++) + { + idx = (lbound + 1) + i; + hr = SafeArrayGetElement(sa, &idx, &val); + if (FAILED(hr)) + goto exit; + + idx = (3 + i); + hr = SafeArrayPutElement(sa2, &idx, &val); + if (FAILED(hr)) + goto exit; + } + + ret = sa2; + +exit: + + if (!ret) + SafeArrayDestroy(sa2); + + SafeArrayDestroy(sa); + return ret; +} + /*********************************************************************** * UiaGetRuntimeId (uiautomationcore.@) */ HRESULT WINAPI UiaGetRuntimeId(HUIANODE huianode, SAFEARRAY **runtime_id) { + const struct uia_prop_info *prop_info = uia_prop_info_from_id(UIA_RuntimeIdPropertyId); struct uia_node *node = unsafe_impl_from_IWineUiaNode((IWineUiaNode *)huianode); HRESULT hr;
- FIXME("(%p, %p): partial stub\n", huianode, runtime_id); + TRACE("(%p, %p)\n", huianode, runtime_id);
if (!node || !runtime_id) return E_INVALIDARG; @@ -704,6 +962,20 @@ HRESULT WINAPI UiaGetRuntimeId(HUIANODE huianode, SAFEARRAY **runtime_id) *runtime_id = sa; return S_OK; } + else + { + VARIANT v; + + hr = get_prop_val_from_node_provider(node, prop_info, &v); + if (FAILED(hr)) + { + VariantClear(&v); + return hr; + } + + if (V_VT(&v) == (VT_I4 | VT_ARRAY)) + *runtime_id = V_ARRAY(&v); + }
- return E_NOTIMPL; + return S_OK; } diff --git a/dlls/uiautomationcore/uia_ids.c b/dlls/uiautomationcore/uia_ids.c index 7cfde7f4c29..a3a60c8aec9 100644 --- a/dlls/uiautomationcore/uia_ids.c +++ b/dlls/uiautomationcore/uia_ids.c @@ -33,9 +33,9 @@ static int __cdecl uia_property_guid_compare(const void *a, const void *b) /* Sorted by GUID. */ static const struct uia_prop_info default_uia_properties[] = { { &AutomationId_Property_GUID, UIA_AutomationIdPropertyId, - UIAutomationType_String, }, + PROP_TYPE_ELEM_PROP, UIAutomationType_String, }, { &FrameworkId_Property_GUID, UIA_FrameworkIdPropertyId, - UIAutomationType_String, }, + PROP_TYPE_ELEM_PROP, UIAutomationType_String, }, { &IsTransformPatternAvailable_Property_GUID, UIA_IsTransformPatternAvailablePropertyId, }, { &IsScrollItemPatternAvailable_Property_GUID, UIA_IsScrollItemPatternAvailablePropertyId, }, { &IsExpandCollapsePatternAvailable_Property_GUID, UIA_IsExpandCollapsePatternAvailablePropertyId, }, @@ -43,24 +43,24 @@ static const struct uia_prop_info default_uia_properties[] = { { &IsTableItemPatternAvailable_Property_GUID, UIA_IsTableItemPatternAvailablePropertyId, }, { &Scroll_HorizontalScrollPercent_Property_GUID, UIA_ScrollHorizontalScrollPercentPropertyId, }, { &AccessKey_Property_GUID, UIA_AccessKeyPropertyId, - UIAutomationType_String, }, + PROP_TYPE_ELEM_PROP, UIAutomationType_String, }, { &RangeValue_Maximum_Property_GUID, UIA_RangeValueMaximumPropertyId, }, { &ClassName_Property_GUID, UIA_ClassNamePropertyId, - UIAutomationType_String, }, + PROP_TYPE_ELEM_PROP, UIAutomationType_String, }, { &Transform2_ZoomMinimum_Property_GUID, UIA_Transform2ZoomMinimumPropertyId, }, { &LegacyIAccessible_Description_Property_GUID, UIA_LegacyIAccessibleDescriptionPropertyId, }, { &Transform2_ZoomLevel_Property_GUID, UIA_Transform2ZoomLevelPropertyId, }, { &Name_Property_GUID, UIA_NamePropertyId, - UIAutomationType_String, }, + PROP_TYPE_ELEM_PROP, UIAutomationType_String, }, { &GridItem_RowSpan_Property_GUID, UIA_GridItemRowSpanPropertyId, }, { &Size_Property_GUID, UIA_SizePropertyId, - UIAutomationType_DoubleArray, }, + PROP_TYPE_ELEM_PROP, UIAutomationType_DoubleArray, }, { &IsTextPattern2Available_Property_GUID, UIA_IsTextPattern2AvailablePropertyId, }, { &Styles_FillPatternStyle_Property_GUID, UIA_StylesFillPatternStylePropertyId, }, { &FlowsTo_Property_GUID, UIA_FlowsToPropertyId, - UIAutomationType_ElementArray, }, + PROP_TYPE_ELEM_PROP, UIAutomationType_ElementArray, }, { &ItemStatus_Property_GUID, UIA_ItemStatusPropertyId, - UIAutomationType_String, }, + PROP_TYPE_ELEM_PROP, UIAutomationType_String, }, { &Scroll_VerticalViewSize_Property_GUID, UIA_ScrollVerticalViewSizePropertyId, }, { &Selection_IsSelectionRequired_Property_GUID, UIA_SelectionIsSelectionRequiredPropertyId, }, { &IsGridItemPatternAvailable_Property_GUID, UIA_IsGridItemPatternAvailablePropertyId, }, @@ -68,12 +68,12 @@ static const struct uia_prop_info default_uia_properties[] = { { &RangeValue_LargeChange_Property_GUID, UIA_RangeValueLargeChangePropertyId, }, { &Selection2_CurrentSelectedItem_Property_GUID, UIA_Selection2CurrentSelectedItemPropertyId, }, { &Culture_Property_GUID, UIA_CulturePropertyId, - UIAutomationType_Int, }, + PROP_TYPE_ELEM_PROP, UIAutomationType_Int, }, { &LegacyIAccessible_DefaultAction_Property_GUID, UIA_LegacyIAccessibleDefaultActionPropertyId, }, { &Level_Property_GUID, UIA_LevelPropertyId, - UIAutomationType_Int, }, + PROP_TYPE_ELEM_PROP, UIAutomationType_Int, }, { &IsKeyboardFocusable_Property_GUID, UIA_IsKeyboardFocusablePropertyId, - UIAutomationType_Bool, }, + PROP_TYPE_ELEM_PROP, UIAutomationType_Bool, }, { &GridItem_Row_Property_GUID, UIA_GridItemRowPropertyId, }, { &IsSpreadsheetItemPatternAvailable_Property_GUID, UIA_IsSpreadsheetItemPatternAvailablePropertyId, }, { &Table_ColumnHeaders_Property_GUID, UIA_TableColumnHeadersPropertyId, }, @@ -90,12 +90,12 @@ static const struct uia_prop_info default_uia_properties[] = { { &SpreadsheetItem_AnnotationObjects_Property_GUID, UIA_SpreadsheetItemAnnotationObjectsPropertyId, }, { &IsInvokePatternAvailable_Property_GUID, UIA_IsInvokePatternAvailablePropertyId, }, { &HasKeyboardFocus_Property_GUID, UIA_HasKeyboardFocusPropertyId, - UIAutomationType_Bool, }, + PROP_TYPE_ELEM_PROP, UIAutomationType_Bool, }, { &ClickablePoint_Property_GUID, UIA_ClickablePointPropertyId, }, { &NewNativeWindowHandle_Property_GUID, UIA_NativeWindowHandlePropertyId, - UIAutomationType_Int, }, + PROP_TYPE_ELEM_PROP, UIAutomationType_Int, }, { &SizeOfSet_Property_GUID, UIA_SizeOfSetPropertyId, - UIAutomationType_Int, }, + PROP_TYPE_ELEM_PROP, UIAutomationType_Int, }, { &LegacyIAccessible_Name_Property_GUID, UIA_LegacyIAccessibleNamePropertyId, }, { &Window_CanMaximize_Property_GUID, UIA_WindowCanMaximizePropertyId, }, { &Scroll_HorizontallyScrollable_Property_GUID, UIA_ScrollHorizontallyScrollablePropertyId, }, @@ -105,17 +105,17 @@ static const struct uia_prop_info default_uia_properties[] = { { &IsScrollPatternAvailable_Property_GUID, UIA_IsScrollPatternAvailablePropertyId, }, { &IsTransformPattern2Available_Property_GUID, UIA_IsTransformPattern2AvailablePropertyId, }, { &LabeledBy_Property_GUID, UIA_LabeledByPropertyId, - UIAutomationType_Element, }, + PROP_TYPE_ELEM_PROP, UIAutomationType_Element, }, { &ItemType_Property_GUID, UIA_ItemTypePropertyId, - UIAutomationType_String, }, + PROP_TYPE_ELEM_PROP, UIAutomationType_String, }, { &Transform_CanMove_Property_GUID, UIA_TransformCanMovePropertyId, }, { &LocalizedControlType_Property_GUID, UIA_LocalizedControlTypePropertyId, - UIAutomationType_String, }, + PROP_TYPE_ELEM_PROP, UIAutomationType_String, }, { &Annotation_AnnotationTypeId_Property_GUID, UIA_AnnotationAnnotationTypeIdPropertyId, }, { &FlowsFrom_Property_GUID, UIA_FlowsFromPropertyId, - UIAutomationType_ElementArray, }, + PROP_TYPE_ELEM_PROP, UIAutomationType_ElementArray, }, { &OptimizeForVisualContent_Property_GUID, UIA_OptimizeForVisualContentPropertyId, - UIAutomationType_Bool, }, + PROP_TYPE_ELEM_PROP, UIAutomationType_Bool, }, { &IsVirtualizedItemPatternAvailable_Property_GUID, UIA_IsVirtualizedItemPatternAvailablePropertyId, }, { &GridItem_Parent_Property_GUID, UIA_GridItemContainingGridPropertyId, }, { &LegacyIAccessible_Help_Property_GUID, UIA_LegacyIAccessibleHelpPropertyId, }, @@ -123,7 +123,7 @@ static const struct uia_prop_info default_uia_properties[] = { { &IsTogglePatternAvailable_Property_GUID, UIA_IsTogglePatternAvailablePropertyId, }, { &LegacyIAccessible_State_Property_GUID, UIA_LegacyIAccessibleStatePropertyId, }, { &PositionInSet_Property_GUID, UIA_PositionInSetPropertyId, - UIAutomationType_Int, }, + PROP_TYPE_ELEM_PROP, UIAutomationType_Int, }, { &RangeValue_IsReadOnly_Property_GUID, UIA_RangeValueIsReadOnlyPropertyId, }, { &Drag_DropEffects_Property_GUID, UIA_DragDropEffectsPropertyId, }, { &RangeValue_SmallChange_Property_GUID, UIA_RangeValueSmallChangePropertyId, }, @@ -135,63 +135,63 @@ static const struct uia_prop_info default_uia_properties[] = { { &SelectionItem_IsSelected_Property_GUID, UIA_SelectionItemIsSelectedPropertyId, }, { &Window_WindowVisualState_Property_GUID, UIA_WindowWindowVisualStatePropertyId, }, { &IsOffscreen_Property_GUID, UIA_IsOffscreenPropertyId, - UIAutomationType_Bool, }, + PROP_TYPE_ELEM_PROP, UIAutomationType_Bool, }, { &Annotation_Author_Property_GUID, UIA_AnnotationAuthorPropertyId, }, { &Orientation_Property_GUID, UIA_OrientationPropertyId, - UIAutomationType_Int, }, + PROP_TYPE_ELEM_PROP, UIAutomationType_Int, }, { &Value_Value_Property_GUID, UIA_ValueValuePropertyId, }, { &VisualEffects_Property_GUID, UIA_VisualEffectsPropertyId, - UIAutomationType_Int, }, + PROP_TYPE_ELEM_PROP, UIAutomationType_Int, }, { &Selection2_FirstSelectedItem_Property_GUID, UIA_Selection2FirstSelectedItemPropertyId, }, { &IsGridPatternAvailable_Property_GUID, UIA_IsGridPatternAvailablePropertyId, }, { &SelectionItem_SelectionContainer_Property_GUID, UIA_SelectionItemSelectionContainerPropertyId, }, { &HeadingLevel_Property_GUID, UIA_HeadingLevelPropertyId, - UIAutomationType_Int, }, + PROP_TYPE_ELEM_PROP, UIAutomationType_Int, }, { &DropTarget_DropTargetEffect_Property_GUID, UIA_DropTargetDropTargetEffectPropertyId, }, { &Grid_ColumnCount_Property_GUID, UIA_GridColumnCountPropertyId, }, { &AnnotationTypes_Property_GUID, UIA_AnnotationTypesPropertyId, - UIAutomationType_IntArray, }, + PROP_TYPE_ELEM_PROP, UIAutomationType_IntArray, }, { &IsPeripheral_Property_GUID, UIA_IsPeripheralPropertyId, - UIAutomationType_Bool, }, + PROP_TYPE_ELEM_PROP, UIAutomationType_Bool, }, { &Transform2_ZoomMaximum_Property_GUID, UIA_Transform2ZoomMaximumPropertyId, }, { &Drag_DropEffect_Property_GUID, UIA_DragDropEffectPropertyId, }, { &MultipleView_CurrentView_Property_GUID, UIA_MultipleViewCurrentViewPropertyId, }, { &Styles_FillColor_Property_GUID, UIA_StylesFillColorPropertyId, }, { &Rotation_Property_GUID, UIA_RotationPropertyId, - UIAutomationType_Double, }, + PROP_TYPE_ELEM_PROP, UIAutomationType_Double, }, { &SpreadsheetItem_Formula_Property_GUID, UIA_SpreadsheetItemFormulaPropertyId, }, { &IsEnabled_Property_GUID, UIA_IsEnabledPropertyId, - UIAutomationType_Bool, }, + PROP_TYPE_ELEM_PROP, UIAutomationType_Bool, }, { &LocalizedLandmarkType_Property_GUID, UIA_LocalizedLandmarkTypePropertyId, - UIAutomationType_String, }, + PROP_TYPE_ELEM_PROP, UIAutomationType_String, }, { &IsDataValidForForm_Property_GUID, UIA_IsDataValidForFormPropertyId, - UIAutomationType_Bool, }, + PROP_TYPE_ELEM_PROP, UIAutomationType_Bool, }, { &IsControlElement_Property_GUID, UIA_IsControlElementPropertyId, - UIAutomationType_Bool, }, + PROP_TYPE_ELEM_PROP, UIAutomationType_Bool, }, { &HelpText_Property_GUID, UIA_HelpTextPropertyId, - UIAutomationType_String, }, + PROP_TYPE_ELEM_PROP, UIAutomationType_String, }, { &Table_RowHeaders_Property_GUID, UIA_TableRowHeadersPropertyId, }, { &ControllerFor_Property_GUID, UIA_ControllerForPropertyId, - UIAutomationType_ElementArray, }, + PROP_TYPE_ELEM_PROP, UIAutomationType_ElementArray, }, { &ProviderDescription_Property_GUID, UIA_ProviderDescriptionPropertyId, }, { &AriaProperties_Property_GUID, UIA_AriaPropertiesPropertyId, - UIAutomationType_String, }, + PROP_TYPE_ELEM_PROP, UIAutomationType_String, }, { &LiveSetting_Property_GUID, UIA_LiveSettingPropertyId, - UIAutomationType_Int, }, + PROP_TYPE_ELEM_PROP, UIAutomationType_Int, }, { &Selection2_LastSelectedItem_Property_GUID, UIA_Selection2LastSelectedItemPropertyId, }, { &Transform2_CanZoom_Property_GUID, UIA_Transform2CanZoomPropertyId, }, { &Window_IsModal_Property_GUID, UIA_WindowIsModalPropertyId, }, { &Annotation_AnnotationTypeName_Property_GUID, UIA_AnnotationAnnotationTypeNamePropertyId, }, { &AriaRole_Property_GUID, UIA_AriaRolePropertyId, - UIAutomationType_String, }, + PROP_TYPE_ELEM_PROP, UIAutomationType_String, }, { &Scroll_VerticallyScrollable_Property_GUID, UIA_ScrollVerticallyScrollablePropertyId, }, { &RangeValue_Value_Property_GUID, UIA_RangeValueValuePropertyId, }, { &ProcessId_Property_GUID, UIA_ProcessIdPropertyId, - UIAutomationType_Int, }, + PROP_TYPE_ELEM_PROP, UIAutomationType_Int, }, { &Scroll_VerticalScrollPercent_Property_GUID, UIA_ScrollVerticalScrollPercentPropertyId, }, { &IsObjectModelPatternAvailable_Property_GUID, UIA_IsObjectModelPatternAvailablePropertyId, }, { &IsDialog_Property_GUID, UIA_IsDialogPropertyId, - UIAutomationType_Bool, }, + PROP_TYPE_ELEM_PROP, UIAutomationType_Bool, }, { &IsTextPatternAvailable_Property_GUID, UIA_IsTextPatternAvailablePropertyId, }, { &LegacyIAccessible_Role_Property_GUID, UIA_LegacyIAccessibleRolePropertyId, }, { &Selection2_ItemCount_Property_GUID, UIA_Selection2ItemCountPropertyId, }, @@ -205,59 +205,60 @@ static const struct uia_prop_info default_uia_properties[] = { { &IsValuePatternAvailable_Property_GUID, UIA_IsValuePatternAvailablePropertyId, }, { &IsItemContainerPatternAvailable_Property_GUID, UIA_IsItemContainerPatternAvailablePropertyId, }, { &IsContentElement_Property_GUID, UIA_IsContentElementPropertyId, - UIAutomationType_Bool, }, + PROP_TYPE_ELEM_PROP, UIAutomationType_Bool, }, { &LegacyIAccessible_KeyboardShortcut_Property_GUID, UIA_LegacyIAccessibleKeyboardShortcutPropertyId, }, { &IsPassword_Property_GUID, UIA_IsPasswordPropertyId, - UIAutomationType_Bool, }, + PROP_TYPE_ELEM_PROP, UIAutomationType_Bool, }, { &IsWindowPatternAvailable_Property_GUID, UIA_IsWindowPatternAvailablePropertyId, }, { &RangeValue_Minimum_Property_GUID, UIA_RangeValueMinimumPropertyId, }, { &BoundingRectangle_Property_GUID, UIA_BoundingRectanglePropertyId, }, { &LegacyIAccessible_Value_Property_GUID, UIA_LegacyIAccessibleValuePropertyId, }, { &IsDragPatternAvailable_Property_GUID, UIA_IsDragPatternAvailablePropertyId, }, { &DescribedBy_Property_GUID, UIA_DescribedByPropertyId, - UIAutomationType_ElementArray, }, + PROP_TYPE_ELEM_PROP, UIAutomationType_ElementArray, }, { &IsSelectionPatternAvailable_Property_GUID, UIA_IsSelectionPatternAvailablePropertyId, }, { &Grid_RowCount_Property_GUID, UIA_GridRowCountPropertyId, }, { &OutlineColor_Property_GUID, UIA_OutlineColorPropertyId, - UIAutomationType_IntArray, }, + PROP_TYPE_ELEM_PROP, UIAutomationType_IntArray, }, { &Table_RowOrColumnMajor_Property_GUID, UIA_TableRowOrColumnMajorPropertyId, }, { &IsDockPatternAvailable_Property_GUID, UIA_IsDockPatternAvailablePropertyId, }, { &IsSynchronizedInputPatternAvailable_Property_GUID,UIA_IsSynchronizedInputPatternAvailablePropertyId, }, { &OutlineThickness_Property_GUID, UIA_OutlineThicknessPropertyId, - UIAutomationType_DoubleArray, }, + PROP_TYPE_ELEM_PROP, UIAutomationType_DoubleArray, }, { &IsLegacyIAccessiblePatternAvailable_Property_GUID,UIA_IsLegacyIAccessiblePatternAvailablePropertyId, }, { &AnnotationObjects_Property_GUID, UIA_AnnotationObjectsPropertyId, - UIAutomationType_ElementArray, }, + PROP_TYPE_ELEM_PROP, UIAutomationType_ElementArray, }, { &IsRequiredForForm_Property_GUID, UIA_IsRequiredForFormPropertyId, - UIAutomationType_Bool, }, + PROP_TYPE_ELEM_PROP, UIAutomationType_Bool, }, { &SpreadsheetItem_AnnotationTypes_Property_GUID, UIA_SpreadsheetItemAnnotationTypesPropertyId, }, { &FillColor_Property_GUID, UIA_FillColorPropertyId, - UIAutomationType_Int, }, + PROP_TYPE_ELEM_PROP, UIAutomationType_Int, }, { &IsStylesPatternAvailable_Property_GUID, UIA_IsStylesPatternAvailablePropertyId, }, { &Window_IsTopmost_Property_GUID, UIA_WindowIsTopmostPropertyId, }, { &IsCustomNavigationPatternAvailable_Property_GUID, UIA_IsCustomNavigationPatternAvailablePropertyId, }, { &Scroll_HorizontalViewSize_Property_GUID, UIA_ScrollHorizontalViewSizePropertyId, }, { &AcceleratorKey_Property_GUID, UIA_AcceleratorKeyPropertyId, - UIAutomationType_String, }, + PROP_TYPE_ELEM_PROP, UIAutomationType_String, }, { &IsTextChildPatternAvailable_Property_GUID, UIA_IsTextChildPatternAvailablePropertyId, }, { &LegacyIAccessible_Selection_Property_GUID, UIA_LegacyIAccessibleSelectionPropertyId, }, { &FillType_Property_GUID, UIA_FillTypePropertyId, - UIAutomationType_Int, }, + PROP_TYPE_ELEM_PROP, UIAutomationType_Int, }, { &ControlType_Property_GUID, UIA_ControlTypePropertyId, - UIAutomationType_Int, }, + PROP_TYPE_ELEM_PROP, UIAutomationType_Int, }, { &IsMultipleViewPatternAvailable_Property_GUID, UIA_IsMultipleViewPatternAvailablePropertyId, }, { &DropTarget_DropTargetEffects_Property_GUID, UIA_DropTargetDropTargetEffectsPropertyId, }, { &LandmarkType_Property_GUID, UIA_LandmarkTypePropertyId, - UIAutomationType_Int, }, + PROP_TYPE_ELEM_PROP, UIAutomationType_Int, }, { &Drag_IsGrabbed_Property_GUID, UIA_DragIsGrabbedPropertyId, }, { &GridItem_ColumnSpan_Property_GUID, UIA_GridItemColumnSpanPropertyId, }, { &Styles_Shape_Property_GUID, UIA_StylesShapePropertyId, }, - { &RuntimeId_Property_GUID, UIA_RuntimeIdPropertyId, }, + { &RuntimeId_Property_GUID, UIA_RuntimeIdPropertyId, + PROP_TYPE_SPECIAL, UIAutomationType_IntArray, }, { &IsSelectionPattern2Available_Property_GUID, UIA_IsSelectionPattern2AvailablePropertyId, }, { &MultipleView_SupportedViews_Property_GUID, UIA_MultipleViewSupportedViewsPropertyId, }, { &Styles_FillPatternColor_Property_GUID, UIA_StylesFillPatternColorPropertyId, }, { &FullDescription_Property_GUID, UIA_FullDescriptionPropertyId, - UIAutomationType_String, }, + PROP_TYPE_ELEM_PROP, UIAutomationType_String, }, };
static const int prop_id_idx[] = { diff --git a/dlls/uiautomationcore/uia_private.h b/dlls/uiautomationcore/uia_private.h index 40ea9db5cfc..ed53da58471 100644 --- a/dlls/uiautomationcore/uia_private.h +++ b/dlls/uiautomationcore/uia_private.h @@ -21,4 +21,10 @@ #include "uiautomation.h" #include "uia_classes.h"
+enum uia_prop_type { + PROP_TYPE_UNKNOWN, + PROP_TYPE_ELEM_PROP, + PROP_TYPE_SPECIAL, +}; + const struct uia_prop_info *uia_prop_info_from_id(PROPERTYID prop_id) DECLSPEC_HIDDEN;
From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/uiautomationcore/tests/uiautomation.c | 90 +++++++++++++++++++++ dlls/uiautomationcore/uia_client.c | 37 +++++++++ dlls/uiautomationcore/uiautomationcore.spec | 2 +- include/uiautomationcoreapi.h | 1 + 4 files changed, 129 insertions(+), 1 deletion(-)
diff --git a/dlls/uiautomationcore/tests/uiautomation.c b/dlls/uiautomationcore/tests/uiautomation.c index 06309566990..9af859f1a7a 100644 --- a/dlls/uiautomationcore/tests/uiautomation.c +++ b/dlls/uiautomationcore/tests/uiautomation.c @@ -4835,6 +4835,95 @@ static void test_UiaGetRuntimeId(void) CoUninitialize(); }
+static LONG Object_ref = 1; +static HRESULT WINAPI Object_QueryInterface(IUnknown *iface, REFIID riid, void **ppv) +{ + *ppv = NULL; + if (IsEqualIID(riid, &IID_IUnknown)) + { + *ppv = iface; + IUnknown_AddRef(iface); + return S_OK; + } + + return E_NOINTERFACE; +} + +static ULONG WINAPI Object_AddRef(IUnknown *iface) +{ + return InterlockedIncrement(&Object_ref); +} + +static ULONG WINAPI Object_Release(IUnknown *iface) +{ + return InterlockedDecrement(&Object_ref); +} + +static IUnknownVtbl ObjectVtbl = { + Object_QueryInterface, + Object_AddRef, + Object_Release +}; + +static IUnknown Object = {&ObjectVtbl}; +static void test_UiaHUiaNodeFromVariant(void) +{ + HUIANODE node; + HRESULT hr; + VARIANT v; + + hr = UiaHUiaNodeFromVariant(NULL, &node); + ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); + + hr = UiaHUiaNodeFromVariant(&v, NULL); + ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); + + node = (void *)0xdeadbeef; + V_VT(&v) = VT_R8; + hr = UiaHUiaNodeFromVariant(&v, &node); + ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); + ok(!node, "node != NULL\n"); + + node = (void *)0xdeadbeef; + V_VT(&v) = VT_UNKNOWN; + V_UNKNOWN(&v) = &Object; + hr = UiaHUiaNodeFromVariant(&v, &node); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(node == (void *)&Object, "node != NULL\n"); + ok(Object_ref == 2, "Unexpected Object_ref %ld\n", Object_ref); + VariantClear(&v); + +#ifdef _WIN64 + node = (void *)0xdeadbeef; + V_VT(&v) = VT_I4; + V_I4(&v) = 0xbeefdead; + hr = UiaHUiaNodeFromVariant(&v, &node); + ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); + ok(!node, "node != NULL\n"); + + node = (void *)0xdeadbeef; + V_VT(&v) = VT_I8; + V_I8(&v) = 0xbeefdead; + hr = UiaHUiaNodeFromVariant(&v, &node); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(node == (void *)V_I8(&v), "node != V_I8\n"); +#else + node = (void *)0xdeadbeef; + V_VT(&v) = VT_I8; + V_I8(&v) = 0xbeefdead; + hr = UiaHUiaNodeFromVariant(&v, &node); + ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); + ok(!node, "node != NULL\n"); + + node = (void *)0xdeadbeef; + V_VT(&v) = VT_I4; + V_I4(&v) = 0xbeefdead; + hr = UiaHUiaNodeFromVariant(&v, &node); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(node == (void *)V_I4(&v), "node != V_I8\n"); +#endif +} + START_TEST(uiautomation) { HMODULE uia_dll = LoadLibraryA("uiautomationcore.dll"); @@ -4857,6 +4946,7 @@ START_TEST(uiautomation) test_UiaNodeFromProvider(); test_UiaGetPropertyValue(); test_UiaGetRuntimeId(); + test_UiaHUiaNodeFromVariant(); if (uia_dll) { pUiaProviderFromIAccessible = (void *)GetProcAddress(uia_dll, "UiaProviderFromIAccessible"); diff --git a/dlls/uiautomationcore/uia_client.c b/dlls/uiautomationcore/uia_client.c index f166ed20b53..0ff01eba5af 100644 --- a/dlls/uiautomationcore/uia_client.c +++ b/dlls/uiautomationcore/uia_client.c @@ -979,3 +979,40 @@ HRESULT WINAPI UiaGetRuntimeId(HUIANODE huianode, SAFEARRAY **runtime_id)
return S_OK; } + +/*********************************************************************** + * UiaHUiaNodeFromVariant (uiautomationcore.@) + */ +HRESULT WINAPI UiaHUiaNodeFromVariant(VARIANT *in_val, HUIANODE *huianode) +{ + const VARTYPE expected_vt = sizeof(void *) == 8 ? VT_I8 : VT_I4; + + TRACE("(%p, %p)\n", in_val, huianode); + + if (!in_val || !huianode) + return E_INVALIDARG; + + *huianode = NULL; + if ((V_VT(in_val) != expected_vt) && (V_VT(in_val) != VT_UNKNOWN)) + { + WARN("Invalid vt %d\n", V_VT(in_val)); + return E_INVALIDARG; + } + + if (V_VT(in_val) == VT_UNKNOWN) + { + if (V_UNKNOWN(in_val)) + IUnknown_AddRef(V_UNKNOWN(in_val)); + *huianode = (HUIANODE)V_UNKNOWN(in_val); + } + else + { +#ifdef _WIN64 + *huianode = (HUIANODE)V_I8(in_val); +#else + *huianode = (HUIANODE)V_I4(in_val); +#endif + } + + return S_OK; +} diff --git a/dlls/uiautomationcore/uiautomationcore.spec b/dlls/uiautomationcore/uiautomationcore.spec index 17e34ee259a..f4e745a644a 100644 --- a/dlls/uiautomationcore/uiautomationcore.spec +++ b/dlls/uiautomationcore/uiautomationcore.spec @@ -70,7 +70,7 @@ @ stub UiaGetUpdatedCache @ stub UiaHPatternObjectFromVariant @ stub UiaHTextRangeFromVariant -@ stub UiaHUiaNodeFromVariant +@ stdcall UiaHUiaNodeFromVariant(ptr ptr) @ stub UiaHasServerSideProvider @ stdcall UiaHostProviderFromHwnd(long ptr) #@ stub UiaIAccessibleFromProvider diff --git a/include/uiautomationcoreapi.h b/include/uiautomationcoreapi.h index 78cbca2e25b..946c8b0fadc 100644 --- a/include/uiautomationcoreapi.h +++ b/include/uiautomationcoreapi.h @@ -396,6 +396,7 @@ HRESULT WINAPI UiaGetPropertyValue(HUIANODE huianode, PROPERTYID prop_id, VARIAN HRESULT WINAPI UiaNodeFromProvider(IRawElementProviderSimple *elprov, HUIANODE *huianode); BOOL WINAPI UiaNodeRelease(HUIANODE huianode); HRESULT WINAPI UiaGetRuntimeId(HUIANODE huianode, SAFEARRAY **runtime_id); +HRESULT WINAPI UiaHUiaNodeFromVariant(VARIANT *in_val, HUIANODE *huianode);
#ifdef __cplusplus }
V2:
- Make dimension check in `get_safearray_bounds()` more clear. - Fix accidental indentation in `ProviderFragment_get_FragmentRoot`.
This merge request was approved by Huw Davies.