mirror of
git://source.winehq.org/git/wine.git
synced 2024-10-14 12:47:16 +00:00
uiautomationcore: Implement IUIAutomationElement::GetCachedPropertyValueEx.
Signed-off-by: Connor McAdams <cmcadams@codeweavers.com>
This commit is contained in:
parent
29a4e096d7
commit
d3d108f9b8
|
@ -10869,11 +10869,25 @@ static const struct prov_method_sequence get_cached_prop_val_seq2[] = {
|
|||
{ 0 },
|
||||
};
|
||||
|
||||
static const struct prov_method_sequence get_cached_prop_val_seq3[] = {
|
||||
{ &Provider, PROV_GET_PROPERTY_VALUE },
|
||||
NODE_CREATE_SEQ(&Provider_child),
|
||||
{ &Provider, PROV_GET_PROPERTY_VALUE },
|
||||
NODE_CREATE_SEQ(&Provider_child),
|
||||
NODE_CREATE_SEQ(&Provider_child2),
|
||||
{ &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
|
||||
{ &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_ControlTypePropertyId */
|
||||
{ &Provider_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_ControlTypePropertyId */
|
||||
{ 0 },
|
||||
};
|
||||
|
||||
static void test_Element_cache_methods(IUIAutomation *uia_iface)
|
||||
{
|
||||
HWND hwnd = create_test_hwnd("test_Element_cache_methods class");
|
||||
IUIAutomationElement *element, *element2;
|
||||
IUIAutomationElement *element, *element2, *element3;
|
||||
IUIAutomationCacheRequest *cache_req;
|
||||
IUIAutomationElementArray *elem_arr;
|
||||
int tmp_rt_id[2], i, len;
|
||||
IUnknown *unk_ns;
|
||||
HRESULT hr;
|
||||
VARIANT v;
|
||||
|
@ -10938,15 +10952,14 @@ static void test_Element_cache_methods(IUIAutomation *uia_iface)
|
|||
|
||||
/* RuntimeId is currently unset, so we'll get the NotSupported value. */
|
||||
hr = IUIAutomationElement_GetCachedPropertyValueEx(element2, UIA_RuntimeIdPropertyId, TRUE, &v);
|
||||
todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
|
||||
todo_wine ok(V_VT(&v) == VT_UNKNOWN, "Unexpected vt %d\n", V_VT(&v));
|
||||
if (SUCCEEDED(hr))
|
||||
ok(V_UNKNOWN(&v) == unk_ns, "unexpected IUnknown %p\n", V_UNKNOWN(&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);
|
||||
|
||||
/* Attempting to get a cached value for a non-cached property. */
|
||||
hr = IUIAutomationElement_GetCachedPropertyValueEx(element2, UIA_IsControlElementPropertyId, TRUE, &v);
|
||||
todo_wine ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
|
||||
ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
|
||||
ok(V_VT(&v) == VT_EMPTY, "Unexpected vt %d\n", V_VT(&v));
|
||||
VariantClear(&v);
|
||||
|
||||
|
@ -10961,10 +10974,9 @@ static void test_Element_cache_methods(IUIAutomation *uia_iface)
|
|||
ok_method_sequence(get_cached_prop_val_seq, "get_cached_prop_val_seq");
|
||||
|
||||
hr = IUIAutomationElement_GetCachedPropertyValueEx(element2, UIA_RuntimeIdPropertyId, TRUE, &v);
|
||||
todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
|
||||
todo_wine ok(V_VT(&v) == (VT_I4 | VT_ARRAY), "Unexpected vt %d\n", V_VT(&v));
|
||||
if (SUCCEEDED(hr))
|
||||
check_runtime_id(Provider_child.runtime_id, ARRAY_SIZE(Provider_child.runtime_id), V_ARRAY(&v));
|
||||
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
|
||||
ok(V_VT(&v) == (VT_I4 | VT_ARRAY), "Unexpected vt %d\n", V_VT(&v));
|
||||
check_runtime_id(Provider_child.runtime_id, ARRAY_SIZE(Provider_child.runtime_id), V_ARRAY(&v));
|
||||
VariantClear(&v);
|
||||
IUIAutomationElement_Release(element2);
|
||||
|
||||
|
@ -10983,22 +10995,116 @@ static void test_Element_cache_methods(IUIAutomation *uia_iface)
|
|||
ok_method_sequence(get_cached_prop_val_seq2, "get_cached_prop_val_seq2");
|
||||
|
||||
hr = IUIAutomationElement_GetCachedPropertyValueEx(element2, UIA_RuntimeIdPropertyId, TRUE, &v);
|
||||
todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
|
||||
todo_wine ok(V_VT(&v) == (VT_I4 | VT_ARRAY), "Unexpected vt %d\n", V_VT(&v));
|
||||
if (SUCCEEDED(hr))
|
||||
check_runtime_id(Provider_child.runtime_id, ARRAY_SIZE(Provider_child.runtime_id), V_ARRAY(&v));
|
||||
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
|
||||
ok(V_VT(&v) == (VT_I4 | VT_ARRAY), "Unexpected vt %d\n", V_VT(&v));
|
||||
check_runtime_id(Provider_child.runtime_id, ARRAY_SIZE(Provider_child.runtime_id), V_ARRAY(&v));
|
||||
VariantClear(&v);
|
||||
|
||||
hr = IUIAutomationElement_GetCachedPropertyValueEx(element2, UIA_IsControlElementPropertyId, TRUE, &v);
|
||||
todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
|
||||
todo_wine ok(check_variant_bool(&v, TRUE), "V_BOOL(&v) = %#x\n", V_BOOL(&v));
|
||||
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
|
||||
ok(check_variant_bool(&v, TRUE), "V_BOOL(&v) = %#x\n", V_BOOL(&v));
|
||||
VariantClear(&v);
|
||||
|
||||
IUIAutomationElement_Release(element2);
|
||||
IUIAutomationCacheRequest_Release(cache_req);
|
||||
|
||||
IUIAutomationElement_Release(element);
|
||||
ok(Provider_child.ref == 1, "Unexpected refcnt %ld\n", Provider_child.ref);
|
||||
|
||||
/* Test cached UIAutomationType_Element properties. */
|
||||
element = create_test_element_from_hwnd(uia_iface, hwnd, TRUE);
|
||||
|
||||
cache_req = NULL;
|
||||
hr = IUIAutomation_CreateCacheRequest(uia_iface, &cache_req);
|
||||
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
|
||||
ok(!!cache_req, "cache_req == NULL\n");
|
||||
|
||||
/* UIAutomationType_Element property. */
|
||||
hr = IUIAutomationCacheRequest_AddProperty(cache_req, UIA_LabeledByPropertyId);
|
||||
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
|
||||
|
||||
/* UIAutomationType_ElementArray property. */
|
||||
hr = IUIAutomationCacheRequest_AddProperty(cache_req, UIA_ControllerForPropertyId);
|
||||
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
|
||||
|
||||
element2 = NULL;
|
||||
hr = IUIAutomationElement_BuildUpdatedCache(element, cache_req, &element2);
|
||||
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
|
||||
ok(!!element2, "element2 == NULL\n");
|
||||
ok(Provider_child.ref == 3, "Unexpected refcnt %ld\n", Provider_child.ref);
|
||||
ok(Provider_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child2.ref);
|
||||
|
||||
tmp_rt_id[0] = UIA_RUNTIME_ID_PREFIX;
|
||||
tmp_rt_id[1] = HandleToULong(hwnd);
|
||||
hr = IUIAutomationElement_GetCachedPropertyValueEx(element2, UIA_RuntimeIdPropertyId, TRUE, &v);
|
||||
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
|
||||
ok(V_VT(&v) == (VT_I4 | VT_ARRAY), "Unexpected vt %d\n", V_VT(&v));
|
||||
check_runtime_id(tmp_rt_id, ARRAY_SIZE(tmp_rt_id), V_ARRAY(&v));
|
||||
VariantClear(&v);
|
||||
|
||||
/* Cached IUIAutomationElement. */
|
||||
hr = IUIAutomationElement_GetCachedPropertyValueEx(element2, UIA_LabeledByPropertyId, TRUE, &v);
|
||||
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
|
||||
ok(V_VT(&v) == VT_UNKNOWN, "Unexpected vt %d\n", V_VT(&v));
|
||||
|
||||
element3 = NULL;
|
||||
hr = IUnknown_QueryInterface(V_UNKNOWN(&v), &IID_IUIAutomationElement, (void **)&element3);
|
||||
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
|
||||
ok(!!element3, "element3 == NULL\n");
|
||||
VariantClear(&v);
|
||||
|
||||
hr = IUIAutomationElement_GetCurrentPropertyValueEx(element3, UIA_IsControlElementPropertyId, TRUE, &v);
|
||||
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
|
||||
ok(check_variant_bool(&v, TRUE), "V_BOOL(&v) = %#x\n", V_BOOL(&v));
|
||||
IUIAutomationElement_Release(element3);
|
||||
VariantClear(&v);
|
||||
|
||||
/* Cached IUIAutomationElementArray. */
|
||||
hr = IUIAutomationElement_GetCachedPropertyValueEx(element2, UIA_ControllerForPropertyId, TRUE, &v);
|
||||
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
|
||||
ok(V_VT(&v) == VT_UNKNOWN, "Unexpected vt %d\n", V_VT(&v));
|
||||
|
||||
hr = IUnknown_QueryInterface(V_UNKNOWN(&v), &IID_IUIAutomationElementArray, (void **)&elem_arr);
|
||||
ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
|
||||
ok(!!elem_arr, "elem_arr == NULL\n");
|
||||
VariantClear(&v);
|
||||
|
||||
hr = IUIAutomationElementArray_get_Length(elem_arr, &len);
|
||||
ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
|
||||
ok(len == ARRAY_SIZE(uia_unk_arr_prop_val), "Unexpected length %d\n", len);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(uia_unk_arr_prop_val); i++)
|
||||
{
|
||||
hr = IUIAutomationElementArray_GetElement(elem_arr, i, &element3);
|
||||
ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
|
||||
ok(!!element3, "element3 == NULL\n");
|
||||
|
||||
hr = IUIAutomationElement_GetCurrentPropertyValueEx(element3, UIA_ControlTypePropertyId, TRUE, &v);
|
||||
ok(hr == S_OK, "elem[%d] Unexpected hr %#lx\n", i, hr);
|
||||
ok(V_VT(&v) == VT_I4, "elem[%d] Unexpected VT %d\n", i, V_VT(&v));
|
||||
ok(V_I4(&v) == uia_i4_prop_val, "elem[%d] Unexpected I4 %#lx\n", i, V_I4(&v));
|
||||
|
||||
IUIAutomationElement_Release(element3);
|
||||
VariantClear(&v);
|
||||
}
|
||||
|
||||
IUIAutomationElementArray_Release(elem_arr);
|
||||
IUIAutomationCacheRequest_Release(cache_req);
|
||||
|
||||
/*
|
||||
* Reference isn't released until the element holding the cache is
|
||||
* destroyed.
|
||||
*/
|
||||
ok(Provider_child.ref == 3, "Unexpected refcnt %ld\n", Provider_child.ref);
|
||||
ok(Provider_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child2.ref);
|
||||
|
||||
IUIAutomationElement_Release(element2);
|
||||
ok(Provider_child.ref == 1, "Unexpected refcnt %ld\n", Provider_child.ref);
|
||||
ok(Provider_child2.ref == 1, "Unexpected refcnt %ld\n", Provider_child2.ref);
|
||||
ok_method_sequence(get_cached_prop_val_seq3, "get_cached_prop_val_seq3");
|
||||
|
||||
IUIAutomationElement_Release(element);
|
||||
ok(Provider.ref == 1, "Unexpected refcnt %ld\n", Provider.ref);
|
||||
IUnknown_Release(unk_ns);
|
||||
|
||||
DestroyWindow(hwnd);
|
||||
|
|
|
@ -1029,6 +1029,11 @@ static HRESULT create_uia_element_array_iface(IUIAutomationElementArray **iface,
|
|||
return S_OK;
|
||||
}
|
||||
|
||||
struct uia_cache_property {
|
||||
int prop_id;
|
||||
VARIANT prop_val;
|
||||
};
|
||||
|
||||
/*
|
||||
* IUIAutomationElement interface.
|
||||
*/
|
||||
|
@ -1038,6 +1043,9 @@ struct uia_element {
|
|||
|
||||
BOOL from_cui8;
|
||||
HUIANODE node;
|
||||
|
||||
struct uia_cache_property *cached_props;
|
||||
int cached_props_count;
|
||||
};
|
||||
|
||||
static inline struct uia_element *impl_from_IUIAutomationElement9(IUIAutomationElement9 *iface)
|
||||
|
@ -1079,6 +1087,15 @@ static ULONG WINAPI uia_element_Release(IUIAutomationElement9 *iface)
|
|||
TRACE("%p, refcount %ld\n", element, ref);
|
||||
if (!ref)
|
||||
{
|
||||
if (element->cached_props_count)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < element->cached_props_count; i++)
|
||||
VariantClear(&element->cached_props[i].prop_val);
|
||||
}
|
||||
|
||||
heap_free(element->cached_props);
|
||||
UiaNodeRelease(element->node);
|
||||
heap_free(element);
|
||||
}
|
||||
|
@ -1126,8 +1143,8 @@ static HRESULT WINAPI uia_element_FindAllBuildCache(IUIAutomationElement9 *iface
|
|||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static HRESULT create_uia_element_from_cache_req(IUIAutomationElement **iface, BOOL from_cui8, SAFEARRAY *req_data,
|
||||
BSTR tree_struct);
|
||||
static HRESULT create_uia_element_from_cache_req(IUIAutomationElement **iface, BOOL from_cui8,
|
||||
struct UiaCacheRequest *cache_req, SAFEARRAY *req_data, BSTR tree_struct);
|
||||
static HRESULT WINAPI uia_element_BuildUpdatedCache(IUIAutomationElement9 *iface, IUIAutomationCacheRequest *cache_req,
|
||||
IUIAutomationElement **updated_elem)
|
||||
{
|
||||
|
@ -1152,7 +1169,7 @@ static HRESULT WINAPI uia_element_BuildUpdatedCache(IUIAutomationElement9 *iface
|
|||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
hr = create_uia_element_from_cache_req(&cache_elem, element->from_cui8, sa, tree_struct);
|
||||
hr = create_uia_element_from_cache_req(&cache_elem, element->from_cui8, cache_req_struct, sa, tree_struct);
|
||||
if (SUCCEEDED(hr))
|
||||
*updated_elem = cache_elem;
|
||||
|
||||
|
@ -1168,45 +1185,78 @@ static HRESULT WINAPI uia_element_GetCurrentPropertyValue(IUIAutomationElement9
|
|||
}
|
||||
|
||||
static HRESULT create_uia_element(IUIAutomationElement **iface, BOOL from_cui8, HUIANODE node);
|
||||
static HRESULT create_element_array_from_node_array(SAFEARRAY *sa, BOOL from_cui8,
|
||||
IUIAutomationElementArray **out_elem_arr)
|
||||
static HRESULT get_element_variant_from_node_variant(VARIANT *var, BOOL from_cui8, int prop_type)
|
||||
{
|
||||
struct uia_element_array *elem_arr_data;
|
||||
IUIAutomationElementArray *elem_arr;
|
||||
LONG idx, lbound, elems, i;
|
||||
HUIANODE node;
|
||||
HRESULT hr;
|
||||
|
||||
*out_elem_arr = NULL;
|
||||
hr = get_safearray_bounds(sa, &lbound, &elems);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
/* ReservedNotSupported interface, just return it. */
|
||||
if (V_VT(var) == VT_UNKNOWN)
|
||||
return S_OK;
|
||||
|
||||
hr = create_uia_element_array_iface(&elem_arr, elems);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
elem_arr_data = impl_from_IUIAutomationElementArray(elem_arr);
|
||||
for (i = 0; i < elems; i++)
|
||||
if (prop_type & UIAutomationType_Array)
|
||||
{
|
||||
HUIANODE node;
|
||||
struct uia_element_array *elem_arr_data;
|
||||
IUIAutomationElementArray *elem_arr;
|
||||
LONG idx, lbound, elems, i;
|
||||
|
||||
idx = lbound + i;
|
||||
hr = SafeArrayGetElement(sa, &idx, &node);
|
||||
if (FAILED(hr))
|
||||
break;
|
||||
|
||||
hr = create_uia_element(&elem_arr_data->elements[i], from_cui8, node);
|
||||
hr = get_safearray_bounds(V_ARRAY(var), &lbound, &elems);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
UiaNodeRelease(node);
|
||||
break;
|
||||
VariantClear(var);
|
||||
return hr;
|
||||
}
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
*out_elem_arr = elem_arr;
|
||||
hr = create_uia_element_array_iface(&elem_arr, elems);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
VariantClear(var);
|
||||
return hr;
|
||||
}
|
||||
|
||||
elem_arr_data = impl_from_IUIAutomationElementArray(elem_arr);
|
||||
for (i = 0; i < elems; i++)
|
||||
{
|
||||
idx = lbound + i;
|
||||
hr = SafeArrayGetElement(V_ARRAY(var), &idx, &node);
|
||||
if (FAILED(hr))
|
||||
break;
|
||||
|
||||
hr = create_uia_element(&elem_arr_data->elements[i], from_cui8, node);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
UiaNodeRelease(node);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
VariantClear(var);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
V_VT(var) = VT_UNKNOWN;
|
||||
V_UNKNOWN(var) = (IUnknown *)elem_arr;
|
||||
}
|
||||
else
|
||||
IUIAutomationElementArray_Release(elem_arr);
|
||||
}
|
||||
else
|
||||
IUIAutomationElementArray_Release(elem_arr);
|
||||
{
|
||||
IUIAutomationElement *out_elem;
|
||||
|
||||
hr = UiaHUiaNodeFromVariant(var, &node);
|
||||
VariantClear(var);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
hr = create_uia_element(&out_elem, from_cui8, node);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
V_VT(var) = VT_UNKNOWN;
|
||||
V_UNKNOWN(var) = (IUnknown *)out_elem;
|
||||
}
|
||||
else
|
||||
UiaNodeRelease(node);
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
@ -1234,53 +1284,8 @@ static HRESULT WINAPI uia_element_GetCurrentPropertyValueEx(IUIAutomationElement
|
|||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
switch (prop_info->type)
|
||||
{
|
||||
case UIAutomationType_Element:
|
||||
{
|
||||
IUIAutomationElement *out_elem;
|
||||
HUIANODE node;
|
||||
|
||||
if (V_VT(ret_val) == VT_UNKNOWN)
|
||||
break;
|
||||
|
||||
hr = UiaHUiaNodeFromVariant(ret_val, &node);
|
||||
VariantClear(ret_val);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
hr = create_uia_element(&out_elem, element->from_cui8, node);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
V_VT(ret_val) = VT_UNKNOWN;
|
||||
V_UNKNOWN(ret_val) = (IUnknown *)out_elem;
|
||||
}
|
||||
else
|
||||
UiaNodeRelease(node);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case UIAutomationType_ElementArray:
|
||||
{
|
||||
IUIAutomationElementArray *out_elem_arr;
|
||||
|
||||
if (V_VT(ret_val) == VT_UNKNOWN)
|
||||
break;
|
||||
|
||||
hr = create_element_array_from_node_array(V_ARRAY(ret_val), element->from_cui8, &out_elem_arr);
|
||||
VariantClear(ret_val);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
V_VT(ret_val) = VT_UNKNOWN;
|
||||
V_UNKNOWN(ret_val) = (IUnknown *)out_elem_arr;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if ((prop_info->type == UIAutomationType_Element) || (prop_info->type == UIAutomationType_ElementArray))
|
||||
hr = get_element_variant_from_node_variant(ret_val, element->from_cui8, prop_info->type);
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
@ -1292,11 +1297,38 @@ static HRESULT WINAPI uia_element_GetCachedPropertyValue(IUIAutomationElement9 *
|
|||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static int __cdecl uia_cached_property_id_compare(const void *a, const void *b)
|
||||
{
|
||||
const PROPERTYID *prop_id = a;
|
||||
const struct uia_cache_property *cache_prop = b;
|
||||
|
||||
return ((*prop_id) > cache_prop->prop_id) - ((*prop_id) < cache_prop->prop_id);
|
||||
}
|
||||
|
||||
static HRESULT WINAPI uia_element_GetCachedPropertyValueEx(IUIAutomationElement9 *iface, PROPERTYID prop_id,
|
||||
BOOL ignore_default, VARIANT *ret_val)
|
||||
{
|
||||
FIXME("%p: stub\n", iface);
|
||||
return E_NOTIMPL;
|
||||
struct uia_element *element = impl_from_IUIAutomationElement9(iface);
|
||||
struct uia_cache_property *cache_prop = NULL;
|
||||
|
||||
TRACE("%p, %d, %d, %p\n", iface, prop_id, ignore_default, ret_val);
|
||||
|
||||
if (!ret_val)
|
||||
return E_POINTER;
|
||||
|
||||
VariantInit(ret_val);
|
||||
if (!uia_prop_info_from_id(prop_id) || !element->cached_props)
|
||||
return E_INVALIDARG;
|
||||
|
||||
if (!ignore_default)
|
||||
FIXME("Default values currently unimplemented\n");
|
||||
|
||||
if (!(cache_prop = bsearch(&prop_id, element->cached_props, element->cached_props_count, sizeof(*cache_prop),
|
||||
uia_cached_property_id_compare)))
|
||||
return E_INVALIDARG;
|
||||
|
||||
VariantCopy(ret_val, &cache_prop->prop_val);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI uia_element_GetCurrentPatternAs(IUIAutomationElement9 *iface, PATTERNID pattern_id,
|
||||
|
@ -2144,9 +2176,19 @@ static HRESULT create_uia_element(IUIAutomationElement **iface, BOOL from_cui8,
|
|||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT create_uia_element_from_cache_req(IUIAutomationElement **iface, BOOL from_cui8, SAFEARRAY *req_data,
|
||||
BSTR tree_struct)
|
||||
static int __cdecl uia_compare_cache_props(const void *a, const void *b)
|
||||
{
|
||||
struct uia_cache_property *prop1 = (struct uia_cache_property *)a;
|
||||
struct uia_cache_property *prop2 = (struct uia_cache_property *)b;
|
||||
|
||||
return (prop1->prop_id > prop2->prop_id) - (prop1->prop_id < prop2->prop_id);
|
||||
}
|
||||
|
||||
static HRESULT create_uia_element_from_cache_req(IUIAutomationElement **iface, BOOL from_cui8,
|
||||
struct UiaCacheRequest *cache_req, SAFEARRAY *req_data, BSTR tree_struct)
|
||||
{
|
||||
IUIAutomationElement *element = NULL;
|
||||
struct uia_element *elem_data;
|
||||
HUIANODE node;
|
||||
LONG idx[2];
|
||||
HRESULT hr;
|
||||
|
@ -2165,11 +2207,61 @@ static HRESULT create_uia_element_from_cache_req(IUIAutomationElement **iface, B
|
|||
goto exit;
|
||||
VariantClear(&v);
|
||||
|
||||
hr = create_uia_element(iface, from_cui8, node);
|
||||
hr = create_uia_element(&element, from_cui8, node);
|
||||
if (FAILED(hr))
|
||||
goto exit;
|
||||
|
||||
elem_data = impl_from_IUIAutomationElement9((IUIAutomationElement9 *)element);
|
||||
if (cache_req->cProperties)
|
||||
{
|
||||
LONG i;
|
||||
|
||||
elem_data->cached_props = heap_alloc_zero(sizeof(*elem_data->cached_props) * cache_req->cProperties);
|
||||
if (!elem_data->cached_props)
|
||||
{
|
||||
hr = E_OUTOFMEMORY;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
elem_data->cached_props_count = cache_req->cProperties;
|
||||
for (i = 0; i < cache_req->cProperties; i++)
|
||||
{
|
||||
const struct uia_prop_info *prop_info = uia_prop_info_from_id(cache_req->pProperties[i]);
|
||||
|
||||
elem_data->cached_props[i].prop_id = prop_info->prop_id;
|
||||
|
||||
idx[0] = 0;
|
||||
idx[1] = 1 + i;
|
||||
hr = SafeArrayGetElement(req_data, idx, &elem_data->cached_props[i].prop_val);
|
||||
if (FAILED(hr))
|
||||
goto exit;
|
||||
|
||||
if ((prop_info->type == UIAutomationType_Element) || (prop_info->type == UIAutomationType_ElementArray))
|
||||
{
|
||||
hr = get_element_variant_from_node_variant(&elem_data->cached_props[i].prop_val, from_cui8,
|
||||
prop_info->type);
|
||||
if (FAILED(hr))
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Sort the array of cached properties by property ID so that we can
|
||||
* access the values with bsearch.
|
||||
*/
|
||||
qsort(elem_data->cached_props, elem_data->cached_props_count, sizeof(*elem_data->cached_props),
|
||||
uia_compare_cache_props);
|
||||
}
|
||||
|
||||
*iface = element;
|
||||
|
||||
exit:
|
||||
if (FAILED(hr))
|
||||
{
|
||||
WARN("Failed to create element from cache request, hr %#lx\n", hr);
|
||||
if (element)
|
||||
IUIAutomationElement_Release(element);
|
||||
}
|
||||
|
||||
SysFreeString(tree_struct);
|
||||
return hr;
|
||||
|
|
Loading…
Reference in a new issue